/*
  songs of life — interactive poetry book.

  The stage is lit like an exhibit in both themes: the paper book is the one
  bright object in a deep blue-green room. Paintings are drawn client-side on
  canvas by poems.js; everything here is stagecraft, typography, and motion.

  All dynamic styling flows through classes and CSS custom properties set via
  CSSOM (the site CSP forbids style attributes), and every large animation has
  a reduced-motion fallback.
*/

.poems-stage {
  /* scoped book tokens — deliberately warmer + inkier than the site UI */
  --pb-serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, "Times New Roman", serif;
  --pb-paper: #f6f2e7;
  --pb-paper-2: #ebe4d3;
  --pb-paper-edge: #d9d0ba;
  --pb-ink: #22333a;
  --pb-ink-soft: rgba(34, 51, 58, 0.66);
  --pb-teal: #2e7d76;
  --pb-deep: #0f3d49;
  --pb-abyss: #081e26;
  --pb-sage: #8fb8aa;
  --pb-mist: #d7e7e0;
  --pb-gold: #c9a86a;

  --pb-stage-a: #0d3540;
  --pb-stage-b: #123f4b;
  --pb-stage-c: #0a2831;

  --pb-turn-dur: 1050ms;
  --pb-turn-ease: cubic-bezier(0.36, 0.08, 0.18, 1);

  position: relative;
  color: var(--pb-ink);
}

html[data-theme="dark"] .poems-stage {
  --pb-stage-a: #071a21;
  --pb-stage-b: #0a232c;
  --pb-stage-c: #050f14;
  --pb-paper: #efe9da;
  --pb-paper-2: #e2dac6;
}

/* ---------------------------------------------------------------------------
   No-JS / pre-JS reading view: the collection as a quietly typeset page.
--------------------------------------------------------------------------- */

.poems-source {
  max-width: 620px;
  margin: 0 auto;
  padding: 56px 22px 80px;
  font-family: var(--pb-serif);
}

.poems-head {
  text-align: center;
  margin-bottom: 64px;
}

.poems-eyebrow {
  font-family: var(--font);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--pb-teal);
  margin: 0 0 14px;
}

.poems-heading {
  font-family: var(--pb-serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(40px, 7vw, 64px);
  line-height: 1.05;
  margin: 0 0 10px;
  color: var(--ink);
  text-wrap: balance;
}

.poems-subtitle {
  font-style: italic;
  color: var(--muted);
  margin: 0;
  font-size: 17px;
}

.poems-noscript {
  margin: 22px auto 0;
  max-width: 46ch;
  font-family: var(--font);
  font-size: 13.5px;
  color: var(--muted);
}

.poems-source .poem {
  margin: 0 0 58px;
}

.poems-source .poem-title {
  font-family: var(--pb-serif);
  font-style: italic;
  font-weight: 400;
  font-size: 26px;
  color: var(--ink);
  margin: 0 0 16px;
}

.poems-source .poem-line {
  font-size: 16.5px;
  line-height: 1.85;
  margin: 0;
  color: var(--ink);
}

.poems-back {
  text-align: center;
  margin-top: 72px;
}

/* Once the book engine mounts, the reading view steps aside entirely. */
.poems-stage.is-book .poems-source {
  display: none;
}

/* ---------------------------------------------------------------------------
   Full-page mode: while the book is mounted, the site chrome bows out and the
   stage owns the whole viewport. Without JavaScript the header/footer remain,
   so the plain reading view keeps its normal navigation.
--------------------------------------------------------------------------- */

body:has(.poems-stage.is-book) {
  padding-top: 0;
}

body:has(.poems-stage.is-book) .site-header,
body:has(.poems-stage.is-book) .site-footer {
  display: none;
}

/* The contents owns the whole screen; the way home would collide with its title. */
.poems-stage:has(.pb-toc.is-open) .pb-home {
  opacity: 0;
  pointer-events: none;
}

/* Floating way home, replacing the hidden header. */
.pb-home {
  position: absolute;
  top: 18px;
  left: 18px;
  z-index: 30;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 10px 16px 10px 13px;
  border-radius: 999px;
  border: 1px solid rgba(143, 184, 170, 0.3);
  background: rgba(8, 30, 38, 0.74);
  color: var(--pb-mist);
  text-decoration: none;
  font-family: var(--font);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease, transform var(--dur-1) ease;
}

.pb-home:hover {
  background: rgba(46, 125, 118, 0.45);
  border-color: rgba(143, 184, 170, 0.65);
  transform: translateY(-1px);
}

.pb-home:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(143, 184, 170, 0.65);
}

