/* livrenz.com — «Tinta Nocturna»
   A fine printed edition set on dark stock: near-black ground, bone-white
   ink, a single rose accent carried through hairline, seal, and petals.
   Zero third-party assets; every effect is CSS plus one small self-hosted
   script (nav-3d.js). */

/* Fraunces — SIL Open Font License, self-hosted (static/fonts), latin
   subset only. One variable file per style covers weight 300–700 and
   the full optical-size axis, so display headlines and small print share
   a single family without a second HTTP request. */
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('/fonts/fraunces-roman.woff2') format('woff2');
}
@font-face {
  font-family: 'Fraunces';
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
  src: url('/fonts/fraunces-italic.woff2') format('woff2');
}

:root {
  --bg: #0B0D10;
  --panel: #1B1F24;
  --ink: #ECE7DD;
  --sepia: #A99AA0;
  --seal: #D9707F;
  --seal-soft: #E89AA5;
  --thread: #B98590;
  --serif: 'Fraunces', 'Iowan Old Style', 'Palatino Linotype', Palatino, 'Book Antiqua', Georgia, serif;
  --navh: 64px;
  color-scheme: dark;
}

html {
  background: var(--bg); scroll-behavior: smooth;
  scroll-padding-top: var(--navh);
  overflow-x: hidden;
}

