/* live-preview.css — the LIVE PREVIEW booklet modal.
 *
 * Self-contained: every class is `lp-`. Colours come from the editors' tokens
 * (--bg, --text, --stamp) with fallbacks, so the module also works in a page
 * that does not define them. Motion follows MOTION.md: transform / opacity
 * only, one prefers-reduced-motion guard, tokens from motion/transitions.css
 * (--flip-dur, --flip-ease). Sizes (--lp-pw, --lp-ph) are written by JS.
 */

.lp-modal {
  --lp-ink: var(--text, #0a0a0a);
  --lp-paper: var(--bg, #f1f1f0);
  --lp-stamp: var(--stamp, #1e3a6b);
  position: fixed;
  inset: 0;
  z-index: 110;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.94);
  animation: lp-fade 0.18s ease-out;
  overscroll-behavior: contain;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
}
@keyframes lp-fade { from { opacity: 0; } to { opacity: 1; } }

/* ---- stage + book ------------------------------------------------------- */

.lp-stage {
  position: relative;
  width: calc(var(--lp-pw) * 2);
  height: var(--lp-ph);
  perspective: calc(var(--lp-pw) * 5);
}

.lp-book {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  will-change: transform;
}

.lp-leaf {
  position: absolute;
  top: 0;
  left: 50%;
  width: var(--lp-pw);
  height: var(--lp-ph);
  transform-origin: left center;
  transform-style: preserve-3d;
}

.lp-face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  /* No background of its own: the page canvas paints its white. A face-sized
     white fill would show as a light fringe wherever a 3D-transformed edge
     lands between two device pixels (dark covers make it obvious). */
  background: transparent;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.lp-face.lp-back { transform: rotateY(180deg); }
/* The bitmap is 1px oversize per side and the face clips it. A page drawn at a
   fractional scale leaves its outermost pixel row/column half-covered (white
   paper showing through a dark cover); this hides that hairline. */
.lp-face canvas {
  position: absolute;
  top: -1px;
  left: -1px;
  display: block;
  width: calc(100% + 2px);
  height: calc(100% + 2px);
}

/* Paper edge + the dark crease where the page meets the staples. */
.lp-face::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.lp-face.lp-front::after {
  background: linear-gradient(to right, rgba(0, 0, 0, 0.28), rgba(0, 0, 0, 0) 7%);
  box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.12);
}
.lp-face.lp-back::after {
  background: linear-gradient(to left, rgba(0, 0, 0, 0.28), rgba(0, 0, 0, 0) 7%);
  box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.12);
}

/* Light drop while a leaf is in the air: opacity is animated by JS (WAAPI). */
.lp-shade {
  position: absolute;
  inset: 0;
  background: #000;
  opacity: 0;
  pointer-events: none;
}

/* The book's own shadow, under the pages. */
.lp-floor {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2.2%;
  height: 4%;
  background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0) 70%);
  pointer-events: none;
}

/* ---- controls ----------------------------------------------------------- */

.lp-arrow {
  position: absolute;
  /* Above the stage: .lp-prev comes BEFORE .lp-stage in the DOM, so without
     this the 3D book (perspective = its own stacking context) painted over
     the left arrow on phones, where the arrows overlap the pages. */
  z-index: 3;
  top: 50%;
  margin-top: -1.6rem;
  width: 3.2rem;
  height: 3.2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  font-size: 1.25rem;
  line-height: 1;
  color: var(--lp-paper);
  background: var(--lp-stamp);
  border: 2px solid var(--lp-paper);
  border-radius: 2px;
  box-shadow: 3px 3px 0 var(--lp-paper);
  cursor: pointer;
  transition: transform var(--dur-micro, 150ms) var(--ease-out, ease),
              box-shadow var(--dur-micro, 150ms) var(--ease-out, ease),
              opacity var(--dur-micro, 150ms) var(--ease-out, ease);
}
.lp-prev { left: 1rem; }
.lp-next { right: 1rem; }
.lp-arrow:hover:not(:disabled) { transform: translate(-1px, -1px); box-shadow: 4px 4px 0 var(--lp-paper); }
.lp-arrow:active:not(:disabled) { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--lp-paper); }
.lp-arrow:disabled { opacity: 0.25; cursor: default; }
.lp-arrow:focus-visible, .lp-close:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