.pb-home-arrow {
  font-size: 14px;
  line-height: 1;
}

@media (max-width: 860px) {
  .pb-home-label { display: none; }
  .pb-home { padding: 10px 13px; }
}

/* ---------------------------------------------------------------------------
   Stage
--------------------------------------------------------------------------- */

.poems-stage.is-book {
  min-height: 100dvh;
  overflow: clip;
  background:
    radial-gradient(120% 90% at 18% 8%, var(--pb-stage-b) 0%, transparent 55%),
    radial-gradient(110% 100% at 85% 92%, var(--pb-stage-b) 0%, transparent 50%),
    linear-gradient(168deg, var(--pb-stage-a) 0%, var(--pb-stage-c) 100%);
}

/* Ambient pigment auras — enormous, soft, drifting almost imperceptibly.
   The softness comes from the radial gradient itself, which already fades to
   transparent at 65%. A blur() on top of that was close to invisible but forced
   three huge filtered layers to re-rasterise on every scale change, which is
   what a pinch or smart zoom is. will-change is redundant too: these run a
   permanent transform animation, so the compositor promotes them anyway, and
   pinning the layer only makes the re-raster more expensive. */
.pb-aura {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0.55;
}

.pb-aura-1 {
  width: 55vw;
  height: 55vw;
  left: -12vw;
  top: -18vw;
  background: radial-gradient(circle at 40% 40%, rgba(46, 125, 118, 0.55), transparent 65%);
  animation: pb-drift-a 46s ease-in-out infinite alternate;
}

.pb-aura-2 {
  width: 48vw;
  height: 48vw;
  right: -14vw;
  bottom: -16vw;
  background: radial-gradient(circle at 55% 45%, rgba(143, 184, 170, 0.34), transparent 62%);
  animation: pb-drift-b 58s ease-in-out infinite alternate;
}

.pb-aura-3 {
  width: 30vw;
  height: 30vw;
  right: 8vw;
  top: -10vw;
  background: radial-gradient(circle at 50% 55%, rgba(15, 61, 73, 0.7), transparent 60%);
  animation: pb-drift-a 64s ease-in-out infinite alternate-reverse;
}

@keyframes pb-drift-a {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(4vw, 3vw, 0) scale(1.08); }
}

@keyframes pb-drift-b {
  from { transform: translate3d(0, 0, 0) scale(1.05); }
  to   { transform: translate3d(-3vw, -2vw, 0) scale(0.97); }
}

.pb-scene {
  position: relative;
  z-index: 1;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 26px;
  padding: 40px 20px 34px;
  box-sizing: border-box;
  perspective: 2600px;
}

/* ---------------------------------------------------------------------------
   The book object
--------------------------------------------------------------------------- */

.pb-book {
  position: relative;
  width: min(1020px, 94vw);
  aspect-ratio: 30 / 19.5;
  max-height: calc(100dvh - 160px);
  transform-style: preserve-3d;
  transform: rotateX(var(--pb-tilt-x, 0deg)) rotateY(var(--pb-tilt-y, 0deg));
  transition: transform 900ms var(--ease);
  opacity: 0;
  translate: 0 26px;
}

.pb-book.is-mounted {
  opacity: 1;
  translate: 0 0;
  transition: opacity 1100ms var(--ease), translate 1100ms var(--ease), transform 900ms var(--ease);
}

