/* ============================================================
   BOOK.os — interactions.css
   Page navigation strip + CRT-channel-change warp transition +
   lexicon hover/flicker effects + index keyword pulses.
   Loaded after the main stylesheets. Hidden in @media print.
   ============================================================ */

/* ---------- Book nav strip — fixed bottom-center ----------
   2026-05-22: scaled up — Fox flagged it was too small to read at a
   glance. Bigger labels + bolder font + brighter accent strokes. */
.book-nav {
  position: fixed;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 100;
  display: flex;
  align-items: stretch;
  gap: 12px;
  background: rgba(10, 10, 18, 0.92);
  border: 1.5px solid rgba(5, 217, 232, 0.5);
  border-radius: 5px;
  padding: 9px 12px;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow:
    0 0 0 1px rgba(255, 42, 109, 0.28),
    0 6px 30px rgba(0, 0, 0, 0.75),
    0 0 40px rgba(5, 217, 232, 0.18);
  font-family: 'Rajdhani', 'Share Tech Mono', sans-serif;
}

.book-nav-btn {
  display: flex;
  align-items: center;
  gap: 14px;
  background: transparent;
  border: 1.5px solid transparent;
  color: var(--paper);
  padding: 10px 18px;
  cursor: pointer;
  font-family: inherit;
  font-size: 15px;
  letter-spacing: 0.06em;
  transition: border-color 0.18s, background 0.18s, color 0.18s;
  min-width: 200px;
}

.book-nav-btn:hover:not(:disabled) {
  border-color: var(--naus-cyan);
  background: rgba(5, 217, 232, 0.12);
  color: var(--naus-cyan);
}

.book-nav-btn:disabled {
  opacity: 0.3;
  cursor: default;
}

.book-nav-prev { justify-content: flex-start; }
.book-nav-next { justify-content: flex-end; }

.book-nav-arrow {
  font-size: 20px;
  color: var(--naus-yellow);
  text-shadow: 0 0 8px rgba(249, 240, 2, 0.65);
  line-height: 1;
}

.book-nav-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.05;
}

.book-nav-next .book-nav-meta { align-items: flex-end; }

.book-nav-tag {
  font-family: 'Share Tech Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(232, 232, 238, 0.65);
  margin-bottom: 4px;
  font-weight: 600;
}