body {
  margin: 0;
  /* the watermark's fade/blur/grayscale is baked into the PNG itself
     (static/libro/cover-watermark.png, alpha ~16%) rather than a live CSS
     filter. background-attachment: fixed below is load-bearing, not just
     "stays put on scroll": without it, the % position in each layer below
     is computed against body's full scroll height (thousands of px), not
     the viewport, so the image renders far below the fold instead of
     behind the hero. */
  background:
    radial-gradient(1100px 620px at 12% -8%, rgba(185, 133, 144, .12), transparent 60%),
    radial-gradient(900px 520px at 92% 10%, rgba(185, 133, 144, .07), transparent 55%),
    radial-gradient(1000px 720px at 88% 105%, rgba(217, 112, 127, .10), transparent 55%),
    url('/libro/cover-watermark.png') no-repeat center 10% / min(60vh, 680px) auto,
    var(--bg);
  background-attachment: fixed;
  color: var(--ink);
  font-family: var(--serif);
  font-optical-sizing: auto;
  font-variant-numeric: oldstyle-figures proportional-nums;
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ---- falling petals — decorative ambient layer, tinted from the seal
   hue so it stays inside the Tinta Nocturna palette rather than reading
   as generic bubblegum pink ---- */
.petals { position: fixed; inset: 0; overflow: hidden; pointer-events: none; z-index: 6; }
.petal {
  position: absolute; top: -8%; left: 0;
  width: 13px; height: 13px;
  background: linear-gradient(135deg, var(--seal-soft), rgba(240, 196, 206, .92));
  border-radius: 0 100% 0 100%;
  opacity: 0; filter: drop-shadow(0 2px 3px rgba(0, 0, 0, .3));
  --dir: 1;
}
@media (prefers-reduced-motion: reduce) { .petals { display: none; } }
@media (prefers-reduced-motion: no-preference) {
  /* alternating --dir per petal mirrors the sway/spin left<->right without
     a second keyframe block; scaleX oscillation is the petal turning
     edge-on mid-tumble, the thing that reads as "falling" rather than
     "sliding" */
  .petal { animation: petal-fall ease-in-out infinite; will-change: transform, opacity; }
  .petal:nth-child(even) { --dir: -1; }
  @keyframes petal-fall {
    0%   { transform: translate(0, -10vh) rotate(0deg) scaleX(1); opacity: 0; }
    8%   { opacity: .65; }
    22%  { transform: translate(calc(var(--dir) * 4vw), 22vh) rotate(calc(var(--dir) * 90deg)) scaleX(.5); }
    38%  { transform: translate(calc(var(--dir) * -3vw), 38vh) rotate(calc(var(--dir) * 165deg)) scaleX(1); }
    55%  { transform: translate(calc(var(--dir) * 5vw), 55vh) rotate(calc(var(--dir) * 235deg)) scaleX(.45); }
    72%  { transform: translate(calc(var(--dir) * -4vw), 72vh) rotate(calc(var(--dir) * 305deg)) scaleX(1); }
    90%  { transform: translate(calc(var(--dir) * 3vw), 92vh) rotate(calc(var(--dir) * 345deg)) scaleX(.55); opacity: .5; }
    100% { transform: translate(calc(var(--dir) * -2vw), 112vh) rotate(calc(var(--dir) * 380deg)) scaleX(1); opacity: 0; }
  }
  .petal:nth-child(1)  { left: 3%;  width: 10px; height: 10px; animation-duration: 13s;   animation-delay: -1s; }
  .petal:nth-child(2)  { left: 10%; width: 15px; height: 15px; animation-duration: 17s;   animation-delay: -6s; }
  .petal:nth-child(3)  { left: 18%; width: 9px;  height: 9px;  animation-duration: 11s;   animation-delay: -3s; }
  .petal:nth-child(4)  { left: 26%; width: 13px; height: 13px; animation-duration: 15s;   animation-delay: -9s; }
  .petal:nth-child(5)  { left: 34%; width: 11px; height: 11px; animation-duration: 19s;   animation-delay: -4s; }
  .petal:nth-child(6)  { left: 42%; width: 16px; height: 16px; animation-duration: 12s;   animation-delay: -10s; }
  .petal:nth-child(7)  { left: 50%; width: 10px; height: 10px; animation-duration: 14s;   animation-delay: -2s; }
  .petal:nth-child(8)  { left: 58%; width: 14px; height: 14px; animation-duration: 18s;   animation-delay: -7s; }
  .petal:nth-child(9)  { left: 66%; width: 9px;  height: 9px;  animation-duration: 13s;   animation-delay: -12s; }
  .petal:nth-child(10) { left: 74%; width: 12px; height: 12px; animation-duration: 16s;   animation-delay: -5s; }
  .petal:nth-child(11) { left: 82%; width: 15px; height: 15px; animation-duration: 11s;   animation-delay: -8s; }
  .petal:nth-child(12) { left: 90%; width: 10px; height: 10px; animation-duration: 20s;   animation-delay: -13s; }
  .petal:nth-child(13) { left: 96%; width: 13px; height: 13px; animation-duration: 15s;   animation-delay: -1.5s; }
  .petal:nth-child(14) { left: 55%; width: 11px; height: 11px; animation-duration: 17s;   animation-delay: -14s; }
  .petal:nth-child(15) { left: 14%; width: 9px;  height: 9px;  animation-duration: 12.5s; animation-delay: -6.5s; }
  .petal:nth-child(16) { left: 70%; width: 14px; height: 14px; animation-duration: 21s;   animation-delay: -10.5s; }
  .petal:nth-child(17) { left: 46%; width: 12px; height: 12px; animation-duration: 16.5s; animation-delay: -3.5s; }
  .petal:nth-child(18) { left: 88%; width: 10px; height: 10px; animation-duration: 13.5s; animation-delay: -11s; }
  .petal:nth-child(19) { left: 6%;  width: 15px; height: 15px; animation-duration: 19.5s; animation-delay: -8.5s; }
  .petal:nth-child(20) { left: 62%; width: 9px;  height: 9px;  animation-duration: 14.5s; animation-delay: -15s; }
}

/* reading-progress ribbon — how far through the book you are */
.progress-ribbon {
  position: fixed; top: 0; left: 0; height: 2px; width: 0%; z-index: 21;
  background: linear-gradient(90deg, var(--thread), var(--seal));
  background-size: 200% 100%;
  transition: width .1s linear;
}
@media (prefers-reduced-motion: reduce) { .progress-ribbon { display: none; } }

/* ambient mesh — a slow, near-static drift behind the page; kept off the
   real body background so it can animate independently of layout paint */
body::before {
  content: "";
  position: fixed; inset: -12%; z-index: -1; pointer-events: none;
  background:
    radial-gradient(700px 520px at 22% 18%, rgba(185, 133, 144, .10), transparent 62%),
    radial-gradient(640px 520px at 78% 82%, rgba(217, 112, 127, .08), transparent 62%);
  filter: blur(6px);
}
@media (prefers-reduced-motion: no-preference) {
  body::before { animation: mesh-drift 46s ease-in-out infinite alternate; }
  @keyframes mesh-drift {
    from { transform: translate(0, 0) scale(1); }
    to   { transform: translate(3%, -2.5%) scale(1.06); }
  }
  .progress-ribbon { animation: ribbon-shimmer 3.4s linear infinite; }
  @keyframes ribbon-shimmer {
    from { background-position: 0% 0; }
    to   { background-position: 200% 0; }
  }
}

/* night grain — same turbulence texture as before, re-tuned to read on dark */
body::after {
  content: "";
  position: fixed; inset: 0;
  pointer-events: none; z-index: 5;
  opacity: .07; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

.sc { font-variant: small-caps; letter-spacing: .24em; font-size: .8rem; text-transform: lowercase; }

a { color: var(--seal); text-underline-offset: 4px; text-decoration-thickness: 1px; }
a:hover { color: var(--seal-soft); }
a:focus-visible, [tabindex]:focus-visible { outline: 2px solid var(--seal); outline-offset: 4px; }
::selection { background: rgba(217, 112, 127, .24); }

.wrap { max-width: 1060px; margin: 0 auto; padding: 0 26px; }
@media (max-width: 640px) { .wrap { padding: 0 18px; } }

.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--seal); color: var(--bg); padding: 10px 18px; z-index: 20;
}
.skip:focus { left: 0; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0, 0, 0, 0); border: 0; white-space: nowrap;
}