/* Stacked page-block: the closed edges of all the pages you are not reading. */
.pb-block {
  position: absolute;
  inset: -2px -5px -8px -5px;
  border-radius: 6px 8px 8px 6px;
  background:
    linear-gradient(180deg, var(--pb-paper-edge), #cfc5ac 60%, #bfb499);
  box-shadow:
    0 40px 90px -30px rgba(3, 14, 18, 0.85),
    0 12px 30px -12px rgba(3, 14, 18, 0.6);
}

.pb-block::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: repeating-linear-gradient(
    180deg,
    transparent 0 2px,
    rgba(255, 255, 255, 0.22) 2px 3px
  );
  opacity: 0.35;
}

.pb-page {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50%;
  overflow: hidden;
  background:
    linear-gradient(115deg, var(--pb-paper) 0%, var(--pb-paper-2) 100%);
}

.pb-left {
  left: 0;
  border-radius: 5px 0 0 5px;
}

.pb-right {
  right: 0;
  border-radius: 0 5px 5px 0;
}

.pb-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* Spine gutter shading gives the flat halves their curl. */
.pb-page-shade {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.pb-left .pb-page-shade {
  background: linear-gradient(270deg, rgba(15, 40, 48, 0.30) 0%, rgba(15, 40, 48, 0.06) 9%, transparent 22%);
}

.pb-right .pb-page-shade {
  background: linear-gradient(90deg, rgba(15, 40, 48, 0.26) 0%, rgba(15, 40, 48, 0.05) 9%, transparent 22%);
}

.pb-spine {
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 2px;
  margin-left: -1px;
  background: linear-gradient(180deg, rgba(15, 40, 48, 0.35), rgba(15, 40, 48, 0.18));
  z-index: 4;
  pointer-events: none;
}

/* ---------------------------------------------------------------------------
   Poem text page
--------------------------------------------------------------------------- */

.pb-text {
  --pb-title-inset: 12%;
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  /* Anchor the block to a fixed top position so a poem's title lands at the
     same height on every page — page i, ii, iii all align. Short poems simply
     leave breathing room below, the way a printed poetry book does. */
  justify-content: flex-start;
  padding: var(--pb-title-inset) 9% 8%;
  box-sizing: border-box;
  font-family: var(--pb-serif);
}

.pb-text-measure {
  visibility: hidden;
  pointer-events: none;
}

/* Pagination measures final painted geometry. The regular entrance transform
   moves every not-yet-inked line down by 6px, which would make even a single
   fitting line look outside the content box and collapse mobile pagination to
   one line per page. Keep animation state out of the hidden measuring copy. */
.pb-text-measure .pb-line {
  opacity: 1;
  filter: none;
  transform: none;
  transition: none;
}

.pb-text.is-overflowing {
  justify-content: flex-start;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}

.pb-poem-title {
  font-style: italic;
  font-weight: 400;
  font-size: clamp(18px, 2.6vw, 27px);
  color: var(--pb-deep);
  margin: 0 0 0.85em;
  letter-spacing: 0.01em;
  overflow-wrap: anywhere;
}

.pb-poem-title .pb-part {
  font-size: 0.62em;
  color: var(--pb-ink-soft);
  font-style: italic;
  margin-left: 0.6em;
  letter-spacing: 0.08em;
}

.pb-line {
  font-size: clamp(12px, 1.55vw, 16.5px);
  line-height: 1.72;
  color: var(--pb-ink);
  margin: 0;
  overflow-wrap: anywhere;
  opacity: 0;
  transform: translateY(6px);
  /* Fade and rise only. A blur() here left every single line carrying a filter
     for the life of the page -- filter is never "none" once set, so blur(0)
     still promotes a layer per line, and all of them re-rasterise on a zoom.
     The unblur was barely visible on 14px text behind a 550ms fade. */
  transition:
    opacity 550ms ease calc(var(--i, 0) * 40ms + 100ms),
    transform 550ms ease calc(var(--i, 0) * 40ms + 100ms);
}

.pb-text.is-inked .pb-line {
  opacity: 1;
  transform: translateY(0);
}

.pb-folio {
  position: absolute;
  bottom: 4.2%;
  left: 0;
  right: 0;
  text-align: center;
  font-family: var(--font);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.3em;
  color: rgba(34, 51, 58, 0.38);
}

/* ---------------------------------------------------------------------------
   The turning sheet
--------------------------------------------------------------------------- */

.pb-sheet {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 50%;
  transform-origin: left center;
  transform-style: preserve-3d;
  z-index: 6;
  pointer-events: none;
  display: none;
}

.pb-book.is-turning .pb-sheet {
  display: block;
  animation: pb-turn-fwd var(--pb-turn-dur) var(--pb-turn-ease) forwards;
}

.pb-book.is-turning-back .pb-sheet {
  display: block;
  animation: pb-turn-back var(--pb-turn-dur) var(--pb-turn-ease) forwards;
}

@keyframes pb-turn-fwd {
  from { transform: rotateY(0deg); }
  to   { transform: rotateY(-180deg); }
}

@keyframes pb-turn-back {
  from { transform: rotateY(-180deg); }
  to   { transform: rotateY(0deg); }
}

.pb-face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  overflow: hidden;
  background: linear-gradient(115deg, var(--pb-paper) 0%, var(--pb-paper-2) 100%);
}