.book-nav-label {
  font-family: 'Orbitron', sans-serif;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.book-nav-position {
  display: flex;
  align-items: center;
  padding: 0 18px;
  border-left: 1.5px solid rgba(5, 217, 232, 0.32);
  border-right: 1.5px solid rgba(255, 42, 109, 0.32);
  font-family: 'Share Tech Mono', monospace;
  font-size: 20px;
  font-weight: 700;
  color: var(--naus-yellow);
  letter-spacing: 0.12em;
  text-shadow: 0 0 10px rgba(249, 240, 2, 0.6);
}

.book-nav-of {
  margin: 0 9px;
  color: var(--naus-magenta);
  opacity: 0.8;
}

/* ===========================================================
   SOFT-GLITCH PAGE TRANSITION — Fox 2026-05-24.
   Replaces the 3D page-flip (.book-turning) on NEXT/PREV button
   clicks, keyboard arrows, and lex-link jumps. The corner-peel
   drag interaction still uses real-book physics — this register
   is only for discrete click-to-navigate jumps.
   "Softly, pleasantly glitches to the next page" — chromatic
   saturate + slight hue-rotate + scale micro-pulse + opacity
   wipe; not slice-displace, not VANTA-corruption. Reads as
   "signal recomposing," tied to the OS-as-medium thesis.
   =========================================================== */
.book-glitching-out .spread,
.book-glitching-in  .spread {
  pointer-events: none;
  transform-origin: 50% 50%;
  will-change: filter, transform, opacity;
}

@keyframes book-soft-glitch-out {
  0%   { filter: none;                                                transform: scale(1);     opacity: 1;    }
  30%  { filter: saturate(1.15) blur(0.3px);                          transform: scale(1.003); opacity: 0.94; }
  65%  { filter: saturate(1.25) hue-rotate(-3deg) blur(0.6px);        transform: scale(1.008); opacity: 0.55; }
  100% { filter: saturate(1.3)  hue-rotate(-5deg) blur(1px);          transform: scale(1.012); opacity: 0;    }
}

@keyframes book-soft-glitch-in {
  0%   { filter: saturate(1.3)  hue-rotate(5deg) blur(1px);           transform: scale(0.988); opacity: 0;    }
  40%  { filter: saturate(1.2)  hue-rotate(2deg) blur(0.5px);         transform: scale(0.995); opacity: 0.7;  }
  100% { filter: none;                                                transform: scale(1);     opacity: 1;    }
}

.book-glitching-out .spread {
  animation: book-soft-glitch-out 220ms cubic-bezier(0.45, 0, 0.55, 1) forwards;
}

.book-glitching-in .spread {
  animation: book-soft-glitch-in 200ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

/* Sweep line — a thin cyan→magenta band travels top→bottom across
   the spread during the out-anim. Reads as "the signal is recomposing
   in scan order." Layered above the filter-glitch, beneath the
   chassis frame brackets (z-index 50). */
.book-glitching-out::after {
  content: "";
  position: fixed;
  left: 0; right: 0;
  height: 2px;
  pointer-events: none;
  z-index: 40;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(106, 240, 255, 0.5) 30%,
    rgba(255, 92, 196, 0.5) 70%,
    transparent 100%);
  box-shadow: 0 0 14px rgba(106, 240, 255, 0.35);
  animation: book-glitch-sweep 220ms ease-in-out forwards;
}

@keyframes book-glitch-sweep {
  0%   { top: 8%;   opacity: 0; }
  15%  {            opacity: 0.95; }
  100% { top: 92%;  opacity: 0; }
}

/* Honour reduced-motion: still need a transition cue (otherwise the
   page just hard-cuts), but make it a pure opacity fade with no
   filter / scale / sweep. ~120ms total. */
@media (prefers-reduced-motion: reduce) {
  .book-glitching-out .spread {
    animation: none;
    opacity: 0.4;
    transition: opacity 120ms linear;
  }
  .book-glitching-in .spread {
    animation: none;
    opacity: 1;
    transition: opacity 120ms linear;
  }
  .book-glitching-out::after { display: none; }
}

/* ===========================================================
   PERSPECTIVE — only enabled during a page-turn, never ambient.
   Killed the always-on tilt per Fox 2026-05-16 (motion sickness).
   The spread sits flat. Perspective is added to .book-turning
   transiently while the flip animates, then removed.
   (Kept for the corner-peel drag interaction, which still uses
   the .book-turning 3D framing on commit. The old click-driven
   warpTransition stage CSS below is currently UNUSED — see
   book.js softGlitchTransition for the active click-nav path.
   The warp CSS can be purged in a separate cleanup pass.)
   =========================================================== */
.book-turning {
  perspective: 2800px;
  perspective-origin: 50% 40%;
}

/* ===========================================================
   PAGE-TURN TRANSITION — the physical flip.
   The turning element is a CLONE of the current spread's right
   (forward) or left (back) page, with the ACTUAL CONTENT visible
   as it rotates. The back face shows the parchment underside
   with a glitch shading overlay. The turn includes a subtle
   scaleX squeeze at midpoint to suggest the page bowing as it
   curves over the spine.
   =========================================================== */

.book-turning .spread {
  pointer-events: none;
}

/* Stage container — positioned over the actual page via JS measurement,
   so the rotation pivots exactly at the spine. GPU-hinted for smooth
   compositing (paraphrased from turn.js's hardware-acceleration approach). */
.book-turn-page {
  position: fixed;
  pointer-events: none;
  z-index: 500;
  transform-style: preserve-3d;
  will-change: transform, box-shadow;
  backface-visibility: visible;
  transform: translateZ(0);  /* force GPU compositing */
}

/* Lift-shadow under the turning page — animates separately so it doesn't
   compound on the rotation transform (avoiding the scaleX/translateZ drift
   bug from earlier iterations). Suggests the page rising off the page
   underneath as it turns. */
.book-turn-lift-shadow {
  position: fixed;
  pointer-events: none;
  z-index: 479;
  background: radial-gradient(
    ellipse at center,
    rgba(0, 0, 0, 0.55) 0%,
    rgba(0, 0, 0, 0.35) 30%,
    rgba(0, 0, 0, 0.1) 60%,
    transparent 100%
  );
  filter: blur(8px);
  opacity: 0;
  animation: liftShadow 1.4s cubic-bezier(0.55, 0, 0.45, 1) forwards;
  will-change: opacity, transform;
}

@keyframes liftShadow {
  0%   { opacity: 0; transform: scaleY(0.85); }
  20%  { opacity: 0.5; transform: scaleY(1); }
  50%  { opacity: 0.7; transform: scaleY(1.15); }
  80%  { opacity: 0.5; transform: scaleY(1); }
  100% { opacity: 0; transform: scaleY(0.85); }
}

/* Forward turn: hinged at LEFT edge (the spine), rotates -180.
   PURE rotateY — no translateZ or scaleX (those caused spine drift).
   The spine point stays pinned exactly where the source page's spine
   was. Bezier is a smooth S-curve for paper-flip easing. */
.book-turn-page.book-turn-page--forward {
  transform-origin: left center;
  animation: pageTurnForward 1.4s cubic-bezier(0.55, 0.0, 0.45, 1.0) forwards;
}

/* Back turn: hinged at RIGHT edge (the spine), rotates +180 */
.book-turn-page.book-turn-page--back {
  transform-origin: right center;
  animation: pageTurnBack 1.4s cubic-bezier(0.55, 0.0, 0.45, 1.0) forwards;
}

/* PREVIEW LAYER — the next page that's revealed UNDERNEATH the turning
   page. Positioned in the same spot as the turning page but with lower
   z-index. Already visible from t=0; as the turning page sweeps away,
   the preview is revealed. */
.book-turn-preview {
  position: fixed;
  pointer-events: none;
  z-index: 480;
  background: var(--paper);
  overflow: hidden;
  box-shadow: inset 0 0 24px rgba(0, 0, 0, 0.4);
}

.book-turn-preview > * {
  /* Page-children inside preview are absolutely positioned by inline style */
  position: absolute;
  inset: 0;
}

/* The two faces — front carries the cloned page DOM, back is the
   parchment underside. Both occupy the same space; backface-visibility
   hides them depending on rotation. */
.book-turn-face {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  overflow: hidden;
  background: var(--paper);
  box-shadow:
    0 0 24px rgba(0, 0, 0, 0.6),
    inset 0 0 0 1px rgba(5, 217, 232, 0.06);
}

/* Front face — holds the cloned page content. Inherits styles via cascade. */
.book-turn-face--front {
  transform: rotateY(0deg);
}

/* Back face — parchment underside with a faint signal-static texture. */
.book-turn-face--back {
  transform: rotateY(180deg);
  background: var(--paper);
  overflow: hidden;
}

/* Fallback watermark — only shown when next-page DOM didn't load */
.book-turn-face--back:not(.book-turn-face--back-loaded) {
  background:
    radial-gradient(ellipse at center, rgba(255, 42, 109, 0.06) 0%, transparent 60%),
    repeating-linear-gradient(0deg, transparent 0px, transparent 3px, rgba(5, 217, 232, 0.04) 4px, transparent 6px),
    var(--paper-shadow);
  background-blend-mode: multiply;
}

.book-turn-face--back:not(.book-turn-face--back-loaded)::after {
  content: "BOOK \00b7 OS";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Orbitron', sans-serif;
  font-size: 92px;
  font-weight: 900;
  letter-spacing: 0.2em;
  color: rgba(5, 217, 232, 0.06);
  text-shadow: 0 0 30px rgba(5, 217, 232, 0.05);
  pointer-events: none;
}

/* Page-curve shading — a moving gradient on the front face that suggests
   the page bowing as it rotates. Slides across during animation. */
.book-turn-face--front::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    115deg,
    rgba(0, 0, 0, 0.0) 0%,
    rgba(0, 0, 0, 0.0) 45%,
    rgba(0, 0, 0, 0.35) 50%,
    rgba(0, 0, 0, 0.0) 55%,
    rgba(0, 0, 0, 0.0) 100%
  );
  background-size: 220% 100%;
  background-position: -120% 0;
  animation: pageCurveShade 1.4s cubic-bezier(0.55, 0.0, 0.45, 1.0) forwards;
  z-index: 100;
  mix-blend-mode: multiply;
}