/* ---- nav: running head ---- */
.navbar {
  position: sticky; top: 0; z-index: 10;
  background: rgba(11, 13, 16, .82);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(236, 231, 221, .12);
  perspective: 1200px;
  transition: box-shadow .35s ease;
}
@media (prefers-reduced-motion: no-preference) {
  .navbar.scrolled { box-shadow: 0 16px 30px -12px rgba(0, 0, 0, .6); }
}
nav { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding: 18px 0 13px; flex-wrap: wrap; }
nav .brand { color: var(--ink); text-decoration: none; }
nav .brand::before { content: "❦ "; color: var(--thread); }
nav ul { display: flex; gap: 4px; list-style: none; margin: 0; padding: 0; flex-wrap: wrap; position: relative; align-items: baseline; }
/* interpunct between chapter links — the same "·" already used for
   ES · EN, folios, and the colophon facts line, so the nav reads as one
   more line set in the book's own type rather than an app menu */
nav ul li:not(:last-child)::after { content: "·"; color: var(--thread); margin-left: 4px; }
nav ul a { color: var(--sepia); text-decoration: none; position: relative; padding: 7px 13px; border-radius: 2px; }
nav ul a:hover { color: var(--seal); }
nav ul a.active { color: var(--seal); }
.lang { color: var(--sepia); text-decoration: none; }
.lang b { color: var(--seal); }

/* small phones: two clean rows (brand + lang, then the full-width link
   list) instead of an unpredictable three-item wrap */
@media (max-width: 640px) {
  nav { padding: 14px 0 11px; gap: 8px 16px; }
  nav .brand { order: 1; }
  nav .lang { order: 2; }
  nav ul { order: 3; width: 100%; justify-content: center; gap: 2px; }
  nav ul a { padding: 6px 10px; font-size: .74rem; }
}

/* ---- bookmark ribbon — a narrow marker that drops behind the current
   nav word instead of a rounded pill, with a notched tail hanging off its
   bottom edge like a fabric ribbon marking a page. Slides between items
   on hover/focus and rests under the current section otherwise, driven by
   nav-3d.js. Sits behind the link text (z-index -1) so it never affects
   readability. ---- */
.nav-mark {
  position: absolute; top: 0; left: 0; width: 0; height: 0;
  z-index: -1; pointer-events: none; opacity: 0;
  background: linear-gradient(180deg, rgba(217, 112, 127, .26), rgba(185, 133, 144, .15));
  border: 1px solid rgba(217, 112, 127, .4); border-bottom: none;
}
.nav-mark::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -7px; height: 7px;
  background: rgba(185, 133, 144, .18);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 52%, 0 100%);
}
.nav-mark.visible { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
  .nav-mark {
    transition: transform .35s cubic-bezier(.22, .85, .25, 1), width .35s cubic-bezier(.22, .85, .25, 1),
      height .35s cubic-bezier(.22, .85, .25, 1), opacity .25s ease;
  }
}