.pb-face-front { border-radius: 0 5px 5px 0; }

.pb-face-back {
  transform: rotateY(180deg);
  border-radius: 5px 0 0 5px;
}

/* Light sweeps across the moving sheet as it lifts through the room. */
.pb-face::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(90deg, rgba(15, 40, 48, 0.0), rgba(15, 40, 48, 0.32));
  opacity: 0;
}

.pb-book.is-turning .pb-face-front::after,
.pb-book.is-turning-back .pb-face-front::after {
  animation: pb-sheet-shade var(--pb-turn-dur) ease-in-out forwards;
}

@keyframes pb-sheet-shade {
  0%   { opacity: 0; }
  45%  { opacity: 0.55; }
  100% { opacity: 0; }
}

/* Shadow the sheet throws on the page beneath it. */
.pb-cast {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 50%;
  z-index: 5;
  pointer-events: none;
  background: linear-gradient(90deg, rgba(6, 20, 26, 0.45), transparent 70%);
  opacity: 0;
}

.pb-book.is-turning .pb-cast,
.pb-book.is-turning-back .pb-cast {
  animation: pb-cast var(--pb-turn-dur) ease-in-out forwards;
}

@keyframes pb-cast {
  0%   { opacity: 0; }
  40%  { opacity: 0.8; }
  100% { opacity: 0; }
}

/* ---------------------------------------------------------------------------
   Cover
--------------------------------------------------------------------------- */

.pb-cover {
  position: absolute;
  inset: 0;
  z-index: 10;
  transform-origin: left center;
  transform-style: preserve-3d;
  border-radius: 6px;
  overflow: hidden;
  box-shadow: 0 30px 70px -24px rgba(3, 14, 18, 0.9);
  transition: transform 1350ms cubic-bezier(0.42, 0.05, 0.16, 1), opacity 500ms ease 900ms;
  cursor: pointer;
  border: 0;
  padding: 0;
  background: var(--pb-deep);
  text-align: center;
}

.pb-book.is-open .pb-cover {
  transform: rotateY(-165deg);
  opacity: 0;
  pointer-events: none;
}

.pb-cover[hidden] {
  display: none;
}

.pb-cover-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

.pb-cover-text {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 6%;
  color: var(--pb-mist);
}

.pb-cover-eyebrow {
  font-family: var(--font);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--pb-sage);
  margin: 0;
  opacity: 0;
  animation: pb-rise 1100ms ease 300ms forwards;
}