/* Same shading on back face — applied during the second half of rotation
   so the next-spread's content gets the paper-curve feel too */
.book-turn-face--back::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    -115deg,
    rgba(0, 0, 0, 0.0) 0%,
    rgba(0, 0, 0, 0.0) 45%,
    rgba(0, 0, 0, 0.3) 50%,
    rgba(0, 0, 0, 0.0) 55%,
    rgba(0, 0, 0, 0.0) 100%
  );
  background-size: 220% 100%;
  background-position: 120% 0;
  animation: pageCurveShadeBack 1.4s cubic-bezier(0.55, 0.0, 0.45, 1.0) forwards;
  z-index: 100;
  mix-blend-mode: multiply;
}

@keyframes pageCurveShadeBack {
  0%   { background-position: 120% 0; }
  50%  { background-position: 0% 0; }
  100% { background-position: -120% 0; }
}

/* The turning page-edge highlight — a thin bright line that flares
   at the spine during the turn (paper edge catching the light). */
.book-turn-page::before {
  content: "";
  position: absolute;
  top: -8px;
  bottom: -8px;
  width: 3px;
  background: linear-gradient(
    180deg,
    transparent 0%,
    rgba(249, 240, 2, 0.8) 40%,
    rgba(249, 240, 2, 0.9) 60%,
    transparent 100%
  );
  filter: blur(1.5px) drop-shadow(0 0 12px rgba(249, 240, 2, 0.6));
  z-index: 600;
  opacity: 0;
  animation: pageEdgeFlash 0.95s ease-out forwards;
}