.lp-close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  z-index: 2;
  padding: 0.55rem 0.95rem 0.5rem;
  font-family: var(--font-label, inherit);
  font-size: 0.82rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  line-height: 1;
  color: var(--lp-paper);
  background: var(--lp-ink);
  border: 1.5px solid var(--lp-paper);
  border-radius: 2px;
  cursor: pointer;
  transition: transform var(--dur-micro, 150ms) var(--ease-out, ease),
              box-shadow var(--dur-micro, 150ms) var(--ease-out, ease);
}
.lp-close:hover { transform: translate(-1px, -1px); box-shadow: 2px 2px 0 var(--lp-paper); }
.lp-close:active { transform: translate(1px, 1px); box-shadow: none; }

.lp-foot {
  margin-top: 1.6rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  color: var(--lp-paper);
}
.lp-label {
  min-width: 9rem;
  text-align: center;
  padding: 0.25rem 0.8rem;
  font-family: var(--font-label, inherit);
  font-size: 0.8rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  border: 2px solid var(--lp-paper);
  background: var(--lp-stamp);
  box-shadow: 3px 3px 0 var(--lp-paper);
}
.lp-dots { display: flex; gap: 0.4rem; }
.lp-dot {
  width: 0.5rem;
  height: 0.5rem;
  padding: 0;
  border: 1px solid var(--lp-paper);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: background-color var(--dur-micro, 150ms) var(--ease-out, ease);
}
.lp-dot.is-on { background: var(--lp-paper); }

/* Phones: the arrows sit over the book's outer edges so the pages keep room. */
@media (max-width: 720px) {
  .lp-prev { left: 0.4rem; }
  .lp-next { right: 0.4rem; }
  .lp-arrow { width: 2.6rem; height: 2.6rem; margin-top: -1.3rem; }
}

/* ---- open / close on phones ----------------------------------------------
   The base `.lp-modal { animation: lp-fade }` out-ranks the shared `.t-exit`
   (same specificity, later in the cascade), so on close the exit never ran:
   exit() waited for an animationend that never came and fell back to its 400 ms
   timer — a dead half-second. These rules win with `.lp-modal.t-exit` and give
   both directions a real animation: the backdrop fades, the book settles in
   (rises, grows from 94%) and on close sinks back, faster than it came.
   Opacity + transform only, no blur on a full-screen layer. All widths. */
@keyframes lp-in  { from { opacity: 0; } to { opacity: 1; } }
@keyframes lp-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes lp-stage-in  { from { opacity: 0; transform: translateY(16px) scale(0.94); } to { opacity: 1; transform: none; } }
@keyframes lp-stage-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(10px) scale(0.96); } }
.lp-modal { animation: lp-in 220ms var(--ease-out, ease-out) both; }
.lp-modal .lp-stage { animation: lp-stage-in 320ms var(--ease-out, ease-out) both; }
.lp-modal.t-exit { animation: lp-out 160ms var(--ease-out, ease-out) both; }
.lp-modal.t-exit .lp-stage { animation: lp-stage-out 160ms var(--ease-out, ease-out) both; }

/* ---- flip (MOTION.md; recipe values live in transitions.css) ------------ */
/* JS animates .lp-leaf / .lp-book / .lp-shade with the WAAPI. With reduced
   motion it does not start any, and the final state is identical. */
@media (prefers-reduced-motion: reduce) {
  .lp-modal, .lp-modal.t-exit, .lp-modal .lp-stage, .lp-modal.t-exit .lp-stage { animation: none; }
  .lp-arrow, .lp-close, .lp-dot { transition: none; }
}