/* ---- chapter dial: shallow 3D index along the right edge ---- */
.chapter-dial {
  position: fixed; right: 22px; top: 50%; z-index: 15;
  display: flex; flex-direction: column; gap: 15px;
  transform: translateY(-50%); perspective: 600px;
}
.chapter-dial a {
  display: block; width: 9px; height: 9px; border-radius: 50%;
  background: rgba(236, 231, 221, .26);
  transform: translateZ(0);
  transition: transform .3s ease, background .3s ease, box-shadow .3s ease;
}
.chapter-dial a:hover { background: var(--seal-soft); }
.chapter-dial a.active {
  background: var(--seal); transform: translateZ(16px) scale(1.4);
  box-shadow: 0 5px 14px rgba(217, 112, 127, .4);
}
@media (max-width: 980px) { .chapter-dial { display: none; } }

/* ---- hero: title page with ex libris ---- */
.hero { text-align: center; padding: 100px 0 92px; position: relative; }
@media (max-width: 640px) { .hero { padding: 60px 0 52px; } }
.hero .overline { color: var(--sepia); margin: 0 0 34px; }
.hero .orn { color: var(--thread); font-size: 1.15rem; letter-spacing: .55em; margin: 0 0 34px; padding-left: .55em; }
h1 {
  font-size: clamp(3.4rem, 10.5vw, 7.4rem);
  font-weight: 500; letter-spacing: .012em; line-height: .98;
  margin: 0 0 34px; text-wrap: balance;
}
.hero .thesis {
  font-style: italic; font-size: clamp(1.25rem, 2.7vw, 1.65rem);
  max-width: 30ch; margin: 0 auto 50px; color: var(--ink);
}
.hero .imprint { color: var(--sepia); margin: 0; }
.hero .imprint::before, .hero .imprint::after { content: "—"; color: var(--thread); margin: 0 16px; }

/* the ex libris seal — signature mark */
.exlibris {
  position: absolute; right: 6%; bottom: 34px;
  width: 108px; height: 108px; border-radius: 50%;
  border: 2px solid var(--seal);
  outline: 1px solid rgba(217, 112, 127, .4); outline-offset: 4px;
  color: var(--seal);
  display: grid; place-items: center; text-align: center;
  transform: rotate(-11deg);
  font-variant: small-caps; letter-spacing: .12em; font-size: .72rem; line-height: 1.45;
  opacity: .92;
  box-shadow: inset 0 0 26px rgba(217, 112, 127, .12);
}
.exlibris b { font-size: 1.5rem; letter-spacing: .06em; display: block; font-weight: 500; }
@media (max-width: 760px) { .exlibris { position: static; margin: 44px auto 0; transform: rotate(-7deg); } }

/* ---- praise — an unattributed pull-quote, like the "advance praise" page
   printed ahead of a book's first chapter. Sits right after the hero so
   it's the first thing a reader hits after the title. ---- */
.praise {
  max-width: 620px; margin: 0 auto; padding: 0 26px; text-align: center; position: relative;
}
.praise::before {
  content: "\201C"; display: block; font-family: var(--serif);
  font-size: 4.2rem; line-height: 1; color: var(--thread); opacity: .55;
  margin-bottom: -20px;
}
.praise p {
  font-style: italic; font-size: clamp(1.1rem, 2vw, 1.32rem);
  line-height: 1.6; color: var(--ink);
  max-width: 56ch; margin: 0 auto;
}

/* ---- sections: running heads + marginalia ---- */
section { padding: 84px 0; position: relative; scroll-margin-top: var(--navh); }
.running {
  display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap; gap: 6px;
  border-top: 1px solid rgba(236, 231, 221, .16);
  padding-top: 13px; margin-bottom: 56px; color: var(--sepia);
}
.running .folio { color: var(--thread); }
@media (max-width: 640px) {
  section { padding: 56px 0; }
  .running { margin-bottom: 40px; }
}
h2 { font-size: clamp(2rem, 4.6vw, 2.9rem); font-weight: 500; margin: 0 0 28px; text-wrap: balance; }
h2 em { color: var(--seal); }

.marginalia {
  display: none; position: absolute; left: -180px; top: 170px;
  width: 140px; font-style: italic; font-size: .85rem; color: var(--sepia);
  line-height: 1.5; text-align: right;
  border-right: 1px solid rgba(185, 133, 144, .45); padding-right: 14px;
}
@media (min-width: 1440px) { .has-margins .marginalia { display: block; } }

/* ---- book spread ---- */
.spread { display: grid; grid-template-columns: minmax(240px, 350px) 1fr; gap: 60px; align-items: start; }
@media (max-width: 840px) { .spread { grid-template-columns: 1fr; } }