.book-turn-page--forward::before { left: -2px; }
.book-turn-page--back::before    { right: -2px; }

/* FORWARD: rotates -180 around left edge. PURE rotation, no translate,
   no scale. Spine stays absolutely fixed. The natural perspective
   foreshortening provides the visual curve. */
@keyframes pageTurnForward {
  0%   { transform: rotateY(0deg); }
  100% { transform: rotateY(-180deg); }
}

@keyframes pageTurnBack {
  0%   { transform: rotateY(0deg); }
  100% { transform: rotateY(180deg); }
}

@keyframes pageCurveShade {
  0%   { background-position: -120% 0; }
  50%  { background-position: 0% 0; }
  100% { background-position: 120% 0; }
}

@keyframes pageEdgeFlash {
  0%   { opacity: 0; }
  15%  { opacity: 1; }
  50%  { opacity: 0.85; }
  100% { opacity: 0; }
}

/* ===========================================================
   GLITCH OVERLAY — fires when page passes vertical (90deg).
   Brief flash of cyan/magenta noise + signal-drop glyph,
   evidence the OS noticed the turn.
   =========================================================== */

.book-warp-curtain {
  position: fixed;
  inset: 0;
  z-index: 600;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.18s ease-out;
}

.book-warping .book-warp-curtain {
  opacity: 1;
}

.book-warp-scanlines {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    0deg,
    transparent 0px,
    transparent 2px,
    rgba(5, 217, 232, 0.18) 3px,
    transparent 4px,
    rgba(255, 42, 109, 0.12) 6px,
    transparent 7px
  );
  opacity: 0;
  animation: warpScanlines 0.5s ease-in-out forwards;
}

