/* ═══════════════════════════════════════════════════════════
   STATES — the book, the lines, the question.

   Written by hand and NEVER minified. The minifier's
   whitespace rule eats the space in `body.state-open .book`,
   which silently turns a descendant selector into a compound
   one and breaks everything. Keep this file out of it.
   ═══════════════════════════════════════════════════════════ */

/* ── THE BOOK ──
   Invisible until reached for. What sits on the table is the
   PAINTED grimoire; ours materialises out of it. */
.book {
  position: absolute;

  /* measured on media/tavern-*.jpg — the painted grimoire's cover
     face spans x 64-79%, y 56-78%. Centre: 71% across, 33% up. */
  left: 71%;
  bottom: 33%;
  width: clamp(150px, 16.5vw, 230px);
  aspect-ratio: .73;
  margin-left: calc(clamp(150px, 16.5vw, 230px) / -2);
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  pointer-events: auto;
  z-index: 4;
  transform-style: preserve-3d;
  will-change: transform, opacity;
  --charge: 0;

  transform: translate3d(0, 26px, 0) rotateX(66deg) rotateZ(-5deg) scale(.94);
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 1.1s ease,
    transform 1.5s cubic-bezier(.16, .84, .26, 1),
    visibility 0s linear 1.1s;
}

/* charging and awake change nothing — it stays hidden */
.book.charging,
.book.awake {
  opacity: 0;
  visibility: hidden;
}

/* HOVERED — it appears, and travels to the centre of frame.
   70.5% - 20.5% = 50%, the same axis as the question. */
.book.approaching {
  visibility: visible;
  opacity: 1;
  transform: translate3d(-21vw, -20vh, 0) rotateX(2deg) rotateZ(0deg) scale(1.34);
  transition:
    opacity 1.1s ease,
    transform 1.5s cubic-bezier(.16, .84, .26, 1),
    visibility 0s;
}

/* OPENED — it flies at you and is gone */
body.state-open .book {
  visibility: visible;
  opacity: 0;
  transform: translate3d(-21vw, -38vh, 0) rotateX(0deg) scale(3.2);
  transition:
    transform 1.2s cubic-bezier(.6, 0, .25, 1),
    opacity .8s ease .35s;
}

/* ── THE COVER LIGHTS, tied to the book being visible ── */

.book.approaching .glow-green  { opacity: .8;  transition: opacity 1.2s ease .35s; }
.book.approaching .glow-gold   { opacity: .75; transition: opacity 1.2s ease .5s; }
.book.approaching .book-cast   { opacity: .85; transition: opacity 1.4s ease .3s; }
.book.approaching .glitter     { opacity: 1; }




/* ── THE OPENING LINE ──
   Surfaces on load. Lifts away when the hand reaches for the book. */
.opening {
  margin: 0;
  max-width: min(90vw, 44rem);
  text-align: center;
  pointer-events: none;
  opacity: 0;
  transform: translateY(-8px);
  animation: opening-surface 2.6s cubic-bezier(.2, .7, .2, 1) .7s forwards;
  will-change: opacity, transform;
  transition: opacity .8s ease, transform .9s cubic-bezier(.4,0,.2,1);
}

body.book-approaching .opening {
  opacity: 0;
  transform: translateY(-18px);
  
  animation: none;
}

body.state-open .opening {
  opacity: 0;
  transform: translateY(-24px);
  transition: opacity .4s ease, transform .4s ease;
}

/* ── THE QUESTION ──
   Rises from beneath as the opening line lifts away. */
.prompt {
  position: absolute;
  left: 50%;
  bottom: 5.5%;
  transform: translateX(-50%) translateY(22px);
  text-align: center;
  width: max-content;
  max-width: 90vw;
  z-index: 6;
  opacity: 0;
  pointer-events: none;
  
  transition: opacity 1s ease .35s, transform 1.1s cubic-bezier(.2,.7,.2,1) .35s;
  will-change: opacity, transform;
}

body.book-approaching .prompt {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  
}

body.state-open .prompt {
  opacity: 0;
  transform: translateX(-50%) translateY(-14px);
  transition: opacity .4s ease, transform .4s ease;
}

/* ── MOBILE ── */


/* ── REDUCED MOTION ── */
@media (prefers-reduced-motion: reduce) {
  .opening {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

/* ── THE TYPE ──
   The words themselves. Caught by the salvage; restored here. */

.opening-line {
  display: block;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  font-weight: 300;
  font-size: clamp(1rem, 1.9vw, 1.42rem);
  line-height: 1.5;
  letter-spacing: .025em;
  color: #8A8070;
  text-shadow: 0 2px 12px rgba(0, 0, 0, .95), 0 0 30px rgba(0, 0, 0, .8);
  animation: opening-breathe 7s ease-in-out 3.4s infinite;
  animation-play-state: var(--play-state);
}

@keyframes opening-breathe {
  0%, 100% { opacity: .72; }
  50%      { opacity: 1; }
}
  50%      { opacity: 1; }

.opening-orn {
  display: block;
  width: clamp(70px, 9vw, 120px);
  height: 1px;
  margin: clamp(.7rem, 1.4vh, 1.1rem) auto 0;
  background: linear-gradient(to right, transparent, rgba(138, 110, 59, .5), transparent);
}

.prompt-text {
  font-family: 'UnifrakturMaguntia', 'Cormorant Garamond', serif;
  font-weight: 400;
  font-size: clamp(1.7rem, 4.4vw, 3rem);
  line-height: 1.15;
  letter-spacing: .01em;
  color: #EFE4C8;
  margin: 0 0 1.1rem;

  /* STATIC. Animating a five-layer text-shadow means re-rendering the
     text and re-blurring five shadows every frame — text cannot be
     composited, it is always a raster. The pulse is opacity now. */
  text-shadow:
    0 0 2px rgba(255, 250, 236, .6),
    0 2px 18px rgba(0, 0, 0, 1),
    0 0 34px rgba(140, 76, 200, .85),
    0 0 60px rgba(100, 224, 140, .5),
    0 0 96px rgba(0, 0, 0, .9);

  animation: question-pulse 4.5s ease-in-out infinite;
  animation-play-state: var(--play-state);
  will-change: opacity;
}

@keyframes question-pulse {
  0%, 100% { opacity: .84; }
  50%      { opacity: 1; }
}
  50% {
    opacity: 1;
    text-shadow:
      0 0 3px rgba(255, 252, 242, .75),
      0 2px 18px rgba(0, 0, 0, 1),
      0 0 42px rgba(150, 80, 210, .95),
      0 0 74px rgba(110, 240, 150, .6),
      0 0 110px rgba(0, 0, 0, .9);
  }

.prompt-rule {
  display: block;
  position: relative;
  width: clamp(160px, 26vw, 260px);
  height: 1px;
  margin: 0 auto;
  background: linear-gradient(to right,
    transparent,
    rgba(200, 160, 90, .15) 20%,
    rgba(220, 190, 130, .6) 50%,
    rgba(200, 160, 90, .15) 80%,
    transparent);
}
/* a diamond at its centre — one ornament, not three */
.prompt-rule::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 7px;
  height: 7px;
  margin: -3.5px 0 0 -3.5px;
  background: rgba(220, 190, 130, .8);
  transform: rotate(45deg);
  box-shadow: 0 0 10px rgba(122, 54, 168, .8);
}

/* ═══════════════════════════════════════════════════════════
   THE HIT AREA

   The book is visibility:hidden, and a hidden element cannot
   receive pointer events — mouseenter can never fire on it.
   This is the target instead: an always-present, transparent
   button sitting exactly over the PAINTED grimoire.

   It is what you hover. It is what you click. The book itself
   is now only scenery, driven by this.
   ═══════════════════════════════════════════════════════════ */

.hitarea {
  position: absolute;

  /* over the painted book, with a little margin so the target
     is generous — a mark you cannot find is a mark that failed */
  left: 70.5%;
  bottom: 24%;
  width: clamp(180px, 20vw, 280px);
  aspect-ratio: 1.15;
  margin-left: calc(clamp(180px, 20vw, 280px) / -2);

  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  pointer-events: auto;
  z-index: 5;
  -webkit-tap-highlight-color: transparent;
}

.hitarea:focus-visible {
  outline: 1px solid rgba(150, 255, 190, .7);
  outline-offset: 6px;
  border-radius: 4px;
}

/* the book itself no longer takes the pointer — it is scenery now */
.book {
  pointer-events: none;
}



/* ═══════════════════════════════════════════════════════════
   THE HIT AREA — TWO TARGETS, NOT ONE

   The bug: the target sat over the PAINTED book, but the animated
   one flew to the centre. Follow it with the cursor and you leave
   the target — mouseleave fires, and it snaps back before you can
   click it.

   The naive fix is to move the target with the book. That fails
   too: while it is in flight the cursor is in the GAP between the
   two positions, and falls out.

   The real fix is two targets:

     .hitarea       the painted book. Always there. It is what
                    you find, and what starts the approach.

     .hitarea-hold  a wide corridor spanning from the painted book
                    all the way to the centre. It only exists WHILE
                    the book is out, and it is what keeps it out —
                    the cursor cannot fall through the gap, because
                    the gap is part of the target.

   Leave the corridor entirely and the book returns, as it should.
   ═══════════════════════════════════════════════════════════ */

.hitarea {
  position: absolute;
  left: 71%;
  bottom: 28%;
  width: clamp(180px, 20vw, 280px);
  aspect-ratio: 1.15;
  margin-left: calc(clamp(180px, 20vw, 280px) / -2);

  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  pointer-events: auto;
  z-index: 5;
  -webkit-tap-highlight-color: transparent;
}

.hitarea:focus-visible {
  outline: 1px solid rgba(150, 255, 190, .7);
  outline-offset: 6px;
  border-radius: 4px;
}

/* ── THE CORRIDOR ──
   Spans the painted book AND the centre AND everything between.
   Dormant until the book is out; then it takes over the pointer,
   so wherever you move within it, the book stays. */
.hitarea-hold {
  position: absolute;
  left: 30%;
  right: 8%;
  top: 10%;
  bottom: 10%;

  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  z-index: 5;

  pointer-events: none;   /* invisible to the cursor until needed */
  -webkit-tap-highlight-color: transparent;
}

body.book-approaching .hitarea-hold {
  pointer-events: auto;
}

/* the book itself never takes the pointer — it is scenery */
.book {
  pointer-events: none;
}



/* ═══════════════════════════════════════════════════════════
   PHONE

   The portrait painting fills the screen. In it, the grimoire
   sits in the lower foreground at roughly 44% across and 26%
   up from the bottom — the interactive book goes there.

   No cursor, so no hover. The book simply ARRIVES, two seconds
   after the page opens, and stays. Tap it to open.

   The beckon glow is gone: it existed to say "click here" while
   the book was hidden. The book is not hidden here, so it has
   nothing left to do.
   ═══════════════════════════════════════════════════════════ */

@media (max-width: 900px) {

  

  /* ── NO PULSE ── */
  .beckon {
    display: none;
  }

  /* ── THE BOOK ──
     Positioned on the PAINTED grimoire: 44% across, 26% up. */
  .book {
    left: 50%;
    bottom: 28%;
    top: auto;

    width: min(58vw, 260px);
    margin-left: calc(min(58vw, 260px) / -2);

    /* it begins lying in the painting, flat and unseen */
    transform: translate3d(0, 20px, 0) rotateX(64deg) rotateZ(-3deg) scale(.86);
    opacity: 0;
    visibility: hidden;
    transition:
      opacity 1.4s ease,
      transform 1.8s cubic-bezier(.16, .84, .26, 1),
      visibility 0s linear 1.4s;
  }

  /* JS adds .risen after 2s — it lifts out of the painting */
  .book.risen {
    visibility: visible;
    opacity: 1;
    transform: translate3d(0, -13vh, 0) rotateX(6deg) rotateZ(0deg) scale(1.05);
    transition:
      opacity 1.4s ease,
      transform 1.8s cubic-bezier(.16, .84, .26, 1),
      visibility 0s;
  }

  /* hover has no meaning here */
  .book.approaching {
    transform: translate3d(0, -13vh, 0) rotateX(6deg) scale(1.05);
  }

  /* the lights come up with it */
  .book.risen .glow-violet { opacity: .85; transition: opacity 1.6s ease .3s; }
  .book.risen .glow-green  { opacity: .75; transition: opacity 1.6s ease .5s; }
  .book.risen .glow-gold   { opacity: .7;  transition: opacity 1.6s ease .7s; }
  .book.risen .book-cast   { opacity: .8;  transition: opacity 1.8s ease .4s; }
  .book.risen .glitter     { opacity: 1;   transition: opacity 1.4s ease .5s; }

  .book.risen .boss {
    filter:
      drop-shadow(0 0 12px rgba(240, 236, 228, .85))
      drop-shadow(0 0 26px rgba(122, 54, 168, .55));
  }

  /* ── THE TAP TARGET ──
     Over the risen book. Generous — a thumb is not a cursor. */
  .hitarea {
    left: 50%;
    bottom: 28%;
    top: auto;
    width: min(70vw, 300px);
    height: min(76vw, 330px);
    margin-left: calc(min(70vw, 300px) / -2);
    transform: translateY(-13vh);
    aspect-ratio: auto;
    z-index: 6;
  }
  .hitarea-hold {
    display: none;
  }

  /* ── THE TYPE ── */
  .prompt {
    bottom: 4%;
  }

  /* the book flies at you on open */
  body.state-open .book {
    transform: translate3d(0, -26vh, 0) scale(2.4);
  }

  /* the runes sit under the book */
  .script {
    left: 50%;
    bottom: 12%;
    width: min(70vw, 300px);
    margin-left: calc(min(70vw, 300px) / -2);
  }
}

/* ═══ PHONE: no parallax ═══
   The portrait plate fills the screen exactly. There is no bleed
   to move within — any parallax would show an edge. */
@media (max-width: 900px) {
  .layer {
    transform: none !important;
  }
}

/* ═══════════════════════════════════════════════════════════
   FITTING THE PAINTING TO ANY PHONE

   The painting is 1495 x 2662 — 1.78 tall.
   Real phones run from 1.33 (iPad) to 2.4 (Xperia).

   object-fit: cover fills the screen, but it crops the
   difference away, and WHERE it crops decides whether the
   room survives:

     tall phone (2.0-2.4)  crops 18-24% off the SIDES.
                           Those are dark walls. Survivable.

     short screen (1.33)   crops 25% off TOP AND BOTTOM.
                           That is the herbs and THE BOOK.
                           Not survivable.

   So: anchor the crop to the BOTTOM. The foreground — the
   table, the grimoire, the white cat — is never cut. Whatever
   gets lost is lost from the ceiling, where there is only more
   of the same herbs.

   And the book is positioned inside a box that tracks the
   PAINTING, not the viewport, so it lands on the painted
   grimoire on every device.
   ═══════════════════════════════════════════════════════════ */

@media (max-width: 900px) {

  

  .stage .plate-lqip {
    background-position: center bottom;
    background-size: cover;
  }

}

/* ═══════════════════════════════════════════════════════════
   THE BOOK ON A PHONE — HELD IN THE RIGHT HAND

   Reach was never the problem. 44% across is well inside the
   right thumb's arc.

   The problem is OCCLUSION. A thumb tip is 45-60px across, and
   the hand behind it hides everything below and right of where
   it lands. Put the target ON the book and you cover the book
   with your own hand at the exact moment you are meant to be
   looking at it.

   This is why iOS puts the action bar at the bottom and the
   content above it. You act low. You look high.

   So:

     1. the book RISES out of the painting into the upper-middle,
        where no hand covers it

     2. the tap target extends BELOW the book, down into the
        thumb's natural resting arc. You tap beneath it — the
        book stays visible above your hand

     3. the target is ~300px tall. Apple's minimum is 44px.
   ═══════════════════════════════════════════════════════════ */

@media (max-width: 900px) {

  .beckon { display: none; }

  /* ── THE BOOK ──
     It starts lying in the painting, where JS measured the
     painted grimoire to be. */
  .book {
    left: var(--book-x, 50%);
    bottom: var(--book-y, 28%);
    top: auto;

    width: var(--book-w, min(58vw, 260px));
    margin-left: calc(var(--book-w, min(58vw, 260px)) / -2);

    transform: translate3d(0, 20px, 0) rotateX(64deg) rotateZ(-3deg) scale(.86);
    opacity: 0;
    visibility: hidden;
    transition:
      opacity 1.4s ease,
      transform 1.9s cubic-bezier(.16, .84, .26, 1),
      visibility 0s linear 1.4s;
  }

  /* ── IT RISES CLEAR OF THE HAND ──
     Up, and slightly toward the middle. It lands around 42% of
     the screen height — above where a thumb ever reaches, so it
     is never covered. */
  .book.risen,
  .book.approaching {
    visibility: visible;
    opacity: 1;
    transform: translate3d(0, var(--book-rise, -19vh), 0) rotateX(6deg) rotateZ(0deg) scale(1.16);
    transition:
      opacity 1.4s ease,
      transform 1.9s cubic-bezier(.16, .84, .26, 1),
      visibility 0s;
  }

  .book.risen .glow-violet { opacity: .85; transition: opacity 1.6s ease .3s; }
  .book.risen .glow-green  { opacity: .75; transition: opacity 1.6s ease .5s; }
  .book.risen .glow-gold   { opacity: .7;  transition: opacity 1.6s ease .7s; }
  .book.risen .book-cast   { opacity: .8;  transition: opacity 1.8s ease .4s; }
  .book.risen .glitter     { opacity: 1;   transition: opacity 1.4s ease .5s; }
  .book.risen .boss {
    filter:
      drop-shadow(0 0 14px rgba(240, 236, 228, .9))
      drop-shadow(0 0 30px rgba(122, 54, 168, .6));
  }

  /* ── THE TAP TARGET ──
     It covers the book AND the space beneath it, all the way
     down into the thumb's arc. Wherever the thumb naturally
     falls, it is on the target — and the book is above it,
     in clear view. */
  .hitarea {
    left: 50%;
    bottom: 8%;
    top: auto;
    width: min(88vw, 420px);
    height: 46vh;
    margin-left: 0;
    transform: translateX(-50%);
    aspect-ratio: auto;
    z-index: 6;
  }
  .hitarea-hold { display: none; }

  /* ── THE INVITATION ──
     With the target below the book, the thumb needs to know it
     is there. A soft glow rises from the bottom of the target —
     not a button, just a warmth in the place your hand already
     rests. */
  .hitarea::after {
    content: '';
    position: absolute;
    left: 50%;
    bottom: 2%;
    width: 62%;
    height: 30%;
    margin-left: -31%;
    border-radius: 50%;
    background: radial-gradient(ellipse at 50% 70%,
      rgba(140, 240, 180, .16) 0%,
      rgba(90, 190, 130, .08) 40%,
      transparent 72%);
    opacity: 0;
    pointer-events: none;
    transition: opacity 1.2s ease;
  }
  body.book-approaching .hitarea::after {
    opacity: 1;
    animation: thumb-glow 3.4s ease-in-out 1s infinite;
    animation-play-state: var(--play-state);
  }
  @keyframes thumb-glow {
    0%, 100% { opacity: .5; transform: scale(.94); }
    50%      { opacity: 1;  transform: scale(1.06); }
  }

  /* pressed */
  .hitarea:active::after {
    opacity: 1;
    animation: none;
    transform: scale(1.12);
  }

  /* ── THE RUNES ── under the book, above the thumb */
  .script {
    left: var(--book-x, 50%);
    bottom: calc(var(--book-y, 28%) + 2vh);
    width: calc(var(--book-w, min(58vw, 260px)) * 1.2);
    margin-left: calc(var(--book-w, min(58vw, 260px)) * -0.6);
  }

  /* ── THE TYPE ──
     The question sits between the book and the thumb — read on
     the way down to the tap. */
  .prompt {
    bottom: 3.5%;
  }

  body.state-open .book {
    transform: translate3d(0, calc(var(--book-rise, -19vh) * 1.6), 0) scale(2.6);
  }

  .layer { transform: none !important; }
}

/* ═══════════════════════════════════════════════════════════
   THE AGED PAGE
   Witch-paper: yellowed, foxed, dirty at the edges where a
   thousand hands have turned it. The damage is worst at the
   fore-edge and the corners — which is where a real book wears.
   ═══════════════════════════════════════════════════════════ */

.page {
  position: relative;
}

.page::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 3;
  mix-blend-mode: multiply;
  background:
    linear-gradient(to left,   rgba(92, 66, 30, .40) 0%, rgba(92, 66, 30, .14) 5%, transparent 16%),
    linear-gradient(to top,    rgba(84, 60, 26, .30) 0%, rgba(84, 60, 26, .10) 4%, transparent 14%),
    linear-gradient(to bottom, rgba(84, 60, 26, .22) 0%, transparent 12%),
    radial-gradient(ellipse 28% 22% at 100% 100%, rgba(74, 52, 20, .42), transparent 70%),
    radial-gradient(ellipse 24% 18% at 100% 0%,   rgba(74, 52, 20, .30), transparent 70%),
    radial-gradient(ellipse 20% 16% at 0% 100%,   rgba(74, 52, 20, .26), transparent 72%),
    radial-gradient(circle 3px at 22% 34%, rgba(120, 84, 40, .3), transparent),
    radial-gradient(circle 5px at 68% 22%, rgba(110, 76, 34, .26), transparent),
    radial-gradient(circle 4px at 44% 74%, rgba(126, 90, 44, .24), transparent),
    radial-gradient(circle 6px at 82% 58%, rgba(112, 78, 36, .2), transparent),
    radial-gradient(circle 3px at 14% 62%, rgba(120, 84, 40, .28), transparent),
    radial-gradient(circle 4px at 58% 88%, rgba(108, 74, 32, .22), transparent);
}

.page-left::after {
  background:
    linear-gradient(to right,  rgba(92, 66, 30, .40) 0%, rgba(92, 66, 30, .14) 5%, transparent 16%),
    linear-gradient(to top,    rgba(84, 60, 26, .30) 0%, rgba(84, 60, 26, .10) 4%, transparent 14%),
    linear-gradient(to bottom, rgba(84, 60, 26, .22) 0%, transparent 12%),
    radial-gradient(ellipse 28% 22% at 0% 100%, rgba(74, 52, 20, .42), transparent 70%),
    radial-gradient(ellipse 24% 18% at 0% 0%,   rgba(74, 52, 20, .30), transparent 70%),
    radial-gradient(circle 4px at 76% 30%, rgba(120, 84, 40, .28), transparent),
    radial-gradient(circle 5px at 32% 66%, rgba(110, 76, 34, .24), transparent),
    radial-gradient(circle 3px at 60% 80%, rgba(126, 90, 44, .22), transparent);
}

/* ═══════════════════════════════════════════════════════════
   THE STAGE
   Holds the painting and everything that sits on it.
   Fills the screen on every device.
   ═══════════════════════════════════════════════════════════ */

.stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.stage .plate {
  position: absolute;
  inset: 0;
}

/* ═══════════════════════════════════════════════════════════
   THE PHONE

   The portrait plate is 9:16 (0.562). Phones range from about
   0.46 (iPhone 14 Pro Max, 9:19.5) to 0.60 (an iPad mini in
   portrait). The image will never match exactly, so something
   must be cropped.

   THE RULE: crop the TOP, never the bottom.

   The book is in the lower third. The ceiling is herbs and
   dark rafters — beautiful, and expendable. Anchor the image
   to the bottom, and the grimoire stays exactly where it is
   no matter how tall the phone.

   Everything else — the fog, the dust, the embers, the grain —
   is unchanged from the desktop.
   ═══════════════════════════════════════════════════════════ */

@media (max-width: 760px) {

  /* ── THE PLATE ──
     One rule. No conflicts. Bottom-anchored. */
  .stage .plate-img {
    position: absolute;
    top: auto;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 100%;

    /* the crop is taken off the TOP — the foreground is sacred */
    object-fit: cover;
    object-position: center bottom;

    /* no transform. It fought object-position and broke the layout. */
    transform: none;
  }

  .stage .plate-lqip {
    background-size: cover;
    background-position: center bottom;
    transform: none;
  }

  /* ── THE GLOW ──
     On the painted grimoire. No ring, no expanding circle —
     just a light in the book, breathing.

     Measured on media/tavern-portrait-*.jpg:
       the cover face spans x 25-60%, y 68-83%
       centre: 42% across, 25% up from the bottom

     Because the image is bottom-anchored, these hold on any
     phone. The book does not move. */
  .beckon {
    display: block;

    /* ── ON THE COVER FACE ──
       Measured on the portrait plate:
         cover face   x 30-63%,  y 69-82%
         pentagram    x 47%,     y 75%
       Set lower and right of the pentagram, so the light sits on
       the face of the book and spills toward the clasp — not
       floating over the middle of it. */
    left: 50%;
    bottom: 24%;
    width: 32%;
    aspect-ratio: 1.5;
    margin-left: -16%;

    z-index: 3;
    opacity: 1;
  }

  /* the light itself */
  .beckon-core {
    inset: 10%;
    border-radius: 50%;
    background: radial-gradient(ellipse at 50% 50%,
      rgba(186, 130, 250, .46) 0%,
      rgba(140, 84, 216, .26) 30%,
      rgba(96, 50, 164, .11) 54%,
      transparent 76%);
    animation: beckon-pulse 3.8s ease-in-out infinite;
    animation-play-state: var(--play-state);
  }

  /* the light it throws on the table around it */
  .beckon-halo {
    inset: -30% -22%;
    border-radius: 50%;
    background: radial-gradient(ellipse,
      rgba(150, 92, 228, .20) 0%,
      rgba(112, 92, 200, .11) 30%,
      rgba(86, 176, 130, .05) 52%,
      transparent 76%);
    animation: beckon-breathe 5.8s ease-in-out infinite;
    animation-play-state: var(--play-state);
  }

  /* NO RING. It read as a target reticle, not a light. */
  .beckon-ring {
    display: none;
  }

  body.book-summoned .beckon {
    opacity: 0;
    transform: scale(1.3);
    transition: opacity .9s ease, transform 1.1s cubic-bezier(.2, .7, .2, 1);
    pointer-events: none;
  }

  /* ── TAP 1 — the painted grimoire ── */
  .hitarea {
    position: absolute;

    /* covers the whole cover face — x 30-63%, y 69-82% — with margin.
       A target you cannot find is a target that failed. */
    left: 50%;
    bottom: 16%;
    top: auto;
    width: 44%;
    height: 20%;
    margin-left: -22%;

    transform: none;
    aspect-ratio: auto;
    z-index: 6;
  }
  body.book-summoned .hitarea {
    pointer-events: none;
  }
  .hitarea-hold {
    display: none;
  }

  /* ── THE BOOK ──
     Hidden. No timer. It appears because you tapped the painting.
     Fixed to the VIEWPORT, so it is dead centre of the screen
     whatever shape the phone is. */
  .book {
    position: fixed;
    left: 50%;
    top: 50%;
    bottom: auto;

    /* vmin, not vw — on a SHORT phone the height is the constraint,
       not the width. This keeps the book from crowding the text. */
    width: min(60vw, 42vmin, 280px);
    margin-left: 0;
    z-index: 20;

    transform: translate3d(-50%, -56%, 0) rotateX(56deg) scale(.5);
    opacity: 0;
    visibility: hidden;
    transition:
      opacity 1.1s ease,
      transform 1.5s cubic-bezier(.16, .84, .26, 1),
      visibility 0s linear 1.1s;
  }

  body.book-summoned .book {
    visibility: visible;
    opacity: 1;

    /* -56% rather than -50%: it sits a little ABOVE the midline, so the
       question below it always has air. On a short phone (iPhone SE)
       dead centre collides with the text. */
    transform: translate3d(-50%, -56%, 0) rotateX(2deg) scale(1);
    transition:
      opacity 1.1s ease,
      transform 1.5s cubic-bezier(.16, .84, .26, 1),
      visibility 0s;
  }

  
  body.book-summoned .glow-green  { opacity: .75; transition: opacity 1.4s ease .5s; }
  body.book-summoned .glow-gold   { opacity: .7;  transition: opacity 1.4s ease .7s; }
  body.book-summoned .book-cast   { opacity: .8;  transition: opacity 1.6s ease .4s; }
  body.book-summoned .glitter     { opacity: 1;   transition: opacity 1.2s ease .5s; }
  

  /* ── TAP 2 — the summoned book ── */
  .hitarea-open {
    position: fixed;
    left: 50%;
    top: 50%;
    width: min(72vw, 330px);
    height: min(96vw, 440px);
    transform: translate(-50%, -56%);
    z-index: 21;
    padding: 0;
    border: 0;
    background: transparent;
    cursor: pointer;
    pointer-events: none;
    opacity: 0;
    -webkit-tap-highlight-color: transparent;
  }
  body.book-summoned .hitarea-open {
    pointer-events: auto;
  }

  /* ── THE TEXT ── */
  .prompt {
    position: fixed;
    left: 50%;
    bottom: 7%;
    z-index: 22;
  }
  body.book-summoned .prompt {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
    filter: blur(0);
  }
  body.book-summoned .opening {
    opacity: 0;
    transform: translateY(-18px);
    filter: blur(3px);
    animation: none;
  }

  /* the room does not dim — the book floats above it */
  

  /* no parallax — there is no cursor */
  .layer {
    transform: none !important;
  }

  body.state-open .book {
    transform: translate3d(-50%, -60%, 0) scale(2.8);
    opacity: 0;
  }
}

/* the light breathes. It does not pulse like a target. */
@keyframes beckon-pulse {
  0%, 100% { transform: translateZ(0) scale(.9);  opacity: .34; }
  50%      { transform: translateZ(0) scale(1.05); opacity: .76; }
}
@keyframes beckon-breathe {
  0%, 100% { transform: translateZ(0) scale(.86); opacity: .38; }
  50%      { transform: translateZ(0) scale(1.12); opacity: .8; }
}

/* ═══════════════════════════════════════════════════════════
   WHEN THE BOOK OPENS

   The tavern, the summoned book, the question and the warning
   must ALL get out of the way. Nothing may float over the pages.

   The z-index war was real: the prompt sat at 22, the open book
   at 20. The question was drawn on top of the page.
   ═══════════════════════════════════════════════════════════ */

.grimoire {
  z-index: 60;          /* above everything: book (20), prompt (22) */
}

/* the tap targets must not intercept taps meant for the page */
body.state-open .hitarea-open,
body.state-open .hitarea {
  display: none;
}

/* ═══════════════════════════════════════════════════════════
   THE OPEN BOOK ON A PHONE

   One leaf at a time. The spread rules were keyed to 860px but
   the phone block is 760px — they were never both applying.
   ═══════════════════════════════════════════════════════════ */

@media (max-width: 760px) {

  .grimoire {
    padding: .7rem .7rem 3.6rem;
    z-index: 60;
  }

  .spread {
    grid-template-columns: 1fr;
    grid-template-rows: 1fr;
    width: 100%;
    height: calc(100svh - 5.4rem);
    border-radius: 4px;
    overflow: visible;
    transform-style: preserve-3d;
    touch-action: pan-y;
  }

  .spine {
    display: none;
  }

  /* every leaf in the same cell — one on top of the next */
  .page {
    grid-area: 1 / 1;
    border-radius: 4px;
    box-shadow: inset 0 0 46px -14px rgba(50, 35, 18, .5);
    transform-origin: left center;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
    will-change: transform, opacity;
    transition:
      transform .72s cubic-bezier(.36, .06, .24, 1),
      opacity .5s ease;
  }

  .page.leaf-current {
    z-index: 3;
    transform: rotateY(0deg);
    opacity: 1;
    pointer-events: auto;
  }
  .page.leaf-next {
    z-index: 2;
    transform: rotateY(0deg) scale(.985) translateY(3px);
    opacity: 0;
    pointer-events: none;
  }
  .page.leaf-prev {
    z-index: 4;
    transform: rotateY(-168deg);
    opacity: 0;
    pointer-events: none;
    box-shadow: none;
  }

  .spread.dragging .page {
    transition: none;
  }

  .page-inner {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 1.9rem 1.4rem 2.6rem;
  }

  .illum { width: 104px; margin-bottom: 1rem; }
  .grim-title { font-size: 2.7rem; }
  .contents-head { font-size: 2.2rem; }
  .contents a { grid-template-columns: 1.8rem 1fr auto; gap: .7rem; }
  .leader { display: none; }

  /* the folded corner belongs to the leaf you are reading */
  

  .close-book {
    top: .5rem;
    bottom: auto;
    padding: .4rem 1rem;
    font-size: .52rem;
    z-index: 62;
  }

  .leafbar {
    display: flex;
    z-index: 62;
  }
}

/* ═══════════════════════════════════════════════════════════
   THE FOLDED CORNER

   On the FIRST page — the one you land on.

   Minimal. A single triangle, lifted. No drop shadow, no
   gradient, no theatre. It breathes just enough to say
   "this can be turned" and then gets out of the way.
   ═══════════════════════════════════════════════════════════ */

.dogear {
  position: absolute;
  right: 0;
  bottom: 0;
  width: clamp(38px, 6%, 58px);
  aspect-ratio: 1;

  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  z-index: 8;
  -webkit-tap-highlight-color: transparent;

  opacity: 0;
  transition: opacity 1.2s ease 1.8s;
}

body.state-open .dogear {
  opacity: 1;
}

.dogear svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* the lifted corner. It rises a little, and settles. */
.fold-leaf,
.fold-under,
.fold-crease {
  transform-origin: 60px 60px;
  animation: dogear-lift 3.6s ease-in-out infinite;
  animation-play-state: var(--play-state);
}
.fold-under {
  animation-name: dogear-under;
}

@keyframes dogear-lift {
  0%, 100% { transform: scale(.88); }
  50%      { transform: scale(1.04); }
}
@keyframes dogear-under {
  0%, 100% { transform: scale(.84); opacity: .5; }
  50%      { transform: scale(1.08); opacity: .85; }
}

.dogear:hover .fold-leaf,
.dogear:active .fold-leaf {
  animation: none;
  transform: scale(1.1);
  transition: transform .3s cubic-bezier(.2, .7, .2, 1);
}

.dogear:focus-visible {
  outline: 1px solid rgba(110, 33, 19, .7);
  outline-offset: 2px;
}


/* ═══════════════════════════════════════════════════════════
   STATE-OPEN BEATS BOOK-SUMMONED

   Both classes are on the body when the book opens. The phone's
   `body.book-summoned .prompt {opacity:1}` sits inside a media
   block that comes LATER in the file, so it was winning — and
   the question stayed on screen, floating over the page.

   Declared here, inside the same media block and after it, so
   the open state wins.
   ═══════════════════════════════════════════════════════════ */

@media (max-width: 760px) {
  body.state-open.book-summoned .prompt,
  body.state-open .prompt {
    opacity: 0;
    transform: translateX(-50%) translateY(-14px);
    transition: opacity .4s ease, transform .4s ease;
    pointer-events: none;
  }
  body.state-open.book-summoned .book,
  body.state-open .book {
    opacity: 0;
    transform: translate3d(-50%, -60%, 0) scale(2.8);
  }
  body.state-open.book-summoned .beckon,
  body.state-open .beckon {
    opacity: 0;
  }
}

/* ═══════════════════════════════════════════════════════════
   THE CORRIDOR — desktop only

   Its rules were lost in an earlier strip, leaving it with no
   `pointer-events`. It defaulted to `auto` and sat OVER the hit
   area, so the book could never be hovered at all.

   It must be dormant until the book is out, and only then take
   the pointer — so the cursor can follow the book to the centre
   without falling through the gap.
   ═══════════════════════════════════════════════════════════ */

.hitarea-hold {
  position: absolute;
  left: 30%;
  right: 8%;
  top: 10%;
  bottom: 10%;

  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  z-index: 5;

  /* DORMANT. It must not intercept the cursor before the book is out. */
  pointer-events: none;
  -webkit-tap-highlight-color: transparent;
}

body.book-approaching .hitarea-hold {
  pointer-events: auto;
}

/* on the phone there is no cursor, so no corridor */
@media (max-width: 760px) {
  .hitarea-hold {
    display: none;
  }
}

/* ═══════════════════════════════════════════════════════════
   MORE GOTHIC

   The cover was silver-on-black. Now it burns: the boss flares,
   the moons take the light, the leaves catch a glint, and the
   whole thing throws violet onto the room behind it.
   ═══════════════════════════════════════════════════════════ */







  50%      { opacity: 1; }


body.book-approaching .vines,
body.book-summoned .vines {
  opacity: 1;
}


/* the cracks fill with light as it wakes */


/* ═══════════════════════════════════════════════════════════
   THE SHINE, harder

   Two sweeps, not one — the second follows the first and catches
   the silver. And the boss keeps a slow rotating glint.
   ═══════════════════════════════════════════════════════════ */


body.book-approaching 

/* the boss never stops catching the light */


  50%      { opacity: 1; }


/* ═══════════════════════════════════════════════════════════
   THE DUST — one canvas

   A hundred DOM motes is a hundred compositor layers. That is
   what took this page to 12 fps.

   One canvas is one layer. Every mote is painted into it, and
   the GPU composites a single texture. We can now afford three
   hundred motes where a hundred divs were unaffordable.
   ═══════════════════════════════════════════════════════════ */

.dustfield {
  position: absolute;
  inset: 0;
  z-index: 7;
  pointer-events: none;
  opacity: .9;
}


/* the spirits follow the book. On the phone it is fixed to the
   viewport centre, so they are too. */
/* the spirits are painted in the canvas, and they must rise IN FRONT
   of the book, not behind it. When the book is out, the canvas lifts
   above it. */



/* ═══════════════════════════════════════════════════════════
   THE BOOK'S GLOW — the right way

   drop-shadow() on a MOVING element is re-rendered and re-blurred
   every single frame. It cannot be cached. Three of them stacked,
   plus three more on the boss inside it, cost 57 fps.

   Instead: one static shadow for depth (never animated), and the
   magic light lives in the .glow-* divs that were already there —
   soft radial gradients on their own layers, breathing on opacity.
   ═══════════════════════════════════════════════════════════ */

.book {
  /* ONE shadow. Static. Never animated. */
  filter: drop-shadow(0 24px 44px rgba(0, 0, 0, .9));
}

/* the silver simply gets brighter — no filters */


/* the boss and the moons breathe on OPACITY, which is free */


  50%      { opacity: 1; }



  50%      { opacity: 1; }




/* ═══════════════════════════════════════════════════════════
   THE COVER IS STATIC

   Every animation INSIDE the book's SVG — the turning rays, the
   burning boss, the glinting moons — forces the whole 220x300
   SVG to re-rasterise on every frame. It is full of gradients
   and paths. That cost 50 fps.

   The cover is beautiful. Let it be still. All the movement is
   in the glow around it and the canvas in front of it, which
   cost nothing.
   ═══════════════════════════════════════════════════════════ */



/* ═══════════════════════════════════════════════════════════
   THE ROOM FALLS BACK

   It used to be `filter: brightness(.4) blur(3px)` on .plate —
   which is 1,296,000 px2, the whole background image. Filtering
   that every frame cost 52 fps.

   A plain dark overlay does the same job for nothing: one div,
   one opacity transition, composited on the GPU.
   ═══════════════════════════════════════════════════════════ */






  25%  { background-position: -13px 7px; }
  50%  { background-position: 9px -11px; }
  75%  { background-position: -6px -4px; }
  100% { background-position: 0 0; }


/* the canvas stays UNDER the book. Above it, every frame it paints
   forces six full-screen layers to re-composite. And the spirits
   should rise from BEHIND the book anyway — that is where a thing
   coming out of a book comes from. */
.dustfield {
  z-index: 6;
}


/* the beckon has done its job the moment the book appears. Its rings
   are large scaling layers; leaving them running costs frames for a
   cue nobody needs any more. */
body.book-approaching .beckon,
body.book-summoned .beckon,
body.state-open .beckon {
  display: none;
}

/* the glitter and the shine are one-shot flourishes. Once they have
   played, take them out of the compositor. */
body.state-open .glitter,
body.state-open .book-embers,
body.state-open 


/* ═══ BASELINE ═══
   Everything stripped. The book appears; nothing else happens.
   Prove 60 fps, then add the magic back one piece at a time. */
/* NO filter on .book. It is a 3D element (preserve-3d + rotateX), and
   drop-shadow() on 3D geometry cannot be cached — it is re-rendered and
   re-blurred every frame. Even one static shadow cost 35 fps.
   The shadow lives on the flat cover instead, as box-shadow, which
   composites. */

/* the shadow, on the flat cover — composited, cached, free */
.cover-front {
  box-shadow:
    inset 0 2px 10px rgba(190, 184, 172, .07),
    inset 0 -22px 46px rgba(0, 0, 0, .85),
    0 26px 50px rgba(0, 0, 0, .92),
    0 8px 18px rgba(0, 0, 0, .7);
}


/* ═══════════════════════════════════════════════════════════
   NO drop-shadow ANYWHERE IN THE BOOK

   .book is preserve-3d with a rotateX. Any drop-shadow() inside
   that 3D context — on the book, the moons, the cord, anything —
   is re-rendered and re-blurred every frame. The browser cannot
   cache the shadow of geometry it is recomputing.

   That was 44 fps, for shadows nobody would miss.
   ═══════════════════════════════════════════════════════════ */

.book,
.book .moons,
.book .cord,
.book .boss,
.book .leaves,
.book .corner-caps,
.book .spikes,
.book .clasp-plate,
.book .cover-art {
  filter: none !important;
}

/* the cover keeps its brightness — that is cheap, it is not a blur */
body.book-approaching .cover-art,
body.book-summoned .cover-art {
  filter: brightness(1.2) contrast(1.06) !important;
}


/* the LQIP blur is a 1,568,000 px2 gaussian that stays in the layer
   tree forever, even at opacity 0. Take it out of the compositor once
   the real plate has loaded. */
body.plate-ready .plate-lqip {
  display: none;
}

/* the spread's drop-shadow is 733,000 px2 and re-blurs whenever
   anything above it moves. box-shadow on the leather boards does the
   same job, composited. */
.spread {
  filter: none !important;
}
.spread::before {
  box-shadow:
    inset 0 1px 0 rgba(180, 150, 100, .12),
    0 44px 84px rgba(0, 0, 0, .92),
    0 12px 28px rgba(0, 0, 0, .7);
}




/* the glows stay unpromoted — promoting them created more layers than
   it saved. They are just smaller now. */
.book-cast   { inset: -40% -30% -30% -30%; }
.glow-violet { inset: -22% -18%; }
.glow-green  { inset: -12% -10%; }


/* ═══════════════════════════════════════════════════════════
   THE MAGIC, ADDED BACK — measured at every step
   ═══════════════════════════════════════════════════════════ */

/* ── THE SHINE ──
   A band of light sweeping the leather. It animates transform on a
   small, promoted layer inside a clipped box. Cheap. */
.cover-shine {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  overflow: hidden;
  border-radius: 2px 5px 5px 2px;
  opacity: 0;
}
.cover-shine::before {
  content: '';
  position: absolute;
  top: -60%;
  left: -150%;
  width: 55%;
  height: 220%;
  background: linear-gradient(105deg,
    transparent 0%,
    rgba(255, 250, 240, .10) 32%,
    rgba(255, 250, 240, .40) 50%,
    rgba(220, 200, 255, .24) 60%,
    transparent 80%);
  transform: rotate(14deg) translateZ(0);
  will-change: transform;
}
body.book-approaching .cover-shine,
body.book-summoned .cover-shine {
  opacity: 1;
}
body.book-approaching .cover-shine::before,
body.book-summoned .cover-shine::before {
  animation: cover-shine 2.6s cubic-bezier(.3, .1, .2, 1) .5s;
}
@keyframes cover-shine {
  0%   { transform: translateX(0) rotate(14deg); }
  100% { transform: translateX(500%) rotate(14deg); }
}

/* ── THE GLOWS come up with the book ── */
body.book-approaching .glow-violet,
body.book-summoned .glow-violet { opacity: .9;  transition: opacity 1.3s ease .2s; }
body.book-approaching .glow-green,
body.book-summoned .glow-green  { opacity: .8;  transition: opacity 1.3s ease .4s; }
body.book-approaching .glow-gold,
body.book-summoned .glow-gold   { opacity: .75; transition: opacity 1.3s ease .6s; }
body.book-approaching .book-cast,
body.book-summoned .book-cast   { opacity: .85; transition: opacity 1.5s ease .3s; }
body.book-approaching .glitter,
body.book-summoned .glitter     { opacity: 1;   transition: opacity 1.2s ease .5s; }

/* ── the silver brightens ── */
body.book-approaching .cover-art,
body.book-summoned .cover-art {
  filter: brightness(1.18) contrast(1.08) !important;
}
body.book-approaching .leaves,
body.book-summoned .leaves,
body.book-approaching .vines,
body.book-summoned .vines,
body.book-approaching .studs,
body.book-summoned .studs {
  opacity: 1;
}
body.book-approaching .cracks,
body.book-summoned .cracks {
  opacity: .28;
}

/* ── THE ROOM FALLS BACK ──
   An overlay, not a filter on the plate. */
.dimmer {
  position: absolute;
  inset: 0;
  z-index: 8;
  pointer-events: none;
  background: radial-gradient(ellipse 72% 62% at 50% 50%,
    rgba(6, 5, 8, .58) 0%,
    rgba(6, 5, 8, .78) 46%,
    rgba(4, 3, 6, .92) 100%);
  opacity: 0;
  transition: opacity 1.3s ease;
  will-change: opacity;
}
body.book-approaching .dimmer,
body.book-summoned .dimmer,
body.state-open .dimmer {
  opacity: 1;
}


/* ── THE EMBERS ──
   Thrown off the book as it rises. Small, promoted, transform+opacity
   only. Seeded by script.js. */
.book-embers {
  position: absolute;
  inset: -30% -22%;
  z-index: 6;
  pointer-events: none;
  opacity: 0;
  transition: opacity .6s ease;
}
body.book-approaching .book-embers,
body.book-summoned .book-embers {
  opacity: 1;
}

.bk-ember {
  position: absolute;
  bottom: 34%;
  border-radius: 50%;
  opacity: 0;
  will-change: transform, opacity;
  transform: translateZ(0);
  animation: bk-ember-rise ease-out forwards;
  animation-play-state: var(--play-state);
}
@keyframes bk-ember-rise {
  0%   { transform: translate3d(0, 0, 0);                   opacity: 0; }
  10%  {                                                    opacity: 1; }
  70%  {                                                    opacity: .7; }
  100% { transform: translate3d(var(--ex), var(--ey), 0);   opacity: 0; }
}

body.state-open .book-embers,
body.state-open .glitter,
body.state-open .cover-shine {
  display: none;
}


/* ═══════════════════════════════════════════════════════════
   THE WARNING, beneath the question

   "Every witch keeps a book. Not all of them are meant to be
   found."  It arrives last, after the question has landed.
   ═══════════════════════════════════════════════════════════ */

.prompt-epigraph {
  margin: clamp(1.2rem, 2.6vh, 2rem) auto 0;
  max-width: 30rem;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  font-weight: 300;
  font-size: clamp(.94rem, 1.6vw, 1.2rem);
  line-height: 1.62;
  letter-spacing: .05em;
  color: #8A8070;
  text-shadow:
    0 2px 12px rgba(0, 0, 0, 1),
    0 0 30px rgba(0, 0, 0, .9);

  opacity: 0;
  transform: translateY(10px);
  transition:
    opacity 1.2s ease 1.2s,
    transform 1.2s cubic-bezier(.2, .7, .2, 1) 1.2s;
}

body.book-approaching .prompt-epigraph,
body.book-summoned .prompt-epigraph {
  opacity: 1;
  transform: translateY(0);
}

body.state-open .prompt-epigraph,
body.state-open.book-summoned .prompt-epigraph {
  opacity: 0;
  transition: opacity .3s ease;
}

/* ═══════════════════════════════════════════════════════════
   WHEN IT OPENS — desktop

   1 fps on open. The tavern is still there, and .spread has a
   3D transform over a full-screen stack. Take the tavern out of
   the compositor entirely once the book is open — it is not
   visible, it should not exist.
   ═══════════════════════════════════════════════════════════ */

body.state-open .tavern {
  display: none;
}
body.state-open .dustfield {
  display: none;
}


/* the spread has a 3D transform (rotateX) over a full-screen stack.
   Once it has settled it never moves again — flatten it, and the
   compositor stops recomputing its geometry. */
body.state-open .spread {
  transform-style: flat;
}
body.state-open .page {
  will-change: auto;
}

/* ═══════════════════════════════════════════════════════════
   THE AURA — rebuilt

   The glows had become `display: inline`. An inline element with
   no width or height paints nothing: the purple aura was not
   faint, it was ABSENT. And .book-cast had lost its gradient
   entirely.

   Declared properly here, and brighter than before.
   ═══════════════════════════════════════════════════════════ */

.glow-violet,
.glow-green,
.glow-gold,
.book-cast {
  position: absolute;
  display: block;
  border-radius: 50%;
  pointer-events: none;
  will-change: opacity;
}

/* the violet aura — the one you asked for. It is the main light. */
.glow-violet {
  inset: -34% -28%;
  z-index: 1;
  background: radial-gradient(ellipse at 50% 50%,
    rgba(176, 108, 255, .78) 0%,
    rgba(146, 78, 232, .52) 20%,
    rgba(112, 52, 190, .30) 40%,
    rgba(76, 30, 140, .13) 60%,
    transparent 78%);
  opacity: 0;
  transition: opacity 1.3s ease .2s;
}

/* the corpse-light beneath it */
.glow-green {
  inset: -20% -16%;
  z-index: 1;
  background: radial-gradient(ellipse at 50% 62%,
    rgba(96, 226, 142, .52) 0%,
    rgba(64, 186, 110, .30) 26%,
    rgba(38, 132, 78, .12) 50%,
    transparent 72%);
  opacity: 0;
  transition: opacity 1.3s ease .4s;
}

/* gold at the seam, where the pages want to open */
.glow-gold {
  inset: 4% 0;
  z-index: 1;
  border-radius: 42%;
  background: radial-gradient(ellipse at 50% 50%,
    rgba(255, 212, 128, .62) 0%,
    rgba(230, 176, 84, .36) 24%,
    rgba(180, 132, 44, .14) 48%,
    transparent 70%);
  opacity: 0;
  transition: opacity 1.3s ease .6s;
}

/* the light it throws back onto the room */
.book-cast {
  inset: -70% -52% -46% -52%;
  z-index: 0;
  background: radial-gradient(ellipse at 50% 50%,
    rgba(150, 84, 230, .32) 0%,
    rgba(120, 70, 200, .18) 24%,
    rgba(86, 208, 126, .08) 44%,
    transparent 70%);
  opacity: 0;
  transition: opacity 1.5s ease .3s;
}

/* they come up with the book */
body.book-approaching .glow-violet,
body.book-summoned .glow-violet { opacity: 1; }
body.book-approaching .glow-green,
body.book-summoned .glow-green  { opacity: .85; }
body.book-approaching .glow-gold,
body.book-summoned .glow-gold   { opacity: .8; }
body.book-approaching .book-cast,
body.book-summoned .book-cast   { opacity: .9; }

/* and the violet BREATHES — opacity only, so it costs nothing */
body.book-approaching .glow-violet,
body.book-summoned .glow-violet {
  animation: aura-breathe 5.5s ease-in-out 1.4s infinite;
  animation-play-state: var(--play-state);
}
@keyframes aura-breathe {
  0%, 100% { opacity: .72; }
  50%      { opacity: 1; }
}

body.book-approaching .glow-green,
body.book-summoned .glow-green {
  animation: aura-breathe-b 7.5s ease-in-out 2s infinite;
  animation-play-state: var(--play-state);
}
@keyframes aura-breathe-b {
  0%, 100% { opacity: .5; }
  50%      { opacity: .9; }
}

/* ═══════════════════════════════════════════════════════════
   THE SPARKLES

   The glitter was EMPTY — seedSparks() was deleted along with
   the old dust code. Rebuilt in script.js.
   ═══════════════════════════════════════════════════════════ */

.glitter {
  position: absolute;
  inset: -40%;
  z-index: 5;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.2s ease .5s;
}
body.book-approaching .glitter,
body.book-summoned .glitter {
  opacity: 1;
}

.spark {
  position: absolute;
  border-radius: 50%;
  opacity: 0;
  will-change: transform, opacity;
  transform: translateZ(0);
  animation: spark-rise linear infinite;
  animation-play-state: var(--play-state);
}
@keyframes spark-rise {
  0%   { transform: translate3d(0, 0, 0) scale(.3);            opacity: 0; }
  12%  {                                                       opacity: 1; }
  70%  {                                                       opacity: .8; }
  100% { transform: translate3d(var(--sx), var(--sy), 0) scale(1.1); opacity: 0; }
}

/* ═══════════════════════════════════════════════════════════
   THE BOOK IS NOT TRANSPARENT

   The cover had lost its own background — it was showing the
   room through it. And the leather must be BLACK, not a wash.
   ═══════════════════════════════════════════════════════════ */

.cover-front {
  background:
    radial-gradient(ellipse at 40% 32%, #35302A 0%, #1C1813 52%, #0C0A08 100%) !important;
  border: 1px solid rgba(120, 110, 96, .38);
  box-shadow:
    inset 0 2px 12px rgba(210, 200, 184, .10),
    inset 0 -26px 52px rgba(0, 0, 0, .88),
    0 28px 54px rgba(0, 0, 0, .94),
    0 10px 22px rgba(0, 0, 0, .75);
}

/* the silver on the cover must READ. It was at brightness .92 —
   darker than it was drawn. */
.cover-art {
  filter: brightness(1.35) contrast(1.12) !important;
}
body.book-approaching .cover-art,
body.book-summoned .cover-art {
  filter: brightness(1.44) contrast(1.14) !important;
}

/* ═══════════════════════════════════════════════════════════
   THE TEXT MUST READ

   It was 84% opacity over a dim room. Bring it up.
   ═══════════════════════════════════════════════════════════ */

.prompt-text {
  color: #F6EEDC !important;
  text-shadow:
    0 0 2px rgba(255, 252, 244, .8),
    0 2px 20px rgba(0, 0, 0, 1),
    0 0 40px rgba(160, 96, 230, .95),
    0 0 70px rgba(110, 230, 150, .5),
    0 0 110px rgba(0, 0, 0, .95) !important;
}
@keyframes question-pulse {
  0%, 100% { opacity: .94; }
  50%      { opacity: 1; }
}

.prompt-epigraph {
  color: #A99E8C !important;
  text-shadow:
    0 2px 14px rgba(0, 0, 0, 1),
    0 0 34px rgba(0, 0, 0, .95) !important;
}

/* the room falls back harder, so the book and the type stand out */
.dimmer {
  background: radial-gradient(ellipse 74% 64% at 50% 48%,
    rgba(5, 4, 7, .72) 0%,
    rgba(5, 4, 7, .86) 44%,
    rgba(3, 2, 5, .96) 100%);
}




/* contain:paint made it worse — it creates a new stacking context and
   costs more than it saves on large elements. The glows stay plain.

   Instead: the aura does not breathe. A static gradient composites
   once and is then only alpha-blended. The breathing was costing
   30 fps for a shimmer you would not miss — and the sparkles and
   embers already give it life. */
body.book-approaching .glow-violet,
body.book-summoned .glow-violet {
  animation: none;
  opacity: 1;
}
body.book-approaching .glow-green,
body.book-summoned .glow-green {
  animation: none;
  opacity: .85;
}


/* .book-cast at inset:-70% -52% is a 900x800px semi-transparent layer
   that must be alpha-blended against the plate, the dimmer and the
   canvas every frame. It is a glow, not a floodlight.

   Halve it. The violet aura is doing the work anyway. */
.book-cast {
  inset: -34% -26% -22% -26%;
  background: radial-gradient(ellipse at 50% 50%,
    rgba(150, 84, 230, .38) 0%,
    rgba(120, 70, 200, .20) 26%,
    rgba(86, 208, 126, .07) 48%,
    transparent 72%);
}

/* the glitter and embers span inset:-40% and -30% of the book — but
   the sparks only ever travel 60-150px. Tighten the boxes. */
.glitter {
  inset: -18% -14%;
}
.book-embers {
  inset: -20% -14%;
}


/* the aura is painted in the canvas now — four overlapping DOM layers
   cost 32 fps in alpha blending alone. */
.glow-violet,
.glow-green,
.glow-gold,
.book-cast {
  display: none !important;
}


/* ═══════════════════════════════════════════════════════════
   THE BOOK SITS IN ITS LIGHT

   The canvas (z 6) was ABOVE the book (z 4) — so the aura was
   painting OVER the leather and washing it out. That is why the
   book looked faint and transparent.

   The book must be above the canvas: it sits IN the light, not
   behind it. The sparkles and the spirits are separate DOM layers
   that go over the top.
   ═══════════════════════════════════════════════════════════ */

.dustfield {
  z-index: 4 !important;
}
.book {
  z-index: 10 !important;
}
.glitter {
  z-index: 12;
}
.book-embers {
  z-index: 12;
}
.cover-shine {
  z-index: 4;
}
.dimmer {
  z-index: 3;
}
.beckon {
  z-index: 5;
}
.prompt {
  z-index: 14;
}

/* ═══════════════════════════════════════════════════════════
   THE CANVAS

   Its CSS was lost in a salvage. A <canvas> with no CSS size
   defaults to 300x150 — which is exactly what it had become.
   The aura, the dust, the spirits and the conjuring were all
   being painted into a postage stamp and stretched.
   ═══════════════════════════════════════════════════════════ */

.dustfield {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 4;
  pointer-events: none;
  opacity: .95;
}

/* ═══════════════════════════════════════════════════════════
   DESKTOP — THE ROOM MUST STILL BE THERE

   The dimmer was crushing the painting to a mean brightness of 8
   — near-black. The book was floating in a void, and the room you
   spent all that effort on had vanished.

   On the phone the book fills most of the screen, so you do not
   notice. On a 1440x900 desktop you are staring at 80% black.

   The room should fall BACK, not disappear.
   ═══════════════════════════════════════════════════════════ */

@media (min-width: 761px) {

  .dimmer {
    background: radial-gradient(ellipse 82% 74% at 50% 46%,
      rgba(6, 5, 9, .30) 0%,
      rgba(5, 4, 8, .52) 46%,
      rgba(3, 2, 6, .74) 100%);
  }

  /* ── THE BOOK IS BIGGER ──
     308x422 on a 900px screen is a postcard. It is the subject —
     let it fill the frame it has been given. */
  .book.approaching {
    transform: translate3d(-21vw, -14vh, 0) rotateX(2deg) rotateZ(0deg) scale(1.6);
  }

  body.state-open .book {
    transform: translate3d(-21vw, -36vh, 0) rotateX(0deg) scale(4);
  }

  /* the hit-corridor must still cover it once it has grown */
  .hitarea-hold {
    left: 24%;
    right: 4%;
    top: 4%;
    bottom: 6%;
  }
}

/* ═══════════════════════════════════════════════════════════
   THE AURA CANVAS

   Sized to the book, not the screen. A full-frame alpha layer
   compositing against a 368x504 book every frame cost 37 fps.
   This one is only as big as the light it carries.
   ═══════════════════════════════════════════════════════════ */

.aura-canvas { display: none; }


/* ═══════════════════════════════════════════════════════════
   PROMOTE THE BOOK

   The canvas beneath the book repaints 30 times a second. Every
   repaint INVALIDATES everything above it — including the book,
   which is a large 3D element with a complex SVG cover. So the
   book was being re-rendered thirty times a second for no reason.

   Promoting it to its own compositor layer means the canvas can
   repaint all it likes: the book is a cached texture, and the GPU
   just re-blends them. It is never re-rendered.
   ═══════════════════════════════════════════════════════════ */

.book {
  will-change: transform, opacity;
  transform: translateZ(0);
  backface-visibility: hidden;
  isolation: isolate;
}

.cover-front,
.cover-back,
.pages-edge {
  will-change: transform;
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* the SVG cover is the expensive part — cache it hardest */
.cover-art {
  will-change: filter;
  transform: translateZ(0);
  backface-visibility: hidden;
}


/* ═══════════════════════════════════════════════════════════
   THE BOOK IS NOT 3D

   `transform-style: preserve-3d` prevents the book from ever
   becoming a flat cached texture — the browser must keep its
   children in a live 3D space and re-render them whenever
   anything beneath changes. The canvas repaints 30x a second,
   so the book was re-rendered 30x a second.

   The 3D bought us: a slight rotateX on a flat cover. Nothing
   else. The cover, the back and the page-edge do not need real
   depth — a couple of translateZ offsets and a rotateX read
   identically in FLAT mode.

   This is the 39 fps.
   ═══════════════════════════════════════════════════════════ */

.book {
  transform-style: flat !important;
  perspective: none;
}

.book-body {
  transform-style: flat !important;
}

/* the depth was faked with translateZ. In flat mode, fake it with
   position and shadow instead — which is what it always looked like. */
.cover-back {
  transform: none !important;
  inset: 3px -4px -4px 3px;
}
.pages-edge {
  transform: none !important;
  right: -5px;
}
.cover-front {
  transform: none !important;
}


/* ═══════════════════════════════════════════════════════════
   FEWER LAYERS

   113 promoted elements. Every `will-change` I added while
   chasing this made another compositor layer, and the GPU now
   had 113 textures to hold and blend. UpdateLayer fired 792
   times in two seconds.

   will-change is a promise, not a fix. Strip it back to the
   things that genuinely move every frame.
   ═══════════════════════════════════════════════════════════ */

.spark,
.bk-ember,
.cover-front,
.cover-back,
.pages-edge,
.cover-art,
.beckon,
.beckon-core,
.beckon-halo,
.beckon-ring,
.script,
.dimmer,
.prompt,
.prompt-text,
.opening,
.masthead,
.plate,
.plate-lqip,
.glow-violet,
.glow-green,
.glow-gold,
.book-cast {
  will-change: auto !important;
}

/* the sparks and embers still need to be composited, but they are
   small — translateZ alone promotes them without the will-change
   memory reservation. */
.spark,
.bk-ember {
  transform: translateZ(0);
}


/* the sparks and embers are painted in the canvas now — thirty DOM
   layers over the book cost 30 fps in compositing alone. */
.glitter,
.book-embers,
.aura-canvas {
  display: none !important;
}

/* the baked cover: a plain <img>, one cached texture */
.cover-baked {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 2;
  object-fit: fill;
  filter: brightness(1.35) contrast(1.12);
  transform: translateZ(0);
}
body.book-approaching .cover-baked,
body.book-summoned .cover-baked {
  filter: brightness(1.44) contrast(1.14);
}


/* the question's glow was violet-green neon. Muted, to match the aura —
   it should look lit by the book, not by a nightclub. */
.prompt-text {
  text-shadow:
    0 0 2px rgba(255, 250, 240, .55),
    0 2px 20px rgba(0, 0, 0, 1),
    0 0 36px rgba(150, 128, 180, .68),
    0 0 66px rgba(120, 140, 128, .30),
    0 0 110px rgba(0, 0, 0, .95) !important;
}


/* ═══ SATIN SHEEN ═══
   The mirror-sweep stays gone. In its place: a broad, motionless
   pool of light on the leather — the hide catching the room, with
   the grain still showing through it. Shine, not gloss. */
.cover-shine {
  display: block !important;
  background:
    radial-gradient(ellipse 95% 62% at 32% 16%,
      rgba(255, 244, 222, .30) 0%,
      rgba(255, 238, 208, .12) 34%,
      transparent 62%),
    linear-gradient(118deg,
      rgba(255, 240, 214, .12) 0%,
      transparent 38%,
      transparent 66%,
      rgba(196, 150, 255, .10) 100%);
  mix-blend-mode: screen;
  opacity: 0;
  transition: opacity 1.3s ease .25s;
}
.cover-shine::before {
  display: none !important;
  animation: none !important;
}
body.book-approaching .cover-shine,
body.book-summoned .cover-shine {
  opacity: .85;
}
body.state-open .cover-shine {
  display: none !important;
}


/* ═══════════════════════════════════════════════════════════
   THE FOG FOLLOWS YOU IN

   The canvas fog dies with the tavern when the book opens
   (state-open removes the dustfield for the spread's sake).
   These two layers take over: enormous soft banks drifting
   behind the spread, animated on TRANSFORM ONLY — composited,
   never repainted. The pages stay clear; the dark around them
   moves.
   ═══════════════════════════════════════════════════════════ */
.grimoire::before,
.grimoire::after {
  content: '';
  position: absolute;
  top: -20%;
  bottom: -20%;
  left: -60%;
  width: 220%;
  z-index: 0;
  pointer-events: none;
  mix-blend-mode: screen;
}
.grimoire::before {
  background:
    radial-gradient(ellipse 26% 30% at 18% 78%, rgba(134,138,156,.19), transparent 70%),
    radial-gradient(ellipse 32% 26% at 52% 30%, rgba(126,130,150,.15), transparent 72%),
    radial-gradient(ellipse 24% 32% at 82% 66%, rgba(134,138,156,.18), transparent 70%);
  animation: grim-fog-a 96s ease-in-out infinite alternate;
  animation-play-state: var(--play-state);
}
.grimoire::after {
  background:
    radial-gradient(ellipse 30% 26% at 30% 40%, rgba(130,128,154,.15), transparent 72%),
    radial-gradient(ellipse 22% 30% at 66% 80%, rgba(138,136,158,.18), transparent 70%),
    radial-gradient(ellipse 28% 24% at 90% 24%, rgba(126,124,150,.14), transparent 72%);
  animation: grim-fog-b 128s ease-in-out infinite alternate;
  animation-play-state: var(--play-state);
}
@keyframes grim-fog-a {
  0%   { transform: translate3d(-6%,  1.5%, 0) scale(1);    }
  50%  { transform: translate3d( 4%, -1.5%, 0) scale(1.05); }
  100% { transform: translate3d(10%,  0.5%, 0) scale(1.02); }
}
@keyframes grim-fog-b {
  0%   { transform: translate3d( 8%, -1%,   0) scale(1.03); }
  50%  { transform: translate3d(-3%,  1.8%, 0) scale(1);    }
  100% { transform: translate3d(-9%, -0.5%, 0) scale(1.05); }
}
@media (prefers-reduced-motion: reduce) {
  .grimoire::before,
  .grimoire::after { animation: none; }
}


/* ═══════════════════════════════════════════════════════════
   THE MARK — the sigil

   The crow's-foot rune was a few heavy strokes and read fine
   at 44px. This one is drawn: fine linework, a circle, a
   spatter of ink. It needs ROOM, or it collapses into a smudge.
   So: bigger, and the rule beside it grows to match.
   ═══════════════════════════════════════════════════════════ */
.brand-mark {
  width: clamp(46px, 5.4vw, 72px) !important;
  aspect-ratio: 1;
  flex: none;
  /* the cream is warm already — a faint amber lift ties it to
     the candles, and the shadow keeps it off the dark wall */
  filter:
    drop-shadow(0 2px 8px rgba(0, 0, 0, .95))
    drop-shadow(0 0 14px rgba(146, 58, 34, .28));
  transition: transform .9s cubic-bezier(.2, .7, .2, 1),
              filter .7s ease;
  animation: mark-breathe 9s ease-in-out infinite;
  animation-play-state: var(--play-state);
}
.brand-mark img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
}

/* it breathes, faintly — the room is alive, so is the mark */
@keyframes mark-breathe {
  0%, 100% { opacity: .90; }
  50%      { opacity: 1; }
}

/* the sigil turns a little under the hand, and the red wakes */
.brand:hover .brand-mark,
.brand:focus-visible .brand-mark {
  transform: rotate(-4deg) scale(1.07);
  filter:
    drop-shadow(0 2px 8px rgba(0, 0, 0, .95))
    drop-shadow(0 0 18px rgba(168, 62, 36, .55))
    brightness(1.10);
}

/* the rule beside it grows with it, or the lockup looks broken */
.brand-rule {
  height: clamp(40px, 4.6vw, 60px) !important;
}

@media (max-width: 640px) {
  .brand-mark { width: 44px !important; }
  .brand-rule { height: 38px !important; }
}
@media (prefers-reduced-motion: reduce) {
  .brand-mark { animation: none; }
}

/* ═══════════════════════════════════════════════════════════
   THE SCROLL

   Hangs at the top left, rolled. Click the mark and it comes
   down: the top rod holds, the bottom rod TRAVELS, and the
   vellum grows between them. That is the whole trick — the
   paper does not fade in, it unrolls.

   Everything animates height/transform/opacity. Nothing here
   filters a full-screen layer.
   ═══════════════════════════════════════════════════════════ */

.scroll {
  position: fixed;
  top: clamp(5.2rem, 12vh, 8.4rem);
  left: clamp(1rem, 3vw, 3rem);
  z-index: 50;

  width: clamp(300px, 30vw, 430px);
  display: flex;
  flex-direction: column;
  align-items: stretch;

  pointer-events: none;
  opacity: 0;
  transform: translateY(-10px);
  transition: opacity .5s ease, transform .6s cubic-bezier(.2,.7,.2,1);
}
body.scroll-open .scroll {
  pointer-events: auto;
  opacity: 1;
  transform: translateY(0);
}
/* the pages must never be fought over */
body.state-open .scroll { display: none; }

/* ── THE RODS ── */
.rod {
  position: relative;
  height: 15px;
  flex: none;
  z-index: 2;
}
.rod-bar {
  position: absolute;
  left: -10px;
  right: -10px;
  top: 50%;
  height: 13px;
  margin-top: -6.5px;
  border-radius: 7px;
  background:
    linear-gradient(to bottom,
      #6B5540 0%, #4A3A28 42%, #2E2318 78%, #241A12 100%);
  box-shadow:
    inset 0 1px 0 rgba(214,186,138,.30),
    inset 0 -3px 6px rgba(0,0,0,.6),
    0 5px 14px rgba(0,0,0,.75);
}
.rod-cap {
  position: absolute;
  top: 50%;
  width: 15px;
  height: 21px;
  margin-top: -10.5px;
  border-radius: 4px;
  background: linear-gradient(to bottom, #8A6E3B, #4A3A20 60%, #2A2012);
  box-shadow: 0 3px 8px rgba(0,0,0,.8), inset 0 1px 0 rgba(232,200,140,.4);
}
.rod-cap-l { left: -17px; }
.rod-cap-r { right: -17px; }

/* the bottom rod travels down as the vellum grows —
   it needs no transform of its own, the flex column does it */
.rod-bottom { margin-top: -2px; }

/* ── THE VELLUM ──
   Closed: zero height. Open: it unrolls. The inner sheet is
   pushed UP when closed and slides down as the paper appears,
   so the writing arrives WITH the paper instead of being
   revealed by a moving window. */
.vellum {
  position: relative;
  overflow: hidden;
  max-height: 0;
  transition: max-height .95s cubic-bezier(.24,.8,.3,1);

  background:
    /* the stains: tea, damp, a thumb, a spill */
    radial-gradient(ellipse 30% 16% at 88% 8%,  rgba(120, 84, 36, .22), transparent 70%),
    radial-gradient(ellipse 22% 12% at 12% 34%, rgba(108, 74, 30, .18), transparent 72%),
    radial-gradient(ellipse 26% 14% at 76% 62%, rgba(126, 90, 44, .16), transparent 72%),
    radial-gradient(ellipse 34% 18% at 24% 88%, rgba(112, 78, 34, .20), transparent 70%),
    radial-gradient(circle 5px at 62% 22%, rgba(96, 64, 26, .34), transparent),
    radial-gradient(circle 7px at 30% 56%, rgba(104, 70, 30, .26), transparent),
    radial-gradient(circle 4px at 84% 44%, rgba(96, 64, 26, .30), transparent),
    /* the darkened edges — a scroll rots inward from the outside */
    linear-gradient(to right,  rgba(88, 60, 24, .40) 0%, transparent 7%,
                               transparent 93%, rgba(88, 60, 24, .40) 100%),
    /* the sheet */
    linear-gradient(172deg, #D8CCAE 0%, #C9BB99 38%, #D2C5A6 62%, #BEAF8C 100%);
  box-shadow:
    inset 0 8px 18px -8px rgba(60, 42, 16, .55),
    inset 0 -10px 20px -8px rgba(60, 42, 16, .45),
    0 22px 46px rgba(0, 0, 0, .78);
}
body.scroll-open .vellum {
  max-height: min(74vh, 760px);
}

/* the fibre of the paper */
.vellum::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .30;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23f)' opacity='.55'/%3E%3C/svg%3E");
}
/* it curls at the sides, so light gathers there */
.vellum::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to right,
      rgba(255,250,232,.30) 0%, transparent 5%,
      transparent 95%, rgba(255,250,232,.22) 100%),
    linear-gradient(to bottom, rgba(70,48,20,.20) 0%, transparent 6%);
}

/* the torn foot */
.vellum-tear {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 9px;
  background:
    radial-gradient(circle 5px at 6%  0%, transparent 4px, #BEAF8C 4px),
    radial-gradient(circle 4px at 20% 2px, transparent 3px, #BEAF8C 3px),
    radial-gradient(circle 6px at 38% 1px, transparent 5px, #BEAF8C 5px),
    radial-gradient(circle 4px at 55% 0%, transparent 3px, #BEAF8C 3px),
    radial-gradient(circle 5px at 72% 2px, transparent 4px, #BEAF8C 4px),
    radial-gradient(circle 4px at 90% 1px, transparent 3px, #BEAF8C 3px);
  opacity: .55;
}

/* ── THE WRITING ──
   Held up inside the roll, and lowered with it. */
.vellum-inner {
  position: relative;
  z-index: 2;
  padding: clamp(1.5rem, 2.6vw, 2.3rem) clamp(1.4rem, 2.4vw, 2.1rem) 2.4rem;
  max-height: min(74vh, 760px);
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: #A2926F transparent;

  transform: translateY(-22px);
  opacity: 0;
  transition: transform 1s cubic-bezier(.24,.8,.3,1) .12s,
              opacity .8s ease .22s;
}
body.scroll-open .vellum-inner {
  transform: translateY(0);
  opacity: 1;
}
.vellum-inner::-webkit-scrollbar { width: 5px; }
.vellum-inner::-webkit-scrollbar-thumb { background: #A2926F; border-radius: 3px; }

.scroll-close {
  position: absolute;
  top: .5rem;
  right: .6rem;
  width: 26px; height: 26px;
  padding: 0;
  background: none;
  border: 1px solid rgba(87,72,53,.30);
  border-radius: 50%;
  color: #6E5A3E;
  font: 400 15px/1 'Cormorant Garamond', Georgia, serif;
  cursor: pointer;
  opacity: .55;
  transition: opacity .3s, color .3s, border-color .3s, background .3s;
}
.scroll-close:hover,
.scroll-close:focus-visible {
  opacity: 1;
  color: #6E2113;
  border-color: rgba(110,33,19,.6);
  background: rgba(110,33,19,.08);
}

.scroll-eyebrow {
  margin: 0 0 .5rem;
  font-family: 'Spectral SC', Georgia, serif;
  font-size: .56rem;
  letter-spacing: .34em;
  text-transform: uppercase;
  text-align: center;
  color: #6E5C40;
  opacity: .85;
}
.scroll-name {
  margin: 0;
  font-family: 'UnifrakturMaguntia', serif;
  font-weight: 400;
  font-size: clamp(1.9rem, 3.4vw, 2.6rem);
  line-height: 1;
  text-align: center;
  color: #2A2018;
}
.scroll-name::first-letter { color: #6E2113; }

.scroll-orn {
  display: flex;
  align-items: center;
  gap: .8rem;
  width: 76%;
  margin: .9rem auto 1.3rem;
  color: #8A6E3B;
  opacity: .7;
}
.scroll-orn span {
  flex: 1;
  height: 1px;
  background: linear-gradient(to right, transparent, #7E6A4A);
}
.scroll-orn span:last-child {
  background: linear-gradient(to left, transparent, #7E6A4A);
}

/* ── HER LIKENESS ── */
.likeness {
  position: relative;
  float: left;
  width: 40%;
  margin: .2rem 1.1rem .7rem 0;
  padding: 0;
}
.likeness img,
.likeness-empty {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  border-radius: 1px;
}
.likeness img {
  object-fit: cover;
  /* a photograph left in a drawer for thirty years */
  filter: sepia(.42) contrast(1.06) brightness(.94) saturate(.8);
  box-shadow: 0 4px 14px rgba(40, 28, 10, .45);
}
/* the empty frame, until a photograph is put in it */
.likeness-empty {
  display: none;
  place-items: center;
  align-content: center;
  gap: .5rem;
  text-align: center;
  color: #8A7758;
  background:
    repeating-linear-gradient(-45deg,
      rgba(140,120,86,.10) 0 6px, transparent 6px 12px),
    rgba(178, 164, 132, .35);
  box-shadow: inset 0 0 0 1px rgba(110, 92, 60, .35);
}
.likeness-empty svg { width: 34%; opacity: .55; }
.likeness-empty em {
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  font-size: .72rem;
  line-height: 1.3;
  opacity: .8;
  padding: 0 .4rem;
}
.likeness.no-pic img { display: none; }
.likeness.no-pic .likeness-empty { display: grid; }

/* the tape holding it to the page */
.likeness-frame {
  position: absolute;
  top: -7px;
  left: 50%;
  width: 46px;
  height: 15px;
  margin-left: -23px;
  z-index: 2;
  background: rgba(214, 198, 158, .55);
  box-shadow: 0 1px 3px rgba(50, 36, 12, .3);
  transform: rotate(-2.5deg);
}
.likeness figcaption {
  margin-top: .38rem;
  font-family: 'Spectral SC', Georgia, serif;
  font-size: .5rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  text-align: center;
  color: #6E5C40;
  opacity: .8;
}

/* ── THE TEXT ── */
.scroll-text {
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-weight: 400;
  font-size: clamp(.92rem, 1.05vw, 1.03rem);
  line-height: 1.62;
  color: #3A2E20;
}
.scroll-text p { margin: 0 0 .78rem; }
.scroll-text .lede {
  font-style: italic;
  font-size: 1.06em;
  color: #2A2018;
}
.scroll-text .lede::first-letter {
  font-size: 1.5em;
  color: #6E2113;
  line-height: 1;
}
.scroll-text strong {
  font-weight: 600;
  color: #6E2113;
}
.scroll-text em { color: #2A2018; }

.scroll-sign {
  clear: both;
  margin: 1.1rem 0 0;
  font-family: 'UnifrakturMaguntia', serif;
  font-size: 1.5rem;
  text-align: right;
  color: #4A3A28;
  opacity: .9;
  transform: rotate(-1.6deg);
}
.scroll-foot {
  margin: .5rem 0 0;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  font-size: .84rem;
  text-align: center;
  color: #6E5C40;
  opacity: .85;
}

/* ── THE SEAL ── */
.wax {
  display: block;
  width: 46px;
  margin: .9rem auto 0;
  color: #7A2417;
  filter: drop-shadow(0 3px 6px rgba(40, 10, 4, .5));
  transform: rotate(-6deg);
}
.wax svg { width: 100%; display: block; }

/* ── PHONE ── */
@media (max-width: 760px) {
  .scroll {
    top: 4.6rem;
    left: 50%;
    transform: translate(-50%, -10px);
    width: min(90vw, 400px);
  }
  body.scroll-open .scroll { transform: translate(-50%, 0); }
  body.scroll-open .vellum,
  .vellum-inner { max-height: min(70vh, 620px); }
  .likeness { width: 44%; }
}

@media (prefers-reduced-motion: reduce) {
  .vellum, .vellum-inner, .scroll { transition: none; }
}


/* ═══════════════════════════════════════════════════════════
   THE PHONE'S OWN PAINTING

   The phone no longer shows a crop of the landscape plate. It
   shows its own portrait artwork, in which the grimoire sits
   elsewhere. Everything that must LAND ON the painted book —
   the glow that says "here", and the target you tap — is now
   pinned to the geometry JS measures at runtime (--book-x /
   --book-y / --book-w), exactly as the book itself is.

   That is the whole point: a percentage of the VIEWPORT drifts
   off the book the moment the crop changes. A percentage of the
   PAINTING never does.
   ═══════════════════════════════════════════════════════════ */
@media (max-width: 760px) {

  /* the glow, sitting on the painted cover */
  .beckon {
    left: var(--book-x, 48%);
    bottom: var(--book-y, 25%);
    width: calc(var(--book-w, 46vw) * 0.92);
    margin-left: calc(var(--book-w, 46vw) * -0.46);
    aspect-ratio: 1.5;
  }

  /* TAP 1 — the painted grimoire. Generous: a thumb is not a cursor. */
  .hitarea {
    left: var(--book-x, 48%);
    bottom: calc(var(--book-y, 25%) - 7%);
    width: calc(var(--book-w, 46vw) * 1.45);
    height: 22vh;
    margin-left: calc(var(--book-w, 46vw) * -0.725);
    transform: none;
  }
}


/* the first frame on a phone must be the PHONE's painting, blurred —
   not the landscape one. */
@media (max-width: 760px) {
  .plate-lqip {
    background-image: url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA4KCw0LCQ4NDA0QDw4RFiQXFhQUFiwgIRokNC43NjMuMjI6QVNGOj1OPjIySGJJTlZYXV5dOEVmbWVabFNbXVn/2wBDAQ8QEBYTFioXFypZOzI7WVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVn/wAARCAAgABIDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDhwFIHysG9KTaAQXBAPWpkgy6qrZJGeM8elQ+WSe7eppDAGHHIfP4UVL9nH9xj+Boouh2ZHA7eYJNxXHU4z+lWI8xQyMhJLEL0qoZVCqApxjnnrWhDfaetk0cltI0zD7+88HscdKAKBkcHGWoqY6g5JOxTnuepooDTuf/Z') !important;
    background-position: center bottom;
  }
}

/* ═══════════════════════════════════════════════════════════
   THE PHONE — THE CALL, AND WHAT ANSWERS IT

   There is no cursor here, so nothing can be discovered by
   hovering. The painted book must ASK to be touched. So the
   glow sits right on its cover, low and toward the cat, and
   it PULSES — slow, alive, unmistakably a thing you press.

   Then it is answered: the real grimoire comes up, and it
   comes up BIG. On a phone the book is the whole event; there
   is no room around it to be subtle in.
   ═══════════════════════════════════════════════════════════ */
@media (max-width: 760px) {

  /* ── THE CALL ──
     Pinned to its own measured point on the painting (--glow-x /
     --glow-y), not to a viewport percentage — so it stays on the
     cover whatever shape the handset is. */
  .beckon {
    display: block;
    left: var(--glow-x, 52%);
    bottom: var(--glow-y, 21%);
    width: min(46vw, 230px);
    margin-left: min(-23vw, -115px);
    aspect-ratio: 1.35;
    z-index: 5;
    opacity: 1;
  }

  /* the light in the book */
  .beckon-core {
    inset: 6%;
    border-radius: 50%;
    background: radial-gradient(ellipse at 50% 50%,
      rgba(214, 168, 255, .72) 0%,
      rgba(176, 116, 246, .46) 26%,
      rgba(128, 66, 200, .22) 50%,
      rgba(86, 40, 150, .08) 70%,
      transparent 82%);
    animation: beckon-pulse 2.6s ease-in-out infinite;
    animation-play-state: var(--play-state);
  }

  /* the light it throws on the table around it */
  .beckon-halo {
    inset: -34% -26%;
    border-radius: 50%;
    background: radial-gradient(ellipse,
      rgba(168, 108, 240, .34) 0%,
      rgba(132, 92, 214, .18) 32%,
      rgba(96, 186, 140, .06) 56%,
      transparent 78%);
    animation: beckon-breathe 4.4s ease-in-out infinite;
    animation-play-state: var(--play-state);
  }

  /* ONE ring, very soft — a ripple leaving the book, not a reticle */
  .beckon-ring {
    display: block;
    inset: 4%;
    border-radius: 50%;
    border: 1.5px solid rgba(206, 160, 255, .40);
    animation: beckon-ripple 3.4s cubic-bezier(.15, .6, .3, 1) infinite;
    animation-play-state: var(--play-state);
  }
  .beckon-ring-2 { display: none; }

  @keyframes beckon-pulse {
    0%, 100% { transform: translateZ(0) scale(.80); opacity: .40; }
    50%      { transform: translateZ(0) scale(1.12); opacity: 1;   }
  }
  @keyframes beckon-breathe {
    0%, 100% { transform: translateZ(0) scale(.84); opacity: .42; }
    50%      { transform: translateZ(0) scale(1.16); opacity: .92; }
  }
  @keyframes beckon-ripple {
    0%   { transform: translateZ(0) scale(.55); opacity: 0;   }
    18%  {                                      opacity: .75; }
    100% { transform: translateZ(0) scale(1.7); opacity: 0;   }
  }

  /* it has done its job the moment the book answers */
  body.book-summoned .beckon {
    opacity: 0;
    transform: scale(1.35);
    transition: opacity .8s ease, transform 1s cubic-bezier(.2,.7,.2,1);
    pointer-events: none;
  }

  /* ── WHAT ANSWERS ──
     Bigger. It was 60vw / 42vmin, which on a tall phone left it
     stranded in the middle of a lot of dark. */
  .book {
    width: min(80vw, 56vmin, 360px);
  }
  body.book-summoned .book {
    transform: translate3d(-50%, -54%, 0) rotateX(2deg) scale(1.06);
  }
  body.state-open .book,
  body.state-open.book-summoned .book {
    transform: translate3d(-50%, -60%, 0) scale(3);
  }

  /* the tap target that OPENS it grows with it */
  .hitarea-open {
    width: min(88vw, 400px);
    height: min(112vw, 520px);
    transform: translate(-50%, -54%);
  }
}

/* the target follows the CALL — you press where it glows.
   Generous, and reaching a little below it, because a thumb
   covers what it touches. */
@media (max-width: 760px) {
  .hitarea {
    position: absolute;
    left: var(--glow-x, 52%);
    bottom: calc(var(--glow-y, 21%) - 7vh);
    top: auto;
    width: min(72vw, 350px);
    height: 26vh;
    margin-left: min(-36vw, -175px);
    transform: none;
    aspect-ratio: auto;
    z-index: 6;
  }
}

/* ═══════════════════════════════════════════════════════════
   THE OPEN TARGET IS FORGIVING

   The book is roughly 80vw wide and 110vw tall. The target that
   opens it now overhangs that on every side — a thumb aimed at
   the edge of the cover still lands on it.

   And a tap that misses ENTIRELY does nothing at all: the book
   stays out. It was called; it does not leave because you
   touched the dark next to it.
   ═══════════════════════════════════════════════════════════ */
@media (max-width: 760px) {
  .hitarea-open {
    width: min(96vw, 440px);
    height: min(128vw, 600px);
    transform: translate(-50%, -54%);
  }
}

/* ═══════════════════════════════════════════════════════════
   THE PHONE — READING THE BOOK

   A two-page spread on a 390px screen is two columns of about
   180px each. That is not a book, it is a pamphlet. So the
   phone gets ONE LEAF, and the leaf gets the WHOLE SCREEN —
   edge to edge, no frame, no letterbox — and you read it by
   scrolling, and turn it by swiping. iBooks, not a shrunken
   desktop.
   ═══════════════════════════════════════════════════════════ */
@media (max-width: 760px) {

  /* no stage, no margin. The vellum IS the screen. */
  .grimoire {
    padding: 0;
    display: block;
    background: #0A0705;
  }
  .spread {
    width: 100%;
    height: 100svh;          /* svh: the real height, minus the URL bar */
    min-height: 100svh;
    border-radius: 0;
    transform: none !important;
    opacity: 1;
    filter: none !important;
    box-shadow: none;
  }
  /* the leather boards behind the spread have nothing to frame now */
  .spread::before { display: none; }

  .page {
    border-radius: 0;
    box-shadow: none;
  }
  /* the fore-edge shading was drawn for a page bound at one side */
  .page-left,
  .page-right { box-shadow: none; }

  /* ── THE READING COLUMN ──
     Room at the top for the close pill, room at the bottom for the
     page bar, and the notch/home-bar respected on both. */
  .page-inner {
    height: 100%;
    max-height: none;
    padding:
      calc(env(safe-area-inset-top, 0px) + 4.4rem)
      clamp(1.3rem, 6vw, 2.2rem)
      calc(env(safe-area-inset-bottom, 0px) + 5.2rem);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;   /* momentum, like iBooks */
    overscroll-behavior: contain;
  }

  /* the type can breathe on a full page */
  .illum        { width: 118px; margin-bottom: 1.2rem; }
  .grim-title   { font-size: clamp(2.8rem, 13vw, 3.8rem); }
  .contents-head{ font-size: clamp(2.2rem, 10vw, 3rem); }
  .grim-note,
  .grim-sub     { max-width: 34rem; }
  .contents a   { padding: .85rem .3rem; }

  /* ═══ CLOSE THE GRIMOIRE ═══
     It was 0.58rem uppercase at 65% opacity on a dark page — a
     whisper. It is now a pressed wax-and-parchment pill, top
     right, that you can actually see and actually hit. */
  .close-book {
    position: fixed;
    top: calc(env(safe-area-inset-top, 0px) + .7rem);
    right: .8rem;
    bottom: auto;
    left: auto;
    transform: none;
    z-index: 70;

    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .62rem 1.05rem;
    min-height: 44px;                 /* Apple's minimum. Non-negotiable. */

    background: linear-gradient(to bottom, #6E2113, #4E1409);
    border: 1px solid rgba(226, 200, 150, .45);
    border-radius: 999px;
    box-shadow:
      0 3px 10px rgba(0, 0, 0, .55),
      inset 0 1px 0 rgba(255, 226, 180, .25);

    color: #F2E6CC;
    font-family: 'Spectral SC', Georgia, serif;
    font-size: .62rem;
    letter-spacing: .16em;
    text-transform: uppercase;
    text-shadow: 0 1px 2px rgba(0, 0, 0, .7);

    opacity: 0;
    transition: opacity .7s ease 1.2s, transform .25s ease;
  }
  body.state-open .close-book { opacity: 1; }
  .close-book:active {
    transform: scale(.95);
    background: linear-gradient(to bottom, #8E3A22, #6E2113);
  }

  /* ═══ THE PAGE BAR ═══
     It had display:flex and nothing else — no position, no skin.
     It was floating in the text. */
  .leafbar {
    position: fixed;
    left: 50%;
    bottom: calc(env(safe-area-inset-bottom, 0px) + .8rem);
    transform: translateX(-50%);
    z-index: 70;

    display: flex;
    align-items: center;
    gap: .35rem;
    padding: .3rem .4rem;

    background: rgba(28, 20, 12, .82);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    border: 1px solid rgba(138, 110, 59, .35);
    border-radius: 999px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .55);

    opacity: 0;
    transition: opacity .7s ease 1.2s;
  }
  body.state-open .leafbar { opacity: 1; }

  .leaf-turn {
    width: 42px;
    height: 42px;
    display: grid;
    place-items: center;
    padding: 0;
    background: none;
    border: 0;
    border-radius: 50%;
    color: #D8CBAC;
    cursor: pointer;
    transition: background .25s ease, color .25s ease, opacity .25s ease;
  }
  .leaf-turn svg { width: 13px; height: 13px; }
  .leaf-turn:active { background: rgba(110, 33, 19, .55); color: #FFF2DA; }
  .leaf-turn:disabled { opacity: .25; pointer-events: none; }

  .leaf-count {
    min-width: 3.6rem;
    text-align: center;
    font-family: 'Spectral SC', Georgia, serif;
    font-size: .6rem;
    letter-spacing: .18em;
    color: #C9BFA6;
    opacity: .8;
  }

  /* the folded corner is redundant next to a page bar, and it
     sat under the thumb anyway */
  .dogear { display: none; }
}

/* ═══════════════════════════════════════════════════════════
   THE PHONE SPREAD — SPECIFICITY

   book.min.css declares the spread as `.grimoire .spread` — TWO
   classes. Every mobile override I wrote was `.spread` — ONE.
   A media query adds no specificity, so the desktop's three-column
   grid (1fr auto 1fr) kept winning, and the leaf was rendered into
   the FIRST COLUMN: a half-width strip of vellum with the title
   running off the edge and black filling the rest of the screen.

   Matched selector, matched specificity. One column, full bleed.
   ═══════════════════════════════════════════════════════════ */
@media (max-width: 760px) {

  .grimoire .spread {
    grid-template-columns: 1fr;
    grid-template-rows: 1fr;
    width: 100%;
    max-width: none;
    height: 100svh;
    min-height: 100svh;
    margin: 0;
    border-radius: 0;
    overflow: visible;
    transform: none;
    opacity: 1;
    filter: none;
    box-shadow: none;
  }
  .grimoire .spread::before { display: none; }
  .grimoire .spine { display: none; }

  /* every leaf stacked in the one and only cell */
  .grimoire .page {
    grid-area: 1 / 1;
    width: 100%;
    height: 100%;
    border-radius: 0;
    box-shadow: none;
  }
  .grimoire .page-inner {
    height: 100%;
    max-height: none;
  }

  /* the title must never run off the leaf again */
  .grim-title,
  .contents-head {
    overflow-wrap: break-word;
    hyphens: none;
    max-width: 100%;
  }
  .grim-title { font-size: clamp(2.4rem, 11.5vw, 3.6rem); }
}

/* ═══════════════════════════════════════════════════════════
   THE COVER — THE REAL BINDING

   The hand-drawn SVG cover (sunburst boss, four moons, vines,
   braided cord) is gone. In its place: a photograph of the
   actual book.

   Everything AROUND it is untouched — the violet aura, the
   sparks, the conjuring burst, the satin sheen, the dimmer, the
   flight into the page. Only the face of the book has changed.
   ═══════════════════════════════════════════════════════════ */

/* the book takes the artwork's shape, so the engraved border is
   never cropped away by object-fit */
.book {
  aspect-ratio: .671;
}

.cover-art,
picture.cover-art {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  z-index: 2;
  border-radius: 2px 5px 5px 2px;
  overflow: hidden;
}
picture.cover-art img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  object-position: center;

  /* it is photographed dark. A little lift, no more — the old
     +35% brightness was tuned for flat vector silver and would
     grey out real leather. */
  filter: brightness(1.06) contrast(1.04) saturate(1.02);
  transition: filter .8s ease;
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* under the hand, it catches the light */
body.book-approaching picture.cover-art img,
body.book-summoned  picture.cover-art img {
  filter: brightness(1.20) contrast(1.07) saturate(1.05);
}

/* the old rules pointed at an <svg>/baked <img> and would fight this */
.cover-baked { display: none !important; }

/* the leather beneath needs no gradient now — the photograph IS the
   leather. Keep only the shadow that lifts it off the table. */
.cover-front {
  background: #050505 !important;
  border: 1px solid rgba(90, 84, 76, .30);
  overflow: hidden;
}
/* the grain overlay would only muddy a real photograph */
.cover-front::after { opacity: .07 !important; }

/* The old cover carried `filter: brightness(1.35) ... !important` on
   .cover-art. That selector now matches the <picture> WRAPPER, and a
   filter on a wrapper applies to everything inside it — so the lift
   would land twice: once on the picture, once on the img.

   picture.cover-art is (0,1,1) and beats .cover-art (0,1,0), so this
   !important wins. The wrapper carries no filter; the image carries
   all of it. */
picture.cover-art {
  filter: none !important;
}

/* ═══════════════════════════════════════════════════════════
   THE COVER IS UNRETOUCHED

   The artwork arrives already lit, already graded, already
   textured. Everything this stylesheet was putting ON TOP of it
   was written for a flat vector cover that needed help:

     • brightness / contrast / saturate   — a colour grade
     • the grain overlay                  — fake leather texture
     • the satin sheen                    — a screen-blended
                                            highlight wash

   On a photograph they are all corruption. Stripped. What you
   see is the file, pixel for pixel.

   The aura, the sparks and the conjuring all live BEHIND and
   AROUND the book, not on its face — they are untouched.
   ═══════════════════════════════════════════════════════════ */

picture.cover-art img,
body.book-approaching picture.cover-art img,
body.book-summoned picture.cover-art img {
  filter: none !important;
}

/* no fake grain over a real photograph */
.cover-front::after {
  display: none !important;
}

/* no sheen washing over the leather */
.cover-shine,
body.book-approaching .cover-shine,
body.book-summoned .cover-shine {
  display: none !important;
}

/* ═══════════════════════════════════════════════════════════
   THE MARK GLITCHES

   It sits quiet in the corner and nobody presses it. So every
   few seconds it TEARS — a hard chromatic split, a skew, a
   frame of inverted light — and then it is innocent again.

   Two rules keep it from being a nuisance:

     • the burst is SHORT. Under half a second, then gone.
     • the cycle is PRIME-ISH against its own breathing (11.3s
       against 9s), and carries TWO bursts at uneven points in
       the loop — so it never settles into a rhythm you can
       predict, and never syncs with anything else on the page.

   The glitch lives on the IMG. The hover turn lives on the
   SPAN. They never fight over the same transform.
   ═══════════════════════════════════════════════════════════ */

.brand-mark img {
  animation: mark-glitch 11.3s steps(1, end) infinite;
  animation-play-state: var(--play-state);
  will-change: transform, filter;
}

@keyframes mark-glitch {

  /* ── quiet ── */
  0%, 27% {
    transform: none;
    filter: none;
    opacity: 1;
  }

  /* ── FIRST TEAR ── the signal splits */
  28%   { transform: translate(-2px, 1px)  skewX(-9deg);
          filter: drop-shadow(3px 0 rgba(190, 24, 18, .95))
                  drop-shadow(-3px 0 rgba(40, 200, 210, .75)); }
  29%   { transform: translate(3px, -2px)  skewX(7deg)  scaleY(1.06);
          filter: drop-shadow(-4px 0 rgba(190, 24, 18, .9))
                  drop-shadow(3px 1px 0 rgba(40, 200, 210, .8))
                  brightness(1.5); }
  30%   { transform: translate(-1px, 2px)  scaleX(1.04);
          filter: invert(1) brightness(1.4) hue-rotate(-18deg);
          opacity: .85; }
  31%   { transform: translate(2px, 0)     skewY(3deg);
          filter: drop-shadow(2px 0 rgba(190, 24, 18, .8))
                  drop-shadow(-2px 0 rgba(40, 200, 210, .6)); }
  32%   { transform: none;
          filter: brightness(1.25) saturate(1.3); }
  33%, 71% {
    transform: none;
    filter: none;
    opacity: 1;
  }

  /* ── SECOND TEAR ── shorter, meaner, unevenly spaced from the first */
  72%   { transform: translate(4px, -1px)  skewX(12deg) scaleY(.94);
          filter: drop-shadow(-5px 0 rgba(190, 24, 18, 1))
                  drop-shadow(4px 0 rgba(40, 200, 210, .85)); }
  73%   { transform: translate(-3px, 2px)  skewX(-6deg);
          filter: invert(1) sepia(.5) hue-rotate(-30deg) brightness(1.6);
          opacity: .7; }
  73.8% { transform: translate(1px, -1px);
          filter: drop-shadow(3px 0 rgba(190, 24, 18, .85))
                  drop-shadow(-3px 0 rgba(40, 200, 210, .7)); }
  74.6% { transform: none;
          filter: brightness(1.35); }

  75%, 100% {
    transform: none;
    filter: none;
    opacity: 1;
  }
}

/* under the hand it stops misbehaving and simply lights up —
   a thing that glitches while you are pressing it feels broken,
   not haunted */
.brand:hover .brand-mark img,
.brand:focus-visible .brand-mark img {
  animation: none;
  filter: brightness(1.12) !important;
  transform: none !important;
}

@media (prefers-reduced-motion: reduce) {
  .brand-mark img { animation: none; }
}

/* ═══════════════════════════════════════════════════════════
   THE LOCKUP, LARGER

   The mark grew to 72px and the words never caught up — the
   name was set at 1.7rem beside it, which made the sigil look
   bolted onto a caption. Both lines go up, and the rule between
   them with them.
   ═══════════════════════════════════════════════════════════ */

.brand-name {
  font-size: clamp(1.6rem, 3.1vw, 2.55rem) !important;
  line-height: .95;
}

.brand-sub {
  font-size: clamp(.58rem, 1vw, .8rem) !important;
  letter-spacing: .34em;
}

.brand-words { gap: .3rem; }

@media (max-width: 640px) {
  .brand-name { font-size: 1.5rem !important; }
  .brand-sub  { font-size: .54rem !important; letter-spacing: .22em; }
}

/* ═══════════════════════════════════════════════════════════
   THE NAME IS SET IN BOKOR

   Bokor is not fraktur and must not be treated like it. Where
   UnifrakturMaguntia is dense, black and cluttered, Bokor is
   THIN — hairline strokes, wide counters, a lot of air. Drop it
   in at the old size and it vanishes on a black wall.

   So it gets what a hairline face needs:
     • more SIZE          — thin strokes need scale to survive
     • more TRACKING      — its letters must not touch
     • a real SHADOW      — a 1px stroke on black needs separation
     • no faux-bold       — synthetic weight would clog it shut
   ═══════════════════════════════════════════════════════════ */

.brand-name {
  font-family: 'Bokor', 'UnifrakturMaguntia', serif !important;
  font-weight: 400 !important;          /* never synthesise weight */
  font-size: clamp(1.9rem, 3.7vw, 3rem) !important;
  line-height: 1.05;
  letter-spacing: .045em;
  color: #E2D8C0;

  /* the strokes are a hair wide — give them somewhere to sit */
  text-shadow:
    0 2px 10px rgba(0, 0, 0, 1),
    0 0 22px rgba(0, 0, 0, .9),
    0 0 34px rgba(138, 58, 34, .30);
}

/* the sub-line grows with it so the block stays a block */
.brand-sub {
  font-size: clamp(.6rem, 1.05vw, .82rem) !important;
  letter-spacing: .36em;
}

/* the same hand signs the scroll — it is the same person */
.scroll-name {
  font-family: 'Bokor', 'UnifrakturMaguntia', serif !important;
  font-weight: 400;
  font-size: clamp(2.1rem, 3.8vw, 2.9rem);
  letter-spacing: .04em;
  line-height: 1.1;
}
.scroll-sign {
  font-family: 'Bokor', 'UnifrakturMaguntia', serif !important;
  font-size: 1.7rem;
  letter-spacing: .03em;
}

/* on a phone the hairlines are the first thing to disappear —
   hold the size up rather than letting it shrink away */
@media (max-width: 640px) {
  .brand-name {
    font-size: 1.75rem !important;
    letter-spacing: .03em;
  }
  .brand-sub {
    font-size: .55rem !important;
    letter-spacing: .24em;
  }
}

/* ═══════════════════════════════════════════════════════════
   THE NAME, SIZED AND SEATED

   Two separate problems, easy to confuse:

   SIZE — Bokor at 3rem was overpowering a 72px mark. Down a step.

   ALIGNMENT — Bokor has tall ascenders and a shallow x-height, so
   its optical centre sits ABOVE its geometric centre. Flexbox
   aligns boxes, not ink: `align-items: center` centred the BOX
   perfectly and left the LETTERS riding high beside the sigil.

   The fix is not more centring — it is a nudge. The words drop a
   few pixels so the ink, not the box, lines up with the mark.
   ═══════════════════════════════════════════════════════════ */

.brand-name {
  font-size: clamp(1.55rem, 2.95vw, 2.35rem) !important;
  line-height: 1;
}

/* the whole word-block settles down onto the mark's eyeline */
.brand-words {
  transform: translateY(3px);
  gap: .26rem;
}

.brand-sub {
  font-size: clamp(.55rem, .95vw, .74rem) !important;
  letter-spacing: .32em;
}

@media (max-width: 640px) {
  .brand-name  { font-size: 1.45rem !important; }
  .brand-sub   { font-size: .5rem !important; letter-spacing: .2em; }
  .brand-words { transform: translateY(2px); }
}

/* ═══════════════════════════════════════════════════════════
   THE NAME SPLITS TOO

   A permanent hairline of red on one side, cold cyan on the
   other — the signal never quite locking. On Bokor's thin
   strokes this is enough; a heavy face would need more, and
   would look worse for it.

   And when the sigil TEARS, the name tears with it. Same 11.3s
   cycle, same two uneven bursts, so they are visibly the same
   event rather than two things twitching near each other.

   Stepped, not interpolated. An interpolated text-shadow re-renders
   the glyphs and re-blurs every layer on every frame — that lesson
   is already written in this file, further up. steps(1) means a
   handful of discrete repaints per burst and nothing in between.
   ═══════════════════════════════════════════════════════════ */

.brand-name {
  /* at rest: barely there. You feel it before you see it. */
  text-shadow:
    0 2px 10px rgba(0, 0, 0, 1),
    0 0 22px rgba(0, 0, 0, .9),
    1px 0 0 rgba(190, 24, 18, .38),
    -1px 0 0 rgba(40, 200, 210, .26),
    0 0 34px rgba(138, 58, 34, .28);

  animation: name-split 11.3s steps(1, end) infinite;
  animation-play-state: var(--play-state);
}

@keyframes name-split {

  0%, 27% {
    text-shadow:
      0 2px 10px rgba(0,0,0,1), 0 0 22px rgba(0,0,0,.9),
      1px 0 0 rgba(190,24,18,.38), -1px 0 0 rgba(40,200,210,.26),
      0 0 34px rgba(138,58,34,.28);
    transform: translateY(3px);
  }

  /* ── first tear — with the sigil ── */
  28% {
    text-shadow:
      0 2px 10px rgba(0,0,0,1),
      3px 0 0 rgba(190,24,18,.95), -3px 0 0 rgba(40,200,210,.75),
      0 0 30px rgba(138,58,34,.5);
    transform: translate(-1px, 3px) skewX(-2deg);
  }
  30% {
    text-shadow:
      0 2px 10px rgba(0,0,0,1),
      -4px 0 0 rgba(190,24,18,.9), 3px 0 0 rgba(40,200,210,.8);
    transform: translate(2px, 2px);
  }
  32% {
    text-shadow:
      0 2px 10px rgba(0,0,0,1),
      2px 0 0 rgba(190,24,18,.6), -2px 0 0 rgba(40,200,210,.45);
    transform: translateY(3px);
  }

  33%, 71% {
    text-shadow:
      0 2px 10px rgba(0,0,0,1), 0 0 22px rgba(0,0,0,.9),
      1px 0 0 rgba(190,24,18,.38), -1px 0 0 rgba(40,200,210,.26),
      0 0 34px rgba(138,58,34,.28);
    transform: translateY(3px);
  }

  /* ── second tear — shorter, meaner ── */
  72% {
    text-shadow:
      0 2px 10px rgba(0,0,0,1),
      -5px 0 0 rgba(190,24,18,1), 4px 0 0 rgba(40,200,210,.85);
    transform: translate(2px, 3px) skewX(3deg);
  }
  73.8% {
    text-shadow:
      0 2px 10px rgba(0,0,0,1),
      3px 0 0 rgba(190,24,18,.85), -3px 0 0 rgba(40,200,210,.7);
    transform: translate(-1px, 3px);
  }

  75%, 100% {
    text-shadow:
      0 2px 10px rgba(0,0,0,1), 0 0 22px rgba(0,0,0,.9),
      1px 0 0 rgba(190,24,18,.38), -1px 0 0 rgba(40,200,210,.26),
      0 0 34px rgba(138,58,34,.28);
    transform: translateY(3px);
  }
}

/* under the hand it settles, exactly as the sigil does */
.brand:hover .brand-name,
.brand:focus-visible .brand-name {
  animation: none;
  transform: translateY(3px);
  text-shadow:
    0 2px 10px rgba(0, 0, 0, 1),
    0 0 22px rgba(0, 0, 0, .9),
    0 0 30px rgba(138, 58, 34, .40);
}

@media (prefers-reduced-motion: reduce) {
  .brand-name { animation: none; }
}

/* ═══════════════════════════════════════════════════════════
   THE NAME: ABERRATION ONLY, NO ANIMATION

   The synced tearing is gone. The name does not move, ever.

   What is left is a permanent, static chromatic aberration —
   a hair of red on one edge, cold cyan on the other, as though
   the lens never quite resolved it. Nothing repaints. Nothing
   pulses. It costs precisely one text-shadow.

   The SIGIL still glitches. The name simply sits beside it,
   very slightly out of register.
   ═══════════════════════════════════════════════════════════ */

.brand-name {
  animation: none !important;
  transform: none;

  text-shadow:
    /* the aberration — the whole point */
    1.2px 0 0 rgba(190, 24, 18, .42),
    -1.2px 0 0 rgba(46, 198, 208, .30),

    /* and the dark it sits on, so the hairlines still read */
    0 2px 10px rgba(0, 0, 0, 1),
    0 0 22px rgba(0, 0, 0, .9),
    0 0 34px rgba(138, 58, 34, .26);
}

/* the words keep their seat against the mark */
.brand-words {
  transform: translateY(3px);
}

/* under the hand the lens focuses: the split closes, the red warms */
.brand:hover .brand-name,
.brand:focus-visible .brand-name {
  animation: none !important;
  transform: none;
  text-shadow:
    .5px 0 0 rgba(190, 24, 18, .30),
    -.5px 0 0 rgba(46, 198, 208, .20),
    0 2px 10px rgba(0, 0, 0, 1),
    0 0 30px rgba(138, 58, 34, .45);
  transition: text-shadow .5s ease;
}

/* ═══════════════════════════════════════════════════════════
   "DARE"

   One word, in old blood. The rest of the line keeps its bone
   white exactly as it was.

   The colour has to be forced: .prompt-text carries
   `color: ... !important` from an earlier pass, and a child
   inherits from it. Only an !important on the span beats an
   !important on the parent.

   And it needs its OWN shadow. The line's glow is violet-green
   — spill it under a red word and the red turns muddy brown.
   ═══════════════════════════════════════════════════════════ */

.prompt-text .dare {
  /* faded, dried, not fresh — old blood, not a warning label */
  color: #A24A34 !important;

  text-shadow:
    0 0 2px rgba(200, 120, 96, .45),
    0 2px 18px rgba(0, 0, 0, 1),
    0 0 30px rgba(150, 40, 26, .70),
    0 0 60px rgba(110, 26, 16, .40),
    0 0 100px rgba(0, 0, 0, .9) !important;
}

/* ═══════════════════════════════════════════════════════════
   THE BOOK ACTUALLY OPENS

   Until now the book flew at the camera, vanished, and a
   finished spread faded in behind it. Nothing opened. This is
   a real hinge:

     the front board swings on its SPINE
     the endpaper turns over as it passes 90°
     the page block beneath is revealed
     the whole book advances toward you
     and the readable spread takes over from underneath it

   ── ON PERFORMANCE ──
   `transform-style: preserve-3d` was banned from this book on
   purpose (there is a long comment about it further up): a 3D
   context can never be cached as a flat texture, so the book was
   being re-rendered every time the canvas beneath it repainted —
   thirty times a second, for nothing.

   That reasoning holds for the IDLE book. It does not hold for
   1.4 seconds of deliberate motion. So 3D is switched on ONLY
   while `book-opening` is on the body, and switched off again the
   moment it lands. The canvas is stopped for the same 1.4s, so
   nothing is invalidating the layer while it turns.

   ── ON QUALITY ──
   Nothing here is a raster except the cover photograph, and that
   is served with a `sizes` hint tuned to the OPEN size, so the
   browser fetches the big file up front and never upscales a
   small one. The pages, the endpaper, the gutter and every shadow
   are CSS — resolution-free, sharp at any scale.
   ═══════════════════════════════════════════════════════════ */

/* ── THE 3D CONTEXT: only while opening ── */
body.book-opening .book {
  transform-style: preserve-3d !important;
  perspective: 1600px;
  perspective-origin: 30% 50%;
  z-index: 40 !important;
}
body.book-opening .book-body {
  transform-style: preserve-3d !important;
  position: absolute;
  inset: 0;
}

/* ── THE PAGE BLOCK ── what lives under the cover ── */
.page-block {
  position: absolute;
  inset: 1.5% 1.5% 1.5% 2.5%;
  z-index: 1;
  border-radius: 1px 3px 3px 1px;
  opacity: 0;
  overflow: hidden;

  /* aged paper, drawn — never a texture to upscale */
  background:
    radial-gradient(ellipse 40% 30% at 82% 18%, rgba(120, 84, 36, .18), transparent 70%),
    radial-gradient(ellipse 30% 22% at 20% 78%, rgba(108, 74, 30, .16), transparent 72%),
    linear-gradient(100deg, #B8A987 0%, #D2C6A6 22%, #C6B896 60%, #A89876 100%);
  box-shadow:
    inset 0 0 40px -10px rgba(70, 50, 22, .55),
    inset 0 1px 0 rgba(255, 250, 232, .35);
}
body.book-opening .page-block { opacity: 1; }

/* the gutter: the dark valley where the pages meet the spine */
.page-gutter {
  position: absolute;
  top: 0; bottom: 0; left: 0;
  width: 16%;
  background: linear-gradient(to right,
    rgba(48, 34, 14, .72) 0%,
    rgba(70, 52, 24, .34) 34%,
    rgba(90, 70, 38, .10) 70%,
    transparent 100%);
}
/* the faint ruled block of writing, so the page is not blank */
.page-recto {
  position: absolute;
  inset: 12% 10% 14% 26%;
  background:
    repeating-linear-gradient(to bottom,
      rgba(58, 46, 32, .30) 0 1px,
      transparent 1px 7%);
  opacity: .5;
}

/* ── THE FRONT BOARD: the thing that swings ── */
.board-front {
  position: absolute;
  inset: 0;
  z-index: 3;
  transform-origin: left center;
  transform-style: preserve-3d;
  will-change: transform;
}

/* the two faces, back to back */
.cover-front,
.board-inner {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* the inside of the board — you only ever see it once the board
   has turned past ninety degrees */
.board-inner {
  transform: rotateY(180deg);
  border-radius: 5px 2px 2px 5px;
  overflow: hidden;
  background:
    radial-gradient(ellipse 60% 40% at 30% 24%, rgba(96, 40, 30, .30), transparent 72%),
    radial-gradient(ellipse 50% 36% at 74% 76%, rgba(70, 30, 24, .26), transparent 74%),
    linear-gradient(160deg, #6E4438 0%, #4E2C24 45%, #63382C 78%, #3E2018 100%);
  box-shadow:
    inset 0 0 50px -12px rgba(20, 8, 4, .8),
    inset 0 0 0 6px rgba(30, 14, 8, .5);
}
/* marbling on the endpaper, drawn in gradients */
.board-inner-plate {
  position: absolute;
  inset: 6%;
  border-radius: 1px;
  opacity: .5;
  background:
    repeating-linear-gradient(118deg,
      rgba(214, 176, 130, .16) 0 3px,
      transparent 3px 9px),
    repeating-linear-gradient(62deg,
      rgba(160, 96, 70, .12) 0 2px,
      transparent 2px 11px);
  box-shadow: inset 0 0 0 1px rgba(214, 176, 130, .22);
}

/* ── THE SWING ──
   Slow to break the seal, then it falls open under its own weight. */
body.book-opening .board-front {
  animation: board-swing 1.05s cubic-bezier(.42, 0, .22, 1) .1s forwards;
}
@keyframes board-swing {
  0%   { transform: rotateY(0deg); }
  18%  { transform: rotateY(-9deg); }      /* the seal breaks */
  100% { transform: rotateY(-174deg); }    /* not 180: a board never lies flat */
}

/* ── THE APPROACH ── the book comes to you as it opens ── */
@media (min-width: 761px) {
  body.book-opening .book {
    animation: book-open-desk 1.5s cubic-bezier(.24, .74, .28, 1) forwards;
  }
  @keyframes book-open-desk {
    0%   { transform: translate3d(-21vw, -14vh, 0) rotateX(2deg) scale(1.6);  opacity: 1; }
    40%  { transform: translate3d(-17vw, -10vh, 0) rotateX(1deg) scale(2.0);  opacity: 1; }
    78%  { transform: translate3d(-11vw,  -6vh, 0) rotateX(0deg) scale(2.5);  opacity: 1; }
    100% { transform: translate3d( -8vw,  -4vh, 0) rotateX(0deg) scale(2.75); opacity: 0; }
  }
}
@media (max-width: 760px) {
  body.book-opening .book {
    animation: book-open-phone 1.5s cubic-bezier(.24, .74, .28, 1) forwards;
  }
  @keyframes book-open-phone {
    0%   { transform: translate3d(-50%, -54%, 0) rotateX(2deg) scale(1.06); opacity: 1; }
    40%  { transform: translate3d(-46%, -54%, 0) rotateX(1deg) scale(1.24); opacity: 1; }
    78%  { transform: translate3d(-36%, -54%, 0) rotateX(0deg) scale(1.42); opacity: 1; }
    100% { transform: translate3d(-30%, -54%, 0) rotateX(0deg) scale(1.55); opacity: 0; }
  }
}

/* ── THE ROOM STAYS ──
   The book lives INSIDE the tavern. The old rule killed the tavern
   the instant `state-open` landed — which would have cut the head
   off this animation. The room now survives until the book is done
   turning, and only then goes. */
body.state-open:not(.book-gone) .tavern {
  display: block !important;
  opacity: 1 !important;
  filter: none !important;
  transform: none !important;
}
body.state-open:not(.book-gone) .dustfield { display: none; }
body.book-gone .book { display: none; }

/* ── THE HAND-OFF ──
   The spread rises out of the opening book rather than fading in
   over a corpse. It starts small and close to the book's final size
   and settles — so the motion CONTINUES instead of restarting. */
body.state-open .grimoire {
  transition: opacity .55s ease, visibility 0s linear 0s;
}
body.state-open .spread {
  transition:
    transform .85s cubic-bezier(.2, .78, .26, 1),
    opacity .5s ease;
}
/* the book sits back and small BEFORE it opens... */
body:not(.state-open) .grimoire .spread {
  transform: rotateX(6deg) scale(.72);
}
/* ...and comes fully forward once it has. This rule was missing, which is why
   the spread was stuck at 72% however large its CSS said it was. */
body.state-open .grimoire .spread {
  transform: rotateX(1deg) scale(1);
}

/* the shine sweeps once across the cover as the board turns —
   the only time this book is allowed to look glossy */
body.book-opening .cover-shine {
  display: block !important;
  opacity: .5;
  background: linear-gradient(104deg,
    transparent 30%,
    rgba(255, 248, 232, .16) 46%,
    rgba(255, 248, 232, .34) 52%,
    transparent 68%);
  animation: none;
}

@media (prefers-reduced-motion: reduce) {
  body.book-opening .book,
  body.book-opening .board-front { animation: none; }
  body.book-opening .book { opacity: 0; }
}

/* ═══════════════════════════════════════════════════════════
   THE IDLE BOOK STAYS FLAT

   I gave .board-front a permanent `transform-style: preserve-3d`
   two blocks up — which would quietly undo the whole reason this
   book was flattened in the first place. A 3D subtree cannot be
   cached as a texture, so the idle book would be re-rendered
   every time the canvas beneath it repainted. That was the 39fps
   bug, and I am not paying it again for a hinge that is used for
   1.4 seconds.

   So: flat at rest, 3D only while turning. The endpaper is not
   even in the render tree until the board starts to move.
   ═══════════════════════════════════════════════════════════ */

.board-front {
  transform-style: flat;
}
.board-inner {
  display: none;
}

body.book-opening .board-front {
  transform-style: preserve-3d !important;
}
body.book-opening .board-inner {
  display: block;
}

/* the page block is also inert until it is needed */
.page-block {
  display: none;
}
body.book-opening .page-block {
  display: block;
}

/* ═══════════════════════════════════════════════════════════
   THE OPENING, MADE CHEAP

   The turn was janky for three reasons, all fixable without
   touching a single pixel of quality:

   1. RASTER SIZE.  The book grew to 2.75x. Chrome rasterises an
      animated layer at the animation's MAXIMUM scale — so it was
      building a ~2000x3000px texture of the cover, its border,
      and four blurred box-shadows, on the first frame. Dropping
      the peak to 2.2x nearly halves that (scale is squared), and
      the book is already fading out by then anyway.

   2. EVERYTHING ELSE KEPT MOVING.  Embers, runes, sparks, the
      glitching sigil, the fog behind the pages — twenty-three
      animations, all compositing against a turning 3D layer.
      During the turn there is exactly one thing worth looking at.
      Everything else stops.

   3. THE SHADOWS.  A box-shadow on a scaling element is re-blurred
      whenever the raster scale changes. The cover carried four.
      While it turns it carries one flat one.

   The turn is also 250ms shorter. It was luxuriating.
   ═══════════════════════════════════════════════════════════ */

/* ── 1. A SMALLER PEAK, AND PROMOTED LAYERS ── */
@media (min-width: 761px) {
  @keyframes book-open-desk {
    0%   { transform: translate3d(-21vw, -14vh, 0) rotateX(2deg) scale(1.6);  opacity: 1; }
    42%  { transform: translate3d(-17vw, -10vh, 0) rotateX(1deg) scale(1.85); opacity: 1; }
    80%  { transform: translate3d(-11vw,  -6vh, 0) rotateX(0deg) scale(2.1);  opacity: 1; }
    100% { transform: translate3d( -8vw,  -4vh, 0) rotateX(0deg) scale(2.2);  opacity: 0; }
  }
  body.book-opening .book { animation-duration: 1.25s; }
}
@media (max-width: 760px) {
  @keyframes book-open-phone {
    0%   { transform: translate3d(-50%, -54%, 0) rotateX(2deg) scale(1.06); opacity: 1; }
    42%  { transform: translate3d(-46%, -54%, 0) rotateX(1deg) scale(1.20); opacity: 1; }
    80%  { transform: translate3d(-36%, -54%, 0) rotateX(0deg) scale(1.34); opacity: 1; }
    100% { transform: translate3d(-30%, -54%, 0) rotateX(0deg) scale(1.42); opacity: 0; }
  }
  body.book-opening .book { animation-duration: 1.25s; }
}
body.book-opening .board-front { animation-duration: .9s; }

/* every face is its own cached texture, and the GPU only blends them */
body.book-opening .board-front,
body.book-opening .cover-front,
body.book-opening .board-inner,
body.book-opening .page-block {
  will-change: transform;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  contain: paint;
}

/* ── 2. THE ROOM HOLDS ITS BREATH ──
   Nothing else moves while the board turns. */
body.book-opening .embers,
body.book-opening .script,
body.book-opening .glitter,
body.book-opening .book-embers,
body.book-opening .beckon,
body.book-opening .grain,
body.book-opening .plate-grade {
  display: none !important;
}
body.book-opening .brand-mark img,
body.book-opening .brand-name,
body.book-opening .prompt-text,
body.book-opening .opening-line,
body.book-opening .mk-ring,
body.book-opening .mk-ring-2,
body.book-opening .mk-eye {
  animation: none !important;
}

/* the fog behind the pages must not start drifting DURING the
   hand-off — two full-screen animated layers arriving on the same
   frame as a 3D turn is the worst moment to ask for them.
   They begin once the book has landed. */
body.book-opening .grimoire::before,
body.book-opening .grimoire::after {
  animation: none !important;
  opacity: 0;
}

/* ── 3. NO BLURRED SHADOWS ON A SCALING FACE ── */
body.book-opening .cover-front {
  box-shadow: 0 18px 40px rgba(0, 0, 0, .85) !important;
}
/* the sheen was one more layer for nothing */
body.book-opening .cover-shine {
  display: none !important;
}

/* ── AND THE HAND-OFF SHORTENS TO MATCH ── */
body.state-open .spread {
  transition:
    transform .7s cubic-bezier(.2, .78, .26, 1),
    opacity .42s ease;
}
body.state-open .grimoire {
  transition: opacity .45s ease, visibility 0s linear 0s;
}

/* ═══════════════════════════════════════════════════════════
   THE QUESTION RETIRES WHEN IT IS ANSWERED

   The prompt was only ever dismissed by `state-open` — which,
   before the book learned to open, landed on the same frame as
   the click. It no longer does: `state-open` now arrives 640ms
   in, once the board is most of the way over.

   So for the first two thirds of the turn the question was still
   sitting on the screen, on top of the book, with its pulse frozen
   (I had stopped every animation during the turn). That is the
   "broken" text.

   The question is answered the instant the book is touched. It
   goes then — and takes the warning, the opening line and the
   masthead with it.
   ═══════════════════════════════════════════════════════════ */

body.book-opening .prompt {
  opacity: 0 !important;
  transform: translateX(-50%) translateY(-14px);
  transition: opacity .32s ease, transform .32s ease;
  pointer-events: none;
}

body.book-opening .prompt-epigraph {
  opacity: 0 !important;
  transition: opacity .28s ease;
}

body.book-opening .opening {
  opacity: 0 !important;
  transform: translateY(-18px);
  transition: opacity .3s ease, transform .3s ease;
}

body.book-opening .masthead {
  opacity: 0 !important;
  transform: translateY(-16px);
  transition: opacity .4s ease, transform .5s ease;
  pointer-events: none;
}

/* on the phone the question is fixed to the viewport and carries a
   higher-specificity `body.book-summoned .prompt { opacity: 1 }`
   from the mobile block — which would hold it on screen. Beaten here. */
@media (max-width: 760px) {
  body.book-opening.book-summoned .prompt,
  body.book-opening .prompt {
    opacity: 0 !important;
    transform: translateX(-50%) translateY(-14px);
  }
  body.book-opening.book-summoned .prompt-epigraph {
    opacity: 0 !important;
  }
}

/* ═══════════════════════════════════════════════════════════
   THE SCROLL IS REAL PAPER NOW

   The vellum was a stack of CSS gradients pretending to be
   stained parchment. It is now a photograph of the actual sheet
   — witch, cauldron, foxing, water-marks and all.

   Three things had to change with it:

   1. THE FAKE STAINS GO. Painted stains under a photographed
      stain is mud. The sheet carries its own dirt.

   2. THE HEAD OF THE TEXT MOVES DOWN. The woodcut witch sits in
      the top-left corner of the paper. Text laid over her looks
      like a mistake; text set BELOW her looks like an illuminated
      header. So the writing starts beneath the block she occupies.

   3. THE SHEET IS BIGGER. A scroll this detailed cannot be read
      at 430px. It grows, and the paper is cropped to the panel's
      exact shape so the witch and the cauldron are never lost.
   ═══════════════════════════════════════════════════════════ */

.scroll {
  width: clamp(330px, 34vw, 520px);
}

.vellum {
  /* the real sheet */
  background-image:
    image-set(url('../media/scroll-paper-1200.webp') type('image/webp'),
              url('../media/scroll-paper-1200.jpg')  type('image/jpeg'));
  background-image:
    -webkit-image-set(url('../media/scroll-paper-1200.webp') 1x);
  background-image: url('../media/scroll-paper-1200.webp');
  background-size: cover;
  background-position: left top;
  background-repeat: no-repeat;
  background-color: #CFC3A5;         /* until it loads */

  /* the paper is dirty enough on its own */
  box-shadow:
    inset 0 10px 22px -12px rgba(60, 42, 16, .45),
    inset 0 -12px 24px -12px rgba(60, 42, 16, .40),
    0 26px 54px rgba(0, 0, 0, .82),
    0 6px 16px rgba(0, 0, 0, .55);
}
body.scroll-open .vellum {
  max-height: min(80vh, 880px);
}

/* the painted grain and the painted stains are gone — they were
   fighting the photograph */
.vellum::before {
  display: none;
}

/* what stays: the curl. Light gathers at the edges of a sheet that
   is not lying flat, and a shadow falls where it meets the rod. */
.vellum::after {
  background:
    linear-gradient(to right,
      rgba(255, 252, 240, .26) 0%, transparent 4%,
      transparent 96%, rgba(255, 252, 240, .18) 100%),
    linear-gradient(to bottom,
      rgba(58, 40, 16, .34) 0%, rgba(58, 40, 16, .10) 3%, transparent 8%),
    linear-gradient(to top,
      rgba(58, 40, 16, .20) 0%, transparent 6%);
}

/* ── THE WRITING CLEARS THE WOODCUT ──
   She occupies roughly the top 16% of the sheet, on the left. */
.vellum-inner {
  padding:
    clamp(4.6rem, 15%, 7.4rem)      /* below the witch */
    clamp(1.7rem, 3vw, 2.6rem)
    2.8rem;
  max-height: min(80vh, 880px);
}

/* the type can breathe on a bigger sheet */
.scroll-name   { font-size: clamp(2.3rem, 4vw, 3.1rem); }
.scroll-text   { font-size: clamp(.95rem, 1.1vw, 1.08rem); line-height: 1.66; }
.likeness      { width: 42%; }
.scroll-eyebrow{ font-size: .58rem; }

/* the seal sits low, near the painted cauldron rather than on it */
.wax {
  width: 42px;
  margin-top: 1.2rem;
  margin-right: 12%;
  margin-left: auto;
}

/* the torn foot was drawn to finish a gradient. The photograph has
   its own edge. */
.vellum-tear { display: none; }

@media (max-width: 760px) {
  .scroll {
    width: min(92vw, 440px);
  }
  body.scroll-open .vellum,
  .vellum-inner {
    max-height: min(74vh, 700px);
  }
  .vellum-inner {
    padding: clamp(4rem, 14%, 6rem) 1.5rem 2.4rem;
  }
  .likeness { width: 45%; }
}

/* ═══════════════════════════════════════════════════════════
   THE CHAPTERS

   The book now has text in it. This is how it is set: like a
   book, not like a web page. Measure, rag, indents, a standfirst,
   an aside in the margin voice — and nothing that looks like a
   blog post.
   ═══════════════════════════════════════════════════════════ */

.chap-title {
  font-family: var(--display, 'UnifrakturMaguntia'), serif;
  font-weight: 400;
  font-size: clamp(2.4rem, 5.2vh, 3.6rem);
  line-height: .98;
  text-align: center;
  margin: 0 0 1rem;
  color: var(--iron-gall, #2A2018);
}
.chap-title::first-letter { color: var(--rubric, #6E2113); }

.chap-head {
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-weight: 600;
  font-size: clamp(1.35rem, 2.6vh, 1.75rem);
  line-height: 1.2;
  margin: 0 0 .9rem;
  color: var(--iron-gall, #2A2018);
}

.chap-standfirst {
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  font-size: clamp(1.02rem, 2vh, 1.2rem);
  line-height: 1.55;
  text-align: center;
  color: var(--iron-faded, #574835);
  margin: 0 0 1rem;
}

/* the body of the page */
.page-inner p {
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-size: clamp(.98rem, 1.95vh, 1.12rem);
  line-height: 1.62;
  color: #3A2E20;
  margin: 0 0 .72rem;
  text-align: justify;
  hyphens: auto;
}
/* the first line of a paragraph following another is indented, as
   in a printed book — no blank-line-and-flush-left web habit */
.page-inner .chap-head + p,
.page-inner .chap-standfirst + p,
.page-inner .page-orn + p { text-indent: 0; }
.page-inner p + p { text-indent: 1.3em; margin-top: -.2rem; }

.page-inner strong { font-weight: 600; color: #2A2018; }
.page-inner em     { font-style: italic; }

/* the marginal voice: her own, set apart */
.chap-note {
  margin: 1rem 0 0 !important;
  padding: .7rem 0 0;
  border-top: 1px solid rgba(87, 72, 53, .22);
  font-style: italic;
  font-size: clamp(.9rem, 1.8vh, 1.02rem) !important;
  line-height: 1.5 !important;
  color: var(--iron-faded, #574835) !important;
  text-align: left !important;
  text-indent: 0 !important;
}

/* the bibliography */
.chap-sources {
  list-style: none;
  margin: 0;
  padding: 0;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-size: clamp(.88rem, 1.7vh, .98rem);
  line-height: 1.45;
  color: #3A2E20;
}
.chap-sources li {
  padding: .42rem 0 .42rem .9rem;
  border-bottom: 1px solid rgba(87, 72, 53, .14);
  text-indent: -.9rem;
}
.chap-sources li:last-child { border-bottom: 0; }

/* a chapter that ends on an odd page leaves a blank verso, as books do */
.page-blank {
  display: grid;
  place-items: center;
  height: 100%;
  font-size: 1.6rem;
  color: var(--iron-faded, #574835);
  opacity: .25;
  text-align: center !important;
  text-indent: 0 !important;
}

/* ═══════════════════════════════════════════════════════════
   THE PAGE BAR, ON EVERY DEVICE

   It was built for the phone and hidden on the desktop, back
   when the desktop had exactly two pages and nowhere to go.
   There are thirteen now.
   ═══════════════════════════════════════════════════════════ */
@media (min-width: 761px) {
  .leafbar {
    display: flex;
    position: fixed;
    left: 50%;
    bottom: 1.15rem;
    transform: translateX(-50%);
    z-index: 70;

    align-items: center;
    gap: .3rem;
    padding: .28rem .38rem;

    background: rgba(24, 17, 11, .82);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    border: 1px solid rgba(138, 110, 59, .34);
    border-radius: 999px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, .6);

    opacity: 0;
    transition: opacity .7s ease 1.4s;
  }
  body.state-open .leafbar { opacity: 1; }

  .leaf-turn {
    width: 34px; height: 34px;
    display: grid; place-items: center;
    padding: 0; background: none; border: 0; border-radius: 50%;
    color: #D8CBAC; cursor: pointer;
    transition: background .25s, color .25s, opacity .25s;
  }
  .leaf-turn svg { width: 12px; height: 12px; }
  .leaf-turn:hover { background: rgba(110, 33, 19, .5); color: #FFF2DA; }
  .leaf-turn:disabled { opacity: .22; pointer-events: none; }
  .leaf-turn[hidden] { display: none; }

  .leaf-count {
    min-width: 5.4rem;
    text-align: center;
    font-family: 'Spectral SC', Georgia, serif;
    font-size: .58rem;
    letter-spacing: .16em;
    color: #C9BFA6;
    opacity: .82;
  }

  /* the close line moves aside for the bar */
  .close-book { bottom: 3.6rem; }
}

/* the home button is a little warmer than the arrows — it goes back */
.leaf-home { color: #C99A6E; }
.leaf-home:hover { background: rgba(110, 33, 19, .55); }

/* the dog-ear belongs to the front matter only; in a chapter the
   page bar is doing that job */
body.in-chapter .dogear { display: none; }

/* ═══════════════════════════════════════════════════════════
   THE GRIMOIRE VOICE

   Three devices, and no more. A page that needs a fourth is a
   page that is trying too hard.

     .drop   the rubric capital — the red letter a scribe drew
             first, before the black
     .lore   the told thing: a charm, a folk fragment, a working.
             Set apart on tinted paper, the way a real book keeps
             its recipes distinct from its argument
     .chap-note  her own hand, in the margin
   ═══════════════════════════════════════════════════════════ */

/* ── THE RUBRIC CAPITAL ── */
.drop {
  float: left;
  margin: .06em .12em -.06em 0;
  font-family: var(--display, 'UnifrakturMaguntia'), serif;
  font-weight: 400;
  font-size: 3.4em;
  line-height: .78;
  color: var(--rubric, #6E2113);
  text-shadow: 0 1px 0 rgba(255, 250, 235, .5);
}
/* the line beside a rubric capital is never indented */
.page-inner p:has(.drop) { text-indent: 0 !important; }

/* ── THE LORE PANEL ── */
.lore {
  position: relative;
  margin: 1rem 0;
  padding: .9rem 1rem .8rem 1.9rem;

  /* older paper than the page it sits on, and a little dirtier */
  background:
    radial-gradient(ellipse 60% 40% at 84% 16%, rgba(122, 88, 40, .10), transparent 70%),
    linear-gradient(178deg, rgba(160, 132, 84, .16), rgba(140, 112, 66, .10));
  border-top: 1px solid rgba(110, 33, 19, .25);
  border-bottom: 1px solid rgba(110, 33, 19, .25);
  box-shadow: inset 0 0 22px -8px rgba(80, 56, 22, .35);
}
.lore p {
  margin: 0 0 .5rem !important;
  text-indent: 0 !important;
  text-align: left !important;
  font-size: clamp(.94rem, 1.85vh, 1.05rem) !important;
  line-height: 1.55 !important;
  color: #3E3122 !important;
}
.lore p:last-child { margin-bottom: 0 !important; }

/* the star in the gutter of the panel */
.lore-mark {
  position: absolute;
  top: .78rem;
  left: .6rem;
  font-size: .8rem;
  line-height: 1;
  color: var(--rubric, #6E2113);
  opacity: .75;
}

/* the line that is spoken rather than instructed */
.lore-said {
  font-style: italic;
  color: var(--iron-faded, #574835) !important;
  padding-top: .35rem;
  border-top: 1px solid rgba(110, 33, 19, .16);
}

/* ── SHORTER PAGES BREATHE ── */
.chap-head { margin-bottom: .8rem; }
.page-inner p { margin-bottom: .62rem; }

@media (max-width: 760px) {
  .drop { font-size: 3rem; }
  .lore { padding: .85rem .9rem .75rem 1.7rem; }
}

/* ═══════════════════════════════════════════════════════════
   A BIGGER BOOK

   The spread was capped at 1240 x 800. On a 1920 monitor that is
   a paperback held at arm's length — and there are pictures
   coming, which a paperback cannot carry.

   It now takes the screen it is given: up to 1800px wide and
   1180 tall, stopping only where the page bar begins. The type
   grows with it, or a bigger book is just a bigger margin.
   ═══════════════════════════════════════════════════════════ */

@media (min-width: 761px) {

  .grimoire {
    padding:
      clamp(.6rem, 1.6vh, 1.4rem)
      clamp(.8rem, 2vw, 2rem)
      4.8rem;                       /* room for the page bar */
  }

  .grimoire .spread {
    width: min(1800px, 97vw);
    height: min(1180px, 88vh);
    max-width: none;
  }

  /* the leather boards grow with the block they hold */
  .spread::before {
    inset: -22px -26px -26px -26px;
    border-radius: 6px;
  }

  /* ── THE READING COLUMN ──
     More room, but the MEASURE is held: a line of text longer than
     about 75 characters is harder to read, not easier. The extra
     width goes into margin and picture, not into longer lines. */
  .page-inner {
    padding: clamp(2.4rem, 4.6vh, 4rem) clamp(2rem, 3.6vw, 4.2rem);
  }

  /* ── THE TYPE, SCALED UP WITH THE PAGE ── */
  .page-inner p {
    font-size: clamp(1.08rem, 1.35vw, 1.34rem);
    line-height: 1.68;
    margin-bottom: .78rem;
    max-width: 40em;                /* the measure */
  }

  .chap-title      { font-size: clamp(3rem, 5.4vw, 4.6rem); }
  .chap-head       { font-size: clamp(1.7rem, 2.3vw, 2.4rem); margin-bottom: 1rem; }
  .chap-standfirst { font-size: clamp(1.2rem, 1.5vw, 1.5rem); }
  .folio-eyebrow   { font-size: .68rem; letter-spacing: .38em; }

  .drop { font-size: 3.6em; }

  .lore {
    margin: 1.3rem 0;
    padding: 1.15rem 1.3rem 1rem 2.3rem;
  }
  .lore p {
    font-size: clamp(1.02rem, 1.28vw, 1.26rem) !important;
    line-height: 1.6 !important;
  }
  .lore-mark { top: 1rem; left: .85rem; font-size: .95rem; }

  .chap-note {
    font-size: clamp(1rem, 1.24vw, 1.22rem) !important;
    line-height: 1.58 !important;
    margin-top: 1.2rem !important;
    padding-top: .9rem;
  }

  .chap-sources    { font-size: clamp(.98rem, 1.16vw, 1.14rem); line-height: 1.5; }
  .chap-sources li { padding: .5rem 0 .5rem 1rem; text-indent: -1rem; }

  /* the front matter grows too, or the first spread looks orphaned */
  .grim-title     { font-size: clamp(3.2rem, 6.4vh, 5.2rem); }
  .grim-sub       { font-size: clamp(1.05rem, 1.3vw, 1.32rem); }
  .grim-note      { font-size: clamp(1.05rem, 1.3vw, 1.28rem); max-width: 32rem; }
  .contents-head  { font-size: clamp(2.4rem, 5vh, 3.8rem); }
  .entry-name     { font-size: clamp(1.15rem, 1.4vw, 1.45rem); }
  .entry-gloss    { font-size: clamp(.9rem, 1.05vw, 1.08rem); }
  .contents a     { padding: clamp(.7rem, 1.5vh, 1.05rem) .35rem; }
  .illum          { width: clamp(140px, 16vh, 210px); }
}

/* ── THE PHONE READS BIGGER TOO ── */
@media (max-width: 760px) {
  .page-inner p        { font-size: clamp(1.06rem, 4.3vw, 1.22rem); line-height: 1.66; }
  .lore p              { font-size: clamp(1rem, 4.1vw, 1.16rem) !important; }
  .chap-note           { font-size: clamp(1rem, 4vw, 1.14rem) !important; }
  .chap-head           { font-size: clamp(1.5rem, 6.4vw, 1.9rem); }
  .chap-standfirst     { font-size: clamp(1.1rem, 4.6vw, 1.3rem); }
  .chap-sources        { font-size: clamp(.96rem, 3.9vw, 1.08rem); }
  .drop                { font-size: 3.2em; }
}

/* ═══════════════════════════════════════════════════════════
   THE CONTROLS — BIGGER, AND IN THE RIGHT ORDER

   They were stacked tight and the wrong way round: the CLOSE
   button sat between the book and its own page bar, so the thing
   you use constantly (turning pages) was pushed further from the
   book than the thing you use once (leaving it).

   Reversed. Nearest the book: the page bar — arrows and Contents.
   Beneath it, held apart, the way out.
   ═══════════════════════════════════════════════════════════ */

@media (min-width: 761px) {

  /* the book leaves room for both, stacked and separated */
  .grimoire { padding-bottom: 8.8rem; }

  /* ── NEAREST THE BOOK: turning pages ── */
  .leafbar {
    bottom: 5.1rem;
    gap: .45rem;
    padding: .42rem .55rem;
    border-radius: 999px;
    background: rgba(26, 18, 12, .9);
    border: 1px solid rgba(138, 110, 59, .42);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .65);
  }

  .leaf-turn {
    width: 46px;
    height: 46px;
  }
  .leaf-turn svg { width: 16px; height: 16px; }

  .leaf-count {
    min-width: 7.5rem;
    padding: 0 .5rem;
    font-size: .72rem;
    letter-spacing: .2em;
    color: #DCD0B4;
    opacity: .95;
  }

  /* ── BENEATH, AND APART: the way out ── */
  .close-book {
    bottom: 1.15rem;
    padding: .78rem 1.9rem;
    min-height: 46px;
    font-size: .68rem;
    letter-spacing: .3em;
    border: 1px solid rgba(138, 110, 59, .42);
    border-radius: 999px;
    background: rgba(26, 18, 12, .82);
    color: #C9BFA6;
    transition: color .3s, border-color .3s, background .3s, opacity .5s;
  }
  .close-book:hover,
  .close-book:focus-visible {
    color: #F2E6CC;
    border-color: rgba(147, 56, 31, .8);
    background: rgba(92, 31, 20, .55);
  }
}

/* ── THE PHONE: same order, same generosity ── */
@media (max-width: 760px) {
  .leafbar {
    bottom: calc(env(safe-area-inset-bottom, 0px) + 1rem);
    gap: .45rem;
    padding: .4rem .5rem;
  }
  .leaf-turn { width: 48px; height: 48px; }
  .leaf-turn svg { width: 15px; height: 15px; }
  .leaf-count {
    min-width: 5.4rem;
    font-size: .66rem;
    letter-spacing: .18em;
  }
  /* the close pill stays out of the way, up in the corner */
  .close-book {
    padding: .7rem 1.15rem;
    min-height: 46px;
    font-size: .66rem;
  }
  /* the reading column clears the bigger bar */
  .grimoire .page-inner {
    padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 6.2rem);
  }
}

/* ═══════════════════════════════════════════════════════════
   THE CORNERS

   A real book is turned by its corner, not by a button. So each
   outer edge of the spread carries an invisible strip. Reach into
   it and the corner of the page LIFTS — you see its underside,
   and a shadow falls where it has peeled away from the sheet.
   Click, and it turns.

   Both pages have one: the right corner goes forward, the left
   goes back. They retire at the ends of the book, because a book
   does not offer you a page that is not there.

   Everything animates width/height/opacity on a small element in
   the corner of the screen. It is not a filter and it is not a
   3D context. It costs nothing.
   ═══════════════════════════════════════════════════════════ */

.turn-zone {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 15%;
  min-width: 90px;
  max-width: 200px;
  z-index: 9;

  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.turn-next { right: 0; }
.turn-prev { left: 0; }

/* at the ends of the book there is nothing to reach for */
.turn-zone:disabled {
  cursor: default;
  pointer-events: none;
}
.turn-zone:disabled .corner { opacity: 0 !important; }

/* ── THE CORNER ITSELF ── */
.corner {
  position: absolute;
  bottom: 0;
  width: 34px;
  height: 34px;
  pointer-events: none;

  /* it is faintly there at rest — a book you can see is turnable */
  opacity: .30;
  transition:
    width .5s cubic-bezier(.2, .8, .25, 1),
    height .5s cubic-bezier(.2, .8, .25, 1),
    opacity .35s ease;
}
.turn-next .corner { right: 0; }
.turn-prev .corner { left: 0; }

/* reach for it, and the page lifts */
.turn-zone:hover .corner,
.turn-zone:focus-visible .corner {
  width: 132px;
  height: 132px;
  opacity: 1;
}
/* press it, and it goes further */
.turn-zone:active .corner {
  width: 158px;
  height: 158px;
  transition-duration: .18s;
}

/* the underside of the page — a different, older paper */
.corner-leaf {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(315deg,
      #E8DEC2 0%,
      #D6C9A8 34%,
      #BCAC88 72%,
      #9E8E6C 100%);
  box-shadow: inset -1px 1px 2px rgba(255, 250, 235, .5);
}
.turn-next .corner-leaf {
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
}
.turn-prev .corner-leaf {
  clip-path: polygon(0 0, 100% 100%, 0 100%);
  background:
    linear-gradient(45deg,
      #E8DEC2 0%,
      #D6C9A8 34%,
      #BCAC88 72%,
      #9E8E6C 100%);
}

/* the shadow the lifted corner throws on the page beneath it */
.corner-shadow {
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 100% 100%,
    rgba(40, 28, 10, .5) 0%,
    rgba(40, 28, 10, .22) 42%,
    transparent 72%);
  filter: blur(2px);
}
.turn-prev .corner-shadow {
  background: radial-gradient(ellipse at 0% 100%,
    rgba(40, 28, 10, .5) 0%,
    rgba(40, 28, 10, .22) 42%,
    transparent 72%);
}

/* the crease — the diagonal where the paper has folded */
.corner-crease {
  position: absolute;
  inset: 0;
  background: linear-gradient(315deg,
    transparent calc(50% - 1px),
    rgba(120, 96, 54, .55) 50%,
    transparent calc(50% + 1px));
}
.turn-prev .corner-crease {
  background: linear-gradient(45deg,
    transparent calc(50% - 1px),
    rgba(120, 96, 54, .55) 50%,
    transparent calc(50% + 1px));
}

/* the old single dog-ear is superseded — every page has corners now */
.dogear { display: none !important; }

/* ── PHONE ──
   No cursor, so nothing to hover. The corners would only sit under
   the thumb and fight the scroll. Swipe already turns the page. */
@media (max-width: 760px) {
  .turn-zone { display: none; }
}

/* ═══════════════════════════════════════════════════════════
   THE BOOK PLATES

   NB: the class is .bookplate, NOT .plate — the tavern background
   already owns .plate, and naming the figures the same thing told the
   PAINTING to float right at 44% width. That is what broke the room.

   Pictures in a book are not decoration bolted to the side of
   the text — they are pinned into it, and the words go round
   them. So: a plate floats to the outer margin, the paragraphs
   wrap, and a caption sits beneath it in the small hand.

   And until the picture exists, the plate shows an EMPTY FRAME
   naming what belongs there — the way an engraver leaves a
   window for a block that has not been cut yet. Drop the file in
   and it fills. Nothing breaks in the meantime.
   ═══════════════════════════════════════════════════════════ */

.bookplate {
  margin: .3rem 0 .9rem 1.4rem;
  padding: 0;
  float: right;
  width: 44%;
  max-width: 320px;
  clear: right;
}
.bookplate-full {
  float: none;
  width: 100%;
  max-width: none;
  margin: 1rem 0 1.2rem;
}

.bookplate img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 1px;

  /* an old plate, foxed and yellowed into the page */
  filter: sepia(.34) contrast(1.06) brightness(.97) saturate(.82);
  box-shadow:
    0 3px 12px rgba(46, 32, 12, .42),
    0 0 0 1px rgba(90, 72, 42, .5),
    0 0 0 6px rgba(214, 200, 168, .35);
}

.bookplate figcaption {
  margin-top: .7rem;
  padding-left: .2rem;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  font-size: clamp(.82rem, .95vw, .96rem);
  line-height: 1.4;
  color: var(--iron-faded, #574835);
  text-align: left;
  border-left: 2px solid rgba(110, 33, 19, .35);
  padding-left: .6rem;
}

/* ── THE WINDOW LEFT FOR A BLOCK NOT YET CUT ── */
.bookplate.is-empty img { display: none; }
.bookplate.is-empty::before {
  content: '';
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  border-radius: 1px;

  background:
    repeating-linear-gradient(-45deg,
      rgba(120, 96, 54, .10) 0 7px,
      transparent 7px 14px),
    linear-gradient(160deg, rgba(190, 176, 142, .5), rgba(160, 144, 108, .45));
  box-shadow:
    inset 0 0 0 1px rgba(110, 92, 60, .5),
    inset 0 0 30px -8px rgba(70, 52, 22, .45);
}
.bookplate.is-empty figcaption::after {
  content: ' — plate wanting';
  font-style: normal;
  font-family: 'Spectral SC', Georgia, serif;
  font-size: .58rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--rubric, #6E2113);
  opacity: .7;
}

/* ── THE FORK IN THE ROAD ──
   The line that hands the reader to another chapter. */
.chap-turn {
  clear: both;
  margin: 1.1rem 0 0 !important;
  padding: .85rem 1rem;
  text-indent: 0 !important;
  text-align: center !important;

  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  font-size: clamp(1.02rem, 1.2vw, 1.2rem) !important;
  line-height: 1.5 !important;
  color: #43301F !important;

  background: linear-gradient(180deg,
    rgba(110, 33, 19, .09), rgba(110, 33, 19, .04));
  border-top: 1px solid rgba(110, 33, 19, .35);
  border-bottom: 1px solid rgba(110, 33, 19, .35);
}
.chap-turn strong {
  font-style: normal;
  color: var(--rubric, #6E2113) !important;
  letter-spacing: .04em;
}

/* the lore panel and the note must never sit under a floated plate */
.lore, .chap-note { clear: both; }

@media (max-width: 760px) {
  .bookplate {
    float: none;
    width: 100%;
    max-width: none;
    margin: .9rem 0 1rem;
  }
}

/* ═══════════════════════════════════════════════════════════
   THE VERSE

   When the book quotes the old tongue it does not paraphrase it
   into a paragraph. It sets it as VERSE — broken where the poet
   broke it, in the language he broke it in — and puts the English
   beneath in a smaller, quieter hand, where a translation belongs.

   The Old Norse is 13th-century. It belongs to nobody now, which
   is the only reason we are allowed to look at it.
   ═══════════════════════════════════════════════════════════ */

.verse {
  clear: both;
  margin: 1.1rem 0;
  padding: 1rem 1.2rem .9rem;

  background: linear-gradient(180deg,
    rgba(150, 122, 70, .12),
    rgba(150, 122, 70, .05));
  border-left: 3px solid rgba(110, 33, 19, .55);
  box-shadow: inset 0 0 26px -10px rgba(80, 56, 22, .4);
}

/* the old tongue */
.verse p[lang="non"] {
  margin: 0 0 .7rem !important;
  text-indent: 0 !important;
  text-align: left !important;

  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  font-size: clamp(1.06rem, 1.3vw, 1.28rem) !important;
  line-height: 1.55 !important;
  color: #3A2A18 !important;
  letter-spacing: .01em;
}
.verse p[lang="non"] strong {
  font-style: italic;
  font-weight: 600;
  color: var(--rubric, #6E2113) !important;
}

/* the English, beneath, and quieter — as a translation should be */
.verse .verse-en {
  margin: 0 0 .6rem !important;
  padding-top: .6rem;
  text-indent: 0 !important;
  text-align: left !important;
  border-top: 1px solid rgba(110, 33, 19, .2);

  font-size: clamp(.94rem, 1.1vw, 1.08rem) !important;
  line-height: 1.5 !important;
  color: var(--iron-faded, #574835) !important;
}
.verse .verse-en strong {
  color: #3A2A18 !important;
  font-weight: 600;
}

.verse cite {
  display: block;
  font-family: 'Spectral SC', Georgia, serif;
  font-style: normal;
  font-size: .6rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--rubric, #6E2113);
  opacity: .8;
}

@media (max-width: 760px) {
  .verse { padding: .9rem 1rem .8rem; }
}

/* ═══════════════════════════════════════════════════════════
   THE PAGES ARE REAL PAPER

   The leaves were a radial gradient wearing a noise filter.
   They are now a photograph of the actual sheet.

   ── ON THE MIRROR ──
   A spread is TWO LEAVES OF ONE SHEET — not the same photo
   printed twice. Print it twice and the eye catches it instantly:
   the same watermark, the same tea-stain, in the same corner of
   both halves. So the verso is the MIRROR of the recto. The
   staining now falls AWAY from the gutter on both sides, as it
   does in any book that has been held.

   ── ON WEIGHT ──
   Cropped to the page's own shape (0.62) rather than left for
   `cover` to slice at random — the heavy foxing lives at the
   edges, which is precisely what we want to keep. 1400px, webp,
   ~90KB a leaf. A phone takes the 900px cut instead.
   ═══════════════════════════════════════════════════════════ */

.grimoire .page {
  background-image: url('../media/paper-recto.webp');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-color: #D8CCAE;          /* until it lands */
}

/* the left-hand leaf is the same sheet, turned over */
.grimoire .page-left {
  background-image: url('../media/paper-verso.webp');
}

/* the painted grain is gone — the photograph has its own */
.grimoire .page::before {
  display: none;
}

/* the aging overlay stays, but light: the paper is already dirty,
   and this is now only the shadow the binding throws */
.grimoire .page::after {
  background:
    linear-gradient(to left,  rgba(92, 66, 30, .16) 0%, transparent 9%),
    linear-gradient(to top,   rgba(84, 60, 26, .10) 0%, transparent 7%),
    linear-gradient(to bottom, rgba(84, 60, 26, .08) 0%, transparent 6%);
  mix-blend-mode: multiply;
  opacity: .9;
}
.grimoire .page-left::after {
  background:
    linear-gradient(to right, rgba(92, 66, 30, .16) 0%, transparent 9%),
    linear-gradient(to top,   rgba(84, 60, 26, .10) 0%, transparent 7%),
    linear-gradient(to bottom, rgba(84, 60, 26, .08) 0%, transparent 6%);
}

/* the gutter shadow — where the sheet dives into the spine.
   Now that the paper is real, this is the only thing selling the
   fold, so it does the whole job. */
@media (min-width: 761px) {
  .grimoire .page-left {
    box-shadow: inset -38px 0 60px -26px rgba(58, 40, 16, .55);
  }
  .grimoire .page-right {
    box-shadow: inset 38px 0 60px -26px rgba(58, 40, 16, .55);
  }
}

/* ── THE PHONE takes the lighter cut ── */
@media (max-width: 760px) {
  .grimoire .page {
    background-image: url('../media/paper-recto-sm.webp');
    box-shadow: none;
  }
  .grimoire .page-left {
    background-image: url('../media/paper-verso-sm.webp');
  }
}

/* ═══════════════════════════════════════════════════════════
   THE LORE PANEL SITS BESIDE THE PLATE

   It carried `clear: both`, which shoved it under any picture on
   the page and left a column of dead paper beside the image.

   Simply removing the clear would be worse: a normal block box
   ignores floats, so the panel's TINTED BACKGROUND would slide
   underneath the photograph while only its text wrapped. You would
   see the paper colour running behind the plate.

   `display: flow-root` makes the panel its own formatting context.
   A BFC box may not overlap a float — so it is placed alongside it
   and narrowed to fit, background and all. Which is exactly what a
   printed page does.
   ═══════════════════════════════════════════════════════════ */

.lore {
  clear: none;
  display: flow-root;
  overflow: hidden;              /* fallback for anything without flow-root */
}

/* the marginal note still takes the full measure, beneath everything */
.chap-note { clear: both; }

/* with the panel now sharing the line, the plate can afford to be
   a little narrower and let more text up beside it */
.bookplate-inset {
  width: 38%;
  max-width: 290px;
  margin: .2rem 0 .9rem 1.3rem;
}

/* a panel squeezed beside a picture needs its air back */
.lore p {
  font-size: clamp(.98rem, 1.15vw, 1.12rem) !important;
  line-height: 1.52 !important;
}

@media (max-width: 760px) {
  /* no room to sit beside anything on a phone — stack it */
  .lore { clear: both; }
  .bookplate-inset { width: 100%; max-width: none; margin: .9rem 0 1rem; }
}

/* ═══════════════════════════════════════════════════════════
   THE FULL PLATE

   A picture that runs the width of the leaf. The caption beneath
   carries an honest note where the image is a reconstruction —
   this book does not pass off a painting as a photograph.
   ═══════════════════════════════════════════════════════════ */

.bookplate-full {
  float: none;
  clear: both;
  width: 100%;
  max-width: none;
  margin: .6rem 0 1.1rem;
}
.bookplate-full img {
  /* a little cooler and deeper than the margin plates — this one is
     a scene, not a document */
  filter: sepia(.22) contrast(1.08) brightness(.94) saturate(.92);
  box-shadow:
    0 6px 20px rgba(46, 32, 12, .5),
    0 0 0 1px rgba(90, 72, 42, .55),
    0 0 0 7px rgba(214, 200, 168, .38);
}
.bookplate-full figcaption {
  font-size: clamp(.88rem, 1.02vw, 1.02rem);
  line-height: 1.45;
}

/* the honest note: where the picture is a reconstruction, say so */
.cap-note {
  display: block;
  margin-top: .35rem;
  font-style: normal;
  font-family: 'Spectral SC', Georgia, serif;
  font-size: .58rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--rubric, #6E2113);
  opacity: .72;
}

/* ═══════════════════════════════════════════════════════════
   THE SPLIT

   A plate on one side, the argument on the other, locked
   together — for pages where the picture and the text ARE the
   same thought and must be read side by side.

   This is a GRID, not a float. A float lets a short block slide
   under it and a tall one push past it; the two halves drift out
   of register and the page looks accidental. A grid holds them.
   ═══════════════════════════════════════════════════════════ */

.split {
  display: grid;
  grid-template-columns: 36% 1fr;
  gap: 1.5rem;
  align-items: start;
  margin: 1rem 0 0;
  clear: both;
}

/* the plate sits in its own column and stops floating */
.split-plate {
  float: none !important;
  width: 100% !important;
  max-width: none !important;
  margin: 0 !important;
}

/* the argument, stacked in the other column */
.split-body > .lore {
  margin-top: 0;
  clear: none;
}
.split-body > .chap-note {
  margin-top: 1rem !important;
}

/* in a narrower column the panel can lose a little air */
.split-body .lore p {
  font-size: clamp(.96rem, 1.1vw, 1.08rem) !important;
  line-height: 1.5 !important;
}

/* ── PHONE: nothing sits beside anything ── */
@media (max-width: 760px) {
  .split {
    grid-template-columns: 1fr;
    gap: 1rem;
  }
}

/* ═══════════════════════════════════════════════════════════
   THE SECTION BREAK

   Two movements on one leaf. Not a new page — a breath. The
   ornament tells the eye that the subject has changed without
   spending a whole sheet of paper to say so.
   ═══════════════════════════════════════════════════════════ */

.section-break {
  display: flex;
  align-items: center;
  gap: .9rem;
  width: min(64%, 16rem);
  margin: 1.8rem auto 1.4rem;
  color: var(--gild, #8A6E3B);
  opacity: .55;
  clear: both;
}
.section-break span {
  flex: 1;
  height: 1px;
  background: linear-gradient(to right, transparent, var(--iron-faded, #574835));
}
.section-break span:last-child {
  background: linear-gradient(to left, transparent, var(--iron-faded, #574835));
}

/* a lore panel that has the whole measure to itself — no plate to
   sit beside, so it may breathe */
.lore-wide p {
  font-size: clamp(1.02rem, 1.24vw, 1.2rem) !important;
  line-height: 1.56 !important;
}

/* ═══════════════════════════════════════════════════════════
   THE OPENING PLATE MUST NOT EAT THE LEAF

   The blót ran the full width as a SQUARE, which on a page this
   tall is most of the sheet — and pushed the opening paragraphs
   off the bottom, so the first thing the reader met was a
   scrollbar.

   The picture is now cropped to 3:2 (sky and empty snow removed,
   nothing that matters lost) and set at 78% of the measure,
   centred. It reads as a mounted plate rather than a poster, and
   the words it was meant to introduce are on the page with it.
   ═══════════════════════════════════════════════════════════ */

.bookplate-full {
  width: 78%;
  margin: .4rem auto 1rem;
}

/* a hard ceiling, so no future picture can do this again */
.bookplate-full img {
  max-height: 46vh;
  object-fit: cover;
  object-position: center;
}

/* the caption tightens with it */
.bookplate-full figcaption {
  font-size: clamp(.84rem, .96vw, .96rem);
  line-height: 1.4;
  margin-top: .55rem;
}
.bookplate-full .cap-note {
  margin-top: .28rem;
  font-size: .55rem;
}

@media (max-width: 760px) {
  .bookplate-full { width: 100%; }
  .bookplate-full img { max-height: 34vh; }
}

/* ═══════════════════════════════════════════════════════════
   A DENSE LEAF

   Some pages carry two movements and a picture. They cannot be
   set at the same generous scale as a page carrying one idea, or
   they run off the bottom — which is what happened here.

   So: a page may declare itself DENSE. Type steps down a notch,
   the leading tightens, the picture is capped, and the whole leaf
   fits without a scrollbar. It is still a book, not a leaflet:
   the drop cap, the panels and the marginal hand all survive.
   ═══════════════════════════════════════════════════════════ */

.dense p {
  font-size: clamp(.96rem, 1.14vw, 1.1rem) !important;
  line-height: 1.55 !important;
  margin-bottom: .55rem;
}
.dense .chap-head {
  font-size: clamp(1.45rem, 1.9vw, 1.95rem);
  margin-bottom: .6rem;
}
.dense .folio-eyebrow {
  margin-bottom: .5rem;
  font-size: .62rem;
}
.dense .drop {
  font-size: 3em;
  margin-bottom: -.04em;
}

.dense .lore {
  margin: .7rem 0;
  padding: .8rem .95rem .7rem 1.9rem;
}
.dense .lore p {
  font-size: clamp(.92rem, 1.06vw, 1.02rem) !important;
  line-height: 1.46 !important;
  margin-bottom: .42rem !important;
}
.dense .lore p:last-child { margin-bottom: 0 !important; }
.dense .lore-mark { top: .68rem; left: .7rem; font-size: .78rem; }

.dense .chap-note {
  margin-top: .7rem !important;
  padding-top: .6rem;
  font-size: clamp(.92rem, 1.06vw, 1.04rem) !important;
  line-height: 1.45 !important;
}

.dense .section-break {
  margin: .9rem auto .7rem;
  width: min(50%, 12rem);
}

/* the plate in a dense split is a thumbnail, not a poster */
.dense .split { gap: 1.2rem; grid-template-columns: 32% 1fr; margin-top: .6rem; }
.dense .split-plate img { max-height: 300px; object-fit: cover; }
.dense .split-plate figcaption {
  margin-top: .45rem;
  font-size: .8rem;
  line-height: 1.35;
}

@media (max-width: 760px) {
  /* a phone scrolls anyway — give the type back */
  .dense p            { font-size: clamp(1.02rem, 4.1vw, 1.16rem) !important; }
  .dense .split       { grid-template-columns: 1fr; }
  .dense .split-plate img { max-height: 40vh; }
}

/* ═══════════════════════════════════════════════════════════
   DENSE, BUT NOT SMALL

   The first dense pass over-corrected: the leaf fits, but it now
   ends a hand's width short of the foot and the type is smaller
   than it needs to be. Empty paper at the bottom of a page is
   wasted room, and small type is the one thing a grimoire may
   never be.

   Everything steps back up — into the space that was there all
   along.
   ═══════════════════════════════════════════════════════════ */

.dense p {
  font-size: clamp(1.06rem, 1.3vw, 1.28rem) !important;
  line-height: 1.6 !important;
  margin-bottom: .66rem;
}

.dense .chap-head {
  font-size: clamp(1.65rem, 2.15vw, 2.2rem);
  margin-bottom: .75rem;
}
.dense .folio-eyebrow {
  font-size: .66rem;
  margin-bottom: .55rem;
}
.dense .drop { font-size: 3.3em; }

.dense .lore {
  margin: .95rem 0;
  padding: .95rem 1.1rem .85rem 2.1rem;
}
.dense .lore p {
  font-size: clamp(1.02rem, 1.22vw, 1.18rem) !important;
  line-height: 1.55 !important;
  margin-bottom: .52rem !important;
}
.dense .lore-mark { top: .82rem; left: .8rem; font-size: .88rem; }

.dense .chap-note {
  margin-top: .85rem !important;
  padding-top: .7rem;
  font-size: clamp(1rem, 1.18vw, 1.16rem) !important;
  line-height: 1.52 !important;
}

.dense .section-break {
  margin: 1.15rem auto .95rem;
  width: min(56%, 14rem);
}

/* the picture grows into the room as well */
.dense .split { grid-template-columns: 34% 1fr; gap: 1.35rem; }
.dense .split-plate img { max-height: 360px; }
.dense .split-plate figcaption {
  font-size: .86rem;
  line-height: 1.4;
  margin-top: .5rem;
}

/* ═══════════════════════════════════════════════════════════
   THE CENTRED PLATE

   A portrait picture that stands alone under the text — not
   floated into the margin, not stretched across the measure.
   Centred, at less than half the width, capped in height, with
   the caption beneath it.

   A tall image run full-width would eat the leaf; a tall image
   floated would leave a ragged column of orphan lines beside it.
   Centred is the only honest option for a vertical plate.
   ═══════════════════════════════════════════════════════════ */

.bookplate-centre {
  float: none;
  clear: both;
  width: 46%;
  max-width: 340px;
  margin: 1.2rem auto .4rem;
}
.bookplate-centre img {
  max-height: 40vh;
  object-fit: cover;
  object-position: center top;

  /* it is charcoal, not vellum — do not sepia it into the paper */
  filter: contrast(1.06) brightness(.97) sepia(.12);
  box-shadow:
    0 6px 20px rgba(30, 22, 10, .55),
    0 0 0 1px rgba(70, 58, 36, .6),
    0 0 0 7px rgba(214, 200, 168, .38);
}
.bookplate-centre figcaption {
  text-align: left;
  font-size: clamp(.84rem, .98vw, .98rem);
  line-height: 1.42;
}

@media (max-width: 760px) {
  .bookplate-centre {
    width: 78%;
    max-width: none;
  }
  .bookplate-centre img { max-height: 42vh; }
}

/* ═══════════════════════════════════════════════════════════
   THE STAFF WANTS ROOM

   It is a landscape photograph in a margin cut for portraits, so
   at 38% it was a postage stamp of a thing you are meant to be
   able to LOOK at. The whole argument of that page is "here is
   the object" — and an object you have to squint at proves
   nothing.

   It takes half the measure now.
   ═══════════════════════════════════════════════════════════ */

.bookplate[data-plate="volva"] {
  width: 52%;
  max-width: 420px;
  margin: .3rem 0 1rem 1.5rem;
}
.bookplate[data-plate="volva"] img {
  max-height: none;
}
.bookplate[data-plate="volva"] figcaption {
  font-size: clamp(.86rem, 1vw, 1rem);
  line-height: 1.42;
}

@media (max-width: 760px) {
  .bookplate[data-plate="volva"] {
    width: 100%;
    max-width: none;
    margin: .9rem 0 1rem;
  }
}

/* ═══════════════════════════════════════════════════════════
   THE PAGE SHADE — ONE DIAL

   The paper was too bright. It is now toned, warmed and
   vignetted in the file itself — but taste is taste, so the last
   few percent live here, in a single number.

       --page-shade : 0    the paper as photographed
                      .06  as shipped
                      .15  candle-lit, dim
                      .25  too far — the ink starts to drown

   It is a MULTIPLY layer, so it darkens the paper and its stains
   together, as light does. It sits under the text (z-index 1),
   never over it — so the ink stays exactly as black as it was.
   ═══════════════════════════════════════════════════════════ */

.grimoire {
  --page-shade: .07;
}

.grimoire .page::before {
  content: '';
  display: block;
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;

  background: #6E5836;                /* the colour of old light */
  mix-blend-mode: multiply;
  opacity: var(--page-shade);
}

/* the writing is above the shade, always */
.grimoire .page-inner { position: relative; z-index: 2; }

/* ═══════════════════════════════════════════════════════════
   THE FAMILIARS

   A line of writing that behaves like the smoke it sits in:
   low on the left, under the cauldron, drifting and never quite
   settling.

   ── HOW THE DRIFT IS BUILT ──
   One animation looks like a loop. Two, of different lengths,
   on nested elements, do not — the eye cannot factor them back
   apart. So:

     .familiars-drift   travels   — long, slow, 23s
     .familiars-sway    tilts and breathes — 17s

   23 and 17 are coprime: the pair does not repeat for six and a
   half minutes. Both animate transform and opacity only, on a
   tiny element. It is free.
   ═══════════════════════════════════════════════════════════ */

.familiars {
  position: absolute;
  left: clamp(1.2rem, 5vw, 4.5rem);
  bottom: clamp(4rem, 13vh, 9rem);
  z-index: 6;

  margin: 0;
  max-width: min(20rem, 30vw);
  pointer-events: none;

  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  font-weight: 300;
  font-size: clamp(.95rem, 1.35vw, 1.25rem);
  line-height: 1.5;
  letter-spacing: .03em;
  color: #A9B3AE;                       /* the green-grey of the cauldron smoke */

  text-shadow:
    0 2px 14px rgba(0, 0, 0, .95),
    0 0 30px rgba(0, 0, 0, .85),
    0 0 46px rgba(110, 200, 150, .22);  /* it catches the brew */

  opacity: 0;
  animation: familiars-arrive 3.4s ease 2.2s forwards;
}

.familiars em {
  font-style: italic;
  color: #CBD6CE;
  text-shadow:
    0 2px 14px rgba(0, 0, 0, 1),
    0 0 24px rgba(130, 220, 170, .38);
}

.familiars-dots { opacity: .55; }

@keyframes familiars-arrive {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ── THE DRIFT ── it wanders */
.familiars-drift {
  display: inline-block;
  animation: familiars-drift 23s ease-in-out infinite;
  animation-play-state: var(--play-state);
  will-change: transform;
}
@keyframes familiars-drift {
  0%   { transform: translate3d(0, 0, 0); }
  25%  { transform: translate3d(7px, -9px, 0); }
  50%  { transform: translate3d(-4px, -15px, 0); }
  75%  { transform: translate3d(-9px, -6px, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

/* ── THE SWAY ── it tilts, and it breathes */
.familiars-sway {
  display: inline-block;
  animation: familiars-sway 17s ease-in-out infinite;
  animation-play-state: var(--play-state);
  will-change: transform, opacity;
}
@keyframes familiars-sway {
  0%   { transform: rotate(-.7deg) skewX(1deg)  scale(1);     opacity: .72; }
  30%  { transform: rotate(.5deg)  skewX(-.6deg) scale(1.015); opacity: 1;   }
  60%  { transform: rotate(-.3deg) skewX(.8deg)  scale(.995);  opacity: .82; }
  100% { transform: rotate(-.7deg) skewX(1deg)  scale(1);     opacity: .72; }
}

/* it goes with the room when the book takes over */
body.book-approaching .familiars,
body.book-summoned .familiars,
body.state-open .familiars {
  opacity: 0 !important;
  transform: translateY(10px);
  transition: opacity .8s ease, transform 1s ease;
}

/* ── PHONE ── higher up the left edge, out of the thumb's way ── */
@media (max-width: 760px) {
  .familiars {
    left: 4vw;
    bottom: 34%;
    max-width: 52vw;
    font-size: clamp(.86rem, 3.6vw, 1rem);
  }
}

@media (prefers-reduced-motion: reduce) {
  .familiars-drift,
  .familiars-sway { animation: none; }
  .familiars { opacity: 1; animation: none; }
}

/* ═══════════════════════════════════════════════════════════
   THE FAMILIARS, MOVED UP TO THE CAT

   Measured on the painting: the grey cat sits on the bar at
   about x 25%, and a little under halfway up. The line now sits
   just beneath him, on the bar itself — where a cat would be
   spoken about — rather than down in the empty floor.

   One line, unbroken. A sentence that wraps looks like a
   paragraph; a sentence that does not looks like a whisper.
   ═══════════════════════════════════════════════════════════ */

.familiars {
  left: 16%;
  bottom: 41%;

  max-width: none;
  white-space: nowrap;

  font-size: clamp(1.32rem, 1.95vw, 1.9rem);
  letter-spacing: .035em;
}

/* the drift must not carry a nowrap line off the edge — keep it small */
@keyframes familiars-drift {
  0%   { transform: translate3d(0, 0, 0); }
  25%  { transform: translate3d(5px, -7px, 0); }
  50%  { transform: translate3d(-3px, -11px, 0); }
  75%  { transform: translate3d(-6px, -4px, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

@media (max-width: 760px) {
  .familiars {
    left: 4vw;
    right: 4vw;
    bottom: 49%;                    /* the cat sits higher in the portrait plate */

    /* it must be allowed to break: at this size a nowrap line would run
       clean off the side of the phone */
    white-space: normal;
    max-width: 84vw;

    font-size: clamp(1.16rem, 5.4vw, 1.5rem);
    line-height: 1.42;
    letter-spacing: .02em;
  }
}

/* ═══════════════════════════════════════════════════════════
   THE HOUSE, NOT THE WITCH

   The masthead named her. It now names the PLACE — and she is
   found only by pressing the sigil, which is the whole point.

   "The Witch's Tavern" is seventeen characters where "Vi Morrigan"
   was eleven. In Bokor — a hairline face with wide counters — that
   is a great deal more line. So it comes down a step and tightens,
   or it runs into the mark.
   ═══════════════════════════════════════════════════════════ */

.brand-name {
  font-size: clamp(1.35rem, 2.5vw, 2.05rem) !important;
  letter-spacing: .02em;
  white-space: nowrap;
}

/* the apostrophe in a hairline face is a speck — give it weight */
.brand-name {
  font-feature-settings: "kern" 1;
}

@media (max-width: 900px) {
  .brand-name { font-size: clamp(1.2rem, 3.2vw, 1.6rem) !important; }
}
@media (max-width: 640px) {
  .brand-name {
    font-size: 1.24rem !important;
    letter-spacing: .01em;
  }
  .brand-sub { font-size: .48rem !important; letter-spacing: .18em; }
}
/* at the very narrowest the tavern keeps its name and drops its subtitle */
@media (max-width: 400px) {
  .brand-name { font-size: 1.12rem !important; }
}

/* ═══════════════════════════════════════════════════════════
   THE FAMILIARS DRIFT WIDER

   Sitting on Gunnar it became a label — a caption naming the cat.
   Dropped below him, on the smoke coming off the bar, it becomes
   what it should be: a voice from somewhere in the room.

   And the leash is off. It now wanders far enough that it never
   settles anywhere long enough to be pinned to anything. The two
   cycles stay coprime (29s against 19s), so the pattern does not
   repeat for nine minutes.
   ═══════════════════════════════════════════════════════════ */

.familiars {
  left: 13%;
  bottom: 31%;
}

/* ── THE DRIFT ── a long, loose orbit rather than a nudge ── */
.familiars-drift {
  animation: familiars-roam 29s ease-in-out infinite;
}
@keyframes familiars-roam {
  0%   { transform: translate3d(0, 0, 0); }
  14%  { transform: translate3d(18px, -14px, 0); }
  29%  { transform: translate3d(34px, -6px, 0); }
  43%  { transform: translate3d(26px, 12px, 0); }
  57%  { transform: translate3d(4px, 20px, 0); }
  71%  { transform: translate3d(-16px, 9px, 0); }
  86%  { transform: translate3d(-11px, -11px, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

/* ── THE SWAY ── it leans further into the turns ── */
.familiars-sway {
  animation: familiars-lean 19s ease-in-out infinite;
}
@keyframes familiars-lean {
  0%   { transform: rotate(-1.4deg) skewX(1.6deg)  scale(.99);  opacity: .62; }
  22%  { transform: rotate(.9deg)   skewX(-1.1deg) scale(1.03); opacity: 1;   }
  48%  { transform: rotate(1.6deg)  skewX(.7deg)   scale(1.01); opacity: .8;  }
  73%  { transform: rotate(-.6deg)  skewX(1.9deg)  scale(.985); opacity: .95; }
  100% { transform: rotate(-1.4deg) skewX(1.6deg)  scale(.99);  opacity: .62; }
}

@media (max-width: 760px) {
  .familiars { left: 4vw; bottom: 42%; }
}

/* ═══════════════════════════════════════════════════════════
   WITCH'S TAVERN

   The definite article is gone. Two words now, not three — so the
   name can take back the size it lost, and the line beneath it
   grows with it. A subtitle set too small stops being a subtitle
   and becomes a footnote.
   ═══════════════════════════════════════════════════════════ */

.brand-name {
  font-size: clamp(1.5rem, 2.85vw, 2.35rem) !important;
  letter-spacing: .025em;
}

.brand-sub {
  font-size: clamp(.68rem, 1.18vw, .94rem) !important;
  letter-spacing: .3em;
  color: #9A907E;
}

.brand-words { gap: .34rem; }

@media (max-width: 900px) {
  .brand-name { font-size: clamp(1.3rem, 3.6vw, 1.8rem) !important; }
  .brand-sub  { font-size: clamp(.6rem, 1.5vw, .78rem) !important; }
}
@media (max-width: 640px) {
  .brand-name { font-size: 1.36rem !important; }
  .brand-sub  { font-size: .56rem !important; letter-spacing: .2em; }
}
@media (max-width: 400px) {
  .brand-name { font-size: 1.2rem !important; }
  .brand-sub  { font-size: .5rem !important; }
}

/* the familiars sink further — down off the bar, into the smoke
   that gathers at floor level */
.familiars {
  bottom: 23%;
}
@media (max-width: 760px) {
  .familiars { bottom: 36%; }
}

/* ═══════════════════════════════════════════════════════════
   THE MARGINS

   Runes down the edge of the Norse pages; the carved and stitched
   signs down the edge of the Slavic ones. Faint — this is a
   watermark in the paper, not a decoration printed over it.

   ── WHY IT SITS ON THE PAGE AND NOT ON THE TEXT ──
   The band is layered into the .page background, UNDER the shade
   and under the writing. Put it above the text and it fights the
   ink; put it in the paper and the eye reads it as part of the
   sheet — which is exactly what a watermark is.

   ── AND IT KEEPS TO THE OUTER EDGE ──
   Recto: right margin. Verso: left. Ornament runs down the open
   edge of a book, never into the gutter, because the gutter is
   where the light dies.
   ═══════════════════════════════════════════════════════════ */

.grimoire .page[data-margin] {
  background-repeat: repeat-y, no-repeat;
  background-size: 52px auto, cover;
  background-position: right 14px top 30px, center;
}
.grimoire .page-left[data-margin] {
  background-position: left 14px top 30px, center;
}

/* the band, then the paper beneath it */
.grimoire .page[data-margin="norse"] {
  background-image: url('../media/orn-norse.svg'), url('../media/paper-recto.webp');
}
.grimoire .page-left[data-margin="norse"] {
  background-image: url('../media/orn-norse.svg'), url('../media/paper-verso.webp');
}
.grimoire .page[data-margin="slavic"] {
  background-image: url('../media/orn-slavic.svg'), url('../media/paper-recto.webp');
}
.grimoire .page-left[data-margin="slavic"] {
  background-image: url('../media/orn-slavic.svg'), url('../media/paper-verso.webp');
}

/* ── HOW FAINT ── one dial, like the shade */
.grimoire { --margin-ink: .16; }

.grimoire .page[data-margin]::after {
  /* the aging layer doubles as the veil that sinks the band into
     the paper — a wash of the paper's own colour over the ink */
  background:
    linear-gradient(to left,  rgba(214, 198, 164, var(--margin-ink)) 0%,
                              rgba(214, 198, 164, calc(var(--margin-ink) * .5)) 5%,
                              transparent 9%),
    linear-gradient(to left,  rgba(92, 66, 30, .16) 0%, transparent 9%),
    linear-gradient(to top,   rgba(84, 60, 26, .10) 0%, transparent 7%),
    linear-gradient(to bottom, rgba(84, 60, 26, .08) 0%, transparent 6%);
}
.grimoire .page-left[data-margin]::after {
  background:
    linear-gradient(to right, rgba(214, 198, 164, var(--margin-ink)) 0%,
                              rgba(214, 198, 164, calc(var(--margin-ink) * .5)) 5%,
                              transparent 9%),
    linear-gradient(to right, rgba(92, 66, 30, .16) 0%, transparent 9%),
    linear-gradient(to top,   rgba(84, 60, 26, .10) 0%, transparent 7%),
    linear-gradient(to bottom, rgba(84, 60, 26, .08) 0%, transparent 6%);
}

/* the writing steps aside for the band */
@media (min-width: 761px) {
  .grimoire .page[data-margin] .page-inner      { padding-right: clamp(3.6rem, 5.4vw, 6rem); }
  .grimoire .page-left[data-margin] .page-inner { padding-left:  clamp(3.6rem, 5.4vw, 6rem);
                                                  padding-right: clamp(2rem, 3.6vw, 4.2rem); }
}

/* ── PHONE — the band narrows and the paper takes the light cut ── */
@media (max-width: 760px) {
  .grimoire .page[data-margin] {
    background-size: 38px auto, cover;
    background-position: right 6px top 24px, center;
  }
  .grimoire .page[data-margin="norse"]  { background-image: url('../media/orn-norse.svg'),  url('../media/paper-recto-sm.webp'); }
  .grimoire .page[data-margin="slavic"] { background-image: url('../media/orn-slavic.svg'), url('../media/paper-recto-sm.webp'); }
  .grimoire .page-left[data-margin="norse"]  { background-image: url('../media/orn-norse.svg'),  url('../media/paper-verso-sm.webp'); }
  .grimoire .page-left[data-margin="slavic"] { background-image: url('../media/orn-slavic.svg'), url('../media/paper-verso-sm.webp'); }
  .grimoire .page[data-margin] .page-inner { padding-right: 2.9rem; }
}

/* ═══════════════════════════════════════════════════════════
   THE PANEL MUST NOT CUT ITS OWN THROAT

   .lore carried `overflow: hidden` — put there as a fallback for
   browsers too old to know `display: flow-root`. Those browsers no
   longer exist, and the property does real harm: the moment a panel
   is squeezed beside a float and its height is constrained by
   anything, overflow:hidden CLIPS the sentence in half. Which is
   exactly what it did.

   flow-root alone gives the same float behaviour and never clips.
   ═══════════════════════════════════════════════════════════ */

.lore {
  overflow: visible;
  display: flow-root;
}

/* a verse in a split column keeps its measure and its air */
.split-body > .verse {
  margin: 0;
  clear: none;
}
.dense .verse {
  padding: .85rem 1rem .75rem;
  margin: 0;
}
.dense .verse p[lang="non"] {
  font-size: clamp(1rem, 1.2vw, 1.18rem) !important;
  line-height: 1.5 !important;
  margin-bottom: .55rem !important;
}
.dense .verse .verse-en {
  font-size: clamp(.9rem, 1.04vw, 1.02rem) !important;
  line-height: 1.44 !important;
  padding-top: .5rem;
}

/* ═══════════════════════════════════════════════════════════
   THE SCORN-POLE IS A TALL PICTURE

   The drawing is a man holding a pole above his head, so it is
   nearly twice as tall as it is wide. Forced into a plate cut for
   landscape it would be cropped through the horse's head — which
   is the only part that matters.

   So it is not cropped. It is CONTAINED: fitted whole inside a
   taller frame, centred in its column, printed on the paper
   itself rather than mounted on a mat.
   ═══════════════════════════════════════════════════════════ */

.split-plate[data-plate="nidstang"] img {
  max-height: 440px;
  width: auto;
  max-width: 100%;
  margin: 0 auto;
  object-fit: contain;

  /* an engraving on the page, not a photograph pinned to it */
  filter: sepia(.3) contrast(1.12) brightness(1.02);
  box-shadow: none;
  mix-blend-mode: multiply;
}
.split-plate[data-plate="nidstang"] figcaption {
  margin-top: .6rem;
}
.dense .split:has([data-plate="nidstang"]) {
  grid-template-columns: 30% 1fr;
}

@media (max-width: 760px) {
  .split-plate[data-plate="nidstang"] img { max-height: 48vh; }
}

/* ═══════════════════════════════════════════════════════════
   DENSE, WITH ROOM TO SPARE

   A dense leaf is not automatically a CRAMPED one. Some carry a
   picture and two panels and are genuinely full; others — like
   the Rúnatal — end well short of the foot, and there the small
   type is simply a waste of paper.

   `.dense-plus` is a dense page that has room. Everything on it
   steps back up. Nothing else in the book is touched, so the
   pages that really are full stay as they are.
   ═══════════════════════════════════════════════════════════ */

.dense-plus p {
  font-size: clamp(1.16rem, 1.44vw, 1.42rem) !important;
  line-height: 1.62 !important;
  margin-bottom: .72rem;
}

.dense-plus .chap-head {
  font-size: clamp(1.8rem, 2.4vw, 2.45rem);
  margin-bottom: .85rem;
}
.dense-plus .folio-eyebrow { font-size: .7rem; }
.dense-plus .drop { font-size: 3.5em; }

.dense-plus .lore {
  padding: 1.05rem 1.2rem .95rem 2.2rem;
  margin: 1.05rem 0;
}
.dense-plus .lore p {
  font-size: clamp(1.12rem, 1.36vw, 1.32rem) !important;
  line-height: 1.58 !important;
}
.dense-plus .lore-mark { font-size: .95rem; top: .95rem; }

.dense-plus .chap-note {
  font-size: clamp(1.08rem, 1.3vw, 1.26rem) !important;
  line-height: 1.55 !important;
  margin-top: 1rem !important;
}

/* the verse is the reason anyone is on this page — set it properly */
.dense-plus .verse {
  padding: 1.05rem 1.25rem .95rem;
}
.dense-plus .verse p[lang="non"] {
  font-size: clamp(1.14rem, 1.4vw, 1.38rem) !important;
  line-height: 1.56 !important;
}
.dense-plus .verse .verse-en {
  font-size: clamp(1rem, 1.18vw, 1.14rem) !important;
  line-height: 1.5 !important;
}
.dense-plus .verse cite { font-size: .66rem; }

.dense-plus .split { grid-template-columns: 33% 1fr; gap: 1.5rem; }
.dense-plus .split-plate img { max-height: 400px; }
.dense-plus .split-plate figcaption {
  font-size: .92rem;
  line-height: 1.45;
}

@media (max-width: 760px) {
  .dense-plus p { font-size: clamp(1.06rem, 4.2vw, 1.2rem) !important; }
}

/* ═══════════════════════════════════════════════════════════
   AN INK PLATE

   Not a photograph mounted on the page — a drawing PRINTED INTO
   it. No frame. No mat. No shadow. The white of the artist's
   paper was turned into transparency when the file was made, so
   what lands on the parchment is only the ink and the wash, and
   the stains of the sheet come up through the smoke.

   `multiply` finishes the job: any grey left in the drawing
   darkens the paper instead of covering it. This is how an
   illustration behaves in a real book, and it is why it will
   never look pasted on.
   ═══════════════════════════════════════════════════════════ */

.bookplate-ink {
  float: none;
  clear: both;
  width: 62%;
  max-width: 400px;
  margin: -.4rem auto 0;          /* it rises to meet the text above it */
}
.bookplate-ink img {
  width: 100%;
  height: auto;
  max-height: 42vh;
  object-fit: contain;

  filter: none;
  box-shadow: none;
  border-radius: 0;
  mix-blend-mode: multiply;
  opacity: .92;
}
.bookplate-ink figcaption {
  margin-top: .3rem;
  text-align: center;
  border-left: 0;
  padding-left: 0;
  font-size: clamp(.82rem, .96vw, .95rem);
}
.bookplate-ink .cap-note {
  display: inline;
  margin-left: .35rem;
  font-size: .54rem;
}

@media (max-width: 760px) {
  .bookplate-ink { width: 84%; max-width: none; }
  .bookplate-ink img { max-height: 40vh; }
}

/* the scorn-pole is ink now, not a photograph of a book page —
   so it loses the mat, the shadow and the sepia, and takes the
   full height of its column */
.split-plate[data-plate="nidstang"] img {
  filter: none;
  box-shadow: none;
  border-radius: 0;
  mix-blend-mode: multiply;
  opacity: .94;
  max-height: 470px;
  width: auto;
  margin: 0 auto;
  object-fit: contain;
}
.split-plate[data-plate="nidstang"] figcaption {
  text-align: center;
  border-left: 0;
  padding-left: 0;
}

/* the pole is a tall, narrow drawing — a marginal illustration, the
   kind a book puts in the outer column and runs the text past */
.dense .split:has([data-plate="nidstang"]) {
  grid-template-columns: 27% 1fr;
  gap: 1.6rem;
}
.split-plate[data-plate="nidstang"] img {
  max-height: 560px;
}

/* ═══════════════════════════════════════════════════════════
   DARKER INK

   The paper was toned down two rounds ago and the ink never
   followed it. Contrast has been quietly falling ever since.

   Two changes, and the second matters more than the first:

   1. The ink goes darker — from a warm mid-brown to something
      much closer to iron-gall as it actually dries: near-black,
      with the brown only showing in the thin strokes.

   2. The weight goes UP a step, 400 → 500. Cormorant is a
      high-contrast old-style face: its hairlines are genuinely
      hair-thin, and on a TEXTURED ground those strokes get eaten
      by the grain of the paper. Darkening a stroke that the
      parchment is swallowing does not help. Giving it more body
      does.

   The rubric red, the marginal hand and the captions all follow —
   but each keeps its distance from the body text, or the page
   flattens into one voice.
   ═══════════════════════════════════════════════════════════ */

.grimoire {
  --iron-gall:   #241B10;
  --iron-faded:  #4A3B26;
}

/* ── THE BODY ── */
.page-inner p,
.dense p,
.dense-plus p {
  color: #2A2015 !important;
  font-weight: 500;
}
.page-inner strong { color: #17110A; font-weight: 600; }
.page-inner em     { color: #241B10; }

/* ── THE HEADINGS ── */
.chap-title,
.chap-head   { color: #1C150C; }
.chap-title::first-letter { color: var(--rubric, #6E2113); }

.chap-standfirst { color: #3E3122 !important; }
.folio-eyebrow   { color: #5C4A31; }

/* ── THE PANELS ── */
.lore p,
.dense .lore p,
.dense-plus .lore p {
  color: #2C2114 !important;
  font-weight: 500;
}
.lore p strong { color: #17110A !important; }
.lore-said     { color: #45351F !important; }

/* ── HER HAND IN THE MARGIN ──
   still lighter than the body, still italic — but no longer a
   whisper you have to lean in for */
.chap-note,
.dense .chap-note,
.dense-plus .chap-note {
  color: #45351F !important;
  font-weight: 500;
}
.chap-note strong { color: #241B10 !important; }

/* ── THE VERSE ── */
.verse p[lang="non"] { color: #241A0E !important; }
.verse .verse-en     { color: #45351F !important; }

/* ── THE BIBLIOGRAPHY ── */
.chap-sources         { color: #2A2015; font-weight: 500; }
.chap-sources strong  { color: #17110A; }

/* ── CAPTIONS ── they may stay quiet, but not invisible */
.bookplate figcaption { color: #4A3B26; font-weight: 500; }

/* ── THE FRONT MATTER ── */
.grim-note, .grim-sub { color: #3E3122; }
.entry-name           { color: #1C150C; }
.entry-gloss          { color: #4A3B26; }

/* ── AND THE SCROLL, which is the same hand on the same paper ── */
.scroll-text p   { color: #2C2114; font-weight: 500; }
.scroll-text .lede { color: #241B10; }

/* ═══════════════════════════════════════════════════════════
   THE SCORN-POLE PAGE

   The drawing is a man holding a pole above his head: nearly
   three times as tall as it is wide. A picture that shape wants
   the whole HEIGHT of a page, not a corner of one.

   So the leaf is built as two columns and everything obeys them:
   the pole runs floor to ceiling down the left, and every word on
   the page — the opening, the working, her note — stacks in the
   right. Nothing runs underneath the image, which is what leaves
   a shelf of dead paper below a tall picture.
   ═══════════════════════════════════════════════════════════ */

.dense .split-pole,
.dense-plus .split-pole {
  grid-template-columns: 37% 1fr;
  gap: 1.9rem;
  align-items: start;
  margin-top: .7rem;
}

.split-pole .split-plate img {
  max-height: 640px !important;
  width: 100%;
  object-fit: contain;
  object-position: top center;
}
.split-pole .split-plate figcaption {
  margin-top: .7rem;
  font-size: clamp(.86rem, 1vw, 1rem);
  line-height: 1.42;
  text-align: center;
}

/* the column of words keeps its own rhythm */
.split-pole .split-body > p:first-child { margin-top: 0; }
.split-pole .lore { margin: 1.1rem 0; }

@media (max-width: 760px) {
  .dense .split-pole,
  .dense-plus .split-pole { grid-template-columns: 1fr; }
  .split-pole .split-plate img { max-height: 52vh !important; }
}

/* the vigil: a wide, dark, quiet picture. It wants the full measure
   and a low ceiling — this page still has a working and a warning
   to fit under it */
.bookplate-full[data-plate="utiseta"] {
  width: 88%;
  margin: .7rem auto .9rem;
}
.bookplate-full[data-plate="utiseta"] img {
  max-height: 33vh;
  object-position: center 42%;   /* keep her, and the moon, in frame */
}
.bookplate-full[data-plate="utiseta"] figcaption {
  text-align: center;
  border-left: 0;
  padding-left: 0;
}
@media (max-width: 760px) {
  .bookplate-full[data-plate="utiseta"] { width: 100%; }
  .bookplate-full[data-plate="utiseta"] img { max-height: 28vh; }
}

/* the rite in the forest: wide, and full of people. It needs width more
   than it needs height, and the page beneath it still has four names
   and a warning to carry */
.bookplate-full[data-plate="thoseknow"] {
  width: 92%;
  margin: .7rem auto .9rem;
}
.bookplate-full[data-plate="thoseknow"] img {
  max-height: 30vh;
  object-position: center 55%;   /* hold the fire and the faces, drop the sky */
}
.bookplate-full[data-plate="thoseknow"] figcaption {
  text-align: center;
  border-left: 0;
  padding-left: 0;
}
@media (max-width: 760px) {
  .bookplate-full[data-plate="thoseknow"] { width: 100%; }
  .bookplate-full[data-plate="thoseknow"] img { max-height: 26vh; }
}

/* ═══════════════════════════════════════════════════════════
   THE PLATE PAIR

   Two pictures set side by side because the ARGUMENT is the
   comparison — the manuscript against the idol, what they kept
   against what we kept. Neither one says anything on its own.

   Equal columns, equal heights, captions aligned. If one were
   larger it would look like the more important of the two, and
   the point of the page is that the smaller inheritance is the
   more stubborn one.
   ═══════════════════════════════════════════════════════════ */

.plate-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.3rem;
  align-items: start;
  clear: both;
  margin: .9rem 0 1rem;
}
.plate-pair .bookplate {
  float: none;
  width: 100%;
  max-width: none;
  margin: 0;
}
.plate-pair .bookplate img {
  width: 100%;
  height: 25vh;
  max-height: 260px;
  object-fit: cover;
  object-position: center;
}
.plate-pair .bookplate[data-plate="zbruch"] img {
  object-fit: contain;          /* four standing stones — do not crop their heads off */
  background: rgba(60, 44, 20, .10);
}
.plate-pair figcaption {
  margin-top: .5rem;
  font-size: clamp(.82rem, .96vw, .95rem);
  line-height: 1.4;
}

@media (max-width: 760px) {
  .plate-pair { grid-template-columns: 1fr; gap: 1rem; }
  .plate-pair .bookplate img { height: auto; max-height: 30vh; }
}

/* the charm: a wide picture, held low, so the formula and the note
   below it are not pushed off the leaf */
.bookplate-full[data-plate="zagovor"] {
  width: 92%;
  margin: .7rem auto .85rem;
}
.bookplate-full[data-plate="zagovor"] img {
  max-height: 29vh;
  object-position: center 40%;   /* the faces and the wreaths, not the canopy */
}
.bookplate-full[data-plate="zagovor"] figcaption {
  text-align: center;
  border-left: 0;
  padding-left: 0;
}
@media (max-width: 760px) {
  .bookplate-full[data-plate="zagovor"] { width: 100%; }
  .bookplate-full[data-plate="zagovor"] img { max-height: 25vh; }
}

/* ═══════════════════════════════════════════════════════════
   A CHALK PLATE

   Red chalk and white gouache on tan paper — so it is NOT
   multiplied into the page like the pen drawings. Multiply
   darkens, and this drawing's brightest, most important mark is
   the white thread running out of Mokosh's hands. Multiply would
   have taken it away.

   The paper was keyed out by COLOUR DISTANCE rather than by
   darkness, so both the red chalk and the white highlights
   survived. What lands on the parchment is the drawing alone,
   printed straight, no mat and no shadow.
   ═══════════════════════════════════════════════════════════ */

.bookplate-chalk img {
  width: 100%;
  height: auto;
  filter: none;
  box-shadow: none;
  border-radius: 0;
  mix-blend-mode: normal;
  opacity: .97;
}
.bookplate-chalk figcaption {
  text-align: center;
  border-left: 0;
  padding-left: 0;
  margin-top: .5rem;
}

/* the leaf: she takes the left, the whole argument runs down the right */
.dense .split-mokosh,
.dense-plus .split-mokosh {
  grid-template-columns: 40% 1fr;
  gap: 1.7rem;
  align-items: start;
  margin-top: .5rem;
}
.split-mokosh .bookplate-chalk img { max-height: 620px; object-fit: contain; }
.split-mokosh .split-body > p:first-child { margin-top: 0; }

@media (max-width: 760px) {
  .dense .split-mokosh,
  .dense-plus .split-mokosh { grid-template-columns: 1fr; }
  .split-mokosh .bookplate-chalk img { max-height: 46vh; }
}

/* ═══════════════════════════════════════════════════════════
   A SHEET LAID INTO THE BOOK

   A whole illustrated plate — title, figure, notes — keyed off
   its own paper and multiplied into ours, so it reads as a leaf
   that was tipped in rather than a picture that was pasted on.

   It takes the full measure, because it has WORDS on it, and a
   plate with words that cannot be read is only wallpaper.
   ═══════════════════════════════════════════════════════════ */

.bookplate-sheet {
  float: none;
  clear: both;
  width: 100%;
  max-width: none;
  margin: 1rem 0 .2rem;
}
.bookplate-sheet img {
  width: 100%;
  height: auto;
  max-height: 46vh;
  object-fit: contain;

  filter: none;
  box-shadow: none;
  border-radius: 0;
  mix-blend-mode: multiply;
  opacity: .95;
}
.bookplate-sheet figcaption {
  text-align: center;
  border-left: 0;
  padding-left: 0;
  margin-top: .45rem;
  font-size: clamp(.82rem, .96vw, .95rem);
}

@media (max-width: 760px) {
  .bookplate-sheet img { max-height: 40vh; }
}

/* ═══════════════════════════════════════════════════════════
   AN ARTWORK, REPRODUCED WHOLE

   Not keyed, not blended, not toned into our paper — the drawing
   as the artist made it, on the artist's own sheet, with the
   artist's own border. It is MOUNTED on the page rather than
   printed into it: a mat, a hairline, a shadow. That is the
   correct way to show somebody else's work, and it is also the
   honest one — you can see exactly where their sheet ends and
   ours begins.

   A credit line goes with it. A book that names its sources in
   the bibliography must name them under the pictures too.
   ═══════════════════════════════════════════════════════════ */

.bookplate-art img {
  width: 100%;
  height: auto;
  filter: none;
  mix-blend-mode: normal;
  opacity: 1;
  border-radius: 1px;
  box-shadow:
    0 5px 18px rgba(46, 32, 12, .5),
    0 0 0 1px rgba(90, 72, 42, .55),
    0 0 0 7px rgba(214, 200, 168, .40);
}
.bookplate-art figcaption {
  text-align: left;
  margin-top: .8rem;
}

/* the credit: quiet, set apart, and never mistaken for the caption */
.cap-credit {
  display: block;
  margin-top: .35rem;
  padding-top: .3rem;
  border-top: 1px solid rgba(110, 33, 19, .22);
  font-style: normal;
  font-family: 'Spectral SC', Georgia, serif;
  font-size: .58rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--iron-faded, #4A3B26);
  opacity: .85;
}
.cap-credit em {
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  text-transform: none;
  letter-spacing: 0;
  font-size: 1.35em;
  color: var(--rubric, #6E2113);
}

/* ── SHE TAKES THE LEFT HALF ── */
.dense .split-mokosh,
.dense-plus .split-mokosh {
  grid-template-columns: 47% 1fr;
  gap: 1.8rem;
  align-items: start;
  margin-top: .5rem;
}
.split-mokosh .bookplate-art img { max-height: 660px; object-fit: contain; }
.split-mokosh .split-body > p:first-child { margin-top: 0; }

@media (max-width: 760px) {
  .dense .split-mokosh,
  .dense-plus .split-mokosh { grid-template-columns: 1fr; }
  .split-mokosh .bookplate-art img { max-height: 52vh; }
}

/* ═══════════════════════════════════════════════════════════
   THE TWO HANDS

   Healing and harming were two pages. They are one leaf now, and
   set as two COLUMNS rather than stacked — because the argument
   of the page is that they are the same craft, done by the same
   woman, on the same afternoon. Stacked, one reads as the sequel
   to the other. Side by side, they read as a pair. That is the
   whole point, and the layout has to carry it.
   ═══════════════════════════════════════════════════════════ */

.duo {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.6rem;
  align-items: start;
  clear: both;
  margin: .9rem 0 0;
}
.duo-col { min-width: 0; }

.chap-sub {
  margin: 0 0 .15rem;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-weight: 600;
  font-size: clamp(1.15rem, 1.55vw, 1.5rem);
  line-height: 1.2;
  color: #1C150C;
}
.duo-lead {
  margin: 0 0 .55rem !important;
  text-indent: 0 !important;
  font-style: italic;
  font-size: clamp(.92rem, 1.06vw, 1.02rem) !important;
  color: var(--rubric, #6E2113) !important;
  opacity: .9;
}

/* the mending hand keeps the warm panel; the other hand does not */
.lore-dark {
  background:
    radial-gradient(ellipse 60% 40% at 84% 16%, rgba(90, 40, 30, .10), transparent 70%),
    linear-gradient(178deg, rgba(96, 62, 48, .16), rgba(78, 50, 38, .10));
  border-top-color: rgba(110, 33, 19, .45);
  border-bottom-color: rgba(110, 33, 19, .45);
}

/* two columns of panel text can afford to be a shade tighter */
.duo .lore p {
  font-size: clamp(.94rem, 1.08vw, 1.06rem) !important;
  line-height: 1.5 !important;
  margin-bottom: .45rem !important;
}
.duo .lore { margin: 0; }

@media (max-width: 760px) {
  .duo { grid-template-columns: 1fr; gap: 1.3rem; }
}

/* ═══════════════════════════════════════════════════════════
   THE GALLERY

   Four photographs, equal, in a block — because the argument of
   the page is not "here is a picture of Kupala", it is "this is
   STILL HAPPENING, and here are four separate nights to prove
   it". One large picture would be a mood. Four small ones are
   evidence.

   Equal sizes, equal weight, a common height, and captions that
   do not describe the image but say what is being DONE in it.
   ═══════════════════════════════════════════════════════════ */

.gallery {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: .75rem;
  clear: both;
  margin: .9rem 0 .3rem;
}
.gallery .gal {
  float: none;
  width: 100%;
  max-width: none;
  margin: 0;
}
.gallery .gal img {
  width: 100%;
  height: 19vh;
  max-height: 190px;
  object-fit: cover;
  object-position: center;

  filter: sepia(.30) contrast(1.06) brightness(.96) saturate(.85);
  box-shadow:
    0 3px 10px rgba(46, 32, 12, .45),
    0 0 0 1px rgba(90, 72, 42, .5),
    0 0 0 4px rgba(214, 200, 168, .35);
}
.gallery .gal[data-plate="koliada"] img { object-position: center 30%; }
.gallery .gal figcaption {
  margin-top: .42rem;
  padding-left: .4rem;
  border-left: 2px solid rgba(110, 33, 19, .3);
  font-size: clamp(.74rem, .86vw, .86rem);
  line-height: 1.32;
}

.gallery-credit {
  display: block;
  margin: .3rem 0 .2rem !important;
  border-top: 0;
  text-align: right;
  padding-top: 0;
}

@media (max-width: 760px) {
  .gallery { grid-template-columns: 1fr 1fr; gap: .6rem; }
  .gallery .gal img { height: 15vh; }
  .gallery-credit { text-align: left; }
}

/* ═══════════════════════════════════════════════════════════
   MOKOSH, AT HER PROPER SIZE

   The plate was a postage stamp, and the cause was inheritance:
   `.bookplate` is written for a figure floated into a MARGIN, so
   it carries `float: right; width: 44%; max-width: 320px`. Drop
   that same class into a grid column and it obediently takes 44%
   OF THE COLUMN — a fifth of the page — and caps itself at 320px.

   Inside a split, a plate is not a marginal figure. It is the
   column. So it fills it.
   ═══════════════════════════════════════════════════════════ */

.split .bookplate,
.split-mokosh .bookplate-art {
  float: none !important;
  width: 100% !important;
  max-width: none !important;
  margin: 0 !important;
}

/* and she takes over half the leaf */
.dense .split-mokosh,
.dense-plus .split-mokosh {
  grid-template-columns: 53% 1fr;
  gap: 1.9rem;
}
.split-mokosh .bookplate-art img {
  width: 100%;
  height: auto;
  max-height: 760px;
  object-fit: contain;
}
.split-mokosh .bookplate-art figcaption {
  font-size: clamp(.86rem, 1vw, 1rem);
  line-height: 1.45;
  margin-top: .7rem;
}

@media (max-width: 760px) {
  .dense .split-mokosh,
  .dense-plus .split-mokosh { grid-template-columns: 1fr; }
  .split-mokosh .bookplate-art img { max-height: 56vh; }
}

/* ═══════════════════════════════════════════════════════════
   THE FEASTS ARE NAMED LOUDER

   Kupala, Koliada, Radunitsa are not emphasis inside a sentence —
   they are the NAMES OF NIGHTS, and each one opens its own
   entry. So they are set like the entries they are: larger, in
   rubric, and given air after them.

   Note this is deliberately NOT the little-caps face used for
   labels elsewhere. These are proper nouns in a body text, and
   small caps would turn them into signage.
   ═══════════════════════════════════════════════════════════ */

.feast {
  font-size: 1.34em;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: .015em;
  color: var(--rubric, #6E2113) !important;
  padding-right: .1em;
}

/* ═══════════════════════════════════════════════════════════
   THE GALLERY, TWO BY TWO — AND A LEGIBLE CREDIT

   1. FOUR ACROSS made each photograph a stamp. Two by two gives
      each one twice the width, which is the difference between
      "I can see there is a fire" and "I can see the wreath".

   2. THE CREDIT was set in the small-caps label face: uppercase,
      letter-spaced. That is fine for a three-word tag. The moment
      it wrapped to two lines it became a wall of spaced capitals,
      which is the least readable thing in typography.

      A credit is a SENTENCE. So it is set as one — italic, mixed
      case, quiet. The capitals are gone.
   ═══════════════════════════════════════════════════════════ */

.gallery {
  grid-template-columns: 1fr 1fr;
  gap: .9rem 1.1rem;
  margin: 1rem 0 .5rem;
}
.gallery .gal img {
  height: 21vh;
  max-height: 230px;
}
.gallery .gal figcaption {
  margin-top: .5rem;
  font-size: clamp(.84rem, .98vw, .96rem);
  line-height: 1.4;
}

/* ── THE CREDIT: a sentence, not a sign ── */
.gallery-credit,
p.cap-credit.gallery-credit {
  display: block;
  margin: .7rem 0 .2rem !important;
  padding-top: .5rem;
  border-top: 1px solid rgba(110, 33, 19, .2);

  font-family: 'Cormorant Garamond', Georgia, serif !important;
  font-style: italic;
  font-weight: 400;
  font-size: clamp(.86rem, 1vw, .98rem) !important;
  line-height: 1.5;
  letter-spacing: 0 !important;
  text-transform: none !important;
  text-align: left;
  color: var(--iron-faded, #4A3B26) !important;
  opacity: 1;
  text-indent: 0 !important;
}
.gallery-credit em {
  font-style: italic;
  color: var(--rubric, #6E2113) !important;
}

@media (max-width: 760px) {
  .gallery { grid-template-columns: 1fr 1fr; gap: .6rem; }
  .gallery .gal img { height: 15vh; }
}

/* ═══════════════════════════════════════════════════════════
   THE PLATES UNDER THE TWO HANDS

   One picture at the foot of each column, so the leaf reads
   downward twice rather than across once: the pour, and what the
   pour leaves behind.

   They are the same size and sit at the same height, because the
   page's whole claim is that these two hands are one pair.
   ═══════════════════════════════════════════════════════════ */

.duo-plate {
  float: none !important;
  width: 100% !important;
  max-width: none !important;
  margin: .9rem 0 0 !important;
  clear: both;
}
.duo-plate img {
  width: 100%;
  height: 20vh;
  max-height: 210px;
  object-fit: cover;
  object-position: center;

  filter: sepia(.26) contrast(1.05) brightness(.97) saturate(.9);
  box-shadow:
    0 3px 12px rgba(46, 32, 12, .48),
    0 0 0 1px rgba(90, 72, 42, .5),
    0 0 0 5px rgba(214, 200, 168, .35);
}
.duo-plate[data-plate="wax-set"] img { object-position: center 45%; }
.duo-plate figcaption {
  margin-top: .45rem;
  padding-left: .45rem;
  border-left: 2px solid rgba(110, 33, 19, .3);
  font-size: clamp(.82rem, .95vw, .94rem);
  line-height: 1.38;
}

@media (max-width: 760px) {
  .duo-plate img { height: 16vh; }
}

/* ═══════════════════════════════════════════════════════════
   THE RIGHTS LINE

   Said once, plainly, in the book's own voice — not four
   apologetic footnotes in four different sizes. Quiet, legible,
   and never mistaken for the caption it follows.
   ═══════════════════════════════════════════════════════════ */

.rights {
  display: block;
  margin-top: .2rem;
  font-style: italic;
  color: var(--iron-faded, #4A3B26);
  opacity: .9;
}

.rights-note {
  margin-top: 1.2rem !important;
  padding-top: .8rem;
  border-top: 1px solid rgba(110, 33, 19, .28);
}
.rights-note strong { color: var(--rubric, #6E2113) !important; }

/* the gallery credit is a sentence; keep it one */
.gallery-credit .rights {
  display: inline;
  margin-top: 0;
}

/* ═══════════════════════════════════════════════════════════
   THE SCORN-POLE, LARGER

   The leaf ends a long way short of the foot, so the picture was
   smaller than it needed to be and the text column narrower than
   it wanted. Both grow into the room.

   The image column widens and the drawing takes the height it
   was cropped for; the words push further right and are set
   larger. Nothing has to be cut — the paper was already there.
   ═══════════════════════════════════════════════════════════ */

.dense .split-pole,
.dense-plus .split-pole {
  grid-template-columns: 44% 1fr;
  gap: 2.4rem;
  margin-top: .8rem;
}

.split-pole .split-plate img {
  max-height: 780px !important;
  width: 100%;
  object-fit: contain;
  object-position: top center;
}

/* the caption grows with the plate — it carries the working's
   detail (the propped jaws) and it was the smallest type on the page */
.split-pole .split-plate figcaption {
  margin-top: .85rem;
  font-size: clamp(.95rem, 1.12vw, 1.1rem);
  line-height: 1.48;
}
.split-pole .split-plate .cap-note {
  margin-top: .4rem;
  font-size: .62rem;
  letter-spacing: .1em;
}

/* the column of words takes the space it has been given */
.split-pole .split-body p {
  font-size: clamp(1.16rem, 1.42vw, 1.4rem) !important;
  line-height: 1.62 !important;
}
.split-pole .split-body .lore p {
  font-size: clamp(1.1rem, 1.34vw, 1.3rem) !important;
  line-height: 1.56 !important;
}
.split-pole .split-body .chap-note {
  font-size: clamp(1.08rem, 1.3vw, 1.26rem) !important;
  line-height: 1.56 !important;
}
.split-pole .split-body .drop { font-size: 3.5em; }

@media (max-width: 760px) {
  .dense .split-pole,
  .dense-plus .split-pole { grid-template-columns: 1fr; gap: 1.2rem; }
  .split-pole .split-plate img { max-height: 52vh !important; }
}

/* ═══════════════════════════════════════════════════════════
   EVERY CREDIT IS A SENTENCE

   I fixed this on the gallery and left it broken everywhere else.
   `.cap-credit` was still uppercase, letter-spaced and tiny —
   which is fine for a two-word tag and hostile for anything
   longer. Spaced capitals destroy word shapes and remove the
   ascenders the eye reads by; two lines of them is a chore.

   So the rule is fixed at the source, and the plate captions grow
   with it. A caption that has to be squinted at is a caption
   nobody reads, and these ones carry the working.
   ═══════════════════════════════════════════════════════════ */

.cap-credit {
  display: block;
  margin-top: .45rem;
  padding-top: .4rem;
  border-top: 1px solid rgba(110, 33, 19, .22);

  font-family: 'Cormorant Garamond', Georgia, serif !important;
  font-style: italic;
  font-weight: 400;
  font-size: clamp(.88rem, 1.02vw, 1rem) !important;
  line-height: 1.5;
  letter-spacing: 0 !important;
  text-transform: none !important;
  color: var(--iron-faded, #4A3B26) !important;
  opacity: 1;
}
.cap-credit em {
  font-style: italic;
  color: var(--rubric, #6E2113) !important;
}

/* the little rubric tag under reconstructions stays a TAG — it is two
   words, and two words in small caps are fine */
.cap-note {
  font-family: 'Spectral SC', Georgia, serif;
  font-size: .6rem;
  letter-spacing: .12em;
  text-transform: uppercase;
}

/* ── MOKOSH'S CAPTION, AT READING SIZE ── */
.split-mokosh .bookplate-art figcaption {
  font-size: clamp(1rem, 1.16vw, 1.16rem);
  line-height: 1.52;
  margin-top: .8rem;
}
.split-mokosh .bookplate-art figcaption strong {
  font-size: 1.1em;
  color: var(--rubric, #6E2113) !important;
}
.split-mokosh .bookplate-art .cap-credit {
  font-size: clamp(.9rem, 1.04vw, 1.02rem) !important;
}

/* ═══════════════════════════════════════════════════════════
   THE WAX PLATES, NEARER THEIR TRUE SHAPE

   Both photographs are TALL — roughly 4:7. I had them in a 210px
   landscape letterbox, which meant the crop was throwing away most
   of each picture: the copper pot at the top of one, and the whole
   spread of set wax in the other.

   They are now set close to portrait (3:4) and given real height,
   so the pour reads as a pour and the tray reads as a tray. The
   captions grow with them.
   ═══════════════════════════════════════════════════════════ */

.duo-plate img {
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 4;
  max-height: 46vh;
  object-fit: cover;
  object-position: center;
}
.duo-plate[data-plate="wax-pour"] img { object-position: center 38%; }
.duo-plate[data-plate="wax-set"]  img { object-position: center 42%; }

.duo-plate figcaption {
  margin-top: .55rem;
  font-size: clamp(.9rem, 1.06vw, 1.05rem);
  line-height: 1.45;
}

/* a little more width for each column to grow into */
.duo { gap: 1.3rem; }

@media (max-width: 760px) {
  .duo-plate img { aspect-ratio: 4 / 5; max-height: 40vh; }
}

/* ═══════════════════════════════════════════════════════════
   THE PLAIN LEAVES READ LARGER

   Pages that carry no picture and no second movement were still
   being set at the size worked out for the crowded ones. There is
   no reason for that — an uncluttered leaf can afford the bigger
   type, and the dvoeverie panel (three gods changing their names)
   is one of the best things in the chapter.

   This lifts the BASE size only. `.dense` and `.dense-plus` are
   more specific, so the crowded leaves keep the smaller setting
   they actually need.
   ═══════════════════════════════════════════════════════════ */

.lore p {
  font-size: clamp(1.08rem, 1.32vw, 1.3rem) !important;
  line-height: 1.6 !important;
  margin-bottom: .6rem !important;
}
.lore p:last-child { margin-bottom: 0 !important; }
.lore-said {
  font-size: clamp(1.04rem, 1.26vw, 1.24rem) !important;
}
.lore-mark { font-size: .95rem; top: .9rem; }
.lore { padding: 1.05rem 1.2rem .95rem 2.2rem; }

/* the saints and the gods they replaced — named a shade louder */
.lore p strong {
  font-size: 1.06em;
}

/* ═══════════════════════════════════════════════════════════
   HER VOICE, RAISED

   Most of this book is written in her hand. Once or twice a
   chapter she stops reporting and simply SAYS something — and
   that gets set apart: larger, indented, in rubric down the
   side. Not a quotation. A declaration.
   ═══════════════════════════════════════════════════════════ */

.voice {
  clear: both;
  margin: 1.1rem 0;
  padding: .3rem 0 .3rem 1.4rem;
  border-left: 3px solid rgba(110, 33, 19, .55);
}
.voice p {
  margin: 0 0 .6rem !important;
  text-indent: 0 !important;
  text-align: left !important;
  font-size: clamp(1.14rem, 1.4vw, 1.38rem) !important;
  line-height: 1.55 !important;
  font-style: italic;
  color: #2A2015 !important;
}
.voice p:last-child { margin-bottom: 0 !important; }
.voice strong {
  font-style: normal;
  color: var(--rubric, #6E2113) !important;
}

/* ── THE HONEST CAVEAT ──
   where she gives the other side its due, and then declines it */
.chap-note.honest {
  border-top-color: rgba(87, 72, 53, .3);
}
.chap-note.honest strong { color: var(--iron-gall, #241B10) !important; }

/* ── A RULE OF THE BOOK ──
   an editorial law, not an aside. It gets the red. */
.chap-note.rule {
  border-top: 1px solid rgba(110, 33, 19, .4);
  border-bottom: 1px solid rgba(110, 33, 19, .4);
  padding: .8rem 0 .75rem;
  background: linear-gradient(180deg,
    rgba(110, 33, 19, .07), rgba(110, 33, 19, .02));
}
.chap-note.rule strong { color: var(--rubric, #6E2113) !important; }

/* the manual and the market: two portrait plates, equal, side by side.
   They are documents, so they are mounted, not printed in — and they are
   the same size, because the argument is that one produced the other */
.plate-pair .bookplate[data-plate="malleus"] img,
.plate-pair .bookplate[data-plate="broadsheet"] img {
  height: 30vh;
  max-height: 330px;
  object-fit: contain;
  background: rgba(60, 44, 20, .07);
}
.plate-pair .bookplate[data-plate="malleus"] figcaption,
.plate-pair .bookplate[data-plate="broadsheet"] figcaption {
  font-size: clamp(.84rem, .98vw, .96rem);
  line-height: 1.42;
}

@media (max-width: 760px) {
  .plate-pair .bookplate[data-plate="malleus"] img,
  .plate-pair .bookplate[data-plate="broadsheet"] img { height: 34vh; }
}

/* ═══════════════════════════════════════════════════════════
   HER MARGINAL HAND, LOUDER

   The notes were the smallest voice on the page — which was
   right when they were asides, and wrong now that they carry the
   arguments: the corrections, the caveats, the rules of the book.
   She is not muttering. She is finishing the page.

   Lifted at the base and on the dense leaves alike, but still a
   step below the body text and still italic — the hierarchy holds,
   it is simply audible now.
   ═══════════════════════════════════════════════════════════ */

.chap-note {
  font-size: clamp(1.1rem, 1.32vw, 1.3rem) !important;
  line-height: 1.58 !important;
}
.dense .chap-note,
.dense-plus .chap-note {
  font-size: clamp(1.06rem, 1.26vw, 1.24rem) !important;
  line-height: 1.56 !important;
}

/* the rule of the book is the loudest of them — it is a law */
.chap-note.rule {
  font-size: clamp(1.1rem, 1.32vw, 1.3rem) !important;
  padding: .9rem 1rem .85rem;
}
.chap-note.rule strong,
.chap-note.honest strong {
  font-size: 1.06em;
}

/* the voice takes another step up with them, or it stops leading */
.voice p {
  font-size: clamp(1.2rem, 1.48vw, 1.46rem) !important;
  line-height: 1.56 !important;
}

/* ═══════════════════════════════════════════════════════════
   THE FURNITURE OF THE TWO HANDS

   Three woodcuts, keyed off their cream paper and printed into
   ours in iron-gall — not photographs, so no mat, no shadow, no
   frame. Multiply, and the page's own stains come up through them.

   THE THREAD and THE CANDLE stand beside the heading — the two
   tools the whole leaf is about, one for each hand.

   THE DISTAFF stands BEHIND the page: a watermark, low in the
   paper, under everything. It is set at the same faintness as the
   marginal runes, because it does the same job — it says what
   country you are in without asking to be read.
   ═══════════════════════════════════════════════════════════ */

.leaf-hands { position: relative; }

/* ── THE HEAD: words left, tools right ── */
.hands-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.4rem;
  margin-bottom: .3rem;
}
.hands-head-words { min-width: 0; }
.hands-head-words .folio-eyebrow,
.hands-head-words .chap-head { margin-bottom: .3rem; }

.hands-head-orn {
  display: flex;
  align-items: flex-end;
  gap: .9rem;
  flex: none;
  padding-bottom: .2rem;
}
.orn-icon {
  display: block;
  height: auto;
  mix-blend-mode: multiply;
  opacity: .82;
  filter: none;
  box-shadow: none;
}
.orn-thread  { width: clamp(52px, 6vw, 78px); }
.orn-candle  { width: clamp(26px, 3.1vw, 40px); }

/* ── THE DISTAFF, IN THE PAPER ── */
.page-decor {
  position: absolute;
  right: -1.5%;
  bottom: -2%;
  width: clamp(90px, 13%, 170px);
  z-index: 0;
  pointer-events: none;
  user-select: none;
}
.page-decor img {
  display: block;
  width: 100%;
  height: auto;
  opacity: .13;                 /* the same whisper as the marginal runes */
  mix-blend-mode: multiply;
  transform: rotate(-4deg);
}

/* everything written stands in front of it */
.leaf-hands > *:not(.page-decor) { position: relative; z-index: 1; }

@media (max-width: 760px) {
  .hands-head { gap: .8rem; }
  .orn-thread { width: 44px; }
  .orn-candle { width: 22px; }
  .page-decor { width: 90px; right: -2%; bottom: -1%; }
}

/* ═══════════════════════════════════════════════════════════
   THE PAIRED PLATES LOSE THEIR FRAMES

   The mat-and-hairline treatment is right for a PHOTOGRAPH — it
   says "this is an object, and here is where it ends". It is
   wrong for a page: the Malleus and the broadsheet are already
   sheets of paper, so mounting them puts a frame around a frame,
   and the doubled border is what looked cheap.

   Frames off. The sheets sit on the parchment, and the caption
   underneath does the work the border was pretending to do.
   ═══════════════════════════════════════════════════════════ */

.plate-pair .bookplate img {
  box-shadow: none !important;
  background: none !important;
  border-radius: 0 !important;
  border: 0 !important;

  /* they are paper on paper — let ours show through theirs */
  mix-blend-mode: multiply;
  filter: contrast(1.04) brightness(1.02);
}

/* without the mat they can afford to be larger */
.plate-pair .bookplate[data-plate="malleus"] img,
.plate-pair .bookplate[data-plate="broadsheet"] img {
  height: 34vh;
  max-height: 390px;
  object-fit: contain;
}
.plate-pair .bookplate[data-plate="zbruch"] img,
.plate-pair .bookplate[data-plate="codex-open"] img {
  height: 27vh;
  max-height: 290px;
}

/* the caption now carries the whole job of separating them */
.plate-pair figcaption {
  margin-top: .75rem;
  padding-top: .5rem;
  border-top: 1px solid rgba(110, 33, 19, .28);
  border-left: 0;
  padding-left: 0;
  text-align: left;
}

/* ═══════════════════════════════════════════════════════════
   THE TOOLS ON THE SHELF

   All three woodcuts now stand beside the title, in the dead
   band of paper that was doing nothing: the wound distaff, the
   ball of thread, the candle. They are the leaf's entire
   argument in three objects — fibre, and fire.

   They sit on a common BASELINE, like things stood on a shelf,
   not centred like icons in a row. And the thread leans, because
   a ball of twine that has been put down does.
   ═══════════════════════════════════════════════════════════ */

.hands-head {
  align-items: flex-end;
  gap: 1.6rem;
  margin-bottom: .5rem;
}

.hands-head-orn {
  display: flex;
  align-items: flex-end;      /* the shelf */
  gap: 1.1rem;
  flex: none;
  padding-bottom: .1rem;
}

.orn-icon {
  display: block;
  height: auto;
  mix-blend-mode: multiply;
  opacity: .88;
  filter: none;
  box-shadow: none;
  transform-origin: bottom center;
}

/* the distaff — tall, thin, standing up */
.orn-spindle {
  width: clamp(24px, 2.8vw, 36px);
  transform: rotate(-3deg);
  opacity: .8;
}

/* the thread — put down, and leaning */
.orn-thread {
  width: clamp(78px, 9vw, 120px);
  transform: rotate(9deg) translateY(-2px);
}

/* the candle — lit, and upright */
.orn-candle {
  width: clamp(36px, 4.2vw, 56px);
  transform: rotate(1.5deg);
}

/* the background watermark is retired: the tools are on the shelf now */
.page-decor { display: none; }

@media (max-width: 760px) {
  .hands-head { gap: .8rem; }
  .hands-head-orn { gap: .7rem; }
  .orn-spindle { width: 18px; }
  .orn-thread  { width: 58px; }
  .orn-candle  { width: 28px; }
}

/* ═══════════════════════════════════════════════════════════
   THE PLATE CAPTIONS READ PROPERLY

   These are not labels. The Malleus caption carries Kramer's
   humiliation at Innsbruck; the broadsheet's carries the whole
   argument about the press. They are prose, and they were being
   set like footnotes.
   ═══════════════════════════════════════════════════════════ */

.plate-pair figcaption,
.bookplate figcaption {
  font-size: clamp(1rem, 1.16vw, 1.14rem) !important;
  line-height: 1.5 !important;
}
.plate-pair figcaption strong,
.bookplate figcaption strong {
  font-size: 1.08em;
  color: var(--rubric, #6E2113) !important;
}

/* the little rubric tag beneath them — still a tag, but no longer a
   squint. Small caps at 0.6rem is a whisper; at 0.72 it is a remark. */
.cap-note {
  font-size: .72rem;
  letter-spacing: .1em;
  line-height: 1.5;
  opacity: .85;
}

@media (max-width: 760px) {
  .plate-pair figcaption,
  .bookplate figcaption { font-size: clamp(.96rem, 3.9vw, 1.08rem) !important; }
  .cap-note { font-size: .66rem; }
}

/* ═══════════════════════════════════════════════════════════
   THE RED DOOR

   A chapter that opens another chapter. It is not a link and it
   is not a footnote — it is a DOOR, and it is the only red object
   in the book that you are invited to press.

   It sits at the foot of the history, after the questions, so
   that pressing it feels like a decision rather than a click.
   ═══════════════════════════════════════════════════════════ */

.leaf-door { position: relative; }

.dark-door {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  width: 100%;
  margin: 1.4rem 0 .3rem;
  padding: 1rem 1.3rem;

  cursor: pointer;
  text-align: left;
  border: 1px solid rgba(110, 33, 19, .55);
  border-radius: 2px;

  background:
    radial-gradient(ellipse 70% 100% at 8% 50%, rgba(150, 40, 26, .16), transparent 70%),
    linear-gradient(180deg, rgba(110, 33, 19, .13), rgba(78, 20, 12, .07));
  box-shadow:
    inset 0 1px 0 rgba(255, 236, 210, .3),
    0 3px 14px rgba(60, 18, 10, .18);

  transition:
    background .45s ease,
    box-shadow .45s ease,
    border-color .45s ease,
    transform .25s cubic-bezier(.2, .7, .2, 1);
}

.dark-door:hover,
.dark-door:focus-visible {
  border-color: rgba(150, 45, 28, .85);
  background:
    radial-gradient(ellipse 80% 100% at 8% 50%, rgba(170, 50, 30, .3), transparent 72%),
    linear-gradient(180deg, rgba(132, 40, 24, .22), rgba(92, 24, 14, .12));
  box-shadow:
    inset 0 1px 0 rgba(255, 236, 210, .4),
    0 6px 22px rgba(90, 22, 12, .3);
  transform: translateY(-1px);
}
.dark-door:active { transform: translateY(0); }

.dark-door-sigil {
  flex: none;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  color: var(--rubric, #6E2113);
  border: 1px solid rgba(110, 33, 19, .4);
  background: rgba(255, 244, 228, .35);
  transition: transform .8s cubic-bezier(.2, .7, .2, 1), color .4s ease;
}
.dark-door:hover .dark-door-sigil {
  transform: rotate(180deg);        /* it inverts. Of course it does. */
  color: #8E2A18;
}

.dark-door-words { min-width: 0; flex: 1; }

.dark-door-label {
  display: block;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-weight: 600;
  font-size: clamp(1.14rem, 1.4vw, 1.38rem);
  line-height: 1.2;
  color: var(--rubric, #6E2113);
  letter-spacing: .01em;
}
.dark-door-sub {
  display: block;
  margin-top: .18rem;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  font-size: clamp(.92rem, 1.06vw, 1.04rem);
  color: var(--iron-faded, #4A3B26);
}

.dark-door-arrow {
  flex: none;
  font-size: 1.3rem;
  color: var(--rubric, #6E2113);
  opacity: .6;
  transition: transform .5s cubic-bezier(.2, .7, .2, 1), opacity .4s ease;
}
.dark-door:hover .dark-door-arrow {
  transform: translateX(5px);
  opacity: 1;
}

@media (max-width: 760px) {
  .dark-door { padding: .9rem 1rem; gap: .8rem; }
  .dark-door-sigil { width: 36px; height: 36px; }
}

/* ═══════════════════════════════════════════════════════════
   THE STAVE IN THE PAPER

   A way-finding stave, keyed off its white and printed into the
   parchment at a whisper — large, centred, and BEHIND every word
   on the leaf.

   It is set at the same faintness as the marginal runes (about a
   tenth), because it is doing the same job: it tells the eye what
   country it is in without ever asking to be read. Any darker and
   it becomes a picture, and a picture behind text is a mistake.
   ═══════════════════════════════════════════════════════════ */

.leaf-stave { position: relative; }

.stave-decor {
  position: absolute;
  top: 46%;
  left: 50%;
  width: min(92%, 640px);
  transform: translate(-50%, -50%);
  z-index: 0;
  pointer-events: none;
  user-select: none;
}
.stave-decor img {
  display: block;
  width: 100%;
  height: auto;
  opacity: .11;
  mix-blend-mode: multiply;
  transform: rotate(-2deg);
}

/* the writing stands in front of it */
.leaf-stave > *:not(.stave-decor) {
  position: relative;
  z-index: 1;
}

@media (max-width: 760px) {
  .stave-decor { width: 96%; top: 44%; }
  .stave-decor img { opacity: .09; }
}

/* ── THE BINDRUNE, DOWN THE RIGHT ──
   The stave on the Freyja leaf is a wheel, so it sits in the middle.
   This one is a COLUMN — tall, narrow, vertical — so it stands down
   the right-hand side of the page instead, where its shape belongs
   and where it will not run underneath the drop cap. */

.stave-right {
  top: 50%;
  left: auto;
  right: -2%;
  width: min(34%, 240px);
  transform: translateY(-50%);
}
.stave-right img {
  opacity: .12;
  transform: rotate(1.5deg);
}

@media (max-width: 760px) {
  .stave-right { width: 40%; right: -4%; }
  .stave-right img { opacity: .09; }
}

/* ── THE RING OVER THE TITLE ──
   The futhark, closed into a circle, crowning the chapter's first
   leaf. It sits HIGH — behind the chapter number and the title —
   rather than centred, because a ring around a word is a seal, and
   a ring floating in the middle of a paragraph is a stain. */

.leaf-title { position: relative; }

.stave-crown {
  top: 0;
  left: 50%;
  width: min(58%, 400px);
  transform: translate(-50%, -14%);
}
.stave-crown img {
  opacity: .13;
  transform: rotate(-3deg);
}

/* the title stands inside its ring */
.leaf-title .chap-title { position: relative; z-index: 1; }

@media (max-width: 760px) {
  .stave-crown { width: 78%; transform: translate(-50%, -10%); }
  .stave-crown img { opacity: .10; }
}

/* ── THE BINDRUNE MOVES UNDER THE PLATE ──
   It was a thin ghost down the whole right edge. It now sits BENEATH
   the photograph of the staff — in the lower right, where the page
   runs out of picture — and it is far larger, so it reads as a mark
   made on the page rather than a smudge in it.

   Larger means it must also stay faint: a big shape at the same
   opacity as a small one is twice as loud. So it drops a shade. */

.stave-right {
  top: auto;
  bottom: 3%;
  right: 1%;
  left: auto;
  width: min(52%, 380px);
  transform: none;
}
.stave-right img {
  opacity: .10;
  transform: rotate(2deg);
}

@media (max-width: 760px) {
  .stave-right {
    width: 62%;
    right: -2%;
    bottom: 1%;
  }
  .stave-right img { opacity: .085; }
}

/* ── THE HELM, LOW IN THE PAPER ──
   Set in the dead ground at the foot of the scorn-pole leaf, where
   the text runs out and half a page of empty parchment was left
   standing. Large, and very faint. */

.stave-corner {
  top: auto;
  left: auto;
  right: 3%;
  bottom: 2%;
  width: min(46%, 340px);
  transform: none;
}
.stave-corner img {
  opacity: .11;
  transform: rotate(-2.5deg);
}

@media (max-width: 760px) {
  .stave-corner { width: 58%; right: 0; bottom: 1%; }
  .stave-corner img { opacity: .09; }
}

/* ═══════════════════════════════════════════════════════════
   FREYJA'S BINDRUNE FILLS THE FOOT OF THE LEAF

   The rune is a tall, narrow COLUMN, so it must be sized by its
   HEIGHT, not its width — set a width on a shape like this and it
   collapses to a sliver, which is what was happening.

   It now stands in the whole dead half of the page beneath the
   staff photograph: floor to caption, centred in that column.

   And because it is now very large, it drops again in opacity.
   The eye reads total ink, not the setting — a big shape at a
   small shape's opacity is twice as loud.
   ═══════════════════════════════════════════════════════════ */

.stave-right {
  top: auto;
  left: auto;
  right: 12%;
  bottom: 3%;
  width: auto;
  height: 52%;
  max-height: 480px;
  transform: none;
}
.stave-right img {
  width: auto;
  height: 100%;
  opacity: .085;
  transform: rotate(1.5deg);
}

@media (max-width: 760px) {
  .stave-right {
    right: 8%;
    bottom: 2%;
    height: 34%;
  }
  .stave-right img { opacity: .07; }
}

/* ═══════════════════════════════════════════════════════════
   THE BOOKS UNDER MOKOSH

   Full strength, not a watermark. The staves in the paper are
   ghosts because they are ATMOSPHERE; this is an ORNAMENT —
   printed ink at the foot of the column, the way a book puts a
   tailpiece under a plate.

   Multiply still, so the parchment's stains come up through it —
   but at full opacity, so it reads as printed rather than
   remembered.
   ═══════════════════════════════════════════════════════════ */

.mokosh-col { min-width: 0; }

.col-orn {
  display: block;
  width: min(62%, 210px);
  margin: 1.3rem auto .2rem;
}
.col-orn img {
  display: block;
  width: 100%;
  height: auto;
  mix-blend-mode: multiply;
  opacity: .95;
  filter: none;
  box-shadow: none;
  transform: rotate(-1.5deg);
}

@media (max-width: 760px) {
  .col-orn { width: min(52%, 170px); margin-top: 1rem; }
}

/* ═══════════════════════════════════════════════════════════
   THE HELM, VISIBLE

   At 11% he was a rumour. He now reads as a drawing in the paper
   — still behind the words, still multiplied into the parchment,
   but present rather than remembered.

   And he moves: down, and to the left, into the middle of the
   empty ground rather than hugging the outer corner of it.
   ═══════════════════════════════════════════════════════════ */

.stave-corner {
  right: 14%;
  bottom: -3%;
  width: min(52%, 380px);
}
.stave-corner img {
  opacity: .30;
  transform: rotate(-2deg);
}

@media (max-width: 760px) {
  .stave-corner {
    right: 6%;
    bottom: -2%;
    width: 62%;
  }
  .stave-corner img { opacity: .24; }
}

/* ═══════════════════════════════════════════════════════════
   BAPHOMET, BEHIND THE WHOLE LEAF

   Lévi's engraving, 1856 — keyed off its sheet and printed into
   the parchment. It fills the page rather than sitting in a
   corner: the leaf is called "The Path Goes Left", and this is
   the face at the end of it.

   Set far darker than the staves — a fifth, not a tenth. Those
   are watermarks and are meant to be felt; this is meant to be
   SEEN, and half-recognised, before the reader has understood
   why. The words still sit in front of it.
   ═══════════════════════════════════════════════════════════ */

.stave-baphomet {
  top: 52%;
  left: 50%;
  right: auto;
  bottom: auto;
  width: auto;
  height: 88%;
  max-height: 900px;
  transform: translate(-50%, -50%);
}
.stave-baphomet img {
  width: auto;
  height: 100%;
  opacity: .20;
  mix-blend-mode: multiply;
  transform: none;
}

/* the red door must never be lost in him */
.leaf-door .dark-door { position: relative; z-index: 2; }

@media (max-width: 760px) {
  .stave-baphomet { height: 72%; top: 48%; }
  .stave-baphomet img { opacity: .15; }
}

/* ── THE HELM SINKS ──
   He was still overlapping the last paragraph. He now sits well
   clear of it, down in the empty ground at the foot of the leaf,
   and slightly larger for the drop. */

.stave-corner {
  right: 12%;
  bottom: -14%;
  width: min(58%, 420px);
}
.stave-corner img {
  opacity: .32;
}

@media (max-width: 760px) {
  .stave-corner {
    right: 4%;
    bottom: -8%;
    width: 66%;
  }
  .stave-corner img { opacity: .25; }
}

/* ── THE RING RISES ──
   It was sitting around the title like a halo, which read as a
   mistake. It now hangs ABOVE the chapter — most of it off the top
   of the leaf, so only the lower arc of the futhark comes down over
   the heading. Larger, and mostly out of sight, which is what a
   ring of runes should be. */

.stave-crown {
  top: 0;
  left: 50%;
  width: min(92%, 640px);
  transform: translate(-50%, -58%);
}
.stave-crown img {
  opacity: .15;
  transform: rotate(-4deg);
}

@media (max-width: 760px) {
  .stave-crown {
    width: 118%;
    transform: translate(-50%, -55%);
  }
  .stave-crown img { opacity: .12; }
}

/* ── FREYJA'S BINDRUNE RISES TO MEET THE TEXT ──
   It was hanging low, leaving a hand's width of dead paper between
   the caption and the top of the rune. It is anchored from the TOP
   now, not the bottom — so it begins immediately beneath the last
   line of the plate's caption and runs all the way down the leaf. */

.stave-right {
  top: 42%;
  bottom: auto;
  right: 12%;
  left: auto;
  width: auto;
  height: 56%;
  max-height: 520px;
  transform: none;
}
.stave-right img {
  width: auto;
  height: 100%;
  opacity: .10;
  transform: rotate(1.5deg);
}

@media (max-width: 760px) {
  .stave-right {
    top: auto;
    bottom: 1%;
    right: 6%;
    height: 34%;
  }
  .stave-right img { opacity: .08; }
}

/* ═══════════════════════════════════════════════════════════
   THE ALLFATHER, CLOSING THE COLUMN

   Full strength, like the books under Mokosh — an ORNAMENT, not
   a watermark. It drops into the second row of the split's first
   column: directly beneath the Codex plate, in the dead band that
   was left standing between the note and the section break.

   Multiply, so the parchment comes up through the linework, but
   no fade: it is printed, not remembered.
   ═══════════════════════════════════════════════════════════ */

.odin-orn {
  /* He has left the split entirely. He now closes the LEAF — the last
     thing on the page, beneath the four words and the völva. A colophon:
     centred on the full measure, with the text finished above him. */
  display: block;
  width: 72%;
  max-width: 420px;
  margin: 1.8rem auto 0;   /* clear air above; he is an ending, not a caption */
}
.odin-orn img {
  display: block;
  width: 100%;
  height: auto;
  /* Multiply, so the parchment — its grain, its stains — comes up THROUGH
     the linework. The figure is printed on the leaf, not laid over it.
     No opacity, no fade: the ink is at full strength. */
  mix-blend-mode: multiply;
  opacity: 1;
  filter: none;
  box-shadow: none;
  transform: rotate(-1deg);    /* set by hand, like everything else here */
}

/* PHONE: the columns have collapsed, so he simply follows the note */
@media (max-width: 760px) {
  .odin-orn {
    width: 66%;
    max-width: 260px;
    margin: 1.2rem auto .1rem;
  }
}

/* ═══════════════════════════════════════════════════════════
   THE CODEX COLUMNS END LEVEL

   The plate column is short, the argument column is tall, so the
   grid's foot was stepped and left a pale void beside it.

   NOTE: this used to hang off `:has(.odin-orn)`. The Allfather has
   since moved to the foot of the leaf, so that selector would no
   longer match and the step would quietly come back. It is keyed to
   the CODEX plate instead — the thing that is actually short.
   ═══════════════════════════════════════════════════════════ */

/* The plate must NOT stretch — cropping a manuscript to tidy a margin is a
   bad trade. The caption takes up the slack instead, so the column ends
   level without a pixel of the Codex being lost. */
.split:has([data-plate="codex"]) { align-items: stretch; }
.split:has([data-plate="codex"]) .split-plate {
  display: flex;
  flex-direction: column;
}
.split:has([data-plate="codex"]) .split-plate img {
  flex: 0 0 auto;   /* the picture keeps its own height, entire */
}
.split:has([data-plate="codex"]) .split-plate figcaption {
  flex: 1 1 auto;   /* the caption's box grows to the foot of the column */
}

/* ═══════════════════════════════════════════════════════════
   THE SCORN-POLE CREDIT, LEGIBLE

   Under the níðstang the caption is doing real work — it says
   what the drawing shows, and then who drew it. Both lines had
   been shrunk to a whisper: the credit was .72rem small-caps at
   .85 opacity, which on toned paper is a rumour of text.

   A caption nobody can read is a caption that isn't there.
   Bigger, and the ink is put back in it.
   ═══════════════════════════════════════════════════════════ */

/* the sentence: "The pole raised, the head set on it…" */
.split-plate[data-plate="nidstang"] figcaption {
  font-size: clamp(1.06rem, 1.24vw, 1.22rem) !important;
  line-height: 1.55 !important;
  color: var(--iron-gall, #2A2018) !important;   /* the true ink, not the faded */
  opacity: 1;
}
.split-plate[data-plate="nidstang"] figcaption em {
  color: var(--rubric, #6E2113) !important;      /* "gapes" keeps its red */
}

/* the credit: "LOUIS MOE, FOR A DANISH SAXO, 1898." — still a tag in
   small caps, but a tag you can actually read */
.split-plate[data-plate="nidstang"] figcaption .cap-note {
  font-size: .82rem !important;
  letter-spacing: .09em;
  line-height: 1.5;
  color: var(--rubric, #6E2113) !important;
  opacity: 1 !important;                          /* the .85 veil comes off */
  margin-top: .5rem;
}

@media (max-width: 760px) {
  .split-plate[data-plate="nidstang"] figcaption {
    font-size: clamp(1rem, 4vw, 1.12rem) !important;
  }
  .split-plate[data-plate="nidstang"] figcaption .cap-note {
    font-size: .76rem !important;
  }
}

/* ═══════════════════════════════════════════════════════════
   BAPHOMET FILLS THE LEAF

   He was sized by HEIGHT (88%, capped at 900px) and centred, with
   width left to follow. On a tall leaf that left him floating in
   the middle with a dead band of bare parchment beneath him — the
   figure stopped, and the page kept going.

   Now he is pinned to all four edges of the leaf and told to
   COVER it: he scales to whichever side is short and lets the
   other overflow, so there is no page left over. The engraving is
   cropped at the margins, which is exactly what a printed
   full-bleed does.
   ═══════════════════════════════════════════════════════════ */

/* WHY THIS IS FIDDLY, so it is not "fixed" back to broken later:
   he sits inside .page-inner, which is the SCROLLING, PADDED box. An
   absolutely-positioned child of it is laid out against its PADDING box,
   so inset:0 stops short of the leaf's edge by the padding — and its
   height:100% resolves against the visible box, not the scroll height.
   Both together were the dead band under him.

   So: pin him to .page-inner but CANCEL its padding with negative insets
   (the same clamp() values .page-inner uses), and take the height from the
   leaf rather than the text. He then reaches all four edges of the page. */
.leaf-stave:has(.stave-baphomet) { position: static; }

.stave-baphomet {
  position: absolute;
  top:    calc(-1 * clamp(2rem, 4.2vh, 3.6rem));
  bottom: calc(-1 * clamp(2rem, 4.2vh, 3.6rem));
  left:   calc(-1 * clamp(1.6rem, 3.4vw, 3.4rem));
  right:  calc(-1 * clamp(1.6rem, 3.4vw, 3.4rem));
  width: auto;
  height: auto;
  min-height: 100%;
  max-height: none;
  transform: none;
  /* no clipping of his own: .page already has overflow:hidden, so the LEAF
     crops him at its edge. That is a full bleed — the plate runs off the
     paper, as a printed one does. */
  z-index: 0;
}
.stave-baphomet img {
  width: 100%;
  height: 100%;
  object-fit: cover;        /* fill the leaf; crop what spills past the edge */
  object-position: 50% 38%; /* the horns and the face held in view */
  opacity: .22;             /* bigger now, so he can afford to be darker */
  mix-blend-mode: multiply;
  transform: none;
}

@media (max-width: 760px) {
  .stave-baphomet { inset: 0; height: auto; top: 0; }
  .stave-baphomet img {
    object-position: 50% 40%;
    opacity: .16;          /* a phone leaf is mostly text — he must not shout */
  }
}

/* ═══════════════════════════════════════════════════════════
   THE PATH GOES LEFT — INK AND THE TURNING SIGIL

   1. The leaf is the hinge of the whole book: it is where the
      history hands over to the Dark Path. Its type was set at
      the ordinary chapter weight and, over Baphomet's ground,
      it was going grey. It takes the true iron-gall now, and a
      size that matches its importance.

   2. The pentagram turns. It was doing a single 180° flip on
      hover; now it turns CONSTANTLY — slowly, the way the
      illumination on the title page does — and it is larger.
      A door with a moving sigil is a door that is open.
   ═══════════════════════════════════════════════════════════ */

/* ── THE TYPE ── */
.leaf-door p {
  font-size: clamp(1.12rem, 1.3vw, 1.3rem) !important;
  line-height: 1.72 !important;
  color: var(--iron-gall, #2A2018) !important;
}
.leaf-door .chap-head {
  font-size: clamp(2.1rem, 2.7vw, 2.9rem) !important;
  color: var(--iron-gall, #2A2018) !important;
}
.leaf-door .lore p {
  font-size: clamp(1.06rem, 1.22vw, 1.2rem) !important;
  line-height: 1.65 !important;
  color: var(--iron-gall, #2A2018) !important;
}
.leaf-door .chap-note {
  font-size: clamp(1.04rem, 1.2vw, 1.18rem) !important;
  color: var(--iron-faded, #4A3B26) !important;
  opacity: 1 !important;
}
/* the rubric words keep their red, only stronger */
.leaf-door strong { color: var(--rubric, #6E2113) !important; }

/* ── THE SIGIL, TURNING ── */
@keyframes sigil-turn {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.dark-door-sigil {
  width: 58px;                       /* was 42 */
  height: 58px;
  border-width: 1px;
}
.dark-door-sigil svg {
  width: 30px;                       /* the star itself, not just its dish */
  height: 30px;
  /* it turns, always — slowly enough to be felt rather than watched */
  animation: sigil-turn 24s linear infinite;
  transform-origin: 50% 50%;
}
/* ── THE TURN, AND THE INVERSION ──
   Two motions on two elements, so they never fight:

     · the STAR (svg) spins, always, on its own animation;
     · the RING (span) is idle — so the hover flip lives THERE.

   Putting the 180° on the svg would not work: the spin animation owns
   its `transform` and simply overwrites it. Keeping them on separate
   elements means the pentagram can invert WHILE it is still turning. */
.dark-door-sigil {
  /* the ring carries the flip; the transition makes it a turn, not a jump */
  transition: transform .7s cubic-bezier(.2, .7, .2, 1), color .4s ease;
}
.dark-door:hover .dark-door-sigil,
.dark-door:focus-visible .dark-door-sigil {
  transform: rotate(180deg);   /* it inverts. Of course it does. */
  color: #8E2A18;
}
.dark-door:hover .dark-door-sigil svg,
.dark-door:focus-visible .dark-door-sigil svg {
  animation-duration: 6s;      /* and it quickens — the door notices you */
}

/* the words grow to keep the button in proportion with its new sigil */
.dark-door-label { font-size: clamp(1.24rem, 1.52vw, 1.5rem); }
.dark-door-sub   { font-size: clamp(.98rem, 1.14vw, 1.12rem); }

@media (max-width: 760px) {
  .dark-door-sigil { width: 48px; height: 48px; }
  .dark-door-sigil svg { width: 26px; height: 26px; }
  .leaf-door p { font-size: clamp(1.06rem, 4.2vw, 1.18rem) !important; }
}

/* someone who has asked for stillness gets stillness */
@media (prefers-reduced-motion: reduce) {
  .dark-door-sigil svg { animation: none; }
}

/* ═══════════════════════════════════════════════════════════
   THE MARK, LARGER

   The sigil was carrying the whole brand and reading as a
   bullet point beside the words. It grows — and the rule and
   the wordmark grow with it, because a lockup scaled in one
   part only is a lockup that looks broken.
   ═══════════════════════════════════════════════════════════ */

.brand-mark {
  width: clamp(64px, 7.4vw, 104px) !important;   /* was 46 → 72 */
}

/* the hairline beside it keeps its proportion to the mark */
.brand-rule {
  height: clamp(52px, 6vw, 82px) !important;
}

@media (max-width: 640px) {
  .brand-mark { width: 58px !important; }
  .brand-rule { height: 48px !important; }
}

.brand-name {
  font-size: clamp(1.5rem, 2.7vw, 2.2rem) !important;
}
.brand-sub {
  font-size: clamp(.54rem, .92vw, .68rem) !important;
  letter-spacing: .3em;
}
@media (max-width: 640px) {
  .brand-name { font-size: 1.35rem !important; }
  .brand-sub  { font-size: .48rem !important; }
}

/* ═══════════════════════════════════════════════════════════
   THE PATH GOES LEFT — GET THE DOOR ABOVE THE FOLD

   Measured: the closing note sat at 828px and the door at 893px,
   on a leaf whose visible bottom is 759px. Both were BELOW THE
   FOLD — 324px of scrolling before you saw either. The line was
   not faint; it was off the page.

   So the leaf is tightened rather than restyled: the air comes
   out of the margins, the panel, and the door, until the ending
   lands on the page it belongs to.
   ═══════════════════════════════════════════════════════════ */

/* ── 1. the paragraphs stop sprawling ── */
.leaf-door p {
  margin-top: .55rem;
  margin-bottom: .55rem;
  line-height: 1.6 !important;   /* was 1.72 */
}
.leaf-door .chap-head {
  margin: .1rem 0 .5rem;
}
.leaf-door .folio-eyebrow {
  margin-bottom: .7rem;
}

/* ── 2. the lore panel gives back its padding ── */
.leaf-door .lore {
  margin: .8rem 0;
  padding: .85rem 1rem .85rem 1.6rem;
}
.leaf-door .lore p {
  margin: .38rem 0;
  line-height: 1.5 !important;
}

/* ── 3. THE CLOSING NOTE — dark, and on the page ──
   It is the punchline of the leaf. It takes the true ink, not the
   faded iron it was set in (rgb 74,59,38 — a whisper on parchment). */
.leaf-door .chap-note {
  margin: .8rem 0 .9rem;
  font-size: clamp(1.06rem, 1.22vw, 1.2rem) !important;
  line-height: 1.5 !important;
  color: var(--iron-gall, #2A2018) !important;
  opacity: 1 !important;
}

/* ── 4. the door rises ── */
.leaf-door .dark-door {
  margin-top: .5rem !important;
  padding: .85rem 1.1rem !important;
}

/* ── AND ON A SHORTER LEAF ──
   At 1440 the ending cleared the fold; at 1280 and below it did not,
   because the leaf loses height faster than the text does. The type on
   this page was raised for legibility, so the saving has to come from
   the SPACING, not by shrinking it back down again. */
@media (max-width: 1366px) {
  .leaf-door p            { margin: .42rem 0; line-height: 1.52 !important; }
  .leaf-door .lore        { margin: .6rem 0; padding: .7rem .9rem .7rem 1.45rem; }
  .leaf-door .lore p      { margin: .3rem 0; line-height: 1.44 !important; }
  .leaf-door .chap-head   { margin: .05rem 0 .38rem; }
  .leaf-door .chap-note   { margin: .6rem 0 .7rem; line-height: 1.44 !important; }
  .leaf-door .dark-door   { margin-top: .35rem !important; padding: .72rem 1rem !important; }
  .leaf-door .dark-door-sub { display: none; }   /* the label carries it alone */
}

/* PHONE: the leaf is a single narrow column and every line costs height.
   The panel keeps its four facts; everything around it gives way. */
@media (max-width: 760px) {
  .leaf-door p          { margin: .38rem 0; line-height: 1.5 !important; }
  .leaf-door .lore      { margin: .55rem 0; padding: .65rem .8rem .65rem 1.35rem; }
  .leaf-door .lore p    { margin: .28rem 0; line-height: 1.42 !important; }
  .leaf-door .chap-note { margin: .55rem 0 .6rem; }
  .leaf-door .dark-door { margin-top: .3rem !important; padding: .7rem .9rem !important; }
}

/* ═══════════════════════════════════════════════════════════
   THE DARK PATH — DARKER INK

   Measured on the Left-Hand Path leaf: the body was sitting at
   rgb(42,32,21) and the closing note at rgb(69,53,31) — a good
   deal lighter than the iron-gall the rest of the book is set
   in, and washing out badly against the toned parchment.

   These pages are the argument the whole book has been walking
   toward. They should read like the darkest ink in it, not the
   faintest. Every level goes to a true black-brown, and the
   notes lose the last of their grey.
   ═══════════════════════════════════════════════════════════ */

.dp-leaf p,
.dp-leaf li {
  color: #17110A !important;
  opacity: 1 !important;
}
.dp-leaf .chap-head {
  color: #120D07 !important;
  opacity: 1 !important;
}
.dp-leaf .folio-eyebrow {
  color: #2E2416 !important;
  opacity: 1 !important;
}
/* the notes were the palest thing on the page. No longer. */
.dp-leaf .chap-note {
  color: #241B10 !important;
  opacity: 1 !important;
}
.dp-leaf .lore p {
  color: #17110A !important;
  opacity: 1 !important;
}
.dp-leaf .lore-said {
  color: #2A1F12 !important;
  opacity: 1 !important;
}
/* the rubric stays red — but a deeper, more saturated red, or it
   looks pink beside ink this dark */
.dp-leaf strong,
.dp-leaf .drop {
  color: #5E1A0F !important;
}
.dp-leaf em { color: inherit !important; }

/* ═══════════════════════════════════════════════════════════
   THE SEALED PAPER

   The Satanism and Dark Path leaves are printed on a different
   sheet: paper bearing the Sigil of Baphomet as a watermark —
   the pentagram, the goat, and the Hebrew of Leviathan around
   the rim.

   The photograph came in at L=132 against the book's L=176, so
   it has been matched channel by channel to the vellum used
   everywhere else: same value, same warmth, same contrast. The
   watermark survives the correction because the map is linear —
   it lifts the paper without flattening the seal.

   HISTORY KEEPS ITS OWN PAPER. Only these two chapters turn.
   ═══════════════════════════════════════════════════════════ */

body[data-chapter="satanism"] .grimoire .page,
body[data-chapter="gods"] .grimoire .page,
body[data-chapter="blood"] .grimoire .page,
body[data-chapter="darkpath"] .grimoire .page {
  background-image: url('../media/paper-satan.webp');
  background-size: cover;
  background-position: center;
}

/* The verso would otherwise show the SAME sheet — the seal twice in
   the same place across one spread, which no real book does. Mirroring
   the background turns the leaf over instead: the same paper, its back. */
body[data-chapter="satanism"] .grimoire .page-left,
body[data-chapter="gods"] .grimoire .page-left,
body[data-chapter="blood"] .grimoire .page-left,
body[data-chapter="darkpath"] .grimoire .page-left {
  /* the same sheet, turned over — a PRE-FLIPPED image, not a transform.
     .page-left needs its transform for the phone's leaf positioning, and
     scaleX(-1) here threw the current leaf clean off the screen. */
  background-image: url('../media/paper-satan-verso.webp');
}

@media (max-width: 760px) {
  body[data-chapter="satanism"] .grimoire .page,
  body[data-chapter="darkpath"] .grimoire .page {
    background-image: url('../media/paper-satan-sm.webp');
  }
}

/* ═══════════════════════════════════════════════════════════
   THE SATANISM OPENING — FIT THE ARGUMENT ON THE LEAF

   This page carries a chapter title, a standfirst, an ornament,
   an opening, a three-part argument AND the closing question.
   The argument is the reason the chapter exists, so it stays;
   the SPACING gives way instead.
   ═══════════════════════════════════════════════════════════ */

body[data-chapter="satanism"] .page-inner .dp-leaf .chap-title {
  margin: .1rem 0 .35rem;
}
body[data-chapter="satanism"] .page-inner .dp-leaf .chap-standfirst {
  margin: 0 0 .6rem;
  line-height: 1.45;
}
body[data-chapter="satanism"] .page-inner .dp-leaf .page-orn {
  margin: .55rem auto .65rem;
}
body[data-chapter="satanism"] .page-inner .dp-leaf > p {
  margin: .5rem 0;
  line-height: 1.55 !important;
}
body[data-chapter="satanism"] .page-inner .dp-leaf .lore {
  margin: .7rem 0;
  padding: .8rem .95rem .8rem 1.5rem;
}
body[data-chapter="satanism"] .page-inner .dp-leaf .lore p {
  margin: .34rem 0;
  line-height: 1.46 !important;
}
body[data-chapter="satanism"] .page-inner .dp-leaf .chap-note {
  margin: .65rem 0 0;
  line-height: 1.45 !important;
}

/* the leaf loses height faster than the words do, so the smaller it gets,
   the harder this page has to be squeezed */
@media (max-width: 1366px) {
  body[data-chapter="satanism"] .page-inner .dp-leaf .chap-standfirst {
    margin-bottom: .45rem; line-height: 1.38;
  }
  body[data-chapter="satanism"] .page-inner .dp-leaf .page-orn { margin: .4rem auto .5rem; }
  body[data-chapter="satanism"] .page-inner .dp-leaf > p {
    margin: .38rem 0; line-height: 1.46 !important;
  }
  body[data-chapter="satanism"] .page-inner .dp-leaf .lore {
    margin: .55rem 0; padding: .65rem .8rem .65rem 1.35rem;
  }
  body[data-chapter="satanism"] .page-inner .dp-leaf .lore p {
    margin: .28rem 0; line-height: 1.4 !important;
  }
  body[data-chapter="satanism"] .page-inner .dp-leaf .chap-note {
    margin-top: .5rem; line-height: 1.4 !important;
  }
}

@media (max-width: 760px) {
  body[data-chapter="satanism"] .page-inner .dp-leaf .page-orn { display: none; }
  body[data-chapter="satanism"] .page-inner .dp-leaf > p { margin: .34rem 0; }
  body[data-chapter="satanism"] .page-inner .dp-leaf .lore { margin: .5rem 0; }
  body[data-chapter="satanism"] .page-inner .dp-leaf .lore p { margin: .26rem 0; }
}

/* ═══════════════════════════════════════════════════════════
   THE SHARDS — THREE PLATES

   The broadsheet is ink on cheap paper; the sigil is a line
   drawing. Both belong to the leaf and print INTO it. The
   Hellfire etching is hand-coloured, so it does not: it is a
   picture pasted in, and it keeps its colour and its mount.
   ═══════════════════════════════════════════════════════════ */

/* Brinvilliers — a broadsheet, so it prints like one */
.split-plate[data-plate="brinvilliers"] img {
  width: 100%;
  height: auto;
  filter: none;
  mix-blend-mode: multiply;
  opacity: .96;
  box-shadow: none;
}

/* de Guaita's plate — BOTH circles: Adam upright above, the Goat of Mendes
   inverted below. The white ground is keyed out, so the parchment comes up
   through the line and it prints into the leaf rather than sitting on it. */
/* the Hellfire club — hand-coloured, so it is MOUNTED, not printed.
   Multiply would turn the reds to mud on this paper. */
.bookplate-wide[data-plate="hellfire"] {
  float: none;
  clear: both;
  width: 100%;
  max-width: none;
  margin: .9rem 0 .2rem;
}
.bookplate-wide[data-plate="hellfire"] img {
  width: 100%;
  height: auto;
  mix-blend-mode: normal;      /* keep the colour — multiply would mud the reds */
  filter: sepia(.14) contrast(1.05) saturate(.92);
  box-shadow: none;            /* NO FRAME: its own paper melts into the leaf */
  border: 0;
  border-radius: 0;
}

/* The Hellfire etching is landscape and was eating the leaf. Cap it, so the
   argument beneath it stays on the page. */
.bookplate-wide[data-plate="hellfire"] img {
  max-height: 300px;
  object-fit: contain;
}
@media (max-width: 1366px) {
  .bookplate-wide[data-plate="hellfire"] img { max-height: 240px; }
  .bookplate-wide[data-plate="hellfire"] { margin: .6rem 0 .1rem; }
}
@media (max-width: 760px) {
  .bookplate-wide[data-plate="hellfire"] img { max-height: 200px; }
}

/* ═══════════════════════════════════════════════════════════
   THE SEALED CHAPTERS — BLACK INK AND BLOOD

   Darker, bigger, and RED where the red does work. Three
   depths of it, not one:

     · rubric   — the bold clause that carries the sentence
     · blood    — the drop cap, the numbers, the names
     · deep     — the closing turn, where the page bites

   And the type comes up, because these are the pages people
   will actually sit and read.
   ═══════════════════════════════════════════════════════════ */

.dp-leaf {
  --ink:    #0F0B06;   /* very nearly black — this is the page's voice */
  --rubric: #7A1710;   /* dark blood */
  --blood:  #8E1B10;   /* a shade brighter, for names and numerals */
  --deep:   #5A0F09;   /* the deepest — the turn of the argument */
}

/* ── THE INK ── */
.dp-leaf p,
.dp-leaf li,
.dp-leaf .lore p {
  color: var(--ink) !important;
  opacity: 1 !important;
  font-size: clamp(1.12rem, 1.3vw, 1.28rem) !important;
  line-height: 1.62 !important;
}
.dp-leaf .chap-head {
  color: #0A0704 !important;
  font-size: clamp(2.1rem, 2.6vw, 2.8rem) !important;
}
.dp-leaf .chap-title {
  color: #0A0704 !important;
}
.dp-leaf .chap-note {
  color: #140E08 !important;
  font-size: clamp(1.08rem, 1.24vw, 1.22rem) !important;
  opacity: 1 !important;
}
.dp-leaf .folio-eyebrow {
  color: var(--deep) !important;
  opacity: .9 !important;
}

/* ── THE BLOOD ── */
.dp-leaf strong {
  color: var(--rubric) !important;
  font-weight: 600;
}
.dp-leaf .drop {
  color: var(--blood) !important;
}
/* the emphasis is the WRITER's voice — it stays in ink, italic, so the red
   never becomes wallpaper. Red everywhere is red nowhere. */
.dp-leaf em {
  color: inherit !important;
  font-style: italic;
}
/* except the closing turn of a page, which earns the deepest red */
.dp-leaf .chap-note strong,
.dp-leaf .chap-note em {
  color: var(--deep) !important;
}
.dp-leaf .lore-said {
  color: var(--deep) !important;
  opacity: 1 !important;
}
/* the panel's star, and the section-break glyph */
.dp-leaf .lore-mark,
.dp-leaf .section-break svg {
  color: var(--blood) !important;
  opacity: .85;
}
/* the standfirst: the promise at the head of a chapter */
.dp-leaf .chap-standfirst {
  color: #1A1209 !important;
  font-size: clamp(1.14rem, 1.34vw, 1.32rem) !important;
}
.dp-leaf .chap-standfirst em {
  color: var(--deep) !important;
}

/* ── THE CAPTIONS keep their place: they are apparatus, not voice ── */
.dp-leaf figcaption { color: #2A2015 !important; }
.dp-leaf .cap-note  { color: var(--rubric) !important; opacity: 1 !important; }

@media (max-width: 1366px) {
  .dp-leaf p, .dp-leaf li, .dp-leaf .lore p {
    font-size: clamp(1.04rem, 1.2vw, 1.16rem) !important;
    line-height: 1.5 !important;
  }
  .dp-leaf .chap-note { font-size: clamp(1rem, 1.14vw, 1.12rem) !important; }
}

/* ── THE BOLD MUST ACTUALLY BE RED ──
   `.page-inner strong` and `.lore p strong` both hard-set a black ink with
   !important, and `.lore p strong` outranks a bare `.dp-leaf strong`. So the
   red has to be claimed at a specificity that beats them, or every bold word
   in these chapters silently paints black — which is what was happening. */
.page-inner .dp-leaf strong,
.page-inner .dp-leaf .lore p strong,
.page-inner .dp-leaf p strong,
.page-inner .dp-leaf li strong {
  color: var(--rubric, #7A1710) !important;
  font-weight: 600;
}
/* the closing turn keeps the deepest red */
.page-inner .dp-leaf .chap-note strong {
  color: var(--deep, #5A0F09) !important;
}
/* and the drop cap the brightest */
.page-inner .dp-leaf .drop {
  color: var(--blood, #8E1B10) !important;
}

/* ═══════════════════════════════════════════════════════════
   THE DOUBLE LEAF

   "He Was a Job" and "A Crime With No Criminals" now share one
   page — two eyebrows, two headings, a panel and two notes. It
   is the fullest leaf in the book, so it is set tighter than
   its neighbours: the argument stays, the air goes.
   ═══════════════════════════════════════════════════════════ */

.dp-leaf:has(.section-break) .chap-head {
  margin: .05rem 0 .4rem;
  font-size: clamp(1.85rem, 2.25vw, 2.4rem) !important;
}
.dp-leaf:has(.section-break) .folio-eyebrow {
  margin: 0 0 .3rem;
}
.dp-leaf:has(.section-break) > p {
  margin: .45rem 0;
  line-height: 1.55 !important;
}
.dp-leaf:has(.section-break) .lore {
  margin: .6rem 0;
  padding: .7rem .9rem .7rem 1.45rem;
}
.dp-leaf:has(.section-break) .lore p {
  margin: .3rem 0;
  line-height: 1.46 !important;
}
.dp-leaf:has(.section-break) .chap-note {
  margin: .5rem 0;
  line-height: 1.48 !important;
}
/* the break between the two halves: a rule, not a gulf */
.dp-leaf:has(.section-break) .section-break {
  margin: .7rem auto .6rem;
}

@media (max-width: 1366px) {
  .dp-leaf:has(.section-break) > p,
  .dp-leaf:has(.section-break) .lore p {
    line-height: 1.42 !important;
  }
  .dp-leaf:has(.section-break) > p { margin: .35rem 0; }
  .dp-leaf:has(.section-break) .lore { margin: .5rem 0; padding: .6rem .8rem .6rem 1.3rem; }
  .dp-leaf:has(.section-break) .chap-note { margin: .4rem 0; }
  .dp-leaf:has(.section-break) .section-break { margin: .55rem auto .45rem; }
}

/* at 1280 the leaf loses height faster than the words do, and this is the
   fullest page in the book — so it gives up its last slack there */
@media (max-width: 1366px) {
  .dp-leaf:has(.section-break) .chap-head {
    font-size: clamp(1.7rem, 2.05vw, 2.1rem) !important;
    margin: .02rem 0 .3rem;
  }
  .dp-leaf:has(.section-break) > p,
  .dp-leaf:has(.section-break) .chap-note {
    font-size: clamp(1rem, 1.14vw, 1.1rem) !important;
    line-height: 1.4 !important;
  }
  .dp-leaf:has(.section-break) .lore p {
    font-size: clamp(.98rem, 1.1vw, 1.06rem) !important;
  }
  .dp-leaf:has(.section-break) .section-break { margin: .45rem auto .35rem; }
}

/* ═══════════════════════════════════════════════════════════
   THE FRONT MATTER — ITS OWN SHEET

   The title leaf ("Opened at the threshold") and the contents
   ("The Book Entire") are printed on the same unmarked stock as
   the sealed chapters — the paper, without the seal.

   Scoped to `body:not(.in-chapter)`, which is precisely the
   front matter: the engine drops that class the moment a
   chapter opens, so no chapter can inherit this by accident.
   ═══════════════════════════════════════════════════════════ */

body:not(.in-chapter) .grimoire .page {
  background-image: url('../media/paper-front.webp');
  background-size: cover;
  background-position: center;
}

/* the verso is the same sheet, turned over */
body:not(.in-chapter) .grimoire .page-left {
  /* pre-flipped image, NOT a transform — see above */
  background-image: url('../media/paper-front-verso.webp');
}

@media (max-width: 760px) {
  body:not(.in-chapter) .grimoire .page {
    background-image: url('../media/paper-front-sm.webp');
  }
}

/* ── AND THE FRONT MATTER'S FAINTEST INK COMES UP TO MEET IT ──
   This sheet is darker than the vellum the front matter was set for. Measured
   against it, the contents glosses fell to 3.2:1 — under the readable floor —
   while everything else held. So only the pale things are lifted. */
body:not(.in-chapter) .entry-gloss {
  color: #3A2C1B !important;   /* was the faded iron, and it vanished */
  opacity: 1 !important;
}
body:not(.in-chapter) .grim-sub,
body:not(.in-chapter) .grim-note,
body:not(.in-chapter) .contents-foot {
  color: #2A2015 !important;
  opacity: 1 !important;
}
body:not(.in-chapter) .num,
body:not(.in-chapter) .pg {
  opacity: 1 !important;
}
body:not(.in-chapter) .leader {
  opacity: .6 !important;
}
body:not(.in-chapter) .folio {
  opacity: .8 !important;
}

/* ═══════════════════════════════════════════════════════════
   THE EPIGRAPHS

   Two quotations, seven centuries apart, saying the same thing.
   They are the argument of the book made before a chapter is
   opened — so they are set as a DIALOGUE, not as two stacked
   paragraphs: each indented from its own side, with a hairline
   between them, so the eye reads a call and an answer.
   ═══════════════════════════════════════════════════════════ */

.grim-epigraph {
  margin: 0;
  padding: 0;
  border: 0;
  max-width: 25rem;
  align-self: center;
  flex: none;
}
.grim-epigraph:first-of-type {
  margin: clamp(1rem, 2.4vh, 1.7rem) 0 0;
}

.grim-epigraph p {
  margin: 0;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  font-size: clamp(1rem, 2vh, 1.22rem);
  line-height: 1.5;
  text-align: center;
  color: var(--iron-gall, #2A2018);
}
.grim-epigraph p em {
  font-style: italic;
  color: var(--rubric, #6E2113);   /* the phrase that carries it */
}

.grim-epigraph cite {
  display: block;
  margin-top: .3rem;
  font-family: 'Spectral SC', Georgia, serif;
  font-style: normal;
  font-size: clamp(.56rem, 1.05vh, .66rem);
  letter-spacing: .18em;
  text-transform: uppercase;
  text-align: center;
  color: var(--iron-faded, #574835);
  opacity: .85;
}

/* ── THE HINGE ──
   A hairline between the two, with a lozenge on it. Seven hundred years
   pass in that gap, and the page should show it. */
.grim-epigraph:first-of-type::after {
  content: '';
  display: block;
  width: 38%;
  height: 1px;
  margin: clamp(.8rem, 1.9vh, 1.3rem) auto;
  background: linear-gradient(to right,
              transparent, rgba(110, 33, 19, .38), transparent);
}

@media (max-width: 760px) {
  .grim-epigraph { max-width: 88%; }
  .grim-epigraph p { font-size: clamp(.96rem, 4vw, 1.08rem); }
}

/* ── THE TITLE LEAF NOW CARRIES MORE, SO IT IS SET TIGHTER ──
   Title, subtitle, TWO epigraphs, an ornament and the colophon. At 1280 the
   colophon was falling off the foot. The epigraphs are the argument of the
   book and the note is its provenance — both stay; the air gives way. */
.page-inner:has(.grim-epigraph) .illum {
  width: clamp(90px, 11vh, 140px);
  margin-bottom: clamp(.6rem, 1.4vh, 1.1rem);
}
.page-inner:has(.grim-epigraph) .grim-title {
  margin-bottom: .8rem;
}
.page-inner:has(.grim-epigraph) .grim-sub {
  margin-bottom: 0;
}
.page-inner:has(.grim-epigraph) .page-orn {
  margin: clamp(.9rem, 2vh, 1.5rem) auto;
}
.page-inner:has(.grim-epigraph) .grim-note {
  line-height: 1.6;
}

@media (max-width: 1366px) {
  .page-inner:has(.grim-epigraph) .illum {
    width: clamp(76px, 9vh, 110px);
    margin-bottom: .55rem;
  }
  .page-inner:has(.grim-epigraph) .grim-title { margin-bottom: .55rem; }
  .grim-epigraph:first-of-type { margin-top: .8rem; }
  .grim-epigraph:first-of-type::after { margin: .65rem auto; }
  .page-inner:has(.grim-epigraph) .page-orn { margin: .75rem auto; }
  .page-inner:has(.grim-epigraph) .grim-note {
    font-size: clamp(.86rem, 1.7vh, .98rem);
    line-height: 1.55;
  }
}

/* ── THE COLOPHON TURNS ──
   The note does two things: it says what the book IS, and then it says where
   the craft came from. The second half is the writer speaking, so it is set
   apart — a beat, and a shift into the personal — without becoming a
   separate paragraph and eating the leaf's last inch of height. */
.grim-note-turn {
  display: block;
  margin-top: .55rem;
  font-style: italic;
  color: var(--iron-gall, #2A2018);
}
.grim-note-turn::before {
  content: '';
  display: block;
  width: 2.2rem;
  height: 1px;
  margin: 0 auto .5rem;
  background: rgba(110, 33, 19, .32);
}

/* ═══════════════════════════════════════════════════════════
   LUCIFER, DOWN THE RIGHT OF THE LEAF

   The light-bringer, on the page that explains he was never a
   person at all — only an office, and a mistranslation.

   He is CROPPED in the source: the wings run off the top and the
   right of the drawing. Rather than fake the missing feathers, the
   ink is dissolved into the paper at those two edges — so he leaves
   the page rather than being cut by it. A hard edge reads as a
   mistake; a bleed reads as a choice.

   He stands BEHIND the writing. The words have to win.
   ═══════════════════════════════════════════════════════════ */

.leaf-lucifer { position: relative; }

/* the writing stands in front of him */
.leaf-lucifer > *:not(.stave-decor) {
  position: relative;
  z-index: 1;
}

/* ── AND THE TEXT MUST NOT DROWN IN HIM ──
   The lore panel sits right where his torso falls. It takes a little more
   of the paper back, so the words keep their ground. */
.leaf-lucifer .lore {
  background: rgba(232, 220, 195, .5);
  backdrop-filter: none;
}

/* ═══════════════════════════════════════════════════════════
   THE GOAT ON THE BROOM

   A tailpiece at the foot of the chapter opening — the thing the
   inquisitors thought they were hunting, riding through the stars.
   Which is the joke: the page above it has just explained that
   nobody was doing this.

   Printed at FULL STRENGTH — multiply, no fade, no opacity drop.
   The parchment comes up through the linework; the ink does not
   give way to it.
   ═══════════════════════════════════════════════════════════ */

/* The opening leaf was ALREADY at its limit before the goat arrived — it was
   squeezed once to keep the closing question on the page. So the tailpiece has
   to be modest, and the leaf gives up its last air to hold him. */
body[data-chapter="satanism"] .page-inner .dp-leaf .lore {
  margin: .5rem 0;
  padding: .6rem .8rem .6rem 1.35rem;
}
body[data-chapter="satanism"] .page-inner .dp-leaf .lore p {
  margin: .24rem 0;
  line-height: 1.38 !important;
}
body[data-chapter="satanism"] .page-inner .dp-leaf > p {
  margin: .32rem 0;
  line-height: 1.44 !important;
}
body[data-chapter="satanism"] .page-inner .dp-leaf .chap-note {
  margin: .4rem 0 0;
  line-height: 1.4 !important;
}
body[data-chapter="satanism"] .page-inner .dp-leaf .chap-standfirst {
  margin-bottom: .35rem;
  line-height: 1.35;
}

/* The star-rule under the standfirst is pure decoration, and it is redundant
   now that a real woodcut closes the leaf. It goes, and the goat gets its
   space. Ornament that costs you the argument is not ornament; it is clutter. */
body[data-chapter="satanism"] .page-inner .dp-leaf .page-orn {
  display: none;
}


/* ═══════════════════════════════════════════════════════════
   THE GOAT, LARGER

   He was 22% of the leaf — a postage stamp, and the whole point of
   him is the joke: the page has just explained that nobody was
   doing this, and then here is the exact thing they thought they
   were hunting.

   A joke that small is not a joke. He roughly doubles. The room
   comes out of the leaf's spacing, not out of the argument.
   ═══════════════════════════════════════════════════════════ */

/* and the leaf gives up the last of its air to hold him */
body[data-chapter="satanism"] .page-inner .dp-leaf .chap-standfirst {
  margin-bottom: .25rem;
  line-height: 1.3;
}
body[data-chapter="satanism"] .page-inner .dp-leaf > p {
  margin: .26rem 0;
  line-height: 1.4 !important;
}
body[data-chapter="satanism"] .page-inner .dp-leaf .lore {
  margin: .4rem 0;
  padding: .5rem .7rem .5rem 1.25rem;
}
body[data-chapter="satanism"] .page-inner .dp-leaf .lore p {
  margin: .2rem 0;
  line-height: 1.34 !important;
}
body[data-chapter="satanism"] .page-inner .dp-leaf .chap-note {
  margin: .3rem 0 0;
  line-height: 1.36 !important;
}

/* ── SIZED BY HIS OWN SHAPE ──
   He is a WIDE, SHORT drawing, and I was sizing him by width while capping his
   height — so every increase in width was immediately clipped by the cap. Size
   him by HEIGHT and let the width follow: he grows into the space he already
   occupies rather than demanding more of it.

   And the argument in the panel above him stays. A picture does not get to
   evict a paragraph. */
/* The plate is 0.76 — TALLER than wide — so height-driven sizing shrank him.
   Width-driven, with a generous height cap: he takes the width of the measure,
   and the leaf is squeezed to afford the height. */
/* ── HE SITS ON THE LEAF, NOT PAST IT ──
   At 56% he was hanging 83px below the paper and the page was clipping his
   broom-tail. Backed off just enough that the whole woodcut lands on the
   sheet — still roughly 1.6x the size he started at, and the argument above
   him is untouched. */
/* ═══════════════════════════════════════════════════════════
   THE SHARDS LEAF

   Two sections on one page — the crimes and the clubs, then the
   poets who crowned him — so the reader scrolls one continuous
   argument instead of turning mid-thought.

   Lévi's Baphomet stands in the second half, on the right, keyed
   out of his white plate and printed INTO the parchment. He is
   the subject of the paragraph beside him: the most satanic image
   in the world, drawn by a man who was not one.
   ═══════════════════════════════════════════════════════════ */

.leaf-shards { position: relative; }

/* ── THE BROADSHEET ──
   Keyed off its white ground, so the parchment shows through the hatching
   rather than a grey plate sitting behind it. */
.split-plate[data-plate="brinvilliers"] img {
  width: 100%;
  height: auto;
  max-height: 320px;
  object-fit: contain;
  mix-blend-mode: multiply;   /* into the paper */
  opacity: .95;
  filter: contrast(1.06);
  box-shadow: none;
  border-radius: 0;
}

/* ── LÉVI'S BAPHOMET ──
   He floats right and the text wraps around him, so the words and the figure
   share the column instead of fighting for it. */
.shard-baphomet {
  float: right;
  width: 34%;
  max-width: 190px;
  margin: .1rem 0 .6rem 1.2rem;
  shape-outside: margin-box;
}
.shard-baphomet img {
  display: block;
  width: 100%;
  height: auto;
  mix-blend-mode: multiply;
  opacity: .88;               /* strong: he is the subject, not a watermark */
  filter: contrast(1.05);
}

/* ── AND THE TYPE READS ──
   This leaf is long and carries two arguments, so the setting is a little
   more generous than its neighbours: the measure is the thing being read. */
.leaf-shards p,
.leaf-shards .lore p {
  font-size: clamp(1.08rem, 1.24vw, 1.22rem) !important;
  line-height: 1.6 !important;
}
.leaf-shards .lore {
  clear: none;
}
.leaf-shards .chap-note {
  clear: both;
}
.leaf-shards .section-break {
  clear: both;
  margin: 1rem auto .9rem;
}

@media (max-width: 1366px) {
  .shard-baphomet { width: 30%; max-width: 150px; margin-left: 1rem; }
  .split-plate[data-plate="brinvilliers"] img { max-height: 250px; }
  .leaf-shards p, .leaf-shards .lore p {
    font-size: clamp(1rem, 1.14vw, 1.12rem) !important;
    line-height: 1.5 !important;
  }
}
@media (max-width: 760px) {
  .shard-baphomet {
    float: none;
    width: 52%;
    max-width: 175px;
    margin: .6rem auto .8rem;
  }
  .split-plate[data-plate="brinvilliers"] img { max-height: 230px; }
}

/* Phone: he was rendering at 370px — nearly the whole column — because the
   width was resolving against the wrong box once the float was dropped.
   Pin it, and centre him between the two halves of the argument. */
@media (max-width: 760px) {
  .leaf-shards .shard-baphomet {
    float: none !important;
    display: block;
    width: 54% !important;
    max-width: 170px !important;
    margin: .7rem auto .9rem !important;
  }
  .leaf-shards .shard-baphomet img { width: 100%; height: auto; }
}


/* ═══════════════════════════════════════════════════════════
   LUCIFER, WHOLE, DOWN THE RIGHT

   He had been cropped to a 46%-tall window with object-fit:cover —
   which showed a slice of drapery floating in the middle of the
   leaf and left the foot of the page empty. That is fixed: he is
   the WHOLE figure now, running the full height of the paper down
   its right-hand edge.

   The words hold the left of the measure. He holds the right.
   ═══════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════
   THE GOAT ON THE BROOM — ONE RULE, AND ONLY ONE

   SIX competing blocks had piled up here across successive
   edits, each overriding the last by cascade — which is why the
   size kept sliding out from under itself. They are all gone.
   This is the only rule that sets him. If he needs resizing,
   change THESE numbers; do not append another block.

   Full-strength ink: multiply, no fade.
   ═══════════════════════════════════════════════════════════ */

.goat-orn {
  display: block;
  width: 56%;
  max-width: 260px;
  margin: .4rem auto 0;
}
.goat-orn img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 250px;
  object-fit: contain;
  mix-blend-mode: multiply;   /* into the paper, not onto it */
  opacity: 1;                 /* no fade */
  filter: none;
  box-shadow: none;
  transform: rotate(-1.5deg);
}

@media (max-width: 1366px) {
  .goat-orn { width: 48%; max-width: 205px; }
  .goat-orn img { max-height: 195px; }
}
@media (max-width: 760px) {
  .goat-orn { width: 58%; max-width: 215px; }
  .goat-orn img { max-height: 205px; }
}

/* ═══════════════════════════════════════════════════════════
   NO SCROLLBAR ON A PIECE OF PAPER

   The leaves scroll, and the browser was drawing a track down
   the right edge of the parchment — a UI element pasted onto a
   book. It goes. The page still scrolls exactly as before; it
   simply stops advertising the fact.
   ═══════════════════════════════════════════════════════════ */

.page-inner {
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* old Edge */
}
.page-inner::-webkit-scrollbar {
  width: 0;
  height: 0;
  display: none;                  /* Chrome, Safari */
}
.page-inner::-webkit-scrollbar-thumb,
.page-inner::-webkit-scrollbar-track {
  background: transparent;
}


/* ═══════════════════════════════════════════════════════════
   LUCIFER, SEATED ON THE FOOT OF THE PAGE

   ONE rule. (Three had piled up, and the one that won caged him
   in a fixed box which object-fit then letterboxed — leaving a
   57px band of dead paper under him that would not close.)

   He is anchored to the PAGE, not to the leaf: the leaf's content
   stops above the foot of the sheet, so anything pinned to it can
   never reach the bottom edge. Anchored to the page, he sits on
   the paper itself.
   ═══════════════════════════════════════════════════════════ */

.leaf-lucifer .stave-lucifer {
  position: fixed;            /* out of the leaf's box entirely */
  position: absolute;
  inset: auto 0 0 auto;       /* bottom-right of the PAGE */
  bottom: 0;
  right: 0;
  top: auto;
  left: auto;
  width: 54%;
  height: auto;
  max-width: none;
  overflow: visible;
  transform: none;
  z-index: 0;
  pointer-events: none;
  display: block;
}
.leaf-lucifer .stave-lucifer img {
  display: block;
  width: 100%;
  height: auto;               /* natural aspect — no cage, no letterbox */
  max-width: none;
  max-height: none;
  object-fit: contain;
  mix-blend-mode: multiply;   /* the paper comes up through the graphite */
  opacity: .42;
  filter: contrast(1.08);
  transform: none;
}

@media (max-width: 760px) {
  .leaf-lucifer .stave-lucifer { width: 74%; }
  .leaf-lucifer .stave-lucifer img { opacity: .3; }
}

/* the page is his containing block, so he can reach its foot */
.page:has(.leaf-lucifer) { position: relative; }
.leaf-lucifer { position: static; }

/* ═══════════════════════════════════════════════════════════
   DE GUAITA'S PAIR

   BOTH circles — the upright star above, the inverted Goat below.
   It was trapped in a two-column split at 142px wide; out of the
   column it can be what it is: a tall plate, centred on the
   measure, printed into the paper.
   ═══════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════
   THE CODA

   The last line of the chapter, standing alone after the break.
   It was set at the same size as a caption's footnote — 17.9px —
   which is no way to land an argument this size. It is the thing
   the whole chapter has been walking toward, and it is set like it.
   ═══════════════════════════════════════════════════════════ */

.dp-leaf .chap-coda {
  font-size: clamp(1.3rem, 1.55vw, 1.56rem) !important;
  line-height: 1.55 !important;
  color: #0F0B06 !important;
  opacity: 1 !important;
  max-width: 34rem;
  margin: 1.1rem auto 0;
  text-align: center;
}
.dp-leaf .chap-coda strong {
  color: var(--rubric, #7A1710) !important;
}
/* the last clause is the one that lands — give it the deepest red */
.dp-leaf .chap-coda em {
  display: block;
  margin-top: .5rem;
  font-style: italic;
  color: var(--deep, #5A0F09) !important;
  font-size: 1.06em;
}
/* ...but the two names in the first sentence stay inline */
.dp-leaf .chap-coda em:first-of-type {
  display: inline;
  margin-top: 0;
  font-size: 1em;
  color: inherit !important;
}

@media (max-width: 1366px) {
  .dp-leaf .chap-coda {
    font-size: clamp(1.16rem, 1.36vw, 1.34rem) !important;
    line-height: 1.45 !important;
  }
}

/* ── AND THE CODA IS NOT A SQUEEZED NOTE ──
   `.dp-leaf:has(.section-break) .chap-note` — the rule that tightens the
   double-leaves — was matching this page (it has a break) and outranking
   `.dp-leaf .chap-coda` on specificity, capping the coda at 16px on anything
   under 1366px. Claim it back at a weight that wins. */
.page-inner .dp-leaf .chap-coda,
.dp-leaf:has(.section-break) .chap-coda,
.dp-leaf:has(.section-break) > p.chap-coda {
  font-size: clamp(1.3rem, 1.55vw, 1.56rem) !important;
  line-height: 1.55 !important;
  margin: 1.1rem auto 0 !important;
}

@media (max-width: 1366px) {
  .page-inner .dp-leaf .chap-coda,
  .dp-leaf:has(.section-break) .chap-coda,
  .dp-leaf:has(.section-break) > p.chap-coda {
    font-size: clamp(1.2rem, 1.42vw, 1.4rem) !important;
    line-height: 1.45 !important;
  }
}
@media (max-width: 760px) {
  .page-inner .dp-leaf .chap-coda,
  .dp-leaf:has(.section-break) .chap-coda,
  .dp-leaf:has(.section-break) > p.chap-coda {
    font-size: clamp(1.16rem, 4.6vw, 1.32rem) !important;
  }
}

/* ═══════════════════════════════════════════════════════════
   DE GUAITA'S PAIR — PLATE LEFT, ARGUMENT RIGHT

   The two circles stand beside the paragraphs that explain them.
   The column is cut to hold the plate at the width it ALREADY
   HAS — 221px — rather than squeezing it back into a gutter the
   way the old split did (it was down to 142px in there).
   ═══════════════════════════════════════════════════════════ */

/* it is IN a column now, so it stops being a centred block */


/* ═══════════════════════════════════════════════════════════
   DE GUAITA'S PAIR — PLATE LEFT, ARGUMENT RIGHT

   ONE rule. Three generations had stacked up here and were
   overriding each other, which is why the plate kept snapping
   back to 142px however I sized it. If it needs resizing, change
   THESE numbers — do not append another block.

   Both circles: the star upright above, the Goat of Mendes
   inverted below. White ground keyed out; it prints into the
   parchment with multiply.
   ═══════════════════════════════════════════════════════════ */

.dense .split.split-guaita,
.split-guaita {
  display: grid;
  grid-template-columns: 46% 1fr !important;
  gap: 1.5rem;
  align-items: start;
  margin: 1rem 0 0;
}

.split-guaita .plate-guaita {
  float: none;
  clear: none;
  width: 100%;
  max-width: none;
  margin: 0;
}
.split-guaita .plate-guaita img {
  display: block;
  width: 100%;
  height: auto;
  max-height: none;           /* no cap: it is a TALL plate, two figures */
  object-fit: contain;
  mix-blend-mode: multiply;   /* the parchment comes up through the line */
  filter: contrast(1.1);
  opacity: .95;
  box-shadow: none;
  border: 0;
  border-radius: 0;
}
.split-guaita .plate-guaita figcaption {
  text-align: left;
  margin-top: .55rem;
}
.split-guaita .split-body > p:first-child {
  margin-top: 0;
}

@media (max-width: 760px) {
  .split-guaita {
    grid-template-columns: 1fr;
    gap: .9rem;
  }
  .split-guaita .plate-guaita {
    width: 74%;
    margin: 0 auto .6rem;
  }
  .split-guaita .plate-guaita figcaption { text-align: center; }
}

/* ═══════════════════════════════════════════════════════════
   THE ORGANISATIONS — SET LARGER

   The leaf measured overflow: 0 — it had room going spare — so
   the type had no reason to be sitting at the chapter default.
   This is the page that names every body on the path, and the
   dates matter; it is set to be read, not scanned.
   ═══════════════════════════════════════════════════════════ */

.leaf-orgs p,
.leaf-orgs .lore p {
  font-size: clamp(1.24rem, 1.44vw, 1.42rem) !important;
  line-height: 1.58 !important;
}
.leaf-orgs .chap-note {
  font-size: clamp(1.18rem, 1.36vw, 1.34rem) !important;
  line-height: 1.5 !important;
}
.leaf-orgs .chap-head {
  font-size: clamp(2.3rem, 2.8vw, 3rem) !important;
}
.leaf-orgs .lore p {
  margin: .42rem 0;
}

@media (max-width: 1366px) {
  .leaf-orgs p,
  .leaf-orgs .lore p {
    font-size: clamp(1.12rem, 1.3vw, 1.28rem) !important;
    line-height: 1.48 !important;
  }
  .leaf-orgs .chap-note {
    font-size: clamp(1.08rem, 1.24vw, 1.2rem) !important;
  }
}
@media (max-width: 760px) {
  .leaf-orgs p,
  .leaf-orgs .lore p {
    font-size: clamp(1.1rem, 4.5vw, 1.24rem) !important;
  }
}

/* phone: the bigger type pushed the closing note below the fold. The words
   keep their size; the air gives way. */
@media (max-width: 760px) {
  .leaf-orgs .lore { margin: .55rem 0; padding: .65rem .8rem .65rem 1.35rem; }
  .leaf-orgs .lore p { margin: .3rem 0; line-height: 1.4 !important; }
  .leaf-orgs > p { margin: .4rem 0; line-height: 1.45 !important; }
  .leaf-orgs .chap-note { margin: .5rem 0 0; line-height: 1.4 !important; }
  .leaf-orgs .chap-head { margin: .05rem 0 .35rem; }
}

/* ═══════════════════════════════════════════════════════════
   THE LEVIATHAN CURRENT

   The brimstone sign, keyed off the page of the Satanic Bible it
   was photographed on, printed INTO the parchment.
   ═══════════════════════════════════════════════════════════ */

.leaf-leviathan { position: relative; }

.brimstone {
  float: right;
  width: 26%;
  max-width: 130px;
  margin: 0 0 .8rem 1.3rem;
  shape-outside: margin-box;
}
.brimstone img {
  display: block;
  width: 100%;
  height: auto;
  mix-blend-mode: multiply;   /* into the paper */
  opacity: .92;
  filter: contrast(1.06);
}

/* ── THE NINE STATEMENTS ──
   A numbered list, set as a list — the numerals in the rubric, the clause that
   carries each one in blood. It is the bedrock; it is set like one. */
.nine {
  list-style: none;
  counter-reset: nine;
  margin: 1rem 0;
  padding: 0;
}
.nine li {
  position: relative;
  counter-increment: nine;
  padding-left: 2.4rem;
  margin: .62rem 0;
  font-size: clamp(1.1rem, 1.28vw, 1.26rem);
  line-height: 1.5;
  color: var(--ink, #0F0B06);
}
.nine li::before {
  content: counter(nine);
  position: absolute;
  left: 0;
  top: -.06em;
  width: 1.7rem;
  text-align: right;
  font-family: 'Spectral SC', Georgia, serif;
  font-size: 1.15em;
  color: var(--blood, #8E1B10);
}
.nine li strong {
  color: var(--rubric, #7A1710);
}

/* ── THE PORTRAITS ──
   Photographs, so they are MOUNTED, not printed: multiply would destroy them. */
.plate-lavey {
  float: right;
  width: 42%;
  max-width: 250px;
  margin: .2rem 0 .8rem 1.3rem;
}
.plate-lavey img {
  display: block;
  width: 100%;
  height: auto;
  mix-blend-mode: normal;      /* keep the photograph */
  filter: sepia(.2) contrast(1.05) saturate(.85) brightness(.98);
  box-shadow:
    0 3px 12px rgba(46, 32, 12, .45),
    0 0 0 1px rgba(90, 72, 42, .5);
}
.plate-lavey figcaption {
  margin-top: .45rem;
  text-align: left;
}

@media (max-width: 760px) {
  .brimstone { float: none; width: 34%; max-width: 110px; margin: .4rem auto .7rem; }
  .plate-lavey {
    float: none;
    width: 74%;
    max-width: 260px;
    margin: .5rem auto .9rem;
  }
  .plate-lavey figcaption { text-align: center; }
  .nine li { font-size: clamp(1.04rem, 4.2vw, 1.16rem); padding-left: 2rem; }
}

/* These leaves carry a lot — two sections on the Leviathan page, nine
   statements on the next — so they are set tight. They scroll, which is
   what a long argument should do; but the air should not be what makes
   them long. */
.leaf-leviathan > p,
.leaf-cos > p {
  margin: .45rem 0;
  line-height: 1.52 !important;
}
.leaf-leviathan .lore,
.leaf-cos .lore {
  margin: .65rem 0;
  padding: .7rem .9rem .7rem 1.45rem;
}
.leaf-leviathan .lore p,
.leaf-cos .lore p {
  margin: .32rem 0;
  line-height: 1.45 !important;
}
.leaf-leviathan .chap-head,
.leaf-nine .chap-head,
.leaf-cos .chap-head {
  margin: .05rem 0 .4rem;
}
.leaf-leviathan .section-break {
  margin: .8rem auto .7rem;
}
.leaf-nine .nine li { margin: .5rem 0; }

/* the small cuts of the verso, for a phone */
@media (max-width: 760px) {
  body[data-chapter="satanism"] .grimoire .page-left,
  body[data-chapter="darkpath"] .grimoire .page-left {
    background-image: url('../media/paper-satan-sm-verso.webp');
  }
  body:not(.in-chapter) .grimoire .page-left {
    background-image: url('../media/paper-front-sm-verso.webp');
  }
}

/* ═══════════════════════════════════════════════════════════
   THE PAGE BAR MUST NOT SIT ON THE WRITING

   On a phone the leafbar is `position: fixed` — 63px tall, 16px
   off the bottom — so it floats OVER the leaf and covered the
   last ~79px of every page. The closing line of a chapter was
   being read through a button.

   The leaf now reserves the bar's whole footprint at its foot:
   the bar's height, its offset, and air enough that the last
   line is not sitting against it. Nothing is hidden.
   ═══════════════════════════════════════════════════════════ */

@media (max-width: 760px) {
  .grimoire .page-inner {
    /* 63px bar + 16px offset + a line of air, and the safe-area on
       phones with a home indicator */
    padding-bottom: calc(63px + 16px + 1.6rem + env(safe-area-inset-bottom, 0px)) !important;
  }
}



/* ═══════════════════════════════════════════════════════════
   THE PAGE FOLDS

   A real leaf hinges on the SPINE, not on its own centre. It has
   a back (which must not show you the text in mirror-writing as
   it goes over), and it falls into the book's own shadow as it
   lifts. All three, below.

   The 3D stage already exists: .grimoire carries perspective,
   .spread carries preserve-3d.
   ═══════════════════════════════════════════════════════════ */

@media (max-width: 760px) {

  .grimoire { perspective: 1400px; }     /* closer, so the fold is felt */
  .grimoire .spread {
    transform-style: preserve-3d;
    --fold: 0;
  }

  .grimoire .page {
    /* THE HINGE. A right-hand leaf turns about its left edge — the spine. */
    transform-origin: left center;
    transform-style: preserve-3d;
    backface-visibility: hidden;         /* no mirrored writing on the way over */
    -webkit-backface-visibility: hidden;
    will-change: transform, filter;
  }
  .grimoire .page-left {
    transform-origin: right center;      /* ...and a left-hand leaf about its right */
  }

  /* while the thumb is down there is no transition — the angle IS the thumb */
  .spread.dragging .page { transition: none !important; }

  /* ── THE BACK OF THE LEAF ──
     As the page passes 90° you are looking at its reverse. Give it one:
     the same paper, and none of the writing. */
  .grimoire .page::after {
    transition: opacity .3s ease;
  }

  /* ── THE SHADOW THE FOLD THROWS ──
     The lifting page darkens the spread beneath it, and the gutter deepens.
     Driven by --fold, which the drag sets from 0 to 1. */
  .grimoire .spread::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 25;
    background: linear-gradient(
      to right,
      rgba(0,0,0,calc(var(--fold) * .38)) 0%,
      rgba(0,0,0,calc(var(--fold) * .12)) 26%,
      transparent 60%);
    opacity: var(--fold);
    transition: opacity .3s ease;
  }

  /* ── THE TAP ZONES ──
     The outer third of the leaf turns the page. A book is reached for at
     its edge; the middle is where the reading happens, and it is left alone. */
  .turn-zone {
    display: block !important;
    position: absolute;
    top: 0;
    bottom: 0;
    width: 26%;
    z-index: 28;
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .turn-prev { left: 0; }
  .turn-next { right: 0; }
  .turn-zone:disabled { pointer-events: none; }

  /* the corner lifts under the thumb, so you can see what the zone does */
  .turn-zone .corner {
    position: absolute;
    bottom: 0;
    width: 46px;
    height: 46px;
    opacity: 0;
    transition: opacity .25s ease, transform .25s ease;
  }
  .turn-next .corner { right: 0; }
  .turn-prev .corner { left: 0; }
  .turn-zone:active .corner {
    opacity: .5;
    transform: scale(1.15);
  }
}

/* someone who asked for stillness gets a cut, not a fold */
@media (prefers-reduced-motion: reduce) {
  .grimoire .page { transition: none !important; }
}

/* ═══════════════════════════════════════════════════════════
   THE PAGE, TAKEN BY HAND

   Three fixes:
     · the fold stuttered because the BROWSER and the script were
       both trying to own the same touch. While a page is held,
       the browser is told to keep its hands off.
     · the corner was 46px — a fist. It is a fingertip now.
     · the edges and corners are draggable, not merely tappable:
       take the leaf by its corner and it PEELS.
   ═══════════════════════════════════════════════════════════ */

@media (max-width: 760px) {

  /* ── ONE OWNER PER GESTURE ──
     While the page is held, nothing else scrolls. This is the stutter. */
  body.page-held .grimoire,
  body.page-held .page-inner,
  body.page-held .spread {
    touch-action: none !important;
    overflow: hidden !important;
  }
  body.page-held { overscroll-behavior: none; }

  /* the leaf still scrolls for READING — 26 pages are taller than a phone —
     but it must never fight a sideways pull */
  .grimoire .page-inner {
    touch-action: pan-y;
    overscroll-behavior: contain;
  }
  .grimoire .spread { touch-action: pan-y; }

  /* ── THE GRAB ZONES ──
     The outer eighth of the leaf, its full height: that is the edge, and it
     is where a hand goes. Above the text, so a pull is never a tap on a word. */
  .turn-zone {
    display: block !important;
    position: absolute;
    top: 0;
    bottom: 0;
    width: 14%;
    min-width: 44px;              /* a thumb, at minimum */
    z-index: 32;
    background: none;
    border: 0;
    padding: 0;
    cursor: grab;
    -webkit-tap-highlight-color: transparent;
    touch-action: none;           /* this strip is ALWAYS a page-turn */
  }
  .turn-prev { left: 0; }
  .turn-next { right: 0; }
  .turn-zone:disabled { pointer-events: none; opacity: 0; }

  /* ── THE CORNER ──
     46px was a fist. A page is taken by a fingertip. */
  .turn-zone .corner {
    position: absolute;
    bottom: 0;
    width: 26px;
    height: 26px;
    opacity: .34;                 /* always faintly there: it invites the hand */
    transition: opacity .25s ease, transform .3s cubic-bezier(.2,.7,.2,1);
    pointer-events: none;
  }
  .turn-next .corner { right: 0; }
  .turn-prev .corner { left: 0; }

  .turn-zone:active .corner,
  .spread.dragging .corner {
    opacity: .7;
    transform: scale(1.2);
  }

  /* while the leaf is being bent, no transition fights the thumb */
  .spread.dragging .page {
    transition: none !important;
  }
}

/* ═══════════════════════════════════════════════════════════
   THE BLOOD PAGE

   Two sections: what was done, and the man who said no. The
   rule is set as a quotation because it IS one — verbatim, and
   the provenance checked.
   ═══════════════════════════════════════════════════════════ */

.voice-rule {
  margin: .9rem 0;
  padding: .9rem 1.2rem;
  border-left: 2px solid var(--rubric, #7A1710);
  background: rgba(122, 23, 16, .05);
}
.voice-rule p {
  margin: 0;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  font-size: clamp(1.18rem, 1.4vw, 1.38rem) !important;
  line-height: 1.5 !important;
  color: var(--ink, #0F0B06) !important;
}
.voice-rule strong { color: var(--rubric, #7A1710) !important; }
.voice-rule cite {
  display: block;
  margin-top: .55rem;
  font-family: 'Spectral SC', Georgia, serif;
  font-style: normal;
  font-size: .62rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--iron-faded, #574835);
}

/* two sections on one leaf — set tight */
.leaf-blood > p { margin: .45rem 0; line-height: 1.55 !important; }
.leaf-blood .lore { margin: .65rem 0; padding: .7rem .9rem .7rem 1.45rem; }
.leaf-blood .lore p { margin: .34rem 0; line-height: 1.46 !important; }
.leaf-blood .chap-head { margin: .05rem 0 .4rem; }
.leaf-blood .section-break { margin: .85rem auto .75rem; }

/* ── THE BLOOD DOOR ──
   The same door, in a deeper red — and its sigil is a drop, which turns like
   the pentagram does but does not invert. A drop has no upside-down. */
.blood-door {
  margin-top: .6rem;
  border-color: rgba(122, 23, 16, .5);
  background: linear-gradient(100deg,
              rgba(92, 16, 10, .16), rgba(58, 10, 6, .1));
}
.blood-door .dark-door-sigil {
  color: #8E1B10;
  border-color: rgba(142, 27, 16, .45);
}
.blood-door .dark-door-sigil svg {
  animation: sigil-turn 34s linear infinite;   /* slower: blood is patient */
}
.blood-door:hover .dark-door-sigil,
.blood-door:focus-visible .dark-door-sigil {
  transform: none;              /* a drop does not invert */
  color: #B32615;
}
.blood-door:hover .dark-door-sigil svg {
  animation-duration: 9s;
}
.blood-door .dark-door-label { color: #7A1710; }

/* ═══════════════════════════════════════════════════════════
   THE OLD GODS

   A page per deity, each one long enough to scroll: what they
   govern, how they come, what to offer, when NOT to call them,
   and an invocation.

   The three families share one ink and one shelf — because the
   argument of the chapter is that they belong on it.
   ═══════════════════════════════════════════════════════════ */

.god-leaf {
  --ink:    #17110A;
  --rubric: #7A1710;
  --blood:  #8E1B10;
  --deep:   #5A0F09;
}

.god-leaf p,
.god-leaf li,
.god-leaf .lore p {
  color: var(--ink) !important;
  opacity: 1 !important;
  font-size: clamp(1.1rem, 1.28vw, 1.26rem) !important;
  line-height: 1.6 !important;
}
.god-leaf .chap-head,
.god-leaf .chap-title {
  color: #0A0704 !important;
}
.god-leaf strong { color: var(--rubric) !important; font-weight: 600; }
.god-leaf .drop  { color: var(--blood) !important; }
.god-leaf em     { color: inherit !important; font-style: italic; }
.god-leaf .chap-note {
  color: #140E08 !important;
  font-size: clamp(1.06rem, 1.22vw, 1.2rem) !important;
  opacity: 1 !important;
}
.god-leaf .chap-note strong { color: var(--deep) !important; }
.god-leaf .lore-said { color: var(--deep) !important; opacity: 1 !important; }
.god-leaf .lore-mark { color: var(--blood) !important; }

/* ── THE EPITHET ──
   The line of domains under a god's name. It is a label, so it is set as one. */
.deity-epithet {
  margin: -.2rem 0 .9rem !important;
  font-family: 'Spectral SC', Georgia, serif;
  font-size: .68rem !important;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--rubric) !important;
  opacity: .9;
  line-height: 1.5 !important;
}

/* ── THE INVOCATION ──
   Not a spell to be recited at a page. A thing you would actually say out
   loud, in your own room, and mean. It is set apart, and it is set to be
   spoken. */
.god-leaf .invocation {
  margin: 1rem 0 .9rem;
  padding: 1rem 1.2rem;
  border-left: 2px solid var(--blood);
  background: linear-gradient(100deg,
              rgba(142, 27, 16, .07), rgba(142, 27, 16, .02));
}
.god-leaf .invocation p {
  margin: 0;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-size: clamp(1.2rem, 1.44vw, 1.42rem) !important;
  line-height: 1.62 !important;
  color: var(--ink) !important;
}
.god-leaf .invocation strong { color: var(--deep) !important; }

/* ── THE FAMILY DIVIDERS ──
   Three shelves, one bookcase. Each family is announced, and then walked. */
.leaf-family { text-align: center; }
.leaf-family .chap-title {
  font-size: clamp(2.2rem, 3vw, 3.2rem) !important;
  margin: .4rem 0 .7rem;
}
.leaf-family .chap-standfirst {
  max-width: 30rem;
  margin: 0 auto 1.4rem;
  font-size: clamp(1.14rem, 1.34vw, 1.32rem) !important;
}
.leaf-family .chap-note {
  max-width: 32rem;
  margin: 0 auto;
}

/* the adversarial family runs a shade darker — not because they are worse,
   but because the paper remembers what was done to them */
.leaf-adversary .drop { color: #A02012 !important; }
.leaf-family-adversary .chap-title { color: #12100C !important; }

/* deity pages are long by design — the reader scrolls the ones they care
   about — so they are set tight enough to be worth the scroll */
.leaf-deity > p { margin: .5rem 0; }
.leaf-deity .lore { margin: .8rem 0; padding: .85rem 1rem .85rem 1.5rem; }
.leaf-deity .lore p { margin: .45rem 0; line-height: 1.52 !important; }
.leaf-deity .chap-head { margin: .05rem 0 .1rem; }

@media (max-width: 1366px) {
  .god-leaf p, .god-leaf .lore p {
    font-size: clamp(1.04rem, 1.2vw, 1.16rem) !important;
    line-height: 1.5 !important;
  }
  .god-leaf .invocation p {
    font-size: clamp(1.1rem, 1.3vw, 1.26rem) !important;
  }
}
@media (max-width: 760px) {
  .god-leaf .invocation { padding: .85rem 1rem; }
  .deity-epithet { font-size: .62rem !important; letter-spacing: .14em; }
}

/* ═══════════════════════════════════════════════════════════
   THE CONTENTS OPEN

   A chapter is not one thing. Hover it — or tap it, on a phone —
   and its parts unfold beneath, each one going to the page it
   actually begins on. A reader looking for Lilith should not
   have to walk through Mokosh to reach her.
   ═══════════════════════════════════════════════════════════ */

.contents li.has-parts {
  position: relative;
}

/* the mark that says there is more inside */
.contents li.has-parts > a::after {
  content: '';
  position: absolute;
  right: .35rem;
  top: 50%;
  width: 5px;
  height: 5px;
  margin-top: -3px;
  border-right: 1px solid var(--rubric, #6E2113);
  border-bottom: 1px solid var(--rubric, #6E2113);
  transform: rotate(45deg);
  opacity: .45;
  transition: transform .35s cubic-bezier(.2,.7,.2,1), opacity .3s ease;
}

/* ── THE FOLD ──
   Collapsed to nothing, and grown from the top — the way a leaf of a book
   opens, not the way a menu drops. */
.entry-parts {
  list-style: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  max-height: 0;
  opacity: 0;
  transition: max-height .5s cubic-bezier(.2,.7,.2,1),
              opacity .35s ease,
              margin .4s ease;
}
.contents li.has-parts:hover > .entry-parts,
.contents li.has-parts:focus-within > .entry-parts,
.contents li.has-parts.is-open > .entry-parts {
  max-height: 34rem;
  opacity: 1;
  margin: .1rem 0 .5rem;
}
.contents li.has-parts:hover > a::after,
.contents li.has-parts.is-open > a::after {
  transform: rotate(-135deg);   /* it points UP once open */
  opacity: .8;
}

/* ── THE PARTS ──
   Indented under their chapter, hung off a rule that runs down the margin —
   so the eye reads them as belonging to it rather than as new entries. */
.entry-parts::before {
  content: '';
  position: absolute;
  left: 2.4rem;
  width: 1px;
  background: linear-gradient(to bottom,
              rgba(110, 33, 19, .35), rgba(110, 33, 19, .05));
}
.entry-parts li {
  border: 0 !important;
}
.entry-parts li:first-child { border-top: 0 !important; }

.contents .part {
  display: block;
  padding: .42rem .3rem .42rem 3.3rem;
  text-decoration: none;
  color: inherit;
  position: relative;
  transition: background .3s ease, padding-left .3s ease;
}
.contents .part::before {
  content: '';
  position: absolute;
  left: 2.4rem;
  top: 50%;
  width: .55rem;
  height: 1px;
  background: rgba(110, 33, 19, .4);
}
.contents .part:hover,
.contents .part:focus-visible {
  background: rgba(110, 33, 19, .07);
  padding-left: 3.6rem;
}

.part-name {
  display: block;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-size: clamp(.94rem, 1.85vh, 1.1rem);
  line-height: 1.3;
  color: var(--iron-gall, #2A2018);
}
.contents .part:hover .part-name { color: var(--rubric, #6E2113); }

.part-gloss {
  display: block;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic;
  font-size: clamp(.72rem, 1.4vh, .86rem);
  line-height: 1.35;
  color: var(--iron-faded, #574835);
  opacity: .8;
  margin-top: .05rem;
}

/* ── TOUCH ──
   There is no hover on a phone. The FIRST tap opens the chapter's parts; the
   second chooses one. Tapping the chapter name never throws you straight in —
   you would never see the parts at all. */
@media (hover: none) {
  .contents li.has-parts > a::after { opacity: .7; }
  .contents .part { padding: .55rem .3rem .55rem 3.3rem; }  /* a thumb, not a cursor */
}

@media (max-width: 760px) {
  .contents .part { padding-left: 2.6rem; }
  .contents .part::before { left: 1.7rem; width: .5rem; }
  .entry-parts::before { left: 1.7rem; }
  .part-gloss { font-size: .74rem; }
}

/* ═══════════════════════════════════════════════════════════
   THE GRIMOIRE FILLS THE WINDOW

   It was capped at 1240×800 with a fat margin of dark around it —
   a book photographed on a table. It should be the book you are
   holding: as large as the glass allows, with only enough dark
   left to keep the edges from touching the frame.
   ═══════════════════════════════════════════════════════════ */

.grimoire {
  padding: clamp(.4rem, 1.4vh, 1.2rem) clamp(.4rem, 1.2vw, 1.2rem);
}

.grimoire .spread {
  /* the right-hand strip is left dark, so the way out has somewhere to stand
     that is not on the paper — and clear of the board's shadow, which reaches
     about 22px past the spread */
  width: min(1800px, calc(99vw - 4.6rem));
  height: min(1150px, 96vh);
  margin-right: 4.6rem;
}

/* ── AND THE BOOK LIES FLATTER ──
   At this size the 7° tilt starts to look like a stunt. Take most of it out:
   the perspective should be felt, not admired. */
body.state-open .spread {
  transform: rotateX(1deg) scale(1);
}

/* ═══════════════════════════════════════════════════════════
   CLOSE THE GRIMOIRE — OUT OF THE WAY

   It was sitting bottom-centre, directly under the page-turn bar
   and directly in the reader's path. It goes to the top-right
   corner, where a reader's eye is not, and it gets small: a way
   out should be findable, not insistent.
   ═══════════════════════════════════════════════════════════ */

.close-book {
  /* ABSOLUTE, not fixed — it belongs to the BOOK, and rides its corner.
     Pinned to the window it drifted away from the board as the screen grew;
     the arrow in the note points back to the board, so that is where it goes. */
  position: absolute;
  top: 0;
  right: -3.1rem;              /* just past the board's edge, in the dark */
  bottom: auto;
  left: auto;
  transform: none;
  z-index: 60;

  padding: .3rem .62rem;
  font-size: .48rem;
  letter-spacing: .18em;

  border: 1px solid rgba(174, 143, 88, .62);
  color: #E2D6BC;                         /* bright vellum: it must be FOUND */
  background: rgba(18, 12, 8, .85);
  backdrop-filter: blur(3px);
  border-radius: 3px;
  box-shadow:
    0 3px 14px rgba(0, 0, 0, .65),
    inset 0 1px 0 rgba(196, 183, 154, .12);

  opacity: 0;
  transition: opacity .8s ease 1.6s, color .3s, border-color .3s, background .3s;
}
body.state-open .close-book { opacity: .92; }  /* findable at a glance */
body.state-open .close-book:hover { opacity: 1; }
.close-book:hover,
.close-book:focus-visible {
  opacity: 1 !important;
  transform: none;
  color: #F0E4CC;
  border-color: rgba(147, 56, 31, .8);
}

@media (max-width: 760px) {
  .grimoire { padding: .3rem; }
  .grimoire .spread {
    /* a lane on the phone too — narrower, because the screen is precious,
       but the button must not stand on the writing */
    width: calc(100vw - 3.1rem);
    height: 100vh;
    margin-right: 3.1rem;
  }
  .close-book {
    top: calc(.5rem + env(safe-area-inset-top, 0px));
    right: .35rem;
    padding: .34rem;
    font-size: .46rem;
  }
}

/* ═══════════════════════════════════════════════════════════
   THE WAY OUT

   At rest it is a small ✕ in the corner — a mark on the paper,
   not a control. Hover it and the words unroll from it:
   CLOSE THE GRIMOIRE.

   A way out should be findable. It should not be shouting at a
   reader who is trying to read.
   ═══════════════════════════════════════════════════════════ */

.close-book {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0;                            /* nothing to space until the words arrive */
  padding: 0;
  line-height: 1;
  width: 38px;                       /* a SQUARE — the mark, and nothing else */
  height: 38px;
  overflow: hidden;
  white-space: nowrap;

  transition:
    gap .45s cubic-bezier(.2, .74, .24, 1),
    padding .45s cubic-bezier(.2, .74, .24, 1),
    opacity .4s ease,
    color .3s ease,
    border-color .3s ease,
    background .3s ease;
}

.close-mark {
  display: grid;
  place-items: center;
  flex: none;
  width: 18px;
  height: 18px;
  transition: transform .5s cubic-bezier(.2, .74, .24, 1);
}
.close-mark svg {
  width: 17px;
  height: 17px;
}
.close-mark svg path { stroke-width: 1.9; }
.close-mark svg { display: block; }

/* ── THE WORDS ──
   Collapsed to nothing at rest — width zero, so they take up no room at all
   and the button is genuinely just the mark. They unroll on hover. */
.close-words {
  display: block;
  order: -1;                 /* the words open to the LEFT of the mark:
                                there is nothing to its right but the frame */
  max-width: 0;
  opacity: 0;
  transform: translateX(6px);
  transition:
    max-width .5s cubic-bezier(.2, .74, .24, 1),
    opacity .32s ease .1s,
    transform .5s cubic-bezier(.2, .74, .24, 1);
}

.close-book:hover,
.close-book:focus-visible {
  gap: .5rem;
  width: auto;                            /* the square opens into a tab */
  padding: 0 .55rem 0 .85rem;             /* it grows leftward */
  /* Expanded, it is wider than the dark lane — so it lifts clear ABOVE the
     paper rather than lying on it: a dark tab held over the page, with the
     board's own shadow beneath it. It never touches the vellum. */
  background: rgba(14, 9, 6, .94);
  box-shadow:
    0 4px 18px rgba(0, 0, 0, .6),
    0 0 0 1px rgba(147, 56, 31, .35);
}
.close-book:hover .close-words,
.close-book:focus-visible .close-words {
  max-width: 12rem;
  opacity: 1;
  transform: translateX(0);
}
.close-book:hover .close-mark,
.close-book:focus-visible .close-mark {
  transform: rotate(90deg);          /* the ✕ turns as it opens */
}

/* on a phone there is no hover — so it stays a mark, and one tap closes.
   The words would only ever be in the way. */
@media (hover: none) {
  .close-book:hover .close-words { max-width: 0; opacity: 0; }
  .close-book:hover { gap: 0; padding: .34rem; }
  .close-book:active .close-mark { transform: rotate(90deg); }
}

/* ── AND IT IS ACTUALLY SQUARE ──
   A global tap-target rule sets min-height: 46px on buttons — a good rule,
   and I am not going to break it for everything. But this one is a MARK, and
   38×46 is not a square. Exempt it, and give the phone a bigger square rather
   than a taller rectangle. */
.close-book {
  min-height: 0 !important;
  min-width: 0 !important;
  width: 38px !important;
  height: 38px !important;
  flex: none;
}
.close-book:hover,
.close-book:focus-visible {
  width: auto !important;      /* it opens into a tab, still 38 tall */
  height: 38px !important;
}

@media (max-width: 760px) {
  .close-book {
    width: 44px !important;    /* a thumb-sized square, not a tall box */
    height: 44px !important;
  }
  .close-book:hover,
  .close-book:focus-visible {
    width: 44px !important;
    height: 44px !important;
  }
}


/* ── IT RIDES THE BOOK'S CORNER ──
   The button is a child of .grimoire, so it is positioned against THAT.
   Anchor the spread instead, and the mark stays glued to the board's top-right
   corner at every size, exactly as the note shows. */
.grimoire .spread { position: relative; }

/* on a phone the board fills the screen — so it tucks into the corner ON the
   frame, where there is no writing */
@media (max-width: 760px) {
  .close-book {
    /* the board fills the phone — there is no lane outside it to stand in.
       So it tucks INSIDE the top-right corner, on the frame above the text. */
    top: .35rem;
    right: .35rem;
  }
}