.pb-cover-title {
  font-family: var(--pb-serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(38px, 6.4vw, 74px);
  line-height: 1.03;
  margin: 0;
  color: #f2f7f2;
  text-shadow: 0 4px 40px rgba(6, 20, 26, 0.6);
  opacity: 0;
  animation: pb-rise 1200ms ease 480ms forwards;
}

.pb-cover-sub {
  font-family: var(--pb-serif);
  font-style: italic;
  font-size: clamp(14px, 1.8vw, 18px);
  color: var(--pb-mist);
  margin: 0 0 18px;
  opacity: 0;
  animation: pb-rise 1200ms ease 640ms forwards;
}

.pb-open-btn {
  display: inline-flex;
  font-family: var(--font);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #eaf3ee;
  background: rgba(46, 125, 118, 0.66);
  border: 1px solid rgba(143, 184, 170, 0.5);
  border-radius: 999px;
  padding: 13px 30px;
  cursor: pointer;
  transition: background var(--dur-2) var(--ease), transform var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
  opacity: 0;
  animation: pb-rise 1200ms ease 820ms forwards;
}

.pb-cover:hover .pb-open-btn {
  background: rgba(46, 125, 118, 0.6);
  transform: translateY(-2px);
  box-shadow: 0 14px 34px -12px rgba(6, 20, 26, 0.8);
}

.pb-continue {
  position: absolute;
  z-index: 11;
  left: 50%;
  top: 72%;
  translate: -50% 0;
  white-space: nowrap;
  font-family: var(--font);
  font-size: 11.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--pb-sage);
  background: none;
  border: 0;
  cursor: pointer;
  padding: 8px;
  opacity: 0;
  animation: pb-rise 1200ms ease 950ms forwards;
  transition: color var(--dur-1) ease;
}

.pb-continue:hover { color: var(--pb-mist); }

.pb-continue[hidden] {
  display: none;
}

@keyframes pb-rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---------------------------------------------------------------------------
   Controls
--------------------------------------------------------------------------- */

.pb-controls {
  display: flex;
  align-items: center;
  gap: 14px;
  font-family: var(--font);
  opacity: 0;
  translate: 0 12px;
  transition: opacity 700ms ease 250ms, translate 700ms ease 250ms;
  pointer-events: none;
}

.pb-controls.is-live {
  opacity: 1;
  translate: 0 0;
  pointer-events: auto;
}

.pb-controls[hidden] {
  display: none;
}

.pb-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: 44px;
  height: 44px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1px solid rgba(143, 184, 170, 0.35);
  background: rgba(8, 30, 38, 0.8);
  color: var(--pb-mist);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease, transform var(--dur-1) ease, opacity var(--dur-1) ease;
}

.pb-btn:hover:not(:disabled) {
  background: rgba(46, 125, 118, 0.45);
  border-color: rgba(143, 184, 170, 0.7);
  transform: translateY(-1px);
}

.pb-btn:disabled {
  opacity: 0.35;
  cursor: default;
}

.pb-btn svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.pb-counter {
  min-width: 92px;
  text-align: center;
  color: var(--pb-sage);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.22em;
  font-variant-numeric: tabular-nums;
  user-select: none;
}

.pb-counter .pb-counter-title {
  display: block;
  font-family: var(--pb-serif);
  font-style: italic;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0.02em;
  font-size: 13.5px;
  color: var(--pb-mist);
  margin-top: 3px;
}

.pb-progress {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  background: rgba(143, 184, 170, 0.12);
  z-index: 2;
}

.pb-progress-fill {
  height: 100%;
  width: 100%;
  transform-origin: left center;
  transform: scaleX(var(--pb-prog, 0));
  background: linear-gradient(90deg, var(--pb-teal), var(--pb-sage));
  transition: transform 700ms var(--ease);
}

/* ---------------------------------------------------------------------------
   Contents overlay
--------------------------------------------------------------------------- */

.pb-toc {
  position: absolute;
  inset: 0;
  z-index: 20;
  display: block;
  opacity: 0;
  pointer-events: none;
  transition: opacity 420ms ease;
  overflow: hidden;
}

.pb-toc[hidden] {
  display: none;
}

.pb-toc.is-open {
  opacity: 1;
  pointer-events: auto;
}

/* Full bleed: the arc runs off both edges, so nothing here is width-capped. */
.pb-toc-panel {
  position: relative;
  z-index: 2;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 26px 28px 0;
  box-sizing: border-box;
}

.pb-toc-head {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 8px;
}

.pb-toc-title {
  font-family: var(--pb-serif);
  font-style: italic;
  font-weight: 400;
  font-size: 30px;
  color: var(--pb-mist);
  margin: 0;
}