.book-warp-glyph {
  position: fixed;
  bottom: 80px;
  left: 50%;
  transform: translateX(-50%);
  color: var(--naus-cyan);
  font-family: 'Share Tech Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  text-shadow: 0 0 8px var(--naus-cyan);
  opacity: 0;
  animation: warpGlyph 0.85s ease-out forwards;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  z-index: 601;
}

@keyframes warpScanlines {
  0%, 100% { opacity: 0; }
  30%, 70% { opacity: 0.85; }
}

@keyframes warpGlyph {
  0%   { opacity: 0; letter-spacing: 0.2em; }
  30%  { opacity: 1; letter-spacing: 0.45em; }
  70%  { opacity: 0.9; letter-spacing: 0.32em; }
  100% { opacity: 0; letter-spacing: 0.3em; }
}

/* ---------- Lexicon term hover + flicker + click ---------- */
.lex {
  transition: color 0.15s, text-shadow 0.15s;
}

.lex--clickable {
  cursor: pointer;
  user-select: none;
}

.lex--hover {
  /* Color shift + brighter glow on hover. No background, no border-bottom,
     no box-shadow — keep the inline reading flow undisturbed. */
  color: var(--naus-cyan);
  text-shadow: 0 0 8px rgba(5, 217, 232, 0.7);
}

/* Lex-ref entries in lexicon-footer also clickable */
.lex-ref--clickable {
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
  padding: 1px 2px;
  border-radius: 1px;
}

.lex-ref--clickable:hover {
  background: rgba(5, 217, 232, 0.1);
}

.lex-ref--clickable:hover .lex-term {
  color: var(--naus-yellow) !important;
  text-shadow: 0 0 6px rgba(249, 240, 2, 0.5);
}

.lex-ref--clickable:hover .lex-gloss {
  color: var(--ink-mid);
}

/* ============================================================
   Search palette — Ctrl/Cmd+K opens.
   Injected into <body> at runtime; CSS only kicks in when present.
   Z-index high enough to sit above all chassis chrome.
   ============================================================ */
.book-search-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 11vh;
  background: rgba(5, 3, 14, 0.78);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: bookSearchFadeIn 0.18s ease-out;
}

@keyframes bookSearchFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.book-search-panel {
  width: min(640px, calc(100vw - 40px));
  background:
    linear-gradient(180deg, rgba(26, 23, 48, 0.98) 0%, rgba(14, 10, 32, 0.98) 100%);
  border: 1px solid rgba(5, 217, 232, 0.32);
  border-radius: 3px;
  overflow: hidden;
  box-shadow:
    0 24px 80px rgba(0, 0, 0, 0.75),
    0 0 0 1px rgba(255, 42, 109, 0.08),
    0 0 60px rgba(5, 217, 232, 0.18);
}

.book-search-input {
  width: 100%;
  padding: 18px 24px;
  background: transparent;
  border: none;
  border-bottom: 1px solid rgba(5, 217, 232, 0.2);
  color: var(--paper);
  font-family: 'Share Tech Mono', monospace;
  font-size: 16px;
  letter-spacing: 0.04em;
  outline: none;
  caret-color: var(--naus-cyan);
}

.book-search-input::placeholder {
  color: rgba(181, 186, 206, 0.45);
  font-style: italic;
}

.book-search-results {
  max-height: 52vh;
  overflow-y: auto;
  /* Custom scrollbar — minimal, in-register */
  scrollbar-width: thin;
  scrollbar-color: rgba(5, 217, 232, 0.3) transparent;
}

.book-search-results::-webkit-scrollbar {
  width: 6px;
}

.book-search-results::-webkit-scrollbar-thumb {
  background: rgba(5, 217, 232, 0.3);
  border-radius: 3px;
}

.book-search-result {
  padding: 10px 24px;
  cursor: pointer;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  display: grid;
  grid-template-columns: max-content 1fr;
  grid-template-rows: auto auto;
  gap: 1px 14px;
  transition: background 0.08s ease-out;
  border-left: 2px solid transparent;
}