.plate-frame {
  background: var(--panel);
  border: 1px solid rgba(236, 231, 221, .14);
  padding: 16px;
  box-shadow: 0 24px 50px -20px rgba(0, 0, 0, .7), 0 0 0 1px rgba(185, 133, 144, .05);
  margin: 0; position: relative;
}
.plate-frame::before {
  content: ""; position: absolute; inset: 8px;
  border: 1px solid rgba(185, 133, 144, .3); pointer-events: none;
}
.plate-frame .art { border: 1px solid rgba(236, 231, 221, .12); position: relative; overflow: hidden; }
.cover-art { aspect-ratio: 5 / 8; }
.cover-art img { display: block; width: 100%; height: 100%; object-fit: cover; }
.plate-frame figcaption { margin-top: 13px; color: var(--sepia); text-align: center; }

.col p { margin: 0 0 1.15em; max-width: 58ch; font-size: 1.08rem; }
.col p.lead::first-letter {
  initial-letter: 3; -webkit-initial-letter: 3;
  color: var(--seal); font-weight: 600; padding-right: .14em;
}
@supports not (initial-letter: 3) {
  .col p.lead::first-letter {
    font-size: 3.5em; float: left; line-height: .84;
    padding: .05em .13em 0 0; color: var(--seal); font-weight: 600;
  }
}
.colophon-line {
  border-top: 1px solid rgba(185, 133, 144, .5);
  border-bottom: 1px solid rgba(185, 133, 144, .5);
  padding: 13px 0; margin: 28px 0; color: var(--sepia);
}
.reedition-note { color: var(--sepia); font-style: italic; margin: -14px 0 26px; }
.ctas { display: flex; gap: 20px; flex-wrap: wrap; align-items: center; }
.cta-primary {
  display: inline-block; background: var(--seal); color: var(--bg);
  text-decoration: none; padding: 14px 30px; letter-spacing: .12em;
  box-shadow: 0 6px 18px rgba(217, 112, 127, .3);
  transition: transform .2s ease, background .2s ease;
}
.cta-primary:hover { background: var(--seal-soft); color: var(--bg); transform: translateY(-2px); }
.cta-secondary {
  display: inline-block; background: transparent; color: var(--seal);
  text-decoration: none; padding: 13px 28px; letter-spacing: .12em;
  border: 1px solid var(--seal);
  transition: transform .2s ease, background .2s ease, color .2s ease;
}
.cta-secondary:hover { background: var(--seal); color: var(--bg); transform: translateY(-2px); }
.cta-text { color: var(--seal); }