/* ---------------------------------------------------------------------------
   The arc

   The plates wrap around the inside of a cylinder and you travel along it.
   The geometry is real, not a fake skew: every plate sits at its own angle on
   a circle and is pushed back by r·(1 − cos θ) so it lands on the surface.

   The room is deliberately NOT flat black. Its three colours are written from
   the centred poem's own palette by poems.js and cross-fade as you move, so
   the space you browse in is lit by whatever poem you are standing in front
   of. @property is what makes a custom property interpolate rather than snap.
--------------------------------------------------------------------------- */

@property --pb-arc-a { syntax: "<color>"; inherits: true; initial-value: #14424e; }
@property --pb-arc-b { syntax: "<color>"; inherits: true; initial-value: #0d3540; }
@property --pb-arc-c { syntax: "<color>"; inherits: true; initial-value: #050f14; }

.pb-arc-field {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(52% 44% at 50% 44%, var(--pb-arc-a) 0%, transparent 70%),
    radial-gradient(74% 58% at 8% 100%, var(--pb-arc-b) 0%, transparent 64%),
    radial-gradient(66% 52% at 96% 0%, var(--pb-arc-b) 0%, transparent 60%),
    linear-gradient(168deg, var(--pb-arc-c) 0%, #03080b 100%);
  transition:
    --pb-arc-a 1100ms var(--ease),
    --pb-arc-b 1100ms var(--ease),
    --pb-arc-c 1100ms var(--ease);
}

/* Grain and vignette, painted once. Keeps the field from reading as a flat
   CSS gradient without costing an animation loop. */
.pb-arc-grain {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0.55;
  /* Drawn as transparent-backed light and dark speckle rather than mid-grey
     under mix-blend-mode. A blend mode forces its own compositing group, and
     that group is re-composited on every scale change. */
}

.pb-arc-stage {
  position: relative;
  z-index: 2;
  flex: 1 1 auto;
  min-height: 0;
  perspective: 1000px;
  perspective-origin: 50% 46%;
  overflow: hidden;
  cursor: grab;
  touch-action: pan-y;
}

.pb-arc-stage.is-dragging { cursor: grabbing; }

.pb-arc-row {
  position: absolute;
  top: 50%;
  left: 0;
  display: flex;
  align-items: center;
  transform-style: preserve-3d;
}

/* will-change only while a drag is actually in flight. Leaving it on pins the
   layer for the whole session, and every pinned layer has to be re-rasterised
   when the page scale changes, which is exactly what a pinch or smart zoom is. */
.pb-arc-stage.is-dragging .pb-arc-row { will-change: transform; }

.pb-arc-item {
  position: relative;
  flex: none;
  border: 0;
  padding: 0;
  margin: 0;
  background: none;
  cursor: pointer;
  transform-style: preserve-3d;
  -webkit-tap-highlight-color: transparent;
}

.pb-arc-plate {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 2px;
  background: var(--pb-paper);
  box-shadow: 0 34px 70px -30px rgba(0, 0, 0, 0.95);
  transform-origin: 50% 50%;
  /* No will-change. These already carry a 3D transform, so the compositor
     promotes them while they move anyway; declaring it here pinned 43 layers
     for the whole session and every one had to be re-rasterised on a zoom. */
}

/* The label stays flat on a shared baseline while the plate above it turns,
   the way a printed index sits under its plate. */
.pb-arc-cap {
  position: absolute;
  left: 0;
  top: 100%;
  margin-top: 15px;
  display: flex;
  gap: 10px;
  align-items: baseline;
  white-space: nowrap;
  transition: opacity 300ms ease;
}

.pb-arc-num {
  font-family: var(--font);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.22em;
  color: rgba(143, 184, 170, 0.55);
  font-variant-numeric: tabular-nums;
}

.pb-arc-name {
  font-family: var(--pb-serif);
  font-style: italic;
  font-size: 14px;
  line-height: 1;
  color: rgba(215, 231, 224, 0.82);
}

.pb-arc-item.is-centre .pb-arc-num { color: var(--pb-gold); }
.pb-arc-item.is-centre .pb-arc-name { color: #fdfbf4; }

.pb-arc-item:focus-visible { outline: none; }
.pb-arc-item:focus-visible .pb-arc-plate {
  box-shadow: 0 0 0 2px var(--pb-gold), 0 34px 70px -30px rgba(0, 0, 0, 0.95);
}

/* Reading position marker, so the arc still tells you where you left off. */
.pb-arc-item.is-current .pb-arc-cap::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--pb-gold);
  align-self: center;
}

.pb-arc-foot {
  position: relative;
  z-index: 2;
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 14px;
  padding: 0 24px 26px;
  min-height: 34px;
}

.pb-arc-count {
  font-family: var(--font);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.24em;
  color: rgba(143, 184, 170, 0.5);
  font-variant-numeric: tabular-nums;
}

.pb-arc-hint {
  font-family: var(--font);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(143, 184, 170, 0.34);
}

@media (max-width: 860px) {
  .pb-toc-panel { padding: 16px 14px 0; }
  .pb-toc-title { font-size: 21px; }
  .pb-arc-name { font-size: 12.5px; }
  .pb-arc-num { font-size: 8.5px; }
  .pb-arc-cap { margin-top: 11px; gap: 7px; }
  .pb-arc-foot { padding: 0 14px 18px; gap: 10px; }
  .pb-arc-hint { display: none; }
  /* A phone drag is horizontal by intent; let the browser keep nothing. */
  .pb-arc-stage { touch-action: none; }
}

@media (prefers-reduced-motion: reduce) {
  .pb-arc-field { transition: none; }
  .pb-arc-plate { will-change: auto; }
}

/* ---------------------------------------------------------------------------
   Focus, hint, small screens, reduced motion
--------------------------------------------------------------------------- */

.pb-btn:focus-visible,
.pb-continue:focus-visible,
.pb-arc-item:focus-visible,
.pb-cover:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(143, 184, 170, 0.65);
}

.pb-hint {
  position: absolute;
  bottom: 14px;
  left: 0;
  right: 0;
  text-align: center;
  font-family: var(--font);
  font-size: 10.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(143, 184, 170, 0.55);
  pointer-events: none;
  opacity: 0;
  transition: opacity 800ms ease;
}

.pb-hint.is-shown { opacity: 1; }

@media (max-width: 860px) {
  .pb-book {
    aspect-ratio: auto;
    height: min(72dvh, 640px);
    width: min(460px, 94vw);
  }

  /* Single-page mode: the painting becomes the page's world, text floats on a
     rising paper scrim. The 3D sheet is desktop-only. */
  .pb-left {
    width: 100%;
    border-radius: 5px;
  }

  .pb-right {
    width: 100%;
    border-radius: 5px;
    background: linear-gradient(
      180deg,
      rgba(246, 242, 231, 0.72) 0%,
      rgba(246, 242, 231, 0.76) 34%,
      rgba(246, 242, 231, 0.88) 52%,
      rgba(246, 242, 231, 0.96) 66%
    );
  }

  .pb-text {
    padding-bottom: 14%;
  }

  .pb-line { font-size: 14px; line-height: 1.66; }

  .pb-sheet, .pb-cast, .pb-spine, .pb-page-shade { display: none !important; }

  .pb-book.is-sliding .pb-page {
    transition: opacity 420ms ease, transform 420ms ease;
    opacity: 0;
    transform: translateX(var(--pb-slide, -18px));
  }

  .pb-counter .pb-counter-title { display: none; }
  .pb-counter { min-width: 64px; }
}

@media (prefers-reduced-motion: reduce) {
  .pb-aura { animation: none !important; }
  .pb-book { transition: opacity 300ms ease; transform: none !important; }
  .pb-cover { transition: opacity 350ms ease; }
  .pb-book.is-open .pb-cover { transform: none; }
  .pb-book.is-turning .pb-sheet,
  .pb-book.is-turning-back .pb-sheet,
  .pb-book.is-turning .pb-cast,
  .pb-book.is-turning-back .pb-cast { animation: none !important; display: none; }
  .pb-line { transition: opacity 350ms ease; filter: none; transform: none; }
  .pb-cover-eyebrow, .pb-cover-title, .pb-cover-sub, .pb-open-btn, .pb-continue {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
  }
}