.book-search-result:hover {
  background: rgba(5, 217, 232, 0.06);
}

.book-search-result--selected {
  background: rgba(5, 217, 232, 0.12);
  border-left-color: var(--naus-cyan);
}

.book-search-result__type {
  grid-column: 1;
  grid-row: 1 / -1;
  align-self: center;
  font-family: 'Share Tech Mono', monospace;
  font-size: 9px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--naus-cyan);
  background: rgba(5, 217, 232, 0.08);
  padding: 4px 8px;
  border-radius: 2px;
  min-width: 56px;
  text-align: center;
}

.book-search-result__title {
  grid-column: 2;
  grid-row: 1;
  font-family: 'Rajdhani', 'Crimson Pro', sans-serif;
  font-weight: 700;
  font-size: 15px;
  color: var(--naus-yellow);
  text-shadow: 0 0 6px rgba(249, 240, 2, 0.25);
  letter-spacing: 0.01em;
}

.book-search-result__sub {
  grid-column: 2;
  grid-row: 2;
  font-family: 'Crimson Pro', serif;
  font-style: italic;
  font-size: 12px;
  color: rgba(181, 186, 206, 0.7);
  line-height: 1.35;
  /* Clamp to 2 lines so long tips don't blow the row height */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.book-search-empty {
  padding: 28px 24px;
  text-align: center;
  color: rgba(181, 186, 206, 0.5);
  font-family: 'Crimson Pro', serif;
  font-style: italic;
}

.book-search-hint {
  padding: 10px 24px;
  border-top: 1px solid rgba(5, 217, 232, 0.2);
  background: rgba(0, 0, 0, 0.35);
  font-family: 'Share Tech Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.14em;
  color: rgba(181, 186, 206, 0.55);
  text-transform: uppercase;
  display: flex;
  gap: 18px;
  align-items: center;
}

.book-search-hint kbd {
  background: rgba(5, 217, 232, 0.12);
  border: 1px solid rgba(5, 217, 232, 0.35);
  border-radius: 2px;
  padding: 2px 6px;
  margin-right: 6px;
  font-size: 9px;
  color: var(--naus-cyan);
  font-family: 'Share Tech Mono', monospace;
}

.lex--flicker {
  animation: lexFlicker 0.42s steps(4);
}

@keyframes lexFlicker {
  0%   { color: inherit; text-shadow: none; }
  20%  { color: var(--naus-yellow); text-shadow: 0 0 6px var(--naus-yellow); }
  40%  { color: var(--naus-magenta); text-shadow: 1px 0 var(--naus-cyan), -1px 0 var(--naus-magenta); }
  60%  { color: var(--naus-cyan); text-shadow: 0 0 4px var(--naus-cyan); }
  100% { color: inherit; text-shadow: none; }
}

/* ---------- Lexicon footer pings (cyan bracket pulse) ---------- */
.lex-ref { transition: color 0.2s, background 0.2s; }

.lex-ref--ping .lex-term {
  animation: lexBracketPing 0.38s ease-out;
}

@keyframes lexBracketPing {
  0%   { color: var(--char-primary, var(--ink)); text-shadow: none; }
  40%  { color: var(--naus-yellow); text-shadow: 0 0 8px var(--naus-yellow); }
  100% { color: var(--char-primary, var(--ink)); text-shadow: none; }
}

/* ---------- Index letter section pulse ---------- */
.idx-letter--pulse {
  animation: idxLetterPulse 0.62s ease-in-out;
}

@keyframes idxLetterPulse {
  0%   { color: var(--naus-magenta); text-shadow: none; transform: translateX(0); }
  30%  { color: var(--naus-yellow); text-shadow: 0 0 12px var(--naus-yellow); transform: translateX(1px); }
  60%  { color: var(--naus-cyan); text-shadow: 2px 0 var(--naus-magenta), -2px 0 var(--naus-cyan); transform: translateX(-1px); }
  100% { color: var(--naus-magenta); text-shadow: none; transform: translateX(0); }
}

/* ---------- Hover-pulse on index entries ---------- */
.idx-entry { transition: background 0.15s, color 0.15s; }
.idx-entry:hover {
  background: rgba(5, 217, 232, 0.06);
}
.idx-entry:hover .idx-term {
  color: var(--naus-cyan);
  text-shadow: 0 0 6px rgba(5, 217, 232, 0.45);
}

/* ===========================================================
   CORNER-PEEL — grab the bottom corner of the page and drag.
   Geometry computed by book.js: F1 on the vertical edge, F2 on
   the bottom edge, fold line is the perpendicular bisector of
   corner-to-drag.

   Z-index discipline (CHASSIS-SAFE):
     viewport frame brackets: 50–51 (NEVER cover these)
     book-nav strip:          100   (above peel)
     peel reveal:             30    (next page content visible through clip)
     peel shadow:             32    (fold-line darkening)
     peel flap:               34    (the lifted corner)
   All peel elements stay BELOW the chassis frame so it remains visible.
   =========================================================== */

/* Hit zones — visible affordances at the bottom corners of each page.
   These are positioned via JS using getBoundingClientRect so the visual
   ALWAYS lands on the actual rendered page corner, regardless of CSS
   stacking context, box-sizing, padding, or layout variant. */
.book-peel-hint {
  position: fixed;
  width: 72px;
  height: 72px;
  pointer-events: none;
  z-index: 40;        /* below viewport frame (50) but above page corners (2) */
  /* Always visible — Fox 2026-05-22: the dog-ear should signal "turn the
     page here" at all times, with a gentle pulse to make the affordance
     obvious. Hidden only during edit/peel/turn modes (below). */
  opacity: 0.85;
  transition: opacity 0.18s ease-out, transform 0.18s ease-out;
  transform: translate(0, 0);
  animation: peelHintPulse 1.8s ease-in-out infinite;
}

@keyframes peelHintPulse {
  0%, 100% {
    opacity: 0.62;
    filter: brightness(1) drop-shadow(0 0 4px rgba(249, 240, 2, 0.35));
  }
  50% {
    opacity: 1;
    filter: brightness(1.35) drop-shadow(0 0 12px rgba(249, 240, 2, 0.7));
  }
}

/* Visible state — applied via JS when the mouse is over the page (gentle
   discovery boost on top of the always-on baseline). */
.book-peel-hint.book-peel-hint--visible {
  opacity: 1;
  animation-duration: 1.1s; /* faster pulse when user is engaged */
}

.book-peel-hint.book-peel-hint--active {
  opacity: 1;
  transform: translate(-2px, -2px);
  animation: none; /* freeze pulse when actively about to peel */
}

body.book-editing .book-peel-hint,
body.book-peeling .book-peel-hint,
body.book-turning .book-peel-hint {
  opacity: 0 !important;
}

/* The dog-ear itself — a triangle that reads as "the corner is already
   turned up." Bigger + brighter than the previous version so it can't
   be missed. Glow + drop-shadow lifts it off the page. */
.book-peel-hint::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    var(--corner-angle, 135deg),
    rgba(249, 240, 2, 0.85) 0%,
    rgba(249, 240, 2, 0.45) 45%,
    rgba(255, 42, 109, 0.25) 75%,
    transparent 95%
  );
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.7))
          drop-shadow(0 0 10px rgba(249, 240, 2, 0.55));
}