/* ---- láminas shelf ---- */
.shelf {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(240px, 310px);
  gap: 34px; overflow-x: auto; padding: 6px 6px 26px;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
}
@media (max-width: 640px) {
  .shelf { grid-auto-columns: minmax(200px, 78vw); gap: 18px; }
}
.shelf > figure { scroll-snap-align: start; }
.shelf .art { aspect-ratio: 4 / 5; }
.art-1 { background: radial-gradient(90% 90% at 30% 25%, rgba(217, 112, 127, .22), transparent 60%), linear-gradient(190deg, #20262C, #14171B); }
.art-2 { background: radial-gradient(90% 110% at 75% 70%, rgba(185, 133, 144, .28), transparent 62%), linear-gradient(150deg, #1C232A, #12161A); }
.art-3 { background: radial-gradient(120% 80% at 50% 0%, rgba(169, 154, 160, .22), transparent 55%), linear-gradient(200deg, #20262C, #171B20); }
.art-4 { background: radial-gradient(80% 80% at 20% 80%, rgba(217, 112, 127, .2), transparent 60%), linear-gradient(170deg, #1E2229, #14171B); }
.shelf-note { color: var(--sepia); max-width: 60ch; margin-top: 8px; font-style: italic; }

/* ---- personajes: character portraits ---- */
.chars-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 300px));
  gap: 34px;
}
.char-frame .art { aspect-ratio: 660 / 810; }
.char-frame .art img { display: block; width: 100%; height: 100%; object-fit: cover; }
.char-frame figcaption { margin-top: 13px; text-align: center; }
.char-name { display: block; font-size: 1.15rem; font-style: italic; color: var(--ink); }
.char-role { display: block; color: var(--thread); margin: 4px 0 8px; }
.char-blurb { display: block; color: var(--sepia); font-size: .92rem; line-height: 1.5; }

.section-lead { color: var(--sepia); font-style: italic; max-width: 58ch; margin: 0 0 44px; font-size: 1.08rem; }

/* asterism section break */
.asterism { text-align: center; color: var(--thread); font-size: 1.3rem; letter-spacing: .8em; padding-left: .8em; margin: 0; }

/* ---- author ---- */
.author { display: grid; grid-template-columns: minmax(220px, 300px) 1fr; gap: 60px; align-items: start; }
@media (max-width: 840px) { .author { grid-template-columns: 1fr; } }
.portrait .art {
  aspect-ratio: 4 / 5;
  background:
    radial-gradient(100% 100% at 50% 28%, rgba(185, 133, 144, .2), transparent 65%),
    linear-gradient(180deg, #1E2229, #14171B);
}
.author .col p { font-size: 1.14rem; }
.tagline-quote { font-style: italic; color: var(--seal); font-size: 1.05rem; margin: -8px 0 22px; }

/* ---- colophon (press + contact) ---- */
.colophon { text-align: center; max-width: 640px; margin: 0 auto; }
.colophon p { margin: 0 0 15px; }
.colophon .soon { color: var(--sepia); font-style: italic; }
.contact-lines { display: grid; gap: 14px; margin-top: 34px; }
.contact-lines a { font-size: 1.08rem; }

footer {
  text-align: center; padding: 34px 0 54px; color: var(--sepia);
  border-top: 1px solid rgba(236, 231, 221, .14);
}
footer .seal-mini { color: var(--seal); }

@media (prefers-reduced-motion: no-preference) {
  .hero > * { animation: settle .9s cubic-bezier(.2, .7, .3, 1) both; }
  .hero > *:nth-child(2) { animation-delay: .1s; }
  .hero > *:nth-child(3) { animation-delay: .2s; }
  .hero > *:nth-child(4) { animation-delay: .3s; }
  .hero > *:nth-child(5) { animation-delay: .4s; }
  .hero > *:nth-child(6) { animation-delay: .55s; }
  @keyframes settle { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
  .plate-frame {
    transition: transform .25s ease, box-shadow .3s ease;
    transform-style: preserve-3d; will-change: transform;
  }
  .plate-frame:hover { box-shadow: 0 32px 64px -18px rgba(0, 0, 0, .75), 0 0 0 1px rgba(185, 133, 144, .16); }
  @supports (animation-timeline: view()) {
    section > * { animation: reveal both; animation-timeline: view(); animation-range: entry 0% entry 40%; }
    @keyframes reveal { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
  }

  /* the running head "turns in" like a leaf, driven by nav-3d.js;
     .turn-init/.turn-in are only ever added when JS is present, so a
     no-JS visit never sees the rotated starting state. */
  .running.turn-init {
    transform: perspective(1100px) rotateY(-14deg) translateX(-10px);
    transform-origin: left center; opacity: 0;
  }
  .running.turn-in {
    transform: perspective(1100px) rotateY(0deg) translateX(0);
    opacity: 1; transition: transform .6s cubic-bezier(.2, .7, .3, 1), opacity .6s ease;
  }

  /* portraits breathe — a slow, continuous Ken Burns drift on the image
     itself, independent of the frame's own pointer-tilt transform */
  .cover-art img, .char-frame .art img {
    animation: kenburns 26s ease-in-out infinite alternate;
    transform-origin: 55% 32%;
  }
  @keyframes kenburns { from { transform: scale(1); } to { transform: scale(1.045); } }

  .exlibris { animation: seal-breathe 7s ease-in-out infinite; }
  @keyframes seal-breathe {
    0%, 100% { box-shadow: inset 0 0 26px rgba(217, 112, 127, .12); }
    50%      { box-shadow: inset 0 0 42px rgba(217, 112, 127, .24); }
  }

  .chapter-dial a.active { animation: dial-pulse 2.6s ease-in-out infinite; }
  @keyframes dial-pulse {
    0%, 100% { box-shadow: 0 5px 14px rgba(217, 112, 127, .4); }
    50%      { box-shadow: 0 5px 24px rgba(217, 112, 127, .7); }
  }

  .asterism { animation: twinkle 5s ease-in-out infinite; }
  @keyframes twinkle { 0%, 100% { opacity: .65; } 50% { opacity: 1; } }
}