.book-peel-hint--right::before {
  --corner-angle: 315deg;
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
}

.book-peel-hint--left::before {
  --corner-angle: 45deg;
  clip-path: polygon(0 0, 100% 100%, 0 100%);
}

/* Faint outline + inset shadow that makes the dog-ear read as a lifted
   paper flap. */
.book-peel-hint::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    var(--corner-angle, 135deg),
    transparent 0%,
    transparent 70%,
    rgba(0, 0, 0, 0.35) 100%
  );
}

.book-peel-hint--right::after {
  --corner-angle: 315deg;
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
}

.book-peel-hint--left::after {
  --corner-angle: 45deg;
  clip-path: polygon(0 0, 100% 100%, 0 100%);
}

/* Cursor on hit zones */
.page--right .book-peel-cursor-zone--right,
.page--left  .book-peel-cursor-zone--left {
  cursor: grab;
}

/* Peel-active state — disable page-turn nav, set grabbing cursor */
body.book-peeling {
  cursor: grabbing !important;
  user-select: none;
}

body.book-peeling * { cursor: grabbing !important; }

/* ----- Peel reveal: the next page content visible through clip ----- */
.book-peel-reveal {
  position: fixed;
  z-index: 30;
  pointer-events: none;
  overflow: hidden;
  background: var(--paper);
}

/* The reveal holds a clone of the next-spread's right page (forward) or
   prev-spread's left page (back). We render it underneath the source
   page's clip-cut so the user sees the next page emerging in the
   corner that's been peeled away. */
.book-peel-reveal > .page {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  border-right: none;
  box-shadow: none;
  /* Strip the spine-valley gradient — the reveal is shown as flat paper */
}

/* ----- Peel flap: the lifted corner of the current page -----
   Paper-back texture only — no content rendered on the flap. The fold's
   F1-F2 reflection transform would mirror any content, and Fox rejected
   every mirrored variant (Option A ghosted + Option B legible-backwards
   both, 2026-05-22). All peek-at-next-page rendering happens via the
   REVEAL layer (un-mirrored content visible in the cut-away triangle). */
.book-peel-flap {
  position: fixed;
  z-index: 34;
  pointer-events: none;
  overflow: hidden;
  background:
    /* Paper backside texture — slightly darker substrate with subtle grain */
    radial-gradient(
      ellipse at 30% 30%,
      rgba(255, 255, 255, 0.04) 0%,
      transparent 60%
    ),
    repeating-linear-gradient(
      45deg,
      rgba(255, 255, 255, 0.015) 0,
      rgba(255, 255, 255, 0.015) 1px,
      transparent 1px,
      transparent 3px
    ),
    linear-gradient(135deg, #14182A 0%, #0A0A12 100%);
  box-shadow:
    inset 0 0 60px rgba(0, 0, 0, 0.4),
    inset 0 0 0 1px rgba(5, 217, 232, 0.12);
  transform-origin: 0 0;
  will-change: transform, clip-path;
}

/* Subtle ghosted hint of what's on the back — the magenta-cyan haze of
   the OS substrate showing through the paper. */
.book-peel-flap::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(
      ellipse at 50% 50%,
      rgba(255, 42, 109, 0.06) 0%,
      transparent 70%
    ),
    radial-gradient(
      ellipse at 70% 30%,
      rgba(5, 217, 232, 0.04) 0%,
      transparent 60%
    );
}

/* ----- Peel shadow: fold-line darkening ----- */
.book-peel-shadow {
  position: fixed;
  z-index: 32;
  pointer-events: none;
  height: 40px;
  background: linear-gradient(
    180deg,
    transparent 0%,
    rgba(0, 0, 0, 0.0) 40%,
    rgba(0, 0, 0, 0.35) 50%,
    rgba(0, 0, 0, 0.0) 60%,
    transparent 100%
  );
  filter: blur(4px);
  transform-origin: 0 0;
  will-change: transform;
  opacity: 0.85;
}

/* ----- Spring-back animation ----- */
.book-peel-flap.book-peel-spring,
.book-peel-shadow.book-peel-spring {
  transition: transform 0.42s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.42s;
  opacity: 0;
}

/* ----- Complete-turn animation ----- */
.book-peel-flap.book-peel-complete,
.book-peel-shadow.book-peel-complete {
  transition: transform 0.35s cubic-bezier(0.5, 0, 0.75, 0.2), opacity 0.35s;
}

/* ---------- Print hides nav + warp + peel ---------- */
@media print {
  .book-nav,
  .book-warp-curtain,
  .book-peel-hint,
  .book-peel-reveal,
  .book-peel-flap,
  .book-peel-shadow {
    display: none !important;
  }
}
