/* =============================================================================
   DESK SCENE — Constrained book on blurred desk background
   Wraps the book in a fixed aspect-ratio frame centered on the desk
   ============================================================================= */

.book-desk-scene {
    position: fixed;
    inset: 0;
    /* Re-enable pointer events — the editor shell wrapper sets pointer-events: none
       on its container, but the book scene needs to be interactive (cover buttons,
       page turns, drag-to-rotate). Editor panels sit alongside, not on top. */
    pointer-events: auto;
    background:
        /* Paper grain texture for organic feel */
        var(--env-paper-grain),
        /* Warm radial vignette — darker at edges, lighter center */
        radial-gradient(ellipse at 50% 45%,
            rgba(250, 245, 240, 0.15) 0%,
            transparent 70%),
        /* Subtle warm wood-tone gradient */
        linear-gradient(175deg,
            #e8ddd4 0%,
            #dfd3c8 25%,
            #d6c8ba 50%,
            #cdbfb0 75%,
            #c4b5a4 100%);
    overflow: hidden;
}

/* Blurred desk layer (prevents blur from affecting children) */
.book-desk-scene::before {
    content: '';
    position: absolute;
    inset: -10px;
    background: inherit;
    filter: blur(var(--book-desk-blur)) brightness(var(--book-desk-brightness, 1)) saturate(var(--book-desk-saturation, 1));
    opacity: var(--book-desk-opacity, 1);
    z-index: 0;
}

/* Subtle darkening overlay */
.book-desk-scene::after {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.06);
    z-index: 1;
}

/* Site background effects layer — full viewport, above blur but below the book */
.book-desk-effects {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
}

/* Depth-of-field overlay — blurs and darkens the desk/site background behind the open book.
   Uses ::after on .book-desk-effects (z-index 2) so it sits above backgrounds but below the book viewport. */
.book-desk-effects::after {
    content: '';
    position: absolute;
    inset: -20px;                /* Bleed past edges to prevent blur fringing */
    z-index: 999;
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    background: rgba(0, 0, 0, 0.15);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.6s ease-out;
}

/* Activate DOF in Settling and Book states */
.book-desk-scene--settling .book-desk-effects::after,
.book-desk-scene--book .book-desk-effects::after {
    opacity: 1;
}

/* Stronger darken in dark mode */
[data-theme="dark"] .book-desk-effects::after {
    background: rgba(0, 0, 0, 0.25);
}

/* When editor is active on site background, allow pointer events for drag */
.book-desk-scene--solo .book-desk-effects,
[data-editor-active] .book-desk-effects {
    pointer-events: auto;
}

/* Orbit mode cursor — grab while hovering, grabbing while dragging */
.book-desk-surface--orbiting { cursor: grab; }
.book-desk-surface--orbiting:active { cursor: grabbing; }

/* When 3D editing is active (geometry panel, orbit, or part selected), allow click-to-select on 3D book parts.
   Scoped to [data-3d-edit] so effects remain clickable when only the visual editor is active. */
[data-3d-edit] .book-3d-depth,
[data-3d-edit] .book-3d-depth > [data-book-part] {
    pointer-events: auto;
    cursor: pointer;
}

/* Also allow front cover selection in 3D edit mode */
[data-3d-edit] .book-cover-page-front[data-book-part] {
    cursor: pointer;
}

/* When editor is active, always allow pointer events on book pages and covers
   so visual effects inside them remain clickable regardless of animation state.
   Without this, states like Cover/Opening/Closing/Table set pointer-events: none
   on .book-page which blocks ALL clicks on effects within those pages. */
[data-editor-active] .book-page,
[data-editor-active] .book-page-front,
[data-editor-active] .book-cover-page-front {
    pointer-events: auto !important;
}

/* Book part selection glow — applied via JS when admin clicks a 3D part */
.book-part--selected {
    outline: 2px solid var(--book-gold-leaf, #D4AF37) !important;
    outline-offset: -1px;
    box-shadow:
        0 0 12px rgba(212, 175, 55, 0.4),
        inset 0 0 8px rgba(212, 175, 55, 0.15) !important;
    transition: outline 0.15s ease, box-shadow 0.15s ease;
}

/* Hover hint on 3D parts when editor is active */
[data-editor-active] [data-book-part]:hover:not(.book-part--selected) {
    outline: 1px dashed rgba(212, 175, 55, 0.4);
    outline-offset: -1px;
}

/* Solo mode — book hidden for background editing */
.book-desk-scene--solo .book-desk-surface {
    display: none;
}

.book-desk-surface {
    position: relative;
    z-index: 3;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: clamp(12px, 2vh, 40px) clamp(12px, 2vw, 40px);
}

.book-frame {
    position: relative;
    display: flex;
    width: min(var(--book-frame-max-w), 50vw);
    aspect-ratio: var(--book-page-ratio);
    max-height: 88vh;
    box-shadow: var(--book-frame-shadow);
    border-radius: 4px 8px 8px 4px;
    overflow: visible;
    isolation: isolate; /* Stacking context for z-index ordering within the frame */
    --book-perspective: 1100px;
    --book-vignette-blur: clamp(30px, 8%, 100px);
    --book-vignette-spread: clamp(15px, 4%, 60px);
}

/* Entrance animation from BookLanding zoom */
.book-frame--entering {
    animation: bookFrameEnter 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

@keyframes bookFrameEnter {
    0%   { opacity: 0; transform: scale(1.08) translateY(0); filter: blur(2px); }
    70%  { opacity: 1; transform: scale(1) translateY(-3px);  filter: blur(0);   }
    85%  { transform: scale(1) translateY(1px); }
    100% { opacity: 1; transform: scale(1) translateY(0);     filter: blur(0);   }
}

/* ─── Content width override for constrained book ─── */
.book-frame .book-page-section-content {
    max-width: 100%;
    padding: clamp(20px, 4%, 50px) clamp(16px, 3%, 40px);
}

/* ─── Mobile book sizing ─── */
@media (max-width: 768px) {
    .book-frame {
        width: min(var(--book-frame-max-w), 96vw);
        max-height: 90vh;
    }
    .book-desk-surface {
        padding: 8px;
    }
    /* Move nav arrows inside the book on mobile */
    .book-nav-arrow--prev { left: 4px; }
    .book-nav-arrow--next { right: 4px; }
}

@media (max-width: 480px) {
    .book-frame {
        width: 98vw;
        max-height: 92vh;
    }
    .book-desk-surface {
        padding: 4px;
    }
    .book-desk-scene {
        --book-desk-blur: 2px;
    }
}


/* ─── Book Frame Right Wrapper ─── */
.book-frame-right {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: visible;
    border-radius: inherit;
}

/* ═══════════════════════════════════════════════════════════════
   3D SPINE ELEMENT (Phase 1B)
   Visible spine between left edge and pages with leather ridges.
   Uses radial gradient for raised ridge texture and ::before/::after
   for physical edge thickness.
   ═══════════════════════════════════════════════════════════════ */

.book-spine-3d {
    position: absolute;
    left: calc(-1 * var(--book-spine-3d-width));
    top: 0;
    bottom: 0;
    width: var(--book-spine-3d-width);
    z-index: 10;
    /* Leather spine with raised ridge texture */
    background:
        /* Horizontal ridges */
        repeating-linear-gradient(to bottom,
            transparent 0px,
            transparent 18px,
            rgba(0, 0, 0, 0.08) 18px,
            rgba(0, 0, 0, 0.08) 19px,
            rgba(255, 255, 255, 0.06) 19px,
            rgba(255, 255, 255, 0.06) 20px,
            transparent 20px,
            transparent 38px),
        /* Base leather gradient — convex outer binding (dark edges, lighter raised center) */
        linear-gradient(to right,
            var(--book-cover-dark) 0%,
            var(--book-cover-leather) 20%,
            color-mix(in srgb, var(--book-cover-leather) 90%, white) 42%,
            color-mix(in srgb, var(--book-cover-leather) 85%, white) 50%,
            color-mix(in srgb, var(--book-cover-leather) 90%, white) 58%,
            var(--book-cover-leather) 80%,
            var(--book-cover-dark) 100%);
    border-radius: 4px 0 0 4px;
    box-shadow: inset 0 0 3px rgba(255, 255, 255, 0.08),
                inset 0 0 6px rgba(0, 0, 0, 0.25),
                -1px 0 3px rgba(0, 0, 0, 0.15),
                1px 0 3px rgba(0, 0, 0, 0.15);
}

/* Top/bottom edge thickness */
.book-spine-3d::before,
.book-spine-3d::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    height: 4px;
    background: linear-gradient(to right,
        var(--book-cover-dark),
        color-mix(in srgb, var(--book-cover-leather) 80%, black),
        var(--book-cover-dark));
}

.book-spine-3d::before {
    top: 0;
    border-radius: 4px 0 0 0;
    box-shadow: 0 -2px 4px rgba(0, 0, 0, 0.15);
}

.book-spine-3d::after {
    bottom: 0;
    border-radius: 0 0 0 4px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
}

/* Gold detail lines on spine */
.book-frame .book-spine-3d {
    background-image:
        /* Gold lines at top and bottom */
        linear-gradient(to bottom,
            transparent 15px,
            rgba(212, 175, 55, 0.3) 16px,
            rgba(212, 175, 55, 0.3) 17px,
            transparent 18px,
            transparent calc(100% - 18px),
            rgba(212, 175, 55, 0.3) calc(100% - 17px),
            rgba(212, 175, 55, 0.3) calc(100% - 16px),
            transparent calc(100% - 15px)),
        /* Horizontal ridges */
        repeating-linear-gradient(to bottom,
            transparent 0px,
            transparent 18px,
            rgba(0, 0, 0, 0.08) 18px,
            rgba(0, 0, 0, 0.08) 19px,
            rgba(255, 255, 255, 0.06) 19px,
            rgba(255, 255, 255, 0.06) 20px,
            transparent 20px,
            transparent 38px),
        /* Base leather — convex outer binding (dark edges, lighter raised center) */
        linear-gradient(to right,
            var(--book-cover-dark) 0%,
            var(--book-cover-leather) 20%,
            color-mix(in srgb, var(--book-cover-leather) 90%, white) 42%,
            color-mix(in srgb, var(--book-cover-leather) 85%, white) 50%,
            color-mix(in srgb, var(--book-cover-leather) 90%, white) 58%,
            var(--book-cover-leather) 80%,
            var(--book-cover-dark) 100%);
}


/* ═══════════════════════════════════════════════════════════════
   PHASE 2: ENHANCED 3D SPINE
   Leather ridge overlay, gold glow sync, enhanced gold band details.
   ═══════════════════════════════════════════════════════════════ */

/* Spine ridge texture overlay — blended on top of base leather */
.book-spine-3d-ridges {
    position: absolute;
    inset: 0;
    background: repeating-linear-gradient(to bottom,
        rgba(60, 40, 20, 0.06) 0px,
        rgba(100, 70, 40, 0.03) 2px,
        transparent 3px,
        transparent 4px);
    background-blend-mode: overlay;
    border-radius: inherit;
    pointer-events: none;
}

/* Gold glow synchronized with page turns */
.book-spine-3d-glow {
    position: absolute;
    inset: 0;
    background: radial-gradient(ellipse at center,
        rgba(212, 175, 55, 0.2) 0%,
        rgba(212, 175, 55, 0.08) 40%,
        transparent 80%);
    opacity: 0;
    transition: opacity 0.3s ease;
    border-radius: inherit;
    pointer-events: none;
}

/* Glow activates during page turns via viewport turning class */
.book-frame:has(.book-viewport--turning) .book-spine-3d-glow {
    animation: spine3dGlowSync 1.2s ease-in-out forwards;
}

@keyframes spine3dGlowSync {
    0%   { opacity: 0; }
    20%  { opacity: 0.15; }
    45%  { opacity: 0.25; }
    70%  { opacity: 0.1; }
    100% { opacity: 0; }
}

/* Enhanced gold band lines — wider with subtle glow */
.book-spine-3d::before,
.book-spine-3d::after {
    height: 4px;
    box-shadow: 0 0 4px rgba(212, 175, 55, 0.15);
}

/* Center gold band on spine */
.book-spine-3d-ridges::after {
    content: '';
    position: absolute;
    left: 15%;
    right: 15%;
    top: 50%;
    height: 2px;
    transform: translateY(-50%);
    background: linear-gradient(to right,
        transparent,
        rgba(212, 175, 55, 0.25) 20%,
        rgba(212, 175, 55, 0.4) 50%,
        rgba(212, 175, 55, 0.25) 80%,
        transparent);
    box-shadow: 0 0 3px rgba(212, 175, 55, 0.1);
}


/* ═══════════════════════════════════════════════════════════════
   PHASE 3: CORNER HOVER PEEL EFFECT
   Enhanced 3D page peel with proximity-driven sizing.
   ═══════════════════════════════════════════════════════════════ */

/* Peel shadow — cast by the peeled corner (bottom-right) */
.book-page-peel-shadow,
.book-page-peel-shadow--br {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 0;
    height: 0;
    background: radial-gradient(ellipse at bottom right,
        rgba(0, 0, 0, 0.12) 0%,
        rgba(0, 0, 0, 0.04) 50%,
        transparent 100%);
    pointer-events: none;
    z-index: 4;
    transition: width 0.5s ease, height 0.5s ease;
    border-radius: 30% 0 0 0;
}

/* Peel underpage — hint of paper beneath (bottom-right) */
.book-page-peel-underpage,
.book-page-peel-underpage--br {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 0;
    height: 0;
    background: linear-gradient(135deg,
        transparent 40%,
        rgba(240, 232, 220, 0.4) 60%,
        rgba(250, 245, 240, 0.6) 80%);
    pointer-events: none;
    z-index: 3;
    transition: width 0.5s ease, height 0.5s ease;
}

/* Peel shadow — top-right corner */
.book-page-peel-shadow--tr {
    position: absolute;
    top: 0;
    right: 0;
    bottom: auto;
    width: 0;
    height: 0;
    background: radial-gradient(ellipse at top right,
        rgba(0, 0, 0, 0.12) 0%,
        rgba(0, 0, 0, 0.04) 50%,
        transparent 100%);
    pointer-events: none;
    z-index: 4;
    transition: width 0.5s ease, height 0.5s ease;
    border-radius: 0 0 0 30%;
}

/* Peel underpage — top-right corner */
.book-page-peel-underpage--tr {
    position: absolute;
    top: 0;
    right: 0;
    bottom: auto;
    width: 0;
    height: 0;
    background: linear-gradient(225deg,
        transparent 40%,
        rgba(240, 232, 220, 0.4) 60%,
        rgba(250, 245, 240, 0.6) 80%);
    pointer-events: none;
    z-index: 3;
    transition: width 0.5s ease, height 0.5s ease;
}

/* ── Left-side peel shadows (on back face, mirrored via rotateY 180deg) ──
   Positioned at right:0 in CSS space → appears at left edge visually.
   Radial gradient origin also at right (mirrors to left for viewer). */

/* Peel shadow — top-left corner (back face)
   Positioned at left:0 because the double rotation (parent -180 + back +180)
   cancels to 0deg — left:0 = visual outer-left edge of the left page. */
.book-page-peel-shadow--tl {
    position: absolute;
    top: 0;
    left: 0;
    bottom: auto;
    right: auto;
    width: 0;
    height: 0;
    background: radial-gradient(ellipse at top left,
        rgba(0, 0, 0, 0.12) 0%,
        rgba(0, 0, 0, 0.04) 50%,
        transparent 100%);
    pointer-events: none;
    z-index: 4;
    transition: width 0.5s ease, height 0.5s ease;
    border-radius: 0 0 30% 0;
}

/* Peel underpage — top-left corner (back face) */
.book-page-peel-underpage--tl {
    position: absolute;
    top: 0;
    left: 0;
    bottom: auto;
    right: auto;
    width: 0;
    height: 0;
    background: linear-gradient(315deg,
        transparent 40%,
        rgba(240, 232, 220, 0.4) 60%,
        rgba(250, 245, 240, 0.6) 80%);
    pointer-events: none;
    z-index: 3;
    transition: width 0.5s ease, height 0.5s ease;
}

/* Peel shadow — bottom-left corner (back face) */
.book-page-peel-shadow--bl {
    position: absolute;
    bottom: 0;
    left: 0;
    top: auto;
    right: auto;
    width: 0;
    height: 0;
    background: radial-gradient(ellipse at bottom left,
        rgba(0, 0, 0, 0.12) 0%,
        rgba(0, 0, 0, 0.04) 50%,
        transparent 100%);
    pointer-events: none;
    z-index: 4;
    transition: width 0.5s ease, height 0.5s ease;
    border-radius: 0 30% 0 0;
}

/* Peel underpage — bottom-left corner (back face) */
.book-page-peel-underpage--bl {
    position: absolute;
    bottom: 0;
    left: 0;
    top: auto;
    right: auto;
    width: 0;
    height: 0;
    background: linear-gradient(45deg,
        transparent 40%,
        rgba(240, 232, 220, 0.4) 60%,
        rgba(250, 245, 240, 0.6) 80%);
    pointer-events: none;
    z-index: 3;
    transition: width 0.5s ease, height 0.5s ease;
}

/* Enhanced corner peel — 3D lift on hover using proximity variable set by JS */
.book-page-corner--next::before {
    transition: width 0.4s ease, height 0.4s ease, box-shadow 0.4s ease,
                border-radius 0.4s ease, transform 0.4s ease;
}

.book-page-corner--next:hover::before {
    transform: perspective(800px) rotateY(-4deg) rotateX(-2deg) translateZ(var(--book-peel-lift-z));
    background: linear-gradient(135deg,
        transparent 32%,
        rgba(0, 0, 0, 0.04) 36%,
        rgba(139, 119, 75, 0.15) 39%,
        rgba(255, 255, 255, 0.2) 41%,
        rgba(250, 245, 240, 0.94) 44%,
        rgba(180, 160, 130, 0.18) 48%,
        rgba(250, 245, 240, 0.97) 52%,
        rgba(255, 255, 255, 0.12) 55%,
        var(--book-page-cream, #faf5f0) 60%,
        #f0e8dc 100%);
}

/* Proximity-driven peel shadow on corner hover */
.book-page-corner--next:hover ~ .book-page-peel-shadow {
    width: calc(var(--book-peel-max) * 0.6);
    height: calc(var(--book-peel-max) * 0.6);
}

/* Top-right corner — enhanced peel at top-right */
.book-page-corner--next-top::before {
    transition: width 0.4s ease, height 0.4s ease, box-shadow 0.4s ease,
                border-radius 0.4s ease, transform 0.4s ease;
}

.book-page-corner--next-top:hover::before {
    transform: perspective(800px) rotateY(-4deg) rotateX(2deg) translateZ(var(--book-peel-lift-z));
    background: linear-gradient(225deg,
        transparent 32%,
        rgba(0, 0, 0, 0.04) 36%,
        rgba(139, 119, 75, 0.15) 39%,
        rgba(255, 255, 255, 0.2) 41%,
        rgba(250, 245, 240, 0.94) 44%,
        rgba(180, 160, 130, 0.18) 48%,
        rgba(250, 245, 240, 0.97) 52%,
        rgba(255, 255, 255, 0.12) 55%,
        var(--book-page-cream, #faf5f0) 60%,
        #f0e8dc 100%);
}

/* Previous page corner — enhanced peel at top-left */
.book-page-corner--prev::before {
    transition: width 0.4s ease, height 0.4s ease, box-shadow 0.4s ease,
                border-radius 0.4s ease, transform 0.4s ease;
}

.book-page-corner--prev:hover::before {
    transform: perspective(800px) rotateY(4deg) rotateX(2deg) translateZ(var(--book-peel-lift-z));
    background: linear-gradient(315deg,
        transparent 32%,
        rgba(0, 0, 0, 0.04) 36%,
        rgba(139, 119, 75, 0.15) 39%,
        rgba(255, 255, 255, 0.2) 41%,
        rgba(250, 245, 240, 0.94) 44%,
        rgba(180, 160, 130, 0.18) 48%,
        rgba(250, 245, 240, 0.97) 52%,
        rgba(255, 255, 255, 0.12) 55%,
        var(--book-page-cream, #faf5f0) 60%,
        #f0e8dc 100%);
}


/* ═══════════════════════════════════════════════════════════════
   PAGE-ATTACHED RIBBON BOOKMARKS
   Each page's ribbon protrudes upward from the top edge and
   physically rotates with the page during 3D turns.
   ═══════════════════════════════════════════════════════════════ */

.book-page-ribbon-container {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 0; /* No height — ribbon protrudes upward via translateY(-100%) */
    pointer-events: none;
    z-index: 7; /* Above sticky notes (6) */
    transform-style: preserve-3d; /* 3D ribbons participate in page's 3D context */
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}

/* Ribbons stay visible during page turns (that's the point — they rotate with the page) */
.book-page--turning .book-page-ribbon-container {
    opacity: 1;
}

/* Hide front ribbon on fully turned pages */
.book-page--turned .book-page-ribbon-container {
    display: none;
}

/* Only show front ribbon on visible (unturned) pages */
.book-page:not(.book-page--turned):not(.book-page--turning) .book-page-ribbon-container {
    display: block;
}

/* ── Back-face ribbon: visible on turned pages for backward navigation ── */
/* Pre-rotated 180deg — when page turns to -180deg, net rotation = 0 → faces viewer.
   backface-visibility: hidden ensures it's invisible when page is unturned. */
.book-page-ribbon-container-back {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 0;
    pointer-events: none;
    z-index: 7;
    transform-style: preserve-3d; /* 3D ribbons participate in page's 3D context */
    transform: rotateY(180deg);
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}

/* Enable clicks on turned pages so user can navigate back */
.book-page--turned .book-page-ribbon-container-back {
    pointer-events: auto;
}

/* Explicitly hide on unturned pages (redundant with backface-visibility but safe) */
.book-page:not(.book-page--turned) .book-page-ribbon-container-back {
    display: none;
}

/* Back ribbon on turned pages: visible for backward navigation.
   The backface-visibility: hidden on the container handles hiding when
   the page is unturned (net rotation = 180deg = away from viewer).
   When turned (net rotation = -180 + 180 = 0deg), it faces the viewer. */


/* ═══════════════════════════════════════════════════════════════
   PHASE 4: INTERACTIVE STICKY NOTE BOOKMARKS
   Clickable tabs peeking from page edges, navigate to sections.
   ═══════════════════════════════════════════════════════════════ */

.book-page-sticky-notes {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 6;
    /* Flatten into page surface so notes don't compound with parent 3D rotation */
    transform-style: flat;
    /* Now a direct child of .book-page (preserve-3d context), so needs backface-visibility
       to hide when the page is turned (rotateY -180deg shows the back) */
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}

/* Hide sticky notes during turn animation to prevent floating artifacts */
.book-page--turning .book-page-sticky-notes {
    display: none;
}

.book-sticky-note {
    position: absolute;
    z-index: 6;
    cursor: pointer;
    border: none;
    background: none;
    padding: 0;
    pointer-events: auto;
    transition: transform 0.25s ease, filter 0.25s ease;
}

/* Position variants */
.book-sticky-note--right-top {
    right: calc(-1 * var(--book-note-protrude));
    top: var(--note-offset, 15%);
}

.book-sticky-note--right-center {
    right: calc(-1 * var(--book-note-protrude));
    top: var(--note-offset, 45%);
}

.book-sticky-note--right-bottom {
    right: calc(-1 * var(--book-note-protrude));
    top: var(--note-offset, 75%);
}

.book-sticky-note--bottom-right {
    bottom: calc(-1 * var(--book-note-protrude) * 0.6);
    right: var(--note-offset, 20%);
}

/* Paper body of the sticky note */
.book-sticky-note-paper {
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--book-note-size);
    min-height: calc(var(--book-note-size) * 0.7);
    padding: 4px 6px;
    background: var(--note-color, rgba(212, 175, 55, 0.3));
    border-radius: 2px 4px 4px 2px;
    box-shadow: var(--book-note-shadow), -2px 0 4px rgba(0, 0, 0, 0.06);
    transform: perspective(400px) rotateY(-3deg) rotate(var(--note-rotate, 0deg));
    transform-origin: left center;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
    position: relative;
}

/* Handwritten-style text */
.book-sticky-note-text {
    font-family: 'Lavishly Yours', var(--font-script), cursive;
    font-size: clamp(0.55rem, 0.7vw, 0.75rem);
    color: rgba(44, 44, 44, 0.75);
    white-space: nowrap;
    line-height: 1.1;
    writing-mode: vertical-rl;
    text-orientation: mixed;
}

/* Small fold at attachment point */
.book-sticky-note-fold {
    position: absolute;
    width: 8px;
    height: 8px;
    background: linear-gradient(135deg,
        transparent 50%,
        rgba(0, 0, 0, 0.06) 50%);
    pointer-events: none;
}

.book-sticky-note--right-top .book-sticky-note-fold,
.book-sticky-note--right-center .book-sticky-note-fold,
.book-sticky-note--right-bottom .book-sticky-note-fold {
    left: 0;
    bottom: 0;
}

.book-sticky-note--bottom-right .book-sticky-note-fold {
    left: 0;
    top: 0;
}

/* Hover: subtle lift */
.book-sticky-note:hover .book-sticky-note-paper {
    transform: perspective(400px) rotateY(-3deg) rotate(var(--note-rotate, 0deg)) translateY(-2px);
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15), -2px 0 4px rgba(0, 0, 0, 0.06);
}

.book-sticky-note:focus-visible {
    outline: 2px solid var(--book-gold-leaf);
    outline-offset: 2px;
    border-radius: 3px;
}

/* Visibility: hide on fully turned pages; turning pages use backface-visibility */
.book-page--turned .book-page-sticky-notes {
    display: none;
}

/* Only topmost unturned page shows sticky notes */
.book-page:not(.book-page--turned):not(.book-page--turning) .book-page-sticky-notes {
    display: block;
}

/* Sticky note reveal animation when page becomes visible */
@keyframes stickyNoteReveal {
    0% {
        opacity: 0;
        transform: translateX(8px) scale(0.9);
    }
    60% {
        opacity: 1;
        transform: translateX(-2px) scale(1.02);
    }
    100% {
        opacity: 1;
        transform: translateX(0) scale(1);
    }
}

/* After a page turn reveals a new page, animate its sticky notes in */
.book-page:not(.book-page--turned):not(.book-page--turning) .book-sticky-note {
    animation: stickyNoteReveal 0.4s ease-out forwards;
}


/* ═══════════════════════════════════════════════════════════════
   PHASE 5: TWO-PAGE SPREAD (BookLeftPageContent)
   Left page of the open book, visible at 1200px+.
   ═══════════════════════════════════════════════════════════════ */

/* Desktop spread layout — two-page book with pages folding from right onto left */
@media (min-width: 1200px) {
    .book-frame {
        width: min(1600px, 85vw);
        aspect-ratio: auto;
        /* Explicit height so .book-frame-right children can resolve height: 100%.
           Without this, the frame's height is content-derived (from info panel),
           which doesn't count as a "definite" height for CSS percentage resolution. */
        height: min(88vh, 800px);
        max-height: 88vh;
        flex-direction: row;
        overflow: visible; /* Allow 3D page flaps during turns — .book-desk-scene contains overflow */
    }

    .book-frame-right {
        width: 50%; /* Symmetric half — pages fold from here onto the left */
        flex: none; /* Override flex growth so width: 50% is respected */
        z-index: 2; /* Above left page so turning pages overlay the left side */
        margin-left: auto; /* Push to the right half of the book frame */
    }

    .book-frame-right .book-page {
        z-index: 3;
    }

    /* Hide leather spine at desktop — the open book interior shows a paper gutter,
       not the exterior leather binding. The ::after gutter handles the center fold. */
    .book-spine-3d {
        display: none;
    }

    /* Allow turning pages to extend past the spine onto the left half */
    .book-viewport {
        overflow: visible;
        clip-path: none; /* Pages extend freely during turns — .book-desk-scene contains overflow */
        /* Perspective origin at the spine (left edge of viewport = center of book)
           so pages fold naturally around the center rather than appearing to detach */
        perspective-origin: 0% 50%;
        /* Spine-side shadow — simulates right pages curving into binding */
        box-shadow: inset 12px 0 20px -8px rgba(0,0,0,0.10);
    }

    /* Center gutter — the deep paper fold where left and right pages meet the binding.
       This is the SOLE center visual at desktop (leather spine is hidden).
       Wider gutter with rounded V-shadow, slight page compression, and ambient
       shadow in the fold for a more physical, less geometric center seam. */
    .book-frame::after {
        content: '';
        position: absolute;
        left: 50%;
        top: 0;
        bottom: 0;
        width: 52px;
        transform: translateX(-50%);
        background:
            /* Vertical darkening — pages press tighter at center height */
            radial-gradient(ellipse 100% 65% at 50% 50%,
                rgba(0,0,0,0.10) 0%,
                transparent 100%),
            /* Soft page-bow curvature — pages curve gently into the fold */
            radial-gradient(ellipse 120% 100% at 50% 50%,
                rgba(0,0,0,0.05) 0%,
                transparent 70%),
            /* Core fold: deep V-shadow with rounded profile and paper highlight at the crease */
            linear-gradient(to right,
                transparent 0%,
                rgba(0,0,0,0.02) 8%,
                rgba(0,0,0,0.08) 20%,
                rgba(0,0,0,0.18) 32%,
                rgba(0,0,0,0.28) 42%,
                rgba(0,0,0,0.35) 47%,
                rgba(0,0,0,0.10) 49.3%,  /* Paper edge catching light */
                rgba(255,255,255,0.08) 50%,
                rgba(0,0,0,0.10) 50.7%,
                rgba(0,0,0,0.35) 53%,
                rgba(0,0,0,0.28) 58%,
                rgba(0,0,0,0.18) 68%,
                rgba(0,0,0,0.08) 80%,
                rgba(0,0,0,0.02) 92%,
                transparent 100%);
        box-shadow:
            /* Page-curve shadows — simulate pages bowing toward the fold */
            -18px 0 30px -10px rgba(0,0,0,0.12),
            18px 0 30px -10px rgba(0,0,0,0.12),
            -8px 0 14px -4px rgba(0,0,0,0.07),
            8px 0 14px -4px rgba(0,0,0,0.07),
            /* Ambient gutter shadow — soft inward glow */
            0 0 8px 2px rgba(0,0,0,0.04);
        z-index: 26;
        pointer-events: none;
    }

    /* During page turns/drags, lower gutter z-index below .book-frame-right (z-index: 2)
       so the turning page renders above the center gutter shadow instead of being clipped.
       Without this, the gutter's z-index: 26 creates a visible dark line through the
       turning page as it crosses the spine — the stacking context on .book-frame-right
       means page z-indices (200) only compete within that context, not against siblings. */
    .book-frame:has(.book-page--turning)::after,
    .book-frame:has(.book-page--dragging)::after {
        z-index: 1;
        transition: z-index 0s; /* Instant — no transition delay on z-index change */
    }

    /* During page turns AND drags, lower the ribbon behind turning pages
       and disable interaction. Turning pages receive z-index ~200 from JS,
       so z-index: 0 ensures the ribbon renders behind them. */
    .book-frame-right:has(.book-viewport--turning) .theme-ribbon,
    .book-frame-right:has(.book-page--dragging) .theme-ribbon {
        z-index: 0;
        pointer-events: none;
    }

    /* During page turns, hide 3D depth elements that bleed through the turning
       page, but KEEP covers visible so the leather border remains visible around
       the spread. Scoped to Book state only — in Cover/Table states the depth
       elements are the book's visible 3D structure and must stay visible even
       when the cover page is dragged (e.g., initiating an open from Cover). */
    .book-desk-scene--book .book-frame:has(.book-page--turning) .book-3d-depth .book-3d-page,
    .book-desk-scene--book .book-frame:has(.book-page--turning) .book-3d-depth .book-3d-spine,
    .book-desk-scene--book .book-frame:has(.book-page--turning) .book-3d-depth .book-3d-edge-right,
    .book-desk-scene--book .book-frame:has(.book-page--turning) .book-3d-depth .book-3d-edge-top,
    .book-desk-scene--book .book-frame:has(.book-page--turning) .book-3d-depth .book-3d-edge-bottom,
    .book-desk-scene--book .book-frame:has(.book-page--turning) .book-3d-depth .book-3d-left-stack,
    .book-desk-scene--book .book-frame:has(.book-page--turning) .book-3d-depth .book-3d-ribbons,
    .book-desk-scene--book .book-frame:has(.book-page--dragging) .book-3d-depth .book-3d-page,
    .book-desk-scene--book .book-frame:has(.book-page--dragging) .book-3d-depth .book-3d-spine,
    .book-desk-scene--book .book-frame:has(.book-page--dragging) .book-3d-depth .book-3d-edge-right,
    .book-desk-scene--book .book-frame:has(.book-page--dragging) .book-3d-depth .book-3d-edge-top,
    .book-desk-scene--book .book-frame:has(.book-page--dragging) .book-3d-depth .book-3d-edge-bottom,
    .book-desk-scene--book .book-frame:has(.book-page--dragging) .book-3d-depth .book-3d-left-stack,
    .book-desk-scene--book .book-frame:has(.book-page--dragging) .book-3d-depth .book-3d-ribbons {
        opacity: 0;
    }

    .book-info-corner {
        position: absolute;
        width: clamp(40px, 4vw, 60px);
        height: clamp(40px, 4vw, 60px);
        color: var(--book-gold-detail, #c9a86a);
        z-index: 6;
        pointer-events: none;
        opacity: 0.7;
    }
    .book-info-corner--tl { top: 8px; left: 8px; }
    .book-info-corner--tr { top: 8px; right: 8px; transform: scaleX(-1); }
    .book-info-corner--bl { bottom: 8px; left: 8px; transform: scaleY(-1); }
    .book-info-corner--br { bottom: 8px; right: 8px; transform: scale(-1); }

    /* Desktop: info panel already provides left V-angle, avoid double-angling pages */
    .book-page:not(.book-page--turned):not(.book-page--turning) {
        --book-page-rest-angle: 0deg;
    }

    /* Hide 3D edge elements at desktop — their rotateY(90deg) causes clipping
       between turned pages in the shared preserve-3d context */
    .book-page-edge-right,
    .book-page-edge-left {
        display: none !important;
    }

    /* Sticky notes: partial protrusion at desktop — attached to page edge */
    .book-sticky-note--right-top,
    .book-sticky-note--right-center,
    .book-sticky-note--right-bottom {
        right: calc(-1 * var(--book-note-protrude) * 0.4);
    }
    .book-sticky-note--bottom-right {
        bottom: calc(-1 * var(--book-note-protrude) * 0.3);
    }
}

/* Info panel content styling */
.book-info-panel-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    padding: clamp(24px, 4%, 48px) clamp(20px, 3%, 40px);
    text-align: center;
    gap: clamp(8px, 1.5vh, 20px);
    position: relative;
}

/* Tinted background */
.book-info-panel-content::before {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--panel-bg-tint, transparent);
    pointer-events: none;
    transition: background 0.6s ease;
}

/* Section icon */
.book-info-section-icon {
    width: clamp(36px, 5vw, 56px);
    height: clamp(36px, 5vw, 56px);
    color: var(--panel-accent, var(--color-sage));
    opacity: 0.7;
    transition: color 0.4s ease;
    position: relative;
}

.book-info-section-icon svg {
    width: 100%;
    height: 100%;
}

/* Section heading */
.book-info-section-heading {
    font-family: var(--font-heading);
    font-size: clamp(1.2rem, 1.8vw, 1.6rem);
    text-transform: uppercase;
    letter-spacing: 0.18em;
    color: var(--panel-accent, var(--color-sage));
    margin: 0;
    transition: color 0.4s ease;
    position: relative;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

/* Subtitle */
.book-info-section-subtitle {
    font-family: var(--font-body);
    font-size: clamp(0.75rem, 0.9vw, 0.9rem);
    color: rgba(44, 44, 44, 0.5);
    font-style: italic;
    margin: 0;
    position: relative;
}

/* Themed dividers */
.book-info-divider {
    width: clamp(80px, 12vw, 140px);
    height: auto;
    color: var(--panel-accent, var(--color-sage));
    position: relative;
}

.book-info-divider svg {
    width: 100%;
    height: auto;
}

/* Couple names */
.book-info-couple {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    position: relative;
}

.book-info-names {
    font-family: var(--font-script);
    font-size: clamp(1.6rem, 2.2vw, 2.2rem);
    color: #3d3530;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.06);
}

.book-info-amp {
    font-family: var(--font-heading);
    font-size: clamp(0.7rem, 0.9vw, 0.9rem);
    color: var(--panel-accent, var(--color-sage));
    opacity: 0.5;
}

/* Venue details */
.book-info-details {
    position: relative;
}

.book-info-details p {
    margin: 0;
    font-family: var(--font-body);
    font-size: clamp(0.7rem, 0.8vw, 0.85rem);
    color: rgba(44, 44, 44, 0.6);
    line-height: 1.6;
}

.book-info-date {
    font-family: var(--font-heading) !important;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: rgba(44, 44, 44, 0.7) !important;
}

/* Table of contents navigation */
.book-info-toc {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: auto;
    padding-top: clamp(12px, 2vh, 24px);
    width: 100%;
    max-width: 200px;
    position: relative;
}

.book-info-toc-item {
    display: flex;
    align-items: center;
    gap: 8px;
    border: none;
    background: none;
    padding: 4px 8px;
    cursor: pointer;
    border-radius: 4px;
    transition: background 0.2s ease;
    font-family: var(--font-body);
    font-size: clamp(0.65rem, 0.75vw, 0.8rem);
    color: rgba(44, 44, 44, 0.5);
    text-align: left;
}

.book-info-toc-item:hover {
    background: rgba(0, 0, 0, 0.03);
    color: rgba(44, 44, 44, 0.8);
}

.book-info-toc-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: rgba(44, 44, 44, 0.15);
    flex-shrink: 0;
    transition: background 0.3s ease, transform 0.3s ease;
}

.book-info-toc-item--active {
    color: var(--panel-accent, var(--color-sage));
}

.book-info-toc-item--active .book-info-toc-dot {
    background: var(--panel-accent, var(--color-sage));
    transform: scale(1.3);
}

/* Content transition animations */
.book-info-panel-content--exit {
    animation: infoPanelExit 0.25s ease-in forwards;
}

.book-info-panel-content--enter {
    animation: infoPanelEnter 0.35s ease-out forwards;
}

@keyframes infoPanelExit {
    0%   { opacity: 1; transform: translateX(0); }
    100% { opacity: 0; transform: translateX(-20px); }
}

@keyframes infoPanelEnter {
    0%   { opacity: 0; transform: translateX(20px); }
    100% { opacity: 1; transform: translateX(0); }
}


/* ═══════════════════════════════════════════════════════════════
   BOOK INDEX — TABLE OF CONTENTS (LEFT PAGE, PAGE 0)
   ═══════════════════════════════════════════════════════════════ */

.book-index {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    padding: clamp(20px, 3%, 40px) clamp(16px, 2.5%, 32px);
    text-align: center;
    gap: clamp(8px, 1.5vh, 16px);
    position: relative;
    color: #3d3530;
}

.book-index-emblem {
    width: clamp(60px, 8vw, 90px);
    height: auto;
    color: #c9a86a;
    opacity: 0.6;
    margin-bottom: 0.25rem;
}

.book-index-emblem svg {
    width: 100%;
    height: auto;
}

.book-index-dedication {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}

.book-index-names {
    font-family: var(--font-script);
    font-size: clamp(1.5rem, 2.2vw, 2rem);
    color: #3d3530;
}

.book-index-amp {
    font-family: var(--font-heading);
    font-size: 0.7rem;
    color: #c9a86a;
    opacity: 0.5;
    letter-spacing: 0.3em;
}

.book-index-date {
    font-family: var(--font-heading);
    font-size: clamp(0.7rem, 0.85vw, 0.85rem);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: rgba(61, 53, 48, 0.6);
}

.book-index-venue {
    font-family: var(--font-body);
    font-size: clamp(0.65rem, 0.75vw, 0.75rem);
    color: rgba(61, 53, 48, 0.45);
    font-style: italic;
}

.book-index-heading {
    font-family: 'Cormorant Garamond', var(--font-heading);
    font-size: clamp(1rem, 1.4vw, 1.3rem);
    text-transform: uppercase;
    letter-spacing: 0.25em;
    color: #3d3530;
    margin: 0;
    font-weight: 600;
}

.book-index-divider {
    width: clamp(80px, 12vw, 140px);
    color: #c9a86a;
}

.book-index-divider svg {
    width: 100%;
    height: auto;
}

.book-index-entries {
    display: flex;
    flex-direction: column;
    gap: clamp(6px, 1vh, 12px);
    width: 100%;
    max-width: 280px;
}

.book-index-entry {
    display: flex;
    align-items: baseline;
    gap: 0;
    border: none;
    background: none;
    padding: clamp(3px, 0.5vh, 6px) 4px;
    cursor: pointer;
    border-radius: 3px;
    transition: background 0.2s ease, color 0.2s ease;
    text-align: left;
    width: 100%;
}

.book-index-entry:hover {
    background: rgba(201, 168, 106, 0.08);
}

.book-index-numeral {
    font-family: 'Cormorant Garamond', serif;
    font-size: clamp(0.75rem, 0.9vw, 0.9rem);
    font-weight: 600;
    color: #c9a86a;
    min-width: 28px;
    flex-shrink: 0;
    font-style: italic;
}

.book-index-title {
    font-family: 'Cormorant Garamond', serif;
    font-size: clamp(0.75rem, 0.85vw, 0.85rem);
    color: #3d3530;
    white-space: nowrap;
    flex-shrink: 0;
}

.book-index-dots {
    flex: 1;
    min-width: 16px;
    border-bottom: 1px dotted rgba(61, 53, 48, 0.2);
    margin: 0 6px;
    position: relative;
    top: -3px;
}

.book-index-page {
    font-family: 'Cormorant Garamond', serif;
    font-size: clamp(0.75rem, 0.85vw, 0.85rem);
    color: rgba(61, 53, 48, 0.5);
    flex-shrink: 0;
    font-style: italic;
}

/* ─── Countdown on Left Page (Page 6) ─── */
.book-countdown-left {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    padding: clamp(16px, 3%, 32px);
    position: relative;
    overflow: hidden;
}

/* Scale countdown to fit within the book page back-face dimensions */
.book-countdown-left .countdown-container {
    padding: clamp(1rem, 2vh, 2rem) 1rem;
    gap: 0;
}

.book-countdown-left .countdown-value {
    font-size: clamp(1.6rem, 3.5vh, 2.8rem);
}

.book-countdown-left .countdown-label {
    font-size: clamp(0.45rem, 0.8vh, 0.6rem);
    letter-spacing: 1.5px;
}

.book-countdown-left .countdown-numbers {
    gap: clamp(0.3rem, 0.8vw, 0.8rem);
}

.book-countdown-left .countdown-unit {
    min-width: clamp(35px, 6vw, 55px);
}

.book-countdown-left .countdown-dot {
    font-size: clamp(0.8rem, 1.5vh, 1.2rem);
    margin-top: 0.4rem;
}

.book-countdown-left .countdown-couple {
    margin-top: clamp(0.8rem, 1.5vh, 2rem);
}

.book-countdown-left .countdown-couple-img {
    width: clamp(90px, 16vh, 150px);
}

.book-countdown-left .countdown-couple-glow {
    width: clamp(100px, 18vh, 180px);
    height: clamp(100px, 18vh, 180px);
}

/* ─── Venue / When & Where Left Page ─── */

.book-venue-page {
    text-align: center;
}

.book-venue-schedule {
    display: flex;
    flex-direction: column;
    gap: clamp(6px, 1vh, 14px);
    margin: clamp(4px, 1vh, 12px) 0;
}

.book-venue-time-entry {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}

.book-venue-time {
    font-family: var(--font-manuscript-heading, 'Playfair Display', serif);
    font-size: clamp(1rem, 1.8vh, 1.35rem);
    letter-spacing: 0.08em;
    color: var(--panel-accent, var(--color-forest));
    opacity: 0.85;
}

.book-venue-event {
    font-family: var(--font-manuscript-body, 'Lato', sans-serif);
    font-size: clamp(0.7rem, 1.2vh, 0.85rem);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    opacity: 0.55;
}

.book-venue-location {
    margin: clamp(4px, 1vh, 12px) 0;
}

.book-venue-name {
    font-family: var(--font-manuscript-heading, 'Playfair Display', serif);
    font-size: clamp(0.95rem, 1.6vh, 1.2rem);
    letter-spacing: 0.1em;
    margin: 0 0 4px 0;
    opacity: 0.8;
}

.book-venue-address {
    font-family: var(--font-manuscript-body, 'Lato', sans-serif);
    font-size: clamp(0.7rem, 1.2vh, 0.85rem);
    letter-spacing: 0.04em;
    margin: 0;
    opacity: 0.55;
    line-height: 1.5;
}

.book-venue-map-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-manuscript-body, 'Lato', sans-serif);
    font-size: clamp(0.65rem, 1.1vh, 0.8rem);
    letter-spacing: 0.06em;
    color: var(--panel-accent, var(--color-forest));
    text-decoration: none;
    padding: 6px 16px;
    border: 1px solid currentColor;
    border-radius: 30px;
    opacity: 0.6;
    transition: opacity 0.3s ease, background 0.3s ease;
    margin: clamp(4px, 0.8vh, 10px) 0;
}

.book-venue-map-link:hover {
    opacity: 0.85;
    background: var(--panel-bg-tint, rgba(61, 89, 65, 0.06));
}

.book-venue-map-icon {
    width: 14px;
    height: 14px;
}

.book-venue-date {
    margin-top: clamp(4px, 0.8vh, 10px);
}

.book-venue-date .book-info-date {
    font-size: clamp(0.7rem, 1.2vh, 0.85rem);
}

/* ─── Closing Page (Right Side, Page 6) ─── */
.book-closing-page {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 80vh;
    text-align: center;
    gap: 1rem;
}

.book-closing-emblem {
    width: 80px;
    height: 80px;
    color: rgba(61, 53, 48, 0.15);
    margin-bottom: 1rem;
}

.book-closing-emblem svg {
    width: 100%;
    height: 100%;
}

.book-closing-text {
    font-family: var(--font-script);
    font-size: clamp(2rem, 3vw, 3rem);
    color: rgba(61, 53, 48, 0.85);
    margin: 0;
}

.book-closing-subtitle {
    font-family: var(--font-body);
    font-size: clamp(0.75rem, 0.9vw, 0.9rem);
    color: rgba(61, 53, 48, 0.7);
    font-style: italic;
    letter-spacing: 0.15em;
    margin: 0;
}


/* ═══════════════════════════════════════════════════════════════
   PHASE 6: PAGE TURN ANIMATION POLISH
   Enhanced fold crease, page flutter, light flash, under-page reveal.
   ═══════════════════════════════════════════════════════════════ */

/* Under-page reveal light wash — left-to-right sweep when a page turns away */
.book-page--turning + .book-page:not(.book-page--turned) .book-page-front::after {
    animation: underPageRevealWash var(--book-page-turn-duration) ease-in-out forwards;
    z-index: 11;
}

@keyframes underPageRevealWash {
    0% {
        opacity: 0;
        background: linear-gradient(to right, rgba(255,255,255,0.08) 0%, transparent 30%);
        background-position: -100% 0;
    }
    25% {
        opacity: 0.08;
        background: linear-gradient(to right, rgba(255,255,255,0.1) 0%, transparent 40%);
    }
    50% {
        opacity: 0.05;
    }
    100% {
        opacity: 0;
    }
}


/* ─── Reduced Motion ─── */
@media (prefers-reduced-motion: reduce) {
    .book-page {
        transition-duration: 0.01ms !important;
    }

    .book-page--turning-forward,
    .book-page--turning-backward {
        animation-duration: 0.01ms !important;
    }

    .book-page--turning-forward .book-page-front::before,
    .book-page--turning-forward .book-page-back::before,
    .book-page--turning-backward .book-page-back::after,
    .book-page--turning-backward .book-page-front::before {
        animation-duration: 0.01ms !important;
    }

    .book-page--turning .book-page-spine-glow,
    .book-page--turning .book-page-edge,
    .book-page--turning .book-page-curl-shadow,
    .book-page--turning .book-mote,
    .book-viewport--turning .book-spine-light {
        animation-duration: 0.01ms !important;
    }

    .book-page--turning-forward > .book-page-front,
    .book-page--turning-backward > .book-page-back {
        animation-duration: 0.01ms !important;
    }

    .book-page--turning + .book-page:not(.book-page--turned) .book-page-front {
        animation-duration: 0.01ms !important;
    }

    .book-page-particles {
        display: none;
    }

    /* Page flutter reveal — keep opacity transition but skip rotateY transform */
    .book-desk-scene--opening .book-page,
    .book-desk-scene--opening .book-frame.book-frame--open .book-page {
        animation-duration: 0.01ms !important;
        animation-delay: 0ms !important;
    }

    /* Opening/Settling state animations — instant for reduced motion */
    .book-desk-scene--opening .book-viewport,
    .book-desk-scene--opening .book-frame.book-frame--open .book-viewport,
    .book-desk-scene--opening .book-3d-depth,
    .book-desk-scene--opening .book-frame.book-frame--open .book-3d-depth,
    .book-desk-scene--settling .book-cover-page {
        animation-duration: 0.01ms !important;
        animation-delay: 0ms !important;
    }

    .book-page-corner--next::before,
    .book-page-corner--prev::before {
        transition-duration: 0.01ms !important;
        animation: none !important;
    }

    .book-page--turned {
        transition-duration: 0.01ms !important;
    }

    /* Ribbon transitions and flutter disabled */
    .book-ribbon {
        transition-duration: 0.01ms !important;
    }

    .book-ribbon,
    .book-frame-right:has(.book-viewport--turning) .book-ribbon,
    .book-frame-right:has(.book-viewport--turning-forward) .book-ribbon,
    .book-frame-right:has(.book-viewport--turning-backward) .book-ribbon {
        animation: none !important;
    }

    /* Spine bloom disabled */
    .book-viewport.book-viewport--turning::before {
        animation: none !important;
    }

    .book-page--turning .book-page-corner {
        animation-duration: 0.01ms !important;
    }

    .book-cover {
        transition-duration: 0.01ms !important;
    }

    .book-cover-name--visible {
        animation-duration: 0.01ms !important;
    }

    .book-frame--entering {
        animation-duration: 0.01ms !important;
    }

    /* Phase 8: Reduced motion for new 3D features */
    .book-page-edge-right,
    .book-page-edge-left {
        display: none;
    }

    .book-sticky-note {
        animation: none !important;
        transition: none !important;
        opacity: 1 !important;
    }

    .book-page-peel-shadow,
    .book-page-peel-underpage {
        display: none;
    }

    .book-spine-3d-glow {
        animation: none !important;
    }

    .book-info-panel-content--exit,
    .book-info-panel-content--enter {
        animation-duration: 0.01ms !important;
    }

    .book-page--turning + .book-page:not(.book-page--turned) .book-page-front::after {
        animation: none !important;
    }
}


/* ═══════════════════════════════════════════════════════════════
   PHASE 8: RESPONSIVE SCALING FOR NEW FEATURES
   ═══════════════════════════════════════════════════════════════ */

/* Mobile (<768px): Reduce 3D edges, hide sticky text, disable peel */
@media (max-width: 768px) {
    .book-page-edge-right span:nth-child(3),
    .book-page-edge-left span:nth-child(3) {
        display: none;
    }

    .book-sticky-note-text {
        display: none;
    }

    .book-sticky-note-paper {
        min-height: calc(var(--book-note-size) * 0.5);
    }

    .book-page-peel-shadow,
    .book-page-peel-underpage {
        display: none;
    }

    .book-page-corner--next:hover::before,
    .book-page-corner--prev:hover::before {
        transform: none;
    }
}

/* Tablet (768px-1439px): Full 3D edges, full sticky notes, peel on hover */
@media (min-width: 769px) and (max-width: 1199px) {
    .book-sticky-note {
        --book-note-size: clamp(28px, 3.5vw, 50px);
    }
}

/* Ultra-wide (2560px+): Proportionally larger */
@media (min-width: 2560px) {
    :root {
        --book-edge-3d-thickness: clamp(2px, 0.2vw, 4px);
        --book-edge-3d-gap: clamp(1px, 0.1vw, 2px);
        --book-note-size: clamp(45px, 5vw, 80px);
        --book-note-protrude: clamp(12px, 1.5vw, 24px);
    }
}


/* ═══════════════════════════════════════════════════════════════
   HARDCOVER BACKING — GLOBALLY HIDDEN
   Replaced by the true 3D back cover (.book-3d-back-cover) which
   stays visible throughout all states and animations. The 3D cover
   provides superior visual quality with real depth, edges, and clips.
   The frame-level .book-3d-back-edge strips provide perpendicular
   leather borders in the open state.
   ═══════════════════════════════════════════════════════════════ */

.book-hardcover {
    display: none;
    position: absolute;
    /* Overhang on all sides — cover is larger than the page block */
    top: calc(-1 * var(--book-cover-overhang));
    bottom: calc(-1 * var(--book-cover-overhang));
    left: calc(-1 * var(--book-cover-overhang));
    right: calc(-1 * var(--book-cover-overhang));
    z-index: -1; /* Behind all page content — isolation:isolate on .book-frame keeps it visible */
    pointer-events: none;

    /* Leather cover texture — subtle directional lighting from top-left */
    background:
        /* Subtle grain texture */
        var(--env-paper-fiber),
        /* Leather gradient with light hitting from upper-left */
        linear-gradient(145deg,
            color-mix(in srgb, var(--book-cover-leather) 92%, white) 0%,
            var(--book-cover-leather) 25%,
            color-mix(in srgb, var(--book-cover-leather) 95%, black) 60%,
            var(--book-cover-dark) 100%);
    background-color: var(--book-cover-leather);

    /* Slightly larger radius than the page block */
    border-radius: 6px 10px 10px 6px;

    /* Depth shadow + subtle top highlight (light catching the cover edge) */
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.08),
        inset 0 -1px 0 rgba(0, 0, 0, 0.1),
        0 3px 10px rgba(0, 0, 0, 0.25),
        0 1px 3px rgba(0, 0, 0, 0.15);
}

/* ─── Spine Caps (Headcap / Tailcap) ─── */
/* Rounded leather bumps at top and bottom of the spine, protruding beyond the cover boards. */
.book-hardcover::before,
.book-hardcover::after {
    content: '';
    position: absolute;
    /* Spine is at the left edge of the page block.
       Since hardcover has negative insets, the page-block left edge = var(--book-cover-overhang) from our left. */
    left: var(--book-cover-overhang);
    width: var(--book-spine-3d-width, 20px);
    height: clamp(5px, 0.6vw, 10px);
    /* Convex leather gradient — rounded bump catching light at center */
    background: linear-gradient(to right,
        var(--book-cover-dark) 0%,
        color-mix(in srgb, var(--book-cover-leather) 90%, white) 40%,
        color-mix(in srgb, var(--book-cover-leather) 85%, white) 50%,
        color-mix(in srgb, var(--book-cover-leather) 90%, white) 60%,
        var(--book-cover-dark) 100%);
    border-radius: 3px 3px 3px 3px;
    z-index: 1; /* Above the hardcover surface */
}

/* Headcap — protrudes above the top cover edge */
.book-hardcover::before {
    top: 0;
    transform: translateY(-40%);
    box-shadow:
        0 -1px 2px rgba(0, 0, 0, 0.25),
        inset 0 1px 0 rgba(255, 255, 255, 0.12);
}

/* Tailcap — protrudes below the bottom cover edge */
.book-hardcover::after {
    bottom: 0;
    transform: translateY(40%);
    box-shadow:
        0 1px 3px rgba(0, 0, 0, 0.3),
        inset 0 -1px 0 rgba(255, 255, 255, 0.08);
}

/* Mobile: smaller overhang + smaller spine caps */
@media (max-width: 768px) {
    :root {
        --book-cover-overhang: 3px;
    }

    .book-hardcover::before,
    .book-hardcover::after {
        height: 4px;
        border-radius: 2px;
    }
}


/* ═══════════════════════════════════════════════════════════════
   BOTTOM PAGE EDGE — paper stack thickness visible at the bottom
   Only visible on unturned pages to show depth of remaining pages.
   ═══════════════════════════════════════════════════════════════ */

.book-page-edge-bottom {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 0;
    transform-origin: bottom center;
    pointer-events: none;
    z-index: 5;
    box-shadow:
        0 1px 0 #d4cfc8,
        0 2px 0 #eae5de,
        0 3px 0 #fff,
        0 4px 0 #d4cfc8,
        0 5px 1px rgba(0, 0, 0, 0.06);
}

/* Only show bottom edge on unturned pages */
.book-page:not(.book-page--turned):not(.book-page--turning) .book-page-edge-bottom {
    display: block;
    opacity: calc(1 - var(--stack-position, 0) * 0.4);
}

.book-page--turned .book-page-edge-bottom,
.book-page--turning .book-page-edge-bottom {
    display: none;
}

/* Hide bottom edge at desktop — same reason as side edges (3D compositing conflicts) */
@media (min-width: 1200px) {
    .book-page-edge-bottom {
        display: none !important;
    }
}

/* Hide bottom edge on mobile (performance) */
@media (max-width: 768px) {
    .book-page-edge-bottom {
        display: none;
    }
}

/* Hide 4th span on mobile to reduce rendering load */
@media (max-width: 768px) {
    .book-page-edge-right span:nth-child(4),
    .book-page-edge-left span:nth-child(4) {
        display: none;
    }
}


/* ═══════════════════════════════════════════════════════════════
   CLOSED BOOK STATE — 3D closed book with depth, spine, and
   page thickness. Opens with a cover-swing animation.
   ═══════════════════════════════════════════════════════════════ */

/* ── Cover state: 3D closed book ──────────────────────────────── */

/* Hide spine and gutter in Cover/Opening state.
   Uses opacity/visibility instead of display:none to allow CSS transitions
   and keep elements in the DOM for the unified book opening sequence. */
.book-desk-scene--cover .book-spine-3d,
.book-desk-scene--opening .book-spine-3d {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none !important;
    transition: opacity 0.4s ease, visibility 0s linear 0.4s;
}

.book-desk-scene--cover .book-frame::after,
.book-desk-scene--opening .book-frame::after {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none;
    transition: opacity 0.4s ease, visibility 0s linear 0.4s;
}

/* Right side takes full width + maintain 3D context for spine/edges */
.book-desk-scene--cover .book-frame-right,
.book-desk-scene--opening .book-frame-right {
    transform-style: preserve-3d;
}

.book-desk-scene--cover .book-frame-right {
    width: 100%;
    flex: 1;
}

/* The desk surface needs preserve-3d for the frame's 3D to render.
   Applied in both Cover and Opening states so the 3D depth elements
   remain properly Z-sorted while fading out during the opening transition. */
.book-desk-scene--cover .book-desk-surface,
.book-desk-scene--opening .book-desk-surface {
    perspective: var(--book-closed-perspective);
    transform-style: preserve-3d;
}

/* 3D transform on the closed book */
.book-desk-scene--cover .book-frame {
    transform-style: preserve-3d;
    transform:
        rotateX(var(--book-closed-rotate-x))
        rotateY(var(--book-closed-rotate-y))
        rotateZ(var(--book-closed-rotate-z));
    transition: transform 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94),
                width var(--book-closed-open-duration) cubic-bezier(0.22, 0.68, 0.18, 1);
}

/* Subtle hover lift — offsets are relative to resting rotation */
.book-desk-scene--cover .book-frame:hover {
    transform:
        rotateX(calc(var(--book-closed-rotate-x) + var(--book-closed-hover-rx-offset)))
        rotateY(calc(var(--book-closed-rotate-y) + var(--book-closed-hover-ry-offset)))
        rotateZ(calc(var(--book-closed-rotate-z) + var(--book-closed-hover-rz-offset)))
        translateY(var(--book-closed-hover-lift))
        translateZ(var(--book-closed-hover-tz));
}

/* Disable hover transform when admin is orbiting or guest is rotating */
.book-desk-scene--cover .book-frame.book-frame--no-hover:hover {
    transform:
        rotateX(var(--book-closed-rotate-x))
        rotateY(var(--book-closed-rotate-y))
        rotateZ(var(--book-closed-rotate-z));
}

/* Suppress CSS transition when JS drives rotation (guest drag + spring-back).
   Without this, clearing inline CSS vars triggers a 0.8s CSS transition that
   conflicts with the JS lerp animation, causing snap-to-wrong-angle bugs. */
.book-desk-scene--cover .book-frame.book-frame--js-driven {
    transition: none !important;
}
.book-desk-scene--cover.guest-rotating .book-frame {
    transition: none !important;
}

/* Back edges hidden in closed state — the 3D depth container's own
   back cover edges handle this. Frame-level edges only needed in open states. */
.book-desk-scene--cover .book-3d-back-edge {
    display: none;
}

/* Maintain 3D context through the full DOM chain (Cover and Opening) */
.book-desk-scene--cover .book-viewport,
.book-desk-scene--cover .book-page-stack,
.book-desk-scene--cover .book-cover-page,
.book-desk-scene--opening .book-viewport,
.book-desk-scene--opening .book-page-stack,
.book-desk-scene--opening .book-cover-page {
    transform-style: preserve-3d;
}

/* Lift the front cover to the top of the page stack (Z = page-depth).
   The back cover sits at Z=0; pages stack between them.
   Negative insets create the hardcover "squares" — cover boards are slightly
   larger than the page block, just like a real book. */
.book-desk-scene--cover .book-cover-page {
    transform:
        translateX(var(--book-front-cover-extra-tx))
        translateY(var(--book-front-cover-extra-ty))
        translateZ(calc(var(--book-closed-page-depth) + 2px + var(--book-front-cover-extra-tz)))
        rotateX(var(--book-front-cover-extra-rx))
        rotateY(var(--book-front-cover-extra-ry))
        rotateZ(var(--book-front-cover-extra-rz));
    top: calc(-1 * var(--book-cover-overhang-top));
    left: 2px; /* 2px inset from spine anchor to prevent CSS 3D painter's algorithm
                   Z-fighting. The front cover's center Z is higher than the spine's,
                   so the browser paints the cover ON TOP of the spine wall. Insetting
                   2px in X separates the surfaces so they don't visually overlap at
                   the binding junction — the spine covers this 2px gap. */
    right: calc(-1 * var(--book-cover-overhang-right));
    bottom: calc(-1 * var(--book-cover-overhang-bottom));
}

/* Ensure nothing clips the 3D depth elements */
.book-desk-scene--cover .book-frame {
    overflow: visible;
    /* CRITICAL: Override isolation:isolate which forces transform-style:flat.
       The CSS spec says isolation:isolate is a grouping property that flattens 3D.
       Without this override, all translateZ/rotateY/rotateX on depth elements
       are invisible. In Cover state, isolation is unnecessary since the 3D depth
       elements handle all back cover rendering. */
    isolation: auto;
}

.book-desk-scene--cover .book-frame-right,
.book-desk-scene--opening .book-frame-right {
    overflow: visible;
}

/* CRITICAL: In Cover state, .book-viewport must NOT have its own perspective
   or opaque background. Its perspective creates a separate 3D context that
   prevents the front cover's translateZ from Z-sorting with the depth elements
   in .book-3d-depth. Its cream background covers depth elements behind it. */
.book-desk-scene--cover .book-viewport {
    perspective: none;
    background: transparent;
}

/* Opening state: viewport starts transparent (preserving 3D Z-sort while cover
   is in front). Animation is scoped to .book-frame--open so it fires when the
   cover actually starts swinging, not when the Opening state enters. */
.book-desk-scene--opening .book-viewport {
    perspective: none;
    background: transparent;
}

/* Cream reveal scoped to cover swing. 0.7s delay from cover start means
   cream bg is established as the cover passes ~82deg (44% of 1.6s swing).
   Pages appear on a clean paper surface, not a transparent/brown backdrop. */
:not(.book-desk-scene--play).book-desk-scene--opening .book-frame.book-frame--open .book-viewport {
    animation: viewportCreamReveal 0.5s ease 0.7s forwards;
}

/* ── Front cover styling in closed state ──────────────────────── */
/* Only an inset vignette — all external depth comes from the true 3D geometry
   (.book-3d-depth children: page layers, spine, edges, back cover).
   The legacy 2D box-shadow page-stack lines were removed because they paint
   in screen-space and don't rotate with the book's 3D transform. */
.book-desk-scene--cover .book-cover-page-front {
    box-shadow: inset 0 0 40px rgba(0, 0, 0, var(--book-cover-vignette-intensity));
}

/* Hide front cover's spine edge in closed state — the 3D spine fully covers the
   binding junction. Without this, the cover edge (at X=0) and spine face (also at X=0)
   are coplanar, causing the cover edge to clip through the spine surface.
   The edge becomes visible again during the Opening animation when the cover swings open. */
.book-desk-scene--cover .book-cover-edge--spine,
.book-desk-scene--table .book-cover-edge--spine,
.book-desk-scene--pickingup .book-cover-edge--spine,
.book-desk-scene--settingdown .book-cover-edge--spine,
.book-desk-scene--book .book-cover-edge--spine,
.book-desk-scene--settling .book-cover-edge--spine {
    opacity: 0;
    transition: opacity 0.3s ease;
}

/* Prevent front cover sub-elements from extending past the parent's left edge
   into the spine's screen zone. The ::before (fill panel, inset:-2px) reaches
   X=0 and the face (inset:-0.5px) reaches X=1.5px — both overlap the spine
   in screen space. Since these children have higher center-Z than the spine,
   CSS 3D sorts them ON TOP of the spine, causing the cover's dark leather
   to bleed through the spine surface. Overriding left:0 keeps them within
   the parent boundary (at X=2px), safely behind the spine's perpendicular face. */
.book-desk-scene--cover .book-cover-page::before,
.book-desk-scene--cover .book-cover-page-front,
.book-desk-scene--table .book-cover-page::before,
.book-desk-scene--table .book-cover-page-front,
.book-desk-scene--pickingup .book-cover-page::before,
.book-desk-scene--pickingup .book-cover-page-front,
.book-desk-scene--settingdown .book-cover-page::before,
.book-desk-scene--settingdown .book-cover-page-front {
    left: 0;
}

/* ── 3D Depth Container ───────────────────────────────────────── */
/* Models a closed book as: front cover (existing) + back cover offset
   behind it + solid page-block edges on right/bottom + spine on left.
   All flat-positioned; the parent .book-frame's 3D rotation gives depth. */

.book-3d-depth {
    position: absolute;
    inset: 0;
    pointer-events: none;
    transform-style: preserve-3d; /* Children participate in .book-frame's 3D context */
    /* Safety transition prevents opacity/visibility pop if state changes bypass
       the proper Closing animation path (e.g., rapid editor state switching) */
    transition: opacity 0.4s ease, visibility 0.4s ease;
}

/* Cover state: 3D depth elements fully visible with transition.
   Ensures smooth opacity handoff from Closing->Cover and Cover->Opening.
   Without this, transitioning to Cover from Book causes depth elements to pop in instantly. */
.book-desk-scene--cover .book-3d-depth {
    opacity: 1;
    visibility: visible;
    pointer-events: none;
    transition: opacity 0.6s ease, visibility 0s linear 0s;
}

/* Page depth layers hidden when cover is on top — prevents CSS 3D flat-element
   Z-sort artifacts where cream pages render through the dark cover during rotation.
   CSS 3D sorts entire elements by center-Z, not per-pixel. When the cover rotates
   even slightly, its center-Z drops below the topmost page layers, causing the
   browser to paint cream pages ON TOP of the dark leather cover.
   Pages only need to be visible during Book/Opening states. */
.book-desk-scene--cover .book-3d-page,
.book-desk-scene--closing .book-3d-page {
    opacity: 0;
    transition: opacity 0.3s ease;
}

/* ── 3D Ground Shadow ─────────────────────────────────────────── */
/* Pseudo-element placed slightly behind the back cover (Z = -2px) so it
   participates in the preserve-3d context and rotates with the book.
   Unlike 2D box-shadows on the covers, this shadow foreshortens correctly
   at any viewing angle set by the BookGeometryEditor. */
.book-desk-scene--cover .book-3d-depth::after {
    content: '';
    position: absolute;
    inset: -4px;
    transform: translateZ(calc(-1 * var(--book-cover-board-thickness) - 2px));
    border-radius: 4px 10px 10px 4px;
    box-shadow:
        8px 12px 35px rgba(0, 0, 0, 0.35),
        4px 6px 15px rgba(0, 0, 0, 0.2);
    pointer-events: none;
}

/* ═══════════════════════════════════════════════════════════════
   TRUE 3D BOOK DEPTH GEOMETRY
   Uses translateZ for real spatial depth instead of 2D diagonal offsets.
   The parent .book-frame's rotateX/rotateY + perspective automatically
   reveals the spine, fore edge, and bottom edge as foreshortened surfaces.
   No skew hacks needed — the browser handles all foreshortening.
   ═══════════════════════════════════════════════════════════════ */

/* ── Back Cover — sits at Z=0 (the desk-facing surface) ── */
/* Same size as front cover. The front cover sits at Z=page-depth (on top).
   Pages stack between them. Slightly larger for the "squares" overhang. */
.book-3d-back-cover {
    position: absolute;
    /* Match front cover exactly — use the same directional overhang variables
       so both covers are controlled by the same editor sliders.
       No left/spine overhang: real book covers are flush at the spine binding. */
    top: calc(-1 * var(--book-cover-overhang-top));
    left: 0;
    right: calc(-1 * var(--book-cover-overhang-right));
    bottom: calc(-1 * var(--book-cover-overhang-bottom));
    /* Shifted backward by board-thickness so the board depth extends OUTWARD
       (toward the desk), matching how a real book's back cover has visible thickness
       from outside. The face at +board-thickness lands at Z=0 (flush with page base).
       The fill panel at this Z shows the desk-facing leather surface. */
    transform:
        translateX(var(--book-back-cover-extra-tx))
        translateY(var(--book-back-cover-extra-ty))
        translateZ(calc(-1 * var(--book-cover-board-thickness) + var(--book-back-cover-extra-tz)))
        rotateX(var(--book-back-cover-extra-rx))
        rotateY(var(--book-back-cover-extra-ry))
        rotateZ(var(--book-back-cover-extra-rz));
    transform-style: preserve-3d;
    border-radius: 4px 8px 8px 4px;
}

/* Interior fill panel — seals the back of the back cover board at Z=0.
   Prevents see-through gaps at corners and edges when viewed at angles. */
.book-3d-back-cover::before {
    content: '';
    position: absolute;
    inset: -2px;
    background: var(--book-cover-dark);
    border-radius: inherit;
    pointer-events: none;
}

/* Back cover face — IDENTICAL leather appearance to front cover face.
   Pushed forward by board-thickness so it's flush with edge fronts.
   Gets hidden in open state (Z-fighting with viewport), but edge children stay visible. */
.book-3d-back-cover-face {
    position: absolute;
    inset: 0;
    /* Same forward push as front cover face */
    transform: translateZ(var(--book-cover-board-thickness, 6px));
    /* Identical leather appearance to .book-cover-page-front */
    background:
        var(--env-paper-grain),
        radial-gradient(ellipse at 30% 20%, rgba(255,255,255,0.06) 0%, transparent 50%),
        radial-gradient(ellipse at 70% 80%, rgba(0,0,0,0.12) 0%, transparent 50%),
        linear-gradient(145deg,
            color-mix(in srgb, var(--book-cover-leather) 90%, white) 0%,
            var(--book-cover-leather) 25%,
            var(--book-cover-dark) 75%,
            color-mix(in srgb, var(--book-cover-dark) 85%, black) 100%);
    background-size: 200px 200px, 100% 100%, 100% 100%, 100% 100%;
    border-radius: inherit;
    box-shadow:
        2px 2px 8px rgba(0, 0, 0, 0.2),
        inset 0 0 40px rgba(0, 0, 0, 0.15),
        inset 0 0 80px rgba(0, 0, 0, 0.08);
}

/* Gold frame inset on back cover — matches front cover's ::after pattern */
.book-3d-back-cover-face::after {
    content: '';
    position: absolute;
    inset: 16px;
    border: 2px solid var(--book-gold-leaf);
    border-radius: 4px;
    opacity: var(--book-cover-gold-opacity);
    pointer-events: none;
    z-index: 2;
}

/* ── Back cover outer content ─────────────────────────────────────
   Container for content visible from the BACK of the 3D book (QR code, etc.).
   Sits at translateZ(-1px) relative to .book-3d-back-cover — just behind
   the ::before fill panel (Z=0) from the front, but IN FRONT of it when
   viewed from behind (smaller Z = closer to the back-facing camera).
   rotateY(180deg) ensures content faces outward (backward). */

.book-3d-back-cover-outer-content {
    position: absolute;
    inset: 0;
    transform: translateZ(-1px) rotateY(180deg);
    pointer-events: none;
    display: flex;
    justify-content: center;
    align-items: flex-start;
    padding-top: 15%;
}

/* ── QR code on back cover outer face ─────────────────────────────
   Centered in the top half. Parent .book-3d-back-cover-outer-content
   already handles rotateY(180deg) and Z-positioning, so the QR code
   just needs centering — no local rotation. */

.back-cover-qr {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    pointer-events: none;
}

.back-cover-qr__frame {
    width: 150px;
    height: 150px;
    padding: 14px;
    background: #fff;
    border-radius: 8px;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid var(--book-gold-leaf, #D4AF37);
    box-shadow: 0 2px 8px rgba(0,0,0,0.15),
                0 0 0 1px rgba(212, 175, 55, 0.3),
                inset 0 0 0 1px rgba(212, 175, 55, 0.15);
}

.back-cover-qr__frame svg {
    display: block;
    width: 100%;
    height: 100%;
}

.back-cover-qr__label {
    display: block;
    margin-top: 8px;
    font-family: var(--font-heading, 'Playfair Display', serif);
    font-size: 0.7rem;
    letter-spacing: 2px;
    text-transform: uppercase;
    color: var(--book-gold-leaf, #D4AF37);
}

/* ── Back cover board-thickness edges ─────────────────────────────
   Four perpendicular surfaces inside .book-3d-back-cover giving it real depth.
   Identical geometry to the front cover edges in storybook-unified.css.
   Each edge rotates 90° from its anchor, spanning Z=0 (fill) to Z=board-thickness (face). */

.book-3d-back-cover-edge {
    position: absolute;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
    pointer-events: none;
}

/* Spine edge (left) — connects back cover to the book's binding */
.book-3d-back-cover-edge--spine {
    top: -2px;
    bottom: -2px;
    left: 0;
    width: var(--book-cover-board-thickness, 6px);
    transform-origin: left center;
    transform: rotateY(-90deg);
    background: linear-gradient(to bottom,
        color-mix(in srgb, var(--book-cover-dark) 85%, var(--book-cover-leather)),
        color-mix(in srgb, var(--book-cover-leather) 70%, black) 30%,
        color-mix(in srgb, var(--book-cover-leather) 80%, black) 50%,
        color-mix(in srgb, var(--book-cover-leather) 70%, black) 70%,
        color-mix(in srgb, var(--book-cover-dark) 85%, var(--book-cover-leather)));
    border-radius: 4px 0 0 4px;
    box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3),
                1px 0 2px rgba(0, 0, 0, 0.15);
}

/* Fore edge (right) — visible at extreme rotation angles */
.book-3d-back-cover-edge--fore {
    top: -1px;
    bottom: -1px;
    right: 0;
    width: var(--book-cover-board-thickness, 6px);
    transform-origin: right center;
    transform: rotateY(90deg);
    background: linear-gradient(to bottom,
        var(--book-cover-dark),
        color-mix(in srgb, var(--book-cover-leather) 60%, black) 50%,
        var(--book-cover-dark));
    border-radius: 0 8px 8px 0;
    box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3),
                -1px 0 2px rgba(0, 0, 0, 0.15);
}

/* Head edge (top) — extends full width to seal corner gaps.
   Overlaps with fore edge at the corner — same dark color prevents Z-fighting artifacts. */
.book-3d-back-cover-edge--head {
    top: 0;
    left: -2px;
    right: -2px;
    height: var(--book-cover-board-thickness, 6px);
    transform-origin: top center;
    transform: rotateX(90deg);
    background: var(--book-cover-dark);
    border-radius: 4px 8px 0 0;
    box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.25),
                0 1px 2px rgba(0, 0, 0, 0.15);
}

/* Tail edge (bottom) — extends full width to seal corner gaps. */
.book-3d-back-cover-edge--tail {
    bottom: 0;
    left: -2px;
    right: -2px;
    height: var(--book-cover-board-thickness, 6px);
    transform-origin: bottom center;
    transform: rotateX(-90deg);
    background: var(--book-cover-dark);
    border-radius: 0 0 8px 4px;
    box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.25),
                0 -1px 2px rgba(0, 0, 0, 0.15);
}

/* Back cover edge strips at .book-frame level — separate purpose (open-state spread borders).
   Same geometry as front cover edges.
   Children of .book-3d-back-cover (which has the overhang insets),
   so they use inset: 0 relative to their parent. No translateZ offset —
   edges rotate from their anchor edges just like the front cover. */
.book-3d-back-edge {
    position: absolute;
    pointer-events: none;
}

.book-3d-back-edge--spine {
    top: 0;
    bottom: 0;
    left: 0;
    width: var(--book-cover-board-thickness, 6px);
    transform-origin: left center;
    transform: rotateY(-90deg);
    background: linear-gradient(to bottom,
        color-mix(in srgb, var(--book-cover-dark) 85%, var(--book-cover-leather)),
        color-mix(in srgb, var(--book-cover-leather) 70%, black) 30%,
        color-mix(in srgb, var(--book-cover-leather) 80%, black) 50%,
        color-mix(in srgb, var(--book-cover-leather) 70%, black) 70%,
        color-mix(in srgb, var(--book-cover-dark) 85%, var(--book-cover-leather)));
    border-radius: 4px 0 0 4px;
    box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3),
                1px 0 2px rgba(0, 0, 0, 0.15);
}

.book-3d-back-edge--fore {
    top: 0;
    bottom: 0;
    right: 0;
    width: var(--book-cover-board-thickness, 6px);
    transform-origin: right center;
    transform: rotateY(90deg);
    background: linear-gradient(to bottom,
        var(--book-cover-dark),
        color-mix(in srgb, var(--book-cover-leather) 60%, black) 50%,
        var(--book-cover-dark));
    border-radius: 0 8px 8px 0;
    box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3),
                -1px 0 2px rgba(0, 0, 0, 0.15);
}

.book-3d-back-edge--head {
    top: 0;
    left: var(--book-cover-board-thickness, 6px);
    right: var(--book-cover-board-thickness, 6px);
    height: var(--book-cover-board-thickness, 6px);
    transform-origin: top center;
    transform: rotateX(90deg);
    background: var(--book-cover-dark);
    border-radius: 4px 8px 0 0;
    box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.25),
                0 1px 2px rgba(0, 0, 0, 0.15);
}

.book-3d-back-edge--tail {
    bottom: 0;
    left: var(--book-cover-board-thickness, 6px);
    right: var(--book-cover-board-thickness, 6px);
    height: var(--book-cover-board-thickness, 6px);
    transform-origin: bottom center;
    transform: rotateX(-90deg);
    background: var(--book-cover-dark);
    border-radius: 0 0 8px 4px;
    box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.25),
                0 -1px 2px rgba(0, 0, 0, 0.15);
}

/* ── Page Layers — stacked along the Z-axis ── */
/* 12 layers between Z=0 (back) and Z≈page-depth (front).
   Slightly inset on 3 sides (top, right, bottom) for cover "squares" overhang.
   Spine side (left) is flush with covers — no overhang at spine. */
.book-3d-page {
    position: absolute;
    top: var(--book-page-inset-top);
    left: 0;
    right: var(--book-page-inset-right);
    bottom: var(--book-page-inset-bottom);
    border-radius: 1px 5px 5px 1px;
    background-color: var(--book-page-color-1);
    transform:
        translateX(var(--book-pages-extra-tx))
        translateY(var(--book-pages-extra-ty))
        translateZ(calc(var(--book-closed-page-depth) * var(--layer-i) / var(--book-3d-layer-total) + var(--book-pages-extra-tz)))
        rotateX(var(--book-pages-extra-rx))
        rotateY(var(--book-pages-extra-ry))
        rotateZ(var(--book-pages-extra-rz));
}

.book-3d-page--alt {
    background-color: var(--book-page-color-2);
}

/* ── Fore Edge (right wall) — page stack visible on right side ── */
/* Rotated 90° around its right edge to form a perpendicular wall.
   The browser's perspective foreshortens it naturally. */
.book-3d-edge-right {
    position: absolute;
    top: -1px;
    bottom: -1px;
    right: 0;
    /* Full book depth: page-depth + back cover board + front cover buffer.
       Spans from the back cover's outward face (Z=-board-thickness) to the
       front cover's resting position (Z=page-depth+2px). */
    width: calc(var(--book-closed-page-depth) + var(--book-cover-board-thickness) + 2px);
    background:
        repeating-linear-gradient(to bottom,
            var(--book-page-color-1) 0px, var(--book-page-color-1) var(--book-edge-line-width),
            var(--book-page-color-2) var(--book-edge-line-width), var(--book-page-color-2) calc(var(--book-edge-line-width) + var(--book-edge-line-gap)),
            var(--book-page-color-1) calc(var(--book-edge-line-width) + var(--book-edge-line-gap)), var(--book-page-color-1) calc(2 * var(--book-edge-line-width) + var(--book-edge-line-gap) + 0.5px)),
        linear-gradient(to right, var(--book-page-color-2), var(--book-page-color-1) 50%, var(--book-page-color-2));
    border-radius: 0; /* Sharp corners — eliminates gaps at edge junctions (fore↔head, fore↔tail) */
    box-shadow:
        inset -3px 0 8px rgba(0, 0, 0, 0.1),
        inset 0 0 6px rgba(0, 0, 0, 0.04);
    transform-origin: right center;
    /* Z shift backward by board-thickness so the wall starts at the back cover's
       outward face, spanning the full book depth to the front cover. */
    transform:
        translateX(var(--book-edge-right-extra-tx))
        translateY(var(--book-edge-right-extra-ty))
        translateZ(calc(-1 * var(--book-cover-board-thickness) + var(--book-edge-right-extra-tz)))
        rotateX(var(--book-edge-right-extra-rx))
        rotateY(calc(90deg + var(--book-edge-right-extra-ry)))
        rotateZ(var(--book-edge-right-extra-rz));
}

/* ── Tail Edge (bottom wall) — page stack visible at the bottom ── */
.book-3d-edge-bottom {
    position: absolute;
    left: -1px;
    right: 0;
    bottom: 0;
    height: calc(var(--book-closed-page-depth) + var(--book-cover-board-thickness) + 2px);
    background:
        repeating-linear-gradient(to right,
            var(--book-page-color-1) 0px, var(--book-page-color-1) var(--book-edge-line-width),
            var(--book-page-color-2) var(--book-edge-line-width), var(--book-page-color-2) calc(var(--book-edge-line-width) + var(--book-edge-line-gap)),
            var(--book-page-color-1) calc(var(--book-edge-line-width) + var(--book-edge-line-gap)), var(--book-page-color-1) calc(2 * var(--book-edge-line-width) + var(--book-edge-line-gap) + 0.5px)),
        linear-gradient(to bottom, var(--book-page-color-2), var(--book-page-color-1) 50%, var(--book-page-color-2));
    border-radius: 0; /* Sharp corners — eliminates gaps at edge junctions */
    box-shadow:
        inset 0 -3px 8px rgba(0, 0, 0, 0.1),
        inset 0 0 6px rgba(0, 0, 0, 0.04);
    transform-origin: bottom center;
    transform:
        translateX(var(--book-edge-bottom-extra-tx))
        translateY(var(--book-edge-bottom-extra-ty))
        translateZ(calc(-1 * var(--book-cover-board-thickness) + var(--book-edge-bottom-extra-tz)))
        rotateX(calc(-90deg + var(--book-edge-bottom-extra-rx)))
        rotateY(var(--book-edge-bottom-extra-ry))
        rotateZ(var(--book-edge-bottom-extra-rz));
}

/* ── Head Edge (top wall) — page stack visible at the top ── */
/* Mirror of bottom edge. Visible when rotateX is negative (looking up at the book).
   Anchored at top edge, rotates forward via rotateX(90deg). */
.book-3d-edge-top {
    position: absolute;
    left: -1px;
    right: 0;
    top: 0;
    height: calc(var(--book-closed-page-depth) + var(--book-cover-board-thickness) + 2px);
    background:
        repeating-linear-gradient(to right,
            var(--book-page-color-1) 0px, var(--book-page-color-1) var(--book-edge-line-width),
            var(--book-page-color-2) var(--book-edge-line-width), var(--book-page-color-2) calc(var(--book-edge-line-width) + var(--book-edge-line-gap)),
            var(--book-page-color-1) calc(var(--book-edge-line-width) + var(--book-edge-line-gap)), var(--book-page-color-1) calc(2 * var(--book-edge-line-width) + var(--book-edge-line-gap) + 0.5px)),
        linear-gradient(to top, var(--book-page-color-2), var(--book-page-color-1) 50%, var(--book-page-color-2));
    border-radius: 0; /* Sharp corners — eliminates gaps at edge junctions */
    box-shadow:
        inset 0 3px 8px rgba(0, 0, 0, 0.1),
        inset 0 0 6px rgba(0, 0, 0, 0.04);
    transform-origin: top center;
    transform:
        translateX(var(--book-edge-top-extra-tx))
        translateY(var(--book-edge-top-extra-ty))
        translateZ(calc(-1 * var(--book-cover-board-thickness) + var(--book-edge-top-extra-tz)))
        rotateX(calc(90deg + var(--book-edge-top-extra-rx)))
        rotateY(var(--book-edge-top-extra-ry))
        rotateZ(var(--book-edge-top-extra-rz));
}

/* .book-3d-spine — leather spine wall, positioned below */

/* ── Spine — true 3D perpendicular left wall connecting front and back covers ── */
/* Uses rotateY(-90deg) to create a real perpendicular surface, mirroring the
   technique used by .book-3d-edge-right on the opposite side.
   Width = page-depth so the wall spans exactly from Z=0 (back cover) to
   Z=page-depth (front cover). The browser's perspective foreshortens it
   naturally — no skew hacks needed.
   The "to right" gradient maps from front cover (viewer-facing) to back cover. */

.book-3d-spine {
    position: absolute;
    /* The spine is the LEFT WALL of the book's rectangular box.
       It is ONE continuous cover surface: back cover → spine → front cover,
       folded around the page block.

       Geometry: the spine is positioned at the left edge of the page block,
       rotated perpendicular via rotateY(-90deg).
       transform-origin: right center anchors the RIGHT edge of the spine
       at X=0 (the covers' left edge). After rotation:
         - Right edge (origin) stays at X=0, Z=0 → back cover's left edge
         - Left edge rotates to X=0, Z=page-depth → front cover's left edge

       Width = full book depth (page-depth + 2×board-thickness + 2px buffer) so
       the spine spans from the back cover's outward face to the front cover's
       outward face. Visibility comes from the parent book-frame's rotateY(-18deg). */
    right: 100%;
    top: calc(-1 * var(--book-spine-overhang-top) + var(--book-spine-offset-y));
    bottom: calc(-1 * var(--book-spine-overhang-bottom) - var(--book-spine-offset-y));
    /* Full book depth — spans from Z=-board-thickness (back cover outer face) to
       Z=page-depth+board-thickness+2 (front cover outer face). Two board-thicknesses
       are needed: one for the back cover board and one for the front cover board.
       Using --book-closed-page-depth directly instead of --book-spine-thickness
       prevents width mismatch if spine-thickness is independently overridden in the DB. */
    width: calc(var(--book-closed-page-depth) + 2 * var(--book-cover-board-thickness) + 2px);
    transform-origin: right center;
    /* CRITICAL: preserve-3d so the headcap/tailcap children can fold perpendicular
       to the spine face via rotateX. Without this, their 90deg rotation is projected
       flat (zero height = invisible). */
    transform-style: preserve-3d;
    /* Z shift backward by board-thickness so the spine's right edge (hinge) aligns
       with the back cover's outward face. rotateY(+90deg) then extends the spine's
       width into positive Z, spanning from Z=-bt to Z=page-depth+bt+2 (front cover
       outer face). */
    transform:
        translateX(calc(var(--book-spine-offset-x) + var(--book-spine-extra-tx)))
        translateY(var(--book-spine-extra-ty))
        translateZ(calc(-1 * var(--book-cover-board-thickness) + var(--book-spine-extra-tz)))
        rotateX(var(--book-spine-extra-rx))
        rotateY(calc(90deg + var(--book-spine-extra-ry)))
        rotateZ(var(--book-spine-extra-rz));
    background:
        /* Layer 1: Procedural leather grain — matches cover ::before technique.
           Tiny conic-gradient noise creates organic leather texture. */
        repeating-conic-gradient(
            rgba(0,0,0,0.025) 0% 25%, transparent 0% 50%
        ) 0 0 / 4px 4px,
        repeating-conic-gradient(
            rgba(255,255,255,0.015) 0% 25%, transparent 0% 50%
        ) 2px 2px / 4px 4px,
        /* Layer 2: Radial wear highlights — aged leather look (from covers).
           Subtle light/dark patches simulate natural leather aging. */
        radial-gradient(ellipse at 30% 20%, rgba(255,255,255,0.05) 0%, transparent 50%),
        radial-gradient(ellipse at 70% 80%, rgba(0,0,0,0.08) 0%, transparent 50%),
        /* Layer 3: Gold tooling lines — decorative gold borders near top/bottom.
           Enhanced opacity (0.4) matches cover frame gold weight. */
        linear-gradient(to bottom,
            transparent 6.5%,
            rgba(212, 175, 55, 0.4) 7%,
            rgba(212, 175, 55, 0.4) 7.8%,
            transparent 8.3%,
            transparent 91.7%,
            rgba(212, 175, 55, 0.4) 92.2%,
            rgba(212, 175, 55, 0.4) 93%,
            transparent 93.5%),
        /* Layer 4: Headcap/tailcap leather reflections — warm leather glow at extremities */
        radial-gradient(circle farthest-corner at 50% -3%, color-mix(in srgb, var(--book-cover-leather) 65%, white) 3%, transparent 10%),
        radial-gradient(circle farthest-corner at 50% 103%, color-mix(in srgb, var(--book-cover-leather) 75%, white) 3%, transparent 10%),
        /* Layer 5: Horizontal ridges — stitching pattern */
        repeating-linear-gradient(to bottom,
            transparent 0px, transparent calc(var(--book-spine-ridge-spacing) * 0.45),
            rgba(0,0,0,var(--book-spine-ridge-opacity)) calc(var(--book-spine-ridge-spacing) * 0.45), rgba(0,0,0,var(--book-spine-ridge-opacity)) calc(var(--book-spine-ridge-spacing) * 0.5),
            rgba(255,255,255,calc(var(--book-spine-ridge-opacity) * 0.6)) calc(var(--book-spine-ridge-spacing) * 0.5), rgba(255,255,255,calc(var(--book-spine-ridge-opacity) * 0.6)) calc(var(--book-spine-ridge-spacing) * 0.55),
            transparent calc(var(--book-spine-ridge-spacing) * 0.55), transparent var(--book-spine-ridge-spacing)),
        /* Layer 6: Enhanced convex leather gradient — smooth curve shading.
           "to right" maps from front cover (viewer) to back cover (desk).
           Wider highlight band and softer transitions than previous version. */
        linear-gradient(to right,
            var(--book-cover-dark) 0%,
            color-mix(in srgb, var(--book-cover-leather) 75%, black) 6%,
            color-mix(in srgb, var(--book-cover-leather) 88%, white) 14%,
            var(--book-cover-leather) 22%,
            color-mix(in srgb, var(--book-cover-leather) var(--book-spine-highlight), white) 35%,
            color-mix(in srgb, var(--book-cover-leather) var(--book-spine-highlight), white) 50%,
            color-mix(in srgb, var(--book-cover-leather) var(--book-spine-highlight), white) 65%,
            var(--book-cover-leather) 78%,
            color-mix(in srgb, var(--book-cover-leather) 88%, white) 86%,
            color-mix(in srgb, var(--book-cover-leather) 75%, black) 94%,
            var(--book-cover-dark) 100%);
    background-size: 4px 4px, 4px 4px, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 100%;
    border-radius: 3px 0 0 3px;
    /* Spine-cover junction — shadow-based groove replaces hard border line.
       Creates a natural leather crease at the spine-cover meeting point. */
    border-right: none;
    box-shadow:
        /* Leather recess vignette — matches cover treatment */
        inset 0 0 20px rgba(0, 0, 0, 0.20),
        /* Beveled light catch — top/left edge highlight (cover technique) */
        inset 1px 1px 0 rgba(255, 255, 255, 0.08),
        /* Beveled shadow — bottom/right edge depth (cover technique) */
        inset -1px -1px 0 rgba(0, 0, 0, 0.12),
        /* Hinge groove shadow — replaces border-right for softer junction */
        3px 0 4px -2px rgba(0, 0, 0, 0.25),
        /* External depth shadow */
        0 1px 4px rgba(0, 0, 0, 0.15);
}

/* Gold decorative bands on spine — upgraded to 5-stop metallic gradient
   matching the gold corner clips for consistent premium metallic sheen. */
.book-3d-spine-band {
    position: absolute;
    left: 8%;
    right: 8%;
    height: calc(var(--book-spine-band-width) + 1px);
    background: linear-gradient(to right,
        transparent 0%,
        #BF953F 8%,
        #FCF6BA 30%,
        #B38728 50%,
        #FBF5B7 70%,
        #AA771C 92%,
        transparent 100%);
    opacity: var(--book-spine-band-opacity);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3),
                0 -1px 1px rgba(255, 255, 255, 0.08),
                0 0 6px rgba(212, 175, 55, calc(var(--book-spine-band-opacity) * 0.4));
    pointer-events: none;
    border-radius: 0.5px;
}

.book-3d-spine-band--top { top: 12%; }
.book-3d-spine-band--mid { top: 50%; transform: translateY(-50%); }
.book-3d-spine-band--bottom { bottom: 12%; }

/* ── Spine fill panel — back wall providing 3D board thickness ──
   Creates visible depth from oblique angles. With barrel strips hidden,
   this provides the spine's inner surface at Z=-board-thickness.
   Enhanced with leather gradient to blend seamlessly with spine face. */
.book-3d-spine::before {
    content: '';
    position: absolute;
    inset: 0;
    background:
        /* Leather grain noise — matches cover grain technique */
        repeating-conic-gradient(
            rgba(0,0,0,0.02) 0% 25%, transparent 0% 50%
        ) 0 0 / 4px 4px,
        /* Darkened leather base — back wall receives less light */
        linear-gradient(to right,
            color-mix(in srgb, var(--book-cover-dark) 90%, black) 0%,
            color-mix(in srgb, var(--book-cover-leather) 60%, black) 30%,
            color-mix(in srgb, var(--book-cover-leather) 65%, black) 50%,
            color-mix(in srgb, var(--book-cover-leather) 60%, black) 70%,
            color-mix(in srgb, var(--book-cover-dark) 90%, black) 100%);
    transform: translateZ(var(--book-cover-board-thickness));
    border-radius: 3px 0 0 3px;
    pointer-events: none;
    box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.25);
}

/* ── Spine headcap & tailcap — perpendicular surfaces at top/bottom ──
   Give the spine visible 3D board thickness, matching cover board edges.
   On a real hardcover book, headbands are decorative woven fabric strips
   visible at the top and bottom of the spine. These caps create that
   visual depth and connect the spine to the cover edges. */
.book-3d-spine-cap {
    position: absolute;
    left: 0;
    right: 0;
    height: 3px; /* Thin decorative headband strip — was calc(board-thickness + 1px) (~7-13px)
                     which created chunky rectangular protrusions visible from oblique angles */
    pointer-events: none;
    border-radius: 1px;
    /* Headband appearance — multi-color woven gradient simulating
       the decorative fabric headbands at top/bottom of premium spines.
       Alternating thread colors (leather dark, gold, cream) create
       the traditional bookbinding detail visible on fine leather books. */
    background:
        /* Woven thread pattern — alternating colored stripes */
        repeating-linear-gradient(to right,
            color-mix(in srgb, var(--book-cover-leather) 60%, black) 0px,
            color-mix(in srgb, var(--book-cover-leather) 60%, black) 2px,
            rgba(212, 175, 55, 0.5) 2px,
            rgba(212, 175, 55, 0.5) 3.5px,
            color-mix(in srgb, var(--book-cover-leather) 85%, white) 3.5px,
            color-mix(in srgb, var(--book-cover-leather) 85%, white) 5px,
            rgba(212, 175, 55, 0.4) 5px,
            rgba(212, 175, 55, 0.4) 6.5px),
        /* Base: dark leather matching cover edges */
        linear-gradient(to right,
            var(--book-cover-dark) 0%,
            color-mix(in srgb, var(--book-cover-leather) 65%, black) 15%,
            color-mix(in srgb, var(--book-cover-leather) 75%, black) 50%,
            color-mix(in srgb, var(--book-cover-leather) 65%, black) 85%,
            var(--book-cover-dark) 100%);
    box-shadow:
        inset 0 0 3px rgba(0, 0, 0, 0.35),
        0 0 2px rgba(212, 175, 55, 0.15);
}

.book-3d-spine-cap--head {
    top: 0;
    transform-origin: top center;
    transform: rotateX(90deg);
    /* Gold headband border — thin decorative bookbinding detail */
    border-bottom: 1px solid rgba(212, 175, 55, 0.5);
}

.book-3d-spine-cap--tail {
    bottom: 0;
    transform-origin: bottom center;
    transform: rotateX(-90deg);
    /* Gold headband border on tail cap */
    border-top: 1px solid rgba(212, 175, 55, 0.5);
}

/* ── 3D Gold corner clips — true 3D metallic corner protectors ────────
   Premium bookbinding detail: L-shaped gold brackets that wrap around
   the fore-edge corners of both covers with 3 surfaces each (face +
   head/tail wrap + fore wrap). Only on the opening side — spine-side
   corners are structurally sealed by the binding and spine caps.
   Each clip is a preserve-3d container with 4 child surfaces
   (face, inner corner wrap, head/tail wrap, fore wrap). */

.book-3d-clip {
    position: absolute;
    --clip-size: clamp(20px, 3vw, 30px);
    --clip-bar: 4px;
    transform-style: preserve-3d;
    pointer-events: none;
}

/* Face piece — L-shaped gold bracket on the cover surface */
.book-3d-clip__face {
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg,
        #BF953F 0%, #FCF6BA 25%, #B38728 50%, #FBF5B7 75%, #AA771C 100%);
    box-shadow: 0 0 4px rgba(212, 175, 55, 0.3);
}

/* Inner corner wrap — diagonal gold triangle filling the L-corner on the cover face.
   Simulates the triangular gold patch visible on real book corner protectors
   where the two L-bars meet at the corner. */
.book-3d-clip__wrap-inner {
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg,
        #BF953F 0%, #FCF6BA 30%, #B38728 60%, #FBF5B7 85%, #AA771C 100%);
    box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.15);
}

/* Horizontal edge wrap — folds around the head or tail edge */
.book-3d-clip__wrap-h {
    position: absolute;
    left: 0;
    right: 0;
    height: calc(var(--book-cover-board-thickness, 6px) + 1px);
    background: linear-gradient(90deg,
        #AA771C 0%, #B38728 20%, #FCF6BA 50%, #B38728 80%, #AA771C 100%);
    box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.2);
}

/* Vertical edge wrap — folds around the fore edge */
.book-3d-clip__wrap-v {
    position: absolute;
    top: 0;
    bottom: 0;
    width: calc(var(--book-cover-board-thickness, 6px) + 1px);
    background: linear-gradient(180deg,
        #AA771C 0%, #B38728 20%, #FCF6BA 50%, #B38728 80%, #AA771C 100%);
    box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.2);
}

/* ── Top-right clip ── */
.book-3d-clip--tr {
    top: -1px;
    right: -1px;
    width: var(--clip-size);
    height: var(--clip-size);
}

/* L-shape: horizontal bar along top + vertical bar along right */
.book-3d-clip--tr .book-3d-clip__face {
    clip-path: polygon(
        100% 0%, 0% 0%, 0% var(--clip-bar),
        calc(100% - var(--clip-bar)) var(--clip-bar),
        calc(100% - var(--clip-bar)) 100%, 100% 100%
    );
}

/* Diagonal triangle at inner L-corner — covers the top-right cover face corner */
.book-3d-clip--tr .book-3d-clip__wrap-inner {
    clip-path: polygon(
        calc(100% - var(--clip-bar) * 4) var(--clip-bar),
        calc(100% - var(--clip-bar)) var(--clip-bar),
        calc(100% - var(--clip-bar)) calc(var(--clip-bar) * 4)
    );
}

.book-3d-clip--tr .book-3d-clip__wrap-h {
    top: 0;
    transform-origin: top center;
    transform: rotateX(90deg);
}

.book-3d-clip--tr .book-3d-clip__wrap-v {
    right: 0;
    transform-origin: right center;
    transform: rotateY(90deg);
}

/* ── Bottom-right clip (mirrored L) ── */
.book-3d-clip--br {
    bottom: -1px;
    right: -1px;
    width: var(--clip-size);
    height: var(--clip-size);
}

/* L-shape: horizontal bar along bottom + vertical bar along right */
.book-3d-clip--br .book-3d-clip__face {
    clip-path: polygon(
        100% 100%, 0% 100%, 0% calc(100% - var(--clip-bar)),
        calc(100% - var(--clip-bar)) calc(100% - var(--clip-bar)),
        calc(100% - var(--clip-bar)) 0%, 100% 0%
    );
}

/* Diagonal triangle at inner L-corner — covers the bottom-right cover face corner */
.book-3d-clip--br .book-3d-clip__wrap-inner {
    clip-path: polygon(
        calc(100% - var(--clip-bar) * 4) calc(100% - var(--clip-bar)),
        calc(100% - var(--clip-bar)) calc(100% - var(--clip-bar)),
        calc(100% - var(--clip-bar)) calc(100% - var(--clip-bar) * 4)
    );
}

.book-3d-clip--br .book-3d-clip__wrap-h {
    bottom: 0;
    transform-origin: bottom center;
    transform: rotateX(-90deg);
}

.book-3d-clip--br .book-3d-clip__wrap-v {
    right: 0;
    transform-origin: right center;
    transform: rotateY(90deg);
}

/* ── Top-left clip (mirrored from TR) ── */
.book-3d-clip--tl {
    top: -1px;
    left: -1px;
    width: var(--clip-size);
    height: var(--clip-size);
}

/* L-shape: horizontal bar along top + vertical bar along left */
.book-3d-clip--tl .book-3d-clip__face {
    clip-path: polygon(
        0% 0%, 100% 0%, 100% var(--clip-bar),
        var(--clip-bar) var(--clip-bar),
        var(--clip-bar) 100%, 0% 100%
    );
}

/* Diagonal triangle at inner L-corner */
.book-3d-clip--tl .book-3d-clip__wrap-inner {
    clip-path: polygon(
        calc(var(--clip-bar) * 4) var(--clip-bar),
        var(--clip-bar) var(--clip-bar),
        var(--clip-bar) calc(var(--clip-bar) * 4)
    );
}

.book-3d-clip--tl .book-3d-clip__wrap-h {
    top: 0;
    transform-origin: top center;
    transform: rotateX(90deg);
}

.book-3d-clip--tl .book-3d-clip__wrap-v {
    left: 0;
    transform-origin: left center;
    transform: rotateY(-90deg);
}

/* ── Bottom-left clip (mirrored from BR) ── */
.book-3d-clip--bl {
    bottom: -1px;
    left: -1px;
    width: var(--clip-size);
    height: var(--clip-size);
}

/* L-shape: horizontal bar along bottom + vertical bar along left */
.book-3d-clip--bl .book-3d-clip__face {
    clip-path: polygon(
        0% 100%, 100% 100%, 100% calc(100% - var(--clip-bar)),
        var(--clip-bar) calc(100% - var(--clip-bar)),
        var(--clip-bar) 0%, 0% 0%
    );
}

/* Diagonal triangle at inner L-corner */
.book-3d-clip--bl .book-3d-clip__wrap-inner {
    clip-path: polygon(
        calc(var(--clip-bar) * 4) calc(100% - var(--clip-bar)),
        var(--clip-bar) calc(100% - var(--clip-bar)),
        var(--clip-bar) calc(100% - var(--clip-bar) * 4)
    );
}

.book-3d-clip--bl .book-3d-clip__wrap-h {
    bottom: 0;
    transform-origin: bottom center;
    transform: rotateX(-90deg);
}

.book-3d-clip--bl .book-3d-clip__wrap-v {
    left: 0;
    transform-origin: left center;
    transform: rotateY(-90deg);
}

/* Front cover clip wraps — fold directions differ from back cover.
   The front cover face sits at translateZ(+board-thickness). Wraps must
   be visible from the spine/edge viewing angle.
   Right-side wraps (TR, BR): Override to rotateY(-90deg) — folds into
     the board thickness (-Z) so they're visible from the fore-edge.
   Left-side wraps (TL, BL): Override to rotateY(90deg) — faces the spine
     direction (+Z to -X) so they're visible from the spine viewing angle.
     backface-visibility: visible ensures they render from all orbit angles.
   Horizontal wraps (wrap-h): Flipped rotateX direction vs base since
     the front face is on the opposite side of the board from the back face. */
.book-cover-page .book-3d-clip--tr .book-3d-clip__wrap-h {
    transform: rotateX(-90deg);
}
.book-cover-page .book-3d-clip--tr .book-3d-clip__wrap-v {
    transform: rotateY(-90deg);
}
.book-cover-page .book-3d-clip--br .book-3d-clip__wrap-h {
    transform: rotateX(90deg);
}
.book-cover-page .book-3d-clip--br .book-3d-clip__wrap-v {
    transform: rotateY(-90deg);
}
.book-cover-page .book-3d-clip--tl .book-3d-clip__wrap-h {
    transform: rotateX(-90deg);
}
.book-cover-page .book-3d-clip--tl .book-3d-clip__wrap-v {
    transform: rotateY(90deg);
    backface-visibility: visible;
    -webkit-backface-visibility: visible;
}
.book-cover-page .book-3d-clip--bl .book-3d-clip__wrap-h {
    transform: rotateX(90deg);
}
.book-cover-page .book-3d-clip--bl .book-3d-clip__wrap-v {
    transform: rotateY(90deg);
    backface-visibility: visible;
    -webkit-backface-visibility: visible;
}

/* ═══════════════════════════════════════════════════════════════
   Phase 2: Fantasy Book Enhancements
   ═══════════════════════════════════════════════════════════════ */

/* ── 2.1 Curved Spine Strips ──────────────────────────────────── */
/* 7 strips at progressive rotateY angles create a smooth barrel/cylinder.
   Each strip is ~14.3% of the spine width with 1.5px overlap to eliminate seams.
   They rotate around their own center relative to the parent spine's
   coordinate system, fanning outward to approximate a curved surface.
   The parent .book-3d-spine provides the base rotateY(-90deg) — strips
   add small offsets on top of that.
   --book-spine-curvature controls total arc spread (default 20deg). */

/* ── Spine 3D box edge walls ─────────────────────────────────────
   Repurposed barrel strips 0-2 as perpendicular connecting walls between the
   spine's outer face (Z=0) and inner fill panel (Z=+board-thickness).
   Matches the back cover edge strip pattern for a sealed 3D box.
   Strips 3-6 remain hidden (unused). */

.book-3d-spine-strip {
    display: none;
}

/* Strip 0 → Head (top) connecting wall — seals the top of the spine box.
   Folds perpendicular from the top edge, spanning Z=0 to Z=+board-thickness. */
.book-3d-spine-strip[style*="--strip-i: 0"] {
    display: block;
    position: absolute;
    top: 0;
    left: -1px;
    right: -1px;
    height: var(--book-cover-board-thickness, 6px);
    width: auto;
    filter: none;
    transform-origin: top center;
    transform: rotateX(90deg);
    background: var(--book-cover-dark);
    border-radius: 3px 0 0 0;
    box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.25),
                0 1px 2px rgba(0, 0, 0, 0.15);
    pointer-events: none;
}

/* Strip 1 → Tail (bottom) connecting wall — seals the bottom of the spine box. */
.book-3d-spine-strip[style*="--strip-i: 1"] {
    display: block;
    position: absolute;
    bottom: 0;
    left: -1px;
    right: -1px;
    height: var(--book-cover-board-thickness, 6px);
    width: auto;
    filter: none;
    transform-origin: bottom center;
    transform: rotateX(-90deg);
    background: var(--book-cover-dark);
    border-radius: 0 0 0 3px;
    box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.25),
                0 -1px 2px rgba(0, 0, 0, 0.15);
    pointer-events: none;
}

/* Strip 2 → Left (outer binding) connecting wall — the visible rounded spine edge.
   Folds perpendicular from the left edge, spanning Z=0 to Z=+board-thickness. */
.book-3d-spine-strip[style*="--strip-i: 2"] {
    display: block;
    position: absolute;
    left: 0;
    top: -1px;
    bottom: -1px;
    width: var(--book-cover-board-thickness, 6px);
    height: auto;
    filter: none;
    transform-origin: left center;
    transform: rotateY(-90deg);
    background: linear-gradient(to bottom,
        color-mix(in srgb, var(--book-cover-dark) 85%, var(--book-cover-leather)),
        color-mix(in srgb, var(--book-cover-leather) 70%, black) 30%,
        color-mix(in srgb, var(--book-cover-leather) 80%, black) 50%,
        color-mix(in srgb, var(--book-cover-leather) 70%, black) 70%,
        color-mix(in srgb, var(--book-cover-dark) 85%, var(--book-cover-leather)));
    border-radius: 3px 0 0 3px;
    box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.3),
                1px 0 2px rgba(0, 0, 0, 0.15);
    pointer-events: none;
}

/* ── 2.2 Leather Texture on Covers ────────────────────────────── */
/* Noise-based leather grain overlay on front and back covers.
   Uses repeating-conic-gradient for a procedural grain pattern
   with zero external dependencies. Layered under the existing
   vignette via background-blend-mode. */

.book-3d-front-cover::before,
.book-cover-page-front::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background:
        /* Procedural leather grain — tiny conic gradients create noise texture */
        repeating-conic-gradient(
            rgba(0,0,0,0.03) 0% 25%, transparent 0% 50%
        ) 0 0 / 4px 4px,
        repeating-conic-gradient(
            rgba(255,255,255,0.02) 0% 25%, transparent 0% 50%
        ) 2px 2px / 4px 4px,
        /* Corner wear — slightly lighter at corners simulating aged leather */
        radial-gradient(circle at 0% 0%, rgba(255,255,255,0.06) 0%, transparent 25%),
        radial-gradient(circle at 100% 0%, rgba(255,255,255,0.05) 0%, transparent 20%),
        radial-gradient(circle at 0% 100%, rgba(255,255,255,0.05) 0%, transparent 20%),
        radial-gradient(circle at 100% 100%, rgba(255,255,255,0.04) 0%, transparent 18%);
    opacity: var(--book-cover-grain-opacity, 0.15);
    pointer-events: none;
    z-index: 1;
}

/* Back cover face gets leather grain */
/* Grain overlay matching front cover (uses --env-paper-grain, same as .book-cover-page-front::before) */
.book-3d-back-cover-face::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: var(--env-paper-grain);
    background-size: 200px 200px;
    opacity: var(--book-cover-grain-opacity, 0.15);
    pointer-events: none;
    z-index: 1;
}

/* ── 2.2b Gold Foil Text Effect ───────────────────────────────── */
/* Metallic gold gradient applied to cover title text via background-clip.
   Multi-stop gradient simulates the sheen of real gold leaf stamping. */

.book-cover-title-gold {
    background: linear-gradient(135deg,
        #BF953F 0%, #FCF6BA 25%, #B38728 50%, #FBF5B7 75%, #AA771C 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.3));
    text-shadow: none;
    transition: background-size 0.3s ease;
}

/* Hover shimmer — gradient slides left-to-right creating foil shine effect */
.book-cover-title-gold:hover {
    background-size: 200% 100%;
    animation: goldShimmer 1.5s ease-in-out;
}

@keyframes goldShimmer {
    0% { background-position: 200% center; }
    100% { background-position: 0% center; }
}

/* ── 2.3 Page Edge Gilding ────────────────────────────────────── */
/* Gold-tinted gradients on the fore/head/tail edge surfaces.
   Overlays the existing page-line pattern at reduced opacity so individual
   pages are still suggested within the gold. Creates luxury gilded-edge look. */

.book-3d-edge-right,
.book-3d-edge-top,
.book-3d-edge-bottom {
    background:
        /* Page line pattern — kept at reduced opacity over gold base */
        repeating-linear-gradient(to bottom,
            rgba(245,240,230,0.3) 0px, rgba(245,240,230,0.3) var(--book-edge-line-width),
            rgba(236,229,216,0.3) var(--book-edge-line-width), rgba(236,229,216,0.3) calc(var(--book-edge-line-width) + var(--book-edge-line-gap)),
            rgba(245,240,230,0.3) calc(var(--book-edge-line-width) + var(--book-edge-line-gap)), rgba(245,240,230,0.3) calc(2 * var(--book-edge-line-width) + var(--book-edge-line-gap) + 0.5px)),
        /* Gold gilding base — warm metallic gradient */
        linear-gradient(to right,
            var(--book-gold-detail) 0%,
            #f5e6b8 15%,
            var(--book-gold-leaf) 35%,
            #faf0d0 50%,
            var(--book-gold-leaf) 65%,
            #f5e6b8 85%,
            var(--book-gold-detail) 100%);
    box-shadow:
        inset -3px 0 8px rgba(0, 0, 0, 0.08),
        inset 0 0 4px rgba(212, 175, 55, 0.15),
        inset 0 0 1px rgba(255, 255, 255, 0.3);
}

/* ── 2.4 Spine Ridges & Raised Bands ─────────────────────────── */
/* Enhanced raised bands with prominent shadow/highlight pairs creating
   physical bump illusion. Gold bands are wider and more opaque. */

.book-3d-spine-band {
    height: calc(var(--book-spine-band-width) + 1px);
    background:
        /* Shadow below band (depth) */
        linear-gradient(to bottom,
            rgba(0, 0, 0, 0.25) 0%, transparent 35%),
        /* Highlight above band (raised surface catching light) */
        linear-gradient(to bottom,
            transparent 60%, rgba(255, 255, 255, 0.12) 100%),
        /* Gold fill */
        linear-gradient(to right,
            transparent 0%,
            rgba(212, 175, 55, calc(var(--book-spine-band-opacity) * 0.7)) 8%,
            rgba(212, 175, 55, var(--book-spine-band-opacity)) 30%,
            rgba(252, 246, 186, calc(var(--book-spine-band-opacity) * 0.9)) 50%,
            rgba(212, 175, 55, var(--book-spine-band-opacity)) 70%,
            rgba(212, 175, 55, calc(var(--book-spine-band-opacity) * 0.7)) 92%,
            transparent 100%);
    box-shadow:
        0 1px 3px rgba(0, 0, 0, 0.3),
        0 -1px 1px rgba(255, 255, 255, 0.08),
        0 0 6px rgba(212, 175, 55, calc(var(--book-spine-band-opacity) * 0.4));
}

/* ── 2.5 Cover Board Thickness Enhancement ────────────────────── */
/* More prominent board thickness with beveled edge appearance */

.book-3d-front-cover {
    box-shadow:
        inset 0 0 40px rgba(0, 0, 0, var(--book-cover-vignette-intensity, 0.15)),
        /* Board edge bevel — light top/left, dark bottom/right */
        inset 2px 2px 0 rgba(255, 255, 255, 0.08),
        inset -1px -1px 0 rgba(0, 0, 0, 0.12),
        /* Depth shadow */
        0 2px 6px rgba(0, 0, 0, 0.2);
}

.book-3d-back-cover-face {
    box-shadow:
        inset 0 0 30px rgba(0, 0, 0, 0.12),
        inset 1px 1px 0 rgba(255, 255, 255, 0.05),
        inset -1px -1px 0 rgba(0, 0, 0, 0.1);
}

/* ── Left Page Stack — turned-page depth slab ──────────────────── */
/* Represents the stack of turned pages on the left half of the open book.
   Hidden in closed state; appears when book opens. Positioned at a shallow
   Z-depth (30% of open-page-depth) since few pages are initially turned. */
.book-3d-left-stack {
    position: absolute;
    top: var(--book-page-inset-top);
    left: 0;
    right: 50%;
    bottom: var(--book-page-inset-bottom);
    background-color: var(--book-page-color-1);
    opacity: 0;
    pointer-events: none;
    transform: translateZ(0);
    transition: opacity 0.6s ease, transform 0.6s ease;
}

/* ═══════════════════════════════════════════════════════════════
   OPEN-BOOK 3D DEPTH GEOMETRY (Unified 3D)
   Transforms the closed-book depth block into open-book geometry:
   - Page layers compress to right-half depth only (unturned stack)
   - Back cover lies flat underneath the full spread
   - Spine becomes a visible center ridge
   - Edges reposition for the right-side page stack only
   - Left-stack slab appears to represent turned pages
   ═══════════════════════════════════════════════════════════════ */

/* Smooth transitions for all depth children during open/close */
.book-desk-scene--settling .book-3d-depth > *,
.book-desk-scene--book .book-3d-depth > * {
    transition: transform 0.6s ease-out, width 0.6s ease-out,
                height 0.6s ease-out, opacity 0.6s ease-out,
                left 0.6s ease-out, right 0.6s ease-out;
}

/* ── Back Cover: lies flat underneath the full spread ── */
/* Container pushed to Z=-1px. Edge strips stay visible (they provide
   the right-side leather border). Only the face is hidden to prevent
   Z-fighting with the cream viewport plane. */
.book-desk-scene--settling .book-3d-back-cover,
.book-desk-scene--book .book-3d-back-cover {
    transform: translateZ(-1px);
    /* Extend overhang in open state so the leather border is clearly
       visible past the page edges despite perspective foreshortening
       from the depth container push-back (~52px behind viewport). */
    top: calc(-1 * var(--book-cover-overhang-top) - 6px);
    right: calc(-1 * var(--book-cover-overhang-right) - 8px);
    bottom: calc(-1 * var(--book-cover-overhang-bottom) - 6px);
}

/* Back cover face VISIBLE in open state — the 3D back cover provides
   the leather border in the overhang area (extending past the viewport).
   The depth container pushes it to Z ≈ -(open-page-depth - 3px), well
   behind the viewport at Z=0, so no Z-fighting occurs. */
.book-desk-scene--settling .book-3d-back-cover-face,
.book-desk-scene--book .book-3d-back-cover-face,
.book-desk-scene--settling .book-3d-back-cover::before,
.book-desk-scene--book .book-3d-back-cover::before {
    opacity: 1;
}

/* Depth shadow on back cover face in open state — adds visual separation
   between the leather cover edge and the page content above it. */
.book-desk-scene--book .book-3d-back-cover-face {
    box-shadow:
        0 0 12px rgba(0, 0, 0, 0.25),
        inset 0 0 40px rgba(0, 0, 0, 0.15),
        inset 0 0 80px rgba(0, 0, 0, 0.08);
}

/* ── Page Layers: compress to right-half only (unturned stack) ── */
/* Slight rotateY creates "tenting" — pages angle up from the spine like a
   real open book, rather than lying perfectly flat. */
/* Small left offset (1px) prevents the rotateY tenting from projecting
   the page edges past the 50% spine boundary under perspective. */
/* Hidden in open state — the tenting angle's forward Z-projection at the
   left edge (sin(3deg) × halfWidth ≈ 15px) pushes the outermost page layer
   in front of the viewport, causing a visible color strip on the right page.
   The cream viewport background hides the layers underneath, so opacity:0
   eliminates the z-fighting without visual impact. */
.book-desk-scene--settling .book-3d-page,
.book-desk-scene--book .book-3d-page {
    left: calc(50% + 4px);
    right: 0;
    opacity: 0;
    transform:
        translateZ(calc(var(--book-open-page-depth) * var(--layer-i) / var(--book-3d-layer-total) - var(--book-page-tent-clearance, 12px)))
        rotateY(var(--book-open-page-tent, 3deg));
}

/* ── Spine: visible rounded ridge in open state ─────────────────
   Wider than the page depth and with dramatically increased curvature so
   the 5 barrel strips fan out into a visible half-cylinder connecting
   left and right halves — matching how a real hardcover spine rounds
   outward when the book is opened flat. The curvature override cascades
   to the strip children which read --book-spine-curvature for their
   individual rotateY offsets. */
.book-desk-scene--settling .book-3d-spine,
.book-desk-scene--book .book-3d-spine {
    right: 50%;
    width: var(--book-open-spine-width, var(--book-open-page-depth));
    --book-spine-curvature: var(--book-open-spine-curvature, 130deg);
    transform-origin: right center;
    /* Hidden in open state — spine Z-compensation brings it to Z=0, same plane
       as the viewport, causing z-fighting. Invisible since the cream viewport
       background covers it. The gutter shadow provides the visual spine effect. */
    opacity: 0;
    /* Z-COMPENSATION: the parent .book-3d-depth is pushed back by
       -(open-page-depth + 2px) in open states. Prepending the inverse
       translateZ brings the spine forward to Z=0 (same plane as
       .book-frame-right pages) so the curved barrel strips are visible
       as a rounded binding ridge, not hidden behind the page surfaces.
       This translateZ operates in the PARENT's coordinate space (before
       rotateY) so it counteracts the container's push exactly. */
    transform:
        translateZ(calc(var(--book-open-page-depth) + 2px))
        translateX(var(--book-spine-extra-tx))
        translateY(var(--book-spine-extra-ty))
        translateZ(var(--book-spine-extra-tz))
        rotateX(var(--book-spine-extra-rx))
        rotateY(calc(90deg + var(--book-spine-extra-ry)))
        rotateZ(var(--book-spine-extra-rz));
}

/* Spine strips transition smoothly when curvature changes from closed→open */
.book-desk-scene--settling .book-3d-spine-strip,
.book-desk-scene--book .book-3d-spine-strip {
    transition: transform 0.6s ease-out;
}

/* ── Right Edge (fore edge): repositioned for right-half stack ── */
/* Hidden — cream viewport covers them; opacity prevents z-fighting. */
.book-desk-scene--settling .book-3d-edge-right,
.book-desk-scene--book .book-3d-edge-right {
    width: var(--book-open-page-depth);
    opacity: 0;
}

/* ── Top Edge: right-half only ── */
.book-desk-scene--settling .book-3d-edge-top,
.book-desk-scene--book .book-3d-edge-top {
    left: 50%;
    height: var(--book-open-page-depth);
    opacity: 0;
}

/* ── Bottom Edge: right-half only ── */
.book-desk-scene--settling .book-3d-edge-bottom,
.book-desk-scene--book .book-3d-edge-bottom {
    left: 50%;
    height: var(--book-open-page-depth);
    opacity: 0;
}

/* ── Left Stack: turned-page slab appears ── */
/* Reverse tenting on left side — pages angle the opposite way from the spine,
   creating a natural V-shape when viewed from above (like a real open book). */
/* Hidden — same rationale as other depth elements: the viewport's cream
   background covers it, and at Z=0.3*depth it z-fights with the viewport. */
.book-desk-scene--settling .book-3d-left-stack,
.book-desk-scene--book .book-3d-left-stack {
    opacity: 0;
    transform: translateZ(calc(var(--book-open-page-depth) * 0.3))
               rotateY(calc(-1 * var(--book-open-page-tent, 3deg)));
    border-radius: 5px 1px 1px 5px;
    box-shadow: inset 3px 0 8px rgba(0,0,0,0.08);
}

/* ── Opening state: depth children begin transitioning ──
   1.2s delay = 75% through the 1.6s cover swing ≈ cover at -148deg (nearly flat).
   Previous 0.8s delay started at -95deg (barely past perpendicular), causing the
   page stack to visibly slide out before the cover had cleared the way.
   The ease-out timing + 0.8s duration ensures movement completes by ~2.0s. */
:not(.book-desk-scene--play).book-desk-scene--opening .book-frame.book-frame--open .book-3d-depth > * {
    transition: transform 0.8s ease-out 1.2s, width 0.8s ease-out 1.2s,
                height 0.8s ease-out 1.2s, opacity 0.8s ease-out 1.2s,
                left 0.8s ease-out 1.2s, right 0.8s ease-out 1.2s;
}

/* During opening, begin morphing page layers to right-half with tenting */
.book-desk-scene--opening .book-frame.book-frame--open .book-3d-page {
    left: calc(50% + 4px);
    right: 0;
    transform:
        translateZ(calc(var(--book-open-page-depth) * var(--layer-i) / var(--book-3d-layer-total) - var(--book-page-tent-clearance, 12px)))
        rotateY(var(--book-open-page-tent, 3deg));
}

/* Spine begins moving to center during opening — wider, more curved,
   and Z-compensated so it's not hidden behind page surfaces */
.book-desk-scene--opening .book-frame.book-frame--open .book-3d-spine {
    right: 50%;
    width: var(--book-open-spine-width, var(--book-open-page-depth));
    --book-spine-curvature: var(--book-open-spine-curvature, 130deg);
    transform:
        translateZ(calc(var(--book-open-page-depth) + 2px))
        translateX(var(--book-spine-extra-tx))
        translateY(var(--book-spine-extra-ty))
        translateZ(var(--book-spine-extra-tz))
        rotateX(var(--book-spine-extra-rx))
        rotateY(calc(90deg + var(--book-spine-extra-ry)))
        rotateZ(var(--book-spine-extra-rz));
}

/* Spine strips transition with the same delay as other depth children */
.book-desk-scene--opening .book-frame.book-frame--open .book-3d-spine-strip {
    transition: transform 0.8s ease-out 1.2s;
}

/* Edges begin repositioning during opening */
.book-desk-scene--opening .book-frame.book-frame--open .book-3d-edge-right {
    width: var(--book-open-page-depth);
}

.book-desk-scene--opening .book-frame.book-frame--open .book-3d-edge-top,
.book-desk-scene--opening .book-frame.book-frame--open .book-3d-edge-bottom {
    left: 50%;
    height: var(--book-open-page-depth);
}

/* Left stack hidden during ENTIRE Opening phase — even before cover starts
   swinging (.book-frame--open). Covers the initial pause + name reveal gap.
   Uses !important to override transition-driven intermediate values from the
   depth children transition (opacity 1.2s ease-out 0.8s).
   The viewport is background:transparent during Opening, and the depth
   container has no negative translateZ push — so any depth element at Z≥0
   would show through. Belt-and-suspenders: opacity + visibility. */
.book-desk-scene--opening .book-3d-left-stack {
    opacity: 0 !important;
    visibility: hidden !important;
    transform: translateZ(0) !important;
}

/* ═══════════════════════════════════════════════════════════════
   3D CLOSED-BOOK RIBBONS
   Ribbons protruding from the head (top) edge of the closed book.
   Each ribbon is positioned at its page's Z-depth within the stack.
   The head edge and pages above naturally occlude the between-page
   portion of the ribbon via the preserve-3d Z-ordering.
   ═══════════════════════════════════════════════════════════════ */

.book-3d-ribbons {
    position: absolute;
    top: 0;
    left: 0;
    right: var(--book-page-inset-right);
    height: 0;
    transform-style: preserve-3d;
    pointer-events: none;
}

.book-3d-ribbon {
    position: absolute;
    top: 0;
    width: var(--ribbon-width);
    transform-style: preserve-3d;
    /* Position at the page's Z-depth within the stack.
       translateY pushes the ribbon above the head edge. */
    transform:
        translateY(calc(-1 * var(--ribbon-3d-protrude-closed)))
        translateZ(calc(var(--book-closed-page-depth) * var(--ribbon-z-layer) / var(--book-3d-layer-total)));
}

.book-3d-ribbon-body {
    position: relative;
    width: 100%;
    height: var(--ribbon-3d-protrude-closed);
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--ribbon-color) 70%, #1a1a2e) 0%,
        color-mix(in srgb, var(--ribbon-color) 50%, #2c1a0e) 40%,
        color-mix(in srgb, var(--ribbon-color) 40%, #1a1a2e) 100%);
    border-radius: 2px 2px 0 0;
    box-shadow: inset 0 1px 2px rgba(255,255,255,0.08),
                inset 0 -1px 2px rgba(0,0,0,0.15);
    border-left: 0.5px solid rgba(212, 175, 55, 0.15);
    border-right: 0.5px solid rgba(212, 175, 55, 0.15);
    transform: translateZ(calc(var(--ribbon-3d-thickness) / 2));
    overflow: hidden;
}

/* Closed-book ribbon label — horizontal text matching open-book ribbon style */
.book-3d-ribbon-label {
    position: absolute;
    top: 4px;
    left: 50%;
    transform: translateX(-50%);
    font-family: 'Cormorant Garamond', var(--font-heading);
    font-size: clamp(8px, 0.7vw, 11px);
    color: #f0e6d0;
    text-shadow: 0 1px 2px rgba(0,0,0,0.6);
    opacity: 0.75;
    white-space: nowrap;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: 600;
    pointer-events: none;
}

.book-3d-ribbon-tail {
    width: 100%;
    height: var(--ribbon-tail-height);
    background: linear-gradient(180deg,
        var(--ribbon-color) 0%,
        color-mix(in srgb, var(--ribbon-color) 60%, #1a1a2e) 100%);
    border-radius: 0 0 2px 2px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
    transform: translateZ(calc(var(--ribbon-3d-thickness) / 2));
}

/* Closed-book ribbons: visible on closed book states */
.book-desk-scene--cover .book-3d-ribbons,
.book-desk-scene--table .book-3d-ribbons,
.book-desk-scene--pickingup .book-3d-ribbons,
.book-desk-scene--settingdown .book-3d-ribbons {
    opacity: 1;
    transition: opacity 0.3s ease;
}

/* Hide closed-book ribbons when book is open (open-book ribbons take over) */
.book-desk-scene--book .book-3d-ribbons,
.book-desk-scene--settling .book-3d-ribbons {
    opacity: 0;
    transition: opacity 0.3s ease;
}

/* Opening state: closed-book ribbons fade out as book opens.
   0.6s delay + 0.5s duration = complete by 1.1s, just before depth
   children start transitioning at 1.2s. Ribbons disappear while the
   cover is still obscuring the depth geometry. */
:not(.book-desk-scene--play).book-desk-scene--opening .book-3d-ribbons {
    opacity: 0;
    transition: opacity 0.5s ease 0.6s;
}

/* Closing state: closed-book ribbons fade back in */
:not(.book-desk-scene--play).book-desk-scene--closing .book-3d-ribbons {
    opacity: 1;
    transition: opacity 0.5s ease 1.5s;
}

/* ── Opening state: cover swings + frame begins settling ──────────
   UNIFIED ANIMATION: Instead of locking the frame in 3D during the
   entire cover swing, then separately flattening in Settling state,
   the frame now begins settling midway through the page cascade.
   This creates ONE continuous arc: "the open book is created by the
   cover opening" rather than "cover opens, then book flattens."

   When .book-frame--open is added (cover starts swinging), the frame
   holds its 3D angle for 1.76s (55% of 3.2s — through cover swing +
   early flyleaf cascade), then gradually flattens in 3 stages over
   1.44s. By the time C# switches to Settling (~2.8s), the frame is
   ~95% flat — Settling just confirms the final position. */

.book-desk-scene--opening .book-frame {
    transform-style: preserve-3d;
    isolation: auto;
    overflow: visible;
    /* Default: locked in 3D angle (before cover starts swinging) */
    transform:
        rotateX(var(--book-closed-rotate-x))
        rotateY(var(--book-closed-rotate-y))
        rotateZ(var(--book-closed-rotate-z));
    /* Allow width to transition (for 1440px+ spread expansion) while
       transform is handled by the frameOpenSettle animation. */
    transition: width 0.6s cubic-bezier(0.22, 0.68, 0.18, 1);
}

/* When cover starts swinging, begin the unified open-settle animation.
   The .book-frame--open class is added when _isOpened becomes true,
   which coincides with the coverPageOpen animation starting. */
:not(.book-desk-scene--play).book-desk-scene--opening .book-frame.book-frame--open {
    animation: frameOpenSettle 3.2s cubic-bezier(0.22, 0.68, 0.12, 1.02) forwards;
}

/* Unified frame animation: hold 3D → gradual settle to open-book tilt.
   The 3D angle is held for 55% of 3.2s ≈ 1.76s — the book stays in its
   beautiful angled presentation while the cover swings and the first
   flyleaves cascade. The settle happens in 3 graduated stages (55→100%)
   easing from the closed-book angle (~10deg/18deg) to the open-book
   reading angle (~6deg/0deg). The book maintains its 3D physical presence
   throughout — it never flattens to a 2D surface.
   Shadows evolve at each stage to reinforce physical plausibility. */
@keyframes frameOpenSettle {
    /* Hold the 3D hero pose through cover swing + early cascade */
    0%, 55% {
        transform:
            rotateX(var(--book-closed-rotate-x))
            rotateY(var(--book-closed-rotate-y))
            rotateZ(var(--book-closed-rotate-z));
        box-shadow:
            4px 6px 15px rgba(0,0,0,0.20),
            8px 12px 35px rgba(0,0,0,0.15);
    }
    /* Stage 1: Begin easing toward reading angle — camera drifts closer.
       7deg/6deg: Y-axis drops first, X-axis eases gently. */
    72% {
        transform: rotateX(7deg) rotateY(6deg) rotateZ(0deg);
        box-shadow:
            2px 4px 12px rgba(0,0,0,0.16),
            4px 8px 28px rgba(0,0,0,0.13);
    }
    /* Stage 2: Approaching open-book reading tilt.
       5deg/1deg: nearly at final X angle, Y nearly zero. */
    88% {
        transform: rotateX(5deg) rotateY(1deg) rotateZ(0deg);
        box-shadow:
            1px 3px 10px rgba(0,0,0,0.12),
            3px 7px 26px rgba(0,0,0,0.14),
            0 10px 36px -4px rgba(0,0,0,0.10);
    }
    /* Final: open-book reading tilt — subtle 3D with visible depth.
       Uses CSS variables so the admin editor can tune the angle.
       Box-shadow matches .book-desk-scene--book .book-frame for seamless handoff. */
    100% {
        transform:
            rotateX(var(--book-open-rotate-x))
            rotateY(var(--book-open-rotate-y))
            rotateZ(var(--book-open-rotate-z));
        box-shadow:
            1px 2px 8px rgba(0,0,0,0.12),
            2px 8px 32px rgba(0,0,0,0.18),
            0 16px 48px -8px rgba(0,0,0,0.14),
            0 24px 64px -16px rgba(0,0,0,0.08);
    }
}

/* Cover overhang + Z-depth continuity — matches Cover state positioning
   so there's no visual jump when transitioning Cover → Opening.
   CRITICAL: The translateZ keeps the cover at the front of the page stack
   during the name reveal phase (before .book-cover-page--opening animation
   starts). Without this, the cover drops to Z=0, exposing page layers as
   a thin pale strip sliding out from behind the book.
   The coverPageOpen animation starts at this exact Z position, so the
   handoff from static transform → animation is seamless. */
.book-desk-scene--opening .book-cover-page {
    top: calc(-1 * var(--book-cover-overhang-top));
    left: 0;
    right: calc(-1 * var(--book-cover-overhang-right));
    bottom: calc(-1 * var(--book-cover-overhang-bottom));
    transform: translateZ(var(--book-closed-page-depth));
}

/* 3D depth elements visible at start of opening — no animation yet.
   Animation only fires when the cover actually starts swinging (.book-frame--open).
   Without this scoping, the depth fade fires 700ms too early (relative to the
   Opening state entering, before the initial pause + name reveal). */
.book-desk-scene--opening .book-3d-depth {
    opacity: 1;
    visibility: visible;
    pointer-events: none;
}

/* Unified 3D: depth stays visible throughout opening — no fade.
   The 3D geometry transitions from closed-book to open-book configuration
   via CSS transitions on the individual depth children (see open-book geometry section).
   CRITICAL: Push depth backward (same as Settling/Book states) to prevent
   depth elements from Z-fighting with the transparent viewport. The cover page
   is NOT inside .book-3d-depth (it's in .book-frame-right), so this push does
   not affect the cover swing animation. */
.book-desk-scene--opening .book-frame.book-frame--open .book-3d-depth {
    opacity: 1;
    visibility: visible;
    transform: translateZ(calc(-1 * (var(--book-open-page-depth) + 2px)));
    /* Delay the Z-push to match children's 1.2s transition delay so the depth
       container and its children move in sync. At 1.2s the cover is at ~-148deg
       (nearly flat), so the backward push is invisible behind the opened cover.
       Previous 0.8s delay started the push at -95deg, causing a visible slide. */
    transition: transform 0.8s ease-out 1.2s, opacity 0.4s ease, visibility 0.4s ease;
}

/* ── Spine gutter shadow — left-page reveal from the hinge ─────── */
/* Creates a subtle shadow at the left edge of the viewport that gives
   the inside cover / left page a sense of attachment to the spine.
   Without this, the cream background looks like a "blank white panel
   entering" rather than a bound page being revealed from the hinge.
   The shadow is the same gradient used in the Book state gutter. */

/* Gutter shadow base — hidden initially. The shadow gives the spine-side
   of the viewport a sense of attachment to the binding. */
.book-desk-scene--opening .book-viewport::before {
    content: '';
    position: absolute;
    left: 0;
    top: 3%;
    bottom: 3%;
    width: clamp(8px, 1.5vw, 18px);
    background: linear-gradient(to right,
        rgba(0,0,0,0.10) 0%,
        rgba(0,0,0,0.04) 40%,
        transparent 100%);
    z-index: 10;
    pointer-events: none;
    opacity: 0;
}

/* Gutter reveal scoped to cover swing start */
:not(.book-desk-scene--play).book-desk-scene--opening .book-frame.book-frame--open .book-viewport::before {
    animation: gutterShadowReveal 0.5s ease-out 0.9s forwards;
}

/* Settling: gutter already visible from Opening, just confirm opacity */
.book-desk-scene--settling .book-viewport::before {
    content: '';
    position: absolute;
    left: 0;
    top: 3%;
    bottom: 3%;
    width: clamp(8px, 1.5vw, 18px);
    background: linear-gradient(to right,
        rgba(0,0,0,0.10) 0%,
        rgba(0,0,0,0.04) 40%,
        transparent 100%);
    z-index: 10;
    pointer-events: none;
    opacity: 1;
}

@keyframes gutterShadowReveal {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* ── Opening keyframes ─────────────────────────────────────────── */

/* Viewport crossfades from transparent to cream during cover swing.
   Timed so cream is established before pages fade in — pages appear
   on a clean paper surface, not on a transparent/brown backdrop. */
@keyframes viewportCreamReveal {
    from { background-color: transparent; }
    to   { background-color: var(--book-page-cream, #f5f0e8); }
}

/* 3D depth elements (spine, page layers, edges, back cover) recede
   during the second half of the cover swing so they don't compete
   with the flat reading surface that's being revealed. */
@keyframes depthFadeOpening {
    0%   { opacity: 1; }
    100% { opacity: 0; }
}

/* ── Settling state: confirms the frame flatten ──────────────────
   The frameOpenSettle animation in Opening state already brought the
   frame to ~95% flat. Settling just confirms the final position with
   a short, imperceptible transition. This eliminates the visible
   "mode switch" that occurred when the full 1.1s flatten started here. */

.book-desk-scene--settling .book-desk-surface {
    perspective: var(--book-open-perspective);
    perspective-origin: 50% 40%;
    transform-style: preserve-3d;
}

:not(.book-desk-scene--play).book-desk-scene--settling .book-frame {
    transform-style: preserve-3d;
    isolation: auto;
    overflow: visible;
    /* Confirm open-book tilt — the frame is already nearly at reading angle
       from the Opening animation. This short transition catches the remainder. */
    transform:
        rotateX(var(--book-open-rotate-x))
        rotateY(var(--book-open-rotate-y))
        rotateZ(var(--book-open-rotate-z));
    transition: transform 0.4s ease-out,
                width var(--book-closed-open-duration) cubic-bezier(0.22, 0.68, 0.18, 1),
                box-shadow 0.4s ease;
    box-shadow:
        1px 2px 8px rgba(0,0,0,0.10),
        2px 6px 24px rgba(0,0,0,0.14),
        0 12px 40px -6px rgba(0,0,0,0.10);
}

/* Maintain 3D context through DOM chain during settling.
   Viewport excluded — must remain a flattening boundary for page content. */
.book-desk-scene--settling .book-page-stack,
.book-desk-scene--settling .book-cover-page {
    transform-style: preserve-3d;
}

/* Viewport already has cream bg from the Opening viewportCreamReveal animation.
   This rule confirms the cream background so there's no flash when the animation
   is removed at the Opening→Settling state change. No transition needed since
   the computed background is already cream. */
.book-desk-scene--settling .book-viewport {
    /* Match Book state perspective to eliminate the snap-recomposite flash
       when transitioning Settling→Book. At settling, all pages are at
       rotateY(0deg) so perspective has negligible visual effect (~0.2% scale). */
    perspective: var(--book-perspective);
    background: var(--book-page-cream, #f5f0e8);
}

.book-desk-scene--settling .book-frame-right {
    transform-style: preserve-3d;
    overflow: visible;
    /* No translateZ — depth layers are pushed backward instead (see .book-3d-depth below) */
}

/* Unified 3D: depth elements remain visible in Settling state.
   The 3D geometry transitions from closed-book to open-book configuration.
   Push backward (same as Book state) to prevent occluding page content. */
.book-desk-scene--settling .book-3d-depth {
    opacity: 1;
    visibility: visible;
    pointer-events: none;
    transform: translateZ(calc(-1 * (var(--book-open-page-depth) + 2px)));
}

/* Cover is already at Z=0 from the opening animation's Z-depth transition
   (coverPageOpen now transitions translateZ from page-depth to 0 during the swing).
   No coverSettleBack animation needed — just confirm the final position. */
.book-desk-scene--settling .book-cover-page {
    transform: translateZ(0px) rotateY(-180deg);
    pointer-events: none;
}

/* Pages fully visible during settling — once revealed in Opening,
   they stay locked to their geometry. No opacity toggling. */
.book-desk-scene--settling .book-page {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}

/* ── Pre-cascade visibility guards ──────────────────────────────
   During PlayBookOpenAnimation(), there's a 700ms gap between the
   Cover→Opening state change and play mode activation (name reveal).
   Without these guards, elements that were display:none/opacity:0 in
   Cover state suddenly appear in the 3D context, causing visible flashes.
   Selector: .book-frame:not(.book-frame--open) only matches the guest
   animation path (editor sets _isOpened=true simultaneously). */
.book-desk-scene--opening .book-frame:not(.book-frame--open) .book-3d-back-edge {
    display: none;
}

/* Also hide back-edges once frame opens — perpendicular 3D surfaces protrude
   above the flattened page viewport, clipping through pages during turns. */
.book-desk-scene--opening .book-frame.book-frame--open .book-3d-back-edge {
    display: none;
}

.book-desk-scene--opening .book-frame:not(.book-frame--open) .book-3d-page {
    opacity: 0;
}

/* Spine edge stays hidden until play mode (matches Cover behavior) */
.book-desk-scene--opening:not(.book-desk-scene--play) .book-cover-edge--spine {
    opacity: 0;
    transition: opacity 0.3s ease;
}

/* Spine and gutter hidden during settling */
.book-desk-scene--settling .book-spine-3d {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.5s ease;
}

.book-desk-scene--settling .book-frame::after {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.5s ease;
}

/* Nav hidden during settling */
.book-desk-scene--settling .book-nav,
.book-desk-scene--settling .book-nav-ribbons {
    opacity: 0;
    pointer-events: none;
}

/* ── Book state: fully open spread with unified 3D ─────────────── */
/* The final resting state. The book maintains a subtle 3D tilt so the
   spine, page depth, and covers remain visible. The transition from
   Settling→Book should be imperceptible — same angle, just class change. */

.book-desk-scene--book .book-desk-surface {
    perspective: var(--book-open-perspective);
    perspective-origin: 50% 40%;
    transform-style: preserve-3d;
    /* Let pointer events pass through the full-screen desk surface so
       ribbon bookmarks protruding above the frame's bounding box are
       clickable. Without this, the desk surface (which fills the viewport)
       intercepts all clicks above the frame and elementFromPoint returns
       "book-desk-surface" instead of the ribbon buttons. Children with
       pointer-events: auto (frame, pages, ribbons) still receive events. */
    pointer-events: none;
}

/* ── Hardcover top-edge leather strip — GLOBALLY HIDDEN ───────────
   Replaced by the 3D back cover system. The increased cover overhang
   on .book-3d-back-cover provides the leather border at the top. */
.book-hardcover-top-clip {
    display: none;
}

.book-desk-scene--book .book-frame {
    transform-style: preserve-3d;
    isolation: auto;
    overflow: visible;
    pointer-events: auto; /* Re-enable after desk-surface pointer-events: none */
    transform:
        rotateX(var(--book-open-rotate-x))
        rotateY(var(--book-open-rotate-y))
        rotateZ(var(--book-open-rotate-z));
    /* Width transition removed — play mode animation handles the width change
       during open/close. When play mode drops, Book CSS catches at the final
       value. A width transition here causes visual sliding when the style
       recalculates between play mode and Book state. */
    transition: transform 0.4s ease, box-shadow 0.6s ease;
    /* Grounded shadow with slight directional offset for 3D tilt */
    box-shadow:
        1px 2px 8px rgba(0,0,0,0.12),
        2px 8px 32px rgba(0,0,0,0.18),
        0 16px 48px -8px rgba(0,0,0,0.14),
        0 24px 64px -16px rgba(0,0,0,0.08);
}

/* Maintain preserve-3d for page-stack and cover in Book state.
   IMPORTANT: .book-viewport must NOT have preserve-3d — it needs to remain
   a flattening boundary with its own perspective for page turns. Adding
   preserve-3d breaks page content rendering (elements get composited in
   the frame's 3D context instead of the viewport's 2D context). */
.book-desk-scene--book .book-page-stack,
.book-desk-scene--book .book-cover-page {
    transform-style: preserve-3d;
}

.book-desk-scene--book .book-frame-right {
    transform-style: preserve-3d;
    overflow: visible;
    /* No translateZ here — depth layers are pushed backward instead (see .book-3d-depth below).
       Keeping .book-frame-right at Z=0 ensures pages share the same Z plane as the left page,
       eliminating the perspective-induced gap at the spine that appeared when the right half
       was 50px forward while the left half stayed at Z=0. */
}

/* Viewport gets proper page background in Book state */
.book-desk-scene--book .book-viewport {
    background: var(--book-page-cream, #f5f0e8);
}

/* ── Center gutter shadow — book depth in the open spread ────────
   Adds a subtle shadow at the left edge of the viewport (the spine/
   gutter) so the open book reads as having a real spine dip and
   page-stack thickness, not just two flat rectangles. */
.book-desk-scene--book .book-viewport::before {
    content: '';
    position: absolute;
    left: 0;
    top: 2%;
    bottom: 2%;
    width: clamp(10px, 1.8vw, 22px);
    background: linear-gradient(to right,
        rgba(0,0,0,0.09) 0%,
        rgba(0,0,0,0.04) 35%,
        rgba(0,0,0,0.01) 65%,
        transparent 100%);
    z-index: 5;
    pointer-events: none;
    border-radius: 0 2px 2px 0;
}

/* Unified 3D: depth elements remain visible in Book state.
   The 3D geometry shows the open-book configuration (right-half page stack,
   visible spine ridge, repositioned edges). pointer-events stay off so
   depth elements don't interfere with page content interaction.
   translateZ pushes the entire depth container BEHIND the reading surfaces
   so page content isn't occluded by cream depth layers. Children retain their
   relative Z positions within the container. This replaces the old approach of
   pushing .book-frame-right forward, which created a perspective-induced gap
   at the spine (right half was ~50px in front of left half). */
.book-desk-scene--book .book-3d-depth {
    opacity: 1;
    visibility: visible;
    pointer-events: none;
    transform: translateZ(calc(-1 * (var(--book-open-page-depth) + 2px)));
}

/* Hide 3D back-edge strips in open/reading states — these perpendicular
   leather surfaces (rotateY/X 90deg) are only useful in the closed 3D view.
   In the open state, their 3D transforms cause them to protrude above the
   flattened page viewport, clipping through pages during turns. */
.book-desk-scene--book .book-3d-back-edge,
.book-desk-scene--settling .book-3d-back-edge {
    display: none;
}

/* Ribbon containers: counteract per-page Z-offsets so all ribbons share
   a consistent forward Z position within the viewport's flattened context.
   The hardcover-top-clip is now at Z=-0.5px (behind .book-frame-right at Z=0),
   so ribbons naturally protrude above the leather edge without needing to
   escape the viewport's flattening boundary. Matches scrub-mode in animation-timeline.css. */
.book-desk-scene--book .book-page-ribbon-container {
    transform: translateZ(calc(var(--page-z-offset, 0) * 0.5px + 2px));
    pointer-events: auto;
}

/* Back-face ribbon on turned pages: push forward in Z so it protrudes above the
   hardcover-top-clip. translateZ is applied BEFORE rotateY(180deg) in the transform
   chain, so it moves forward in world space (toward the viewer). */
.book-desk-scene--book .book-page--turned .book-page-ribbon-container-back {
    transform: translateZ(calc(var(--page-z-offset, 0) * 0.5px + 2px)) rotateY(180deg);
    pointer-events: auto;
}

/* ── Closing state: continuous reverse of Opening ──────────────── */
/* Reverse of the open: book lifts back to 3D angle, then cover swings shut.
   The same physical object in reverse — no rig swap feeling.
   Phase 1 (CSS): Frame re-rotates to 3D, depth elements fade back in.
   Phase 2 (C#): Cover swings shut once frame is back at the 3D angle. */

/* Frame re-rotates to 3D closed position with matching overshoot easing.
   The 0.8s delay allows flyleaves to begin their reverse cascade before
   the frame starts lifting — the cover close starts at 1.0s, so the frame
   begins re-rotating 0.2s before the cover swings to maintain continuity. */
:not(.book-desk-scene--play).book-desk-scene--closing .book-frame {
    transform-style: preserve-3d;
    isolation: auto;
    overflow: visible;
    transform:
        rotateX(var(--book-closed-rotate-x))
        rotateY(var(--book-closed-rotate-y))
        rotateZ(var(--book-closed-rotate-z));
    transition: transform 1.4s cubic-bezier(0.22, 0.68, 0.18, 1) 0.8s,
                width var(--book-closed-open-duration) cubic-bezier(0.22, 0.68, 0.18, 1) 0.8s,
                box-shadow 1.0s ease 0.8s;
    /* Shadow lifts as book rises to 3D angle */
    box-shadow:
        4px 6px 15px rgba(0,0,0,0.20),
        8px 12px 35px rgba(0,0,0,0.15);
}

/* 3D desk surface transitions from open perspective to closed perspective.
   The perspective shift happens alongside the frame rotation change. */
.book-desk-scene--closing .book-desk-surface {
    perspective: var(--book-closed-perspective);
    transform-style: preserve-3d;
    transition: perspective 0.6s ease;
}

/* Maintain 3D context through DOM chain during closing */
.book-desk-scene--closing .book-viewport,
.book-desk-scene--closing .book-page-stack,
.book-desk-scene--closing .book-cover-page {
    transform-style: preserve-3d;
}

/* Cover overhang continuity during closing — the cover should look like a
   proper hardcover board (slightly larger than the page block) as it swings
   shut. Without this, the cover is flush with pages during close, then
   suddenly gains overhangs when Cover state kicks in. */
.book-desk-scene--closing .book-cover-page {
    top: calc(-1 * var(--book-cover-overhang-top));
    left: 0;
    right: calc(-1 * var(--book-cover-overhang-right));
    bottom: calc(-1 * var(--book-cover-overhang-bottom));
}

/* Viewport snaps to transparent immediately during closing — no crossfade.
   The pages are fading out (0.4s) and the 3D depth elements are fading in,
   so we don't want a slow background transition creating a see-through window. */
.book-desk-scene--closing .book-viewport {
    perspective: none;
    background: transparent !important;
    transition: none;
}

/* Remove gutter shadow during closing — it belongs to the open spread,
   not the closing 3D book. Fades out as pages disappear. */
.book-desk-scene--closing .book-viewport::before {
    content: '';
    opacity: 0;
    transition: opacity 0.3s ease;
}

.book-desk-scene--closing .book-frame-right {
    transform-style: preserve-3d;
    overflow: visible;
}

/* Unified 3D: depth stays visible throughout closing — no fade needed since
   it was already visible in Book state. The depth geometry morphs from
   open-book (right-half stack) back to closed-book (solid block) via
   CSS transitions on the individual children.
   CRITICAL: Explicit translateZ(0) + transition prevents the depth container
   from snapping instantly from the Book state's translateZ(-page-depth-2px).
   Without this, all depth children (spine, edges, back cover) jump forward
   by ~50px in a single frame, causing a visible flash. The 0.8s delay + 1.4s
   duration matches the frame rotation timing for lockstep movement. */
.book-desk-scene--closing .book-3d-depth {
    opacity: 1;
    visibility: visible;
    pointer-events: none;
    transform: translateZ(0);
    transition: transform 1.4s cubic-bezier(0.22, 0.68, 0.18, 1) 0.8s,
                opacity 0.4s ease, visibility 0.4s ease;
}

/* Depth children transition back to closed-book positions.
   Timing synced with frame rotation (0.8s delay + 1.4s duration = 2.2s total)
   so depth elements move in lockstep with the frame. Previous timing
   (0.4s + 0.8s = 1.2s) caused children to finish 1.4s before the cover
   closed, creating a visible "slide to meet" effect. */
:not(.book-desk-scene--play).book-desk-scene--closing .book-3d-depth > * {
    transition: transform 1.4s cubic-bezier(0.22, 0.68, 0.18, 1) 0.8s,
                width 1.4s cubic-bezier(0.22, 0.68, 0.18, 1) 0.8s,
                height 1.4s cubic-bezier(0.22, 0.68, 0.18, 1) 0.8s,
                left 1.4s cubic-bezier(0.22, 0.68, 0.18, 1) 0.8s,
                right 1.4s cubic-bezier(0.22, 0.68, 0.18, 1) 0.8s,
                opacity 0.6s ease 0.8s;
}

/* Back cover position targets for CSS-transition close path.
   Locks the base overhang values immediately (no transition on top/right/bottom)
   to prevent the generic depth > * transition from animating the 6-8px difference
   between open-state extended overhang and base overhang, which makes the cover
   appear to slide sideways during close. */
:not(.book-desk-scene--play).book-desk-scene--closing .book-3d-back-cover {
    top: calc(-1 * var(--book-cover-overhang-top));
    right: calc(-1 * var(--book-cover-overhang-right));
    bottom: calc(-1 * var(--book-cover-overhang-bottom));
    /* Override the generic depth > * transition which includes `right 1.4s`.
       Without this, `right` animates the 8px difference over 1.4s instead
       of snapping, creating a visible sideways slide on the back cover. */
    transition: transform 1.4s cubic-bezier(0.22, 0.68, 0.18, 1) 0.8s,
                opacity 0.6s ease 0.8s;
}

/* Spine strips transition back to closed curvature during close */
.book-desk-scene--closing .book-3d-spine-strip {
    transition: transform 1.4s cubic-bezier(0.22, 0.68, 0.18, 1) 0.8s;
}

/* Left stack fades out during closing */
.book-desk-scene--closing .book-3d-left-stack {
    opacity: 0;
    transform: translateZ(0);
}

/* Spine and gutter fade out */
.book-desk-scene--closing .book-spine-3d {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none !important;
    transition: opacity 0.3s ease;
}

.book-desk-scene--closing .book-frame::after {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none;
    transition: opacity 0.3s ease;
}

/* Back edges hidden during closing (3D depth container handles it) */
.book-desk-scene--closing .book-3d-back-edge {
    display: none;
}

/* Hide nav during closing transition */
.book-desk-scene--closing .book-nav,
.book-desk-scene--closing .book-nav-ribbons {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
}

/* Hide book pages during close — they peek out behind the 3D-rotated cover
   when the viewport background is transparent. Fade out early so pages
   vanish before the frame narrows enough to expose them. */
.book-desk-scene--closing .book-page {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.4s ease, visibility 0s linear 0.4s;
}

/* Keep pages hidden in Cover state. In Opening state they snap back to
   visible behind the cover (z-index 100), which is correct since the
   cover visually hides them until it swings open. */
.book-desk-scene--cover .book-page {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

/* Pages visible from start in Opening state — occluded by cover (z:100) and
   flyleaf (z:90-66) stacking. As flyleaves rotate past 90deg, their front faces
   disappear via backface-visibility:hidden, naturally revealing pages behind. */
.book-desk-scene--opening .book-page {
    opacity: 1;
    visibility: visible;
    z-index: 50;
    pointer-events: none;
}

/* pageRevealBehindCover animation removed — pages are now visible from the
   start and occluded by cover/flyleaf z-index stacking instead. */

/* Page reveal — gentle ramp so pages appear progressively, matching
   the physical reveal as the cover swings past the 90deg edge-on point. */
@keyframes pageRevealBehindCover {
    0%   { opacity: 0; }
    35%  { opacity: 0.45; }
    70%  { opacity: 0.85; }
    100% { opacity: 1; }
}

/* ═══════════════════════════════════════════════════════════════════
   FLYLEAF CASCADE — visibility and 3D context per state.
   Flyleaves are decorative pages between cover and content that
   turn in staggered cascade during the opening/closing animation.
   ═══════════════════════════════════════════════════════════════════ */

/* Cover state: flyleaves hidden (same as content pages) */
.book-desk-scene--cover .book-flyleaf {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

/* Opening state: flyleaves are VISIBLE from the start — they sit flat in
   the page stack at Z=0, naturally occluded behind the cover (Z=page-depth)
   in the preserve-3d context. As the cover swings open, the flyleaves are
   physically revealed underneath it — no opacity fade needed. This eliminates
   the "page spawning from nowhere" artifact. The staggered turn animations
   (from storybook-unified.css) control WHEN each page peels and turns, but
   the pages are always present and visible in the stack. */
.book-desk-scene--opening .book-flyleaf {
    opacity: 1;
    visibility: visible;
    pointer-events: none;
}

/* Settling state: flyleaves turned and visible (behind content).
   The .book-flyleaf--turned class (storybook-unified.css) provides the
   rotateY(-180deg) transform — no explicit transform needed here. */
.book-desk-scene--settling .book-flyleaf {
    opacity: 1;
    visibility: visible;
    pointer-events: none;
}

/* Book state: decorative flyleaves 1-3 hidden (turned behind everything).
   Flyleaf 4 stays visible — its back face carries the Table of Contents
   (Spread 0 left page). */
.book-desk-scene--book .book-flyleaf:not(.book-flyleaf--4) {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.3s ease, visibility 0s linear 0.3s;
}
/* Flyleaf 4 visible — its back face is the Table of Contents (Spread 0 left).
   Uses var(--flyleaf-z-open, 2px) to match the flyleafTurnOpen animation's 100%
   end state exactly. This prevents a compositor recomposite flash when play mode
   drops (animation fill-forward → static CSS handoff). The flyleaf's
   backface-visibility: hidden ensures it's invisible on the right half
   (front face faces away at rotateY(-180deg)). When page 0 is turned,
   the turned page at translateZ(0.1px) sits on top of this flyleaf. */
.book-desk-scene--book .book-flyleaf--4 {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translateZ(var(--flyleaf-z-open, 2px)) rotateY(-180deg);
}

/* Closing state: flyleaves visible for reverse cascade */
.book-desk-scene--closing .book-flyleaf {
    opacity: 1;
    visibility: visible;
    pointer-events: none;
}

/* Table/PickingUp/SettingDown: flyleaves hidden */
.book-desk-scene--table .book-flyleaf,
.book-desk-scene--pickingup .book-flyleaf,
.book-desk-scene--settingdown .book-flyleaf {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

/* Maintain 3D context for flyleaves — they must participate in the same
   preserve-3d chain as the cover for correct Z-sorting during cascade. */
.book-desk-scene--cover .book-flyleaf,
.book-desk-scene--opening .book-flyleaf,
.book-desk-scene--closing .book-flyleaf,
.book-desk-scene--settling .book-flyleaf {
    transform-style: preserve-3d;
}

/* ══════════════════════════════════════════════════════════════════
   GUEST ROTATION — Cover state interactivity for all users.
   Hold-to-rotate with spring-back to rest on release.
   ══════════════════════════════════════════════════════════════════ */

/* Cover hint tooltip — shows interaction instructions below the book */
.book-cover-hint {
    position: absolute;
    bottom: 8%;
    left: 50%;
    transform: translateX(-50%);
    z-index: 10;
    text-align: center;
    opacity: 0;
    transition: opacity 0.4s ease;
    pointer-events: none;
    white-space: nowrap;
    background: rgba(0, 0, 0, 0.4);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    padding: 8px 20px;
    border-radius: 20px;
    border: 1px solid rgba(212, 175, 55, 0.15);
}

/* Show hint on hover over the desk scene (not during rotation).
   Uses descendant selector because .guest-rotating is on the parent .book-desk-scene,
   not a sibling of .book-cover-hint. */
.book-desk-scene--cover:not(.guest-rotating):hover > .book-cover-hint {
    opacity: 1;
}

/* Fade hint in when Cover state first enters */
.book-desk-scene--cover .book-cover-hint {
    animation: hintFadeIn 0.8s ease-out 0.8s both;
}

.book-cover-hint__text,
.book-cover-hint__explore {
    font-family: var(--font-heading);
    color: var(--book-gold-leaf, #D4AF37);
    font-size: clamp(0.7rem, 1.4vw, 0.95rem);
    text-shadow: 0 1px 6px rgba(0, 0, 0, 0.3), 0 0 20px rgba(0, 0, 0, 0.15);
    letter-spacing: 0.04em;
}

.book-cover-hint__separator {
    color: var(--book-gold-leaf, #D4AF37);
    opacity: 0.5;
    margin: 0 6px;
    font-size: 0.8rem;
}

.book-cover-hint__explore {
    opacity: 0.7;
    font-style: italic;
}

/* Hide hint during rotation (.guest-rotating is on the parent .book-desk-scene) */
.book-desk-scene.guest-rotating > .book-cover-hint {
    opacity: 0 !important;
    transition: opacity 0.2s ease;
}

/* Rotation indicator pill — "Release to return" */
.book-cover-rotate-indicator {
    position: absolute;
    top: 8%;
    left: 50%;
    transform: translateX(-50%);
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    color: var(--book-gold-leaf, #D4AF37);
    padding: 6px 18px;
    border-radius: 20px;
    font-family: var(--font-body);
    font-size: 0.8rem;
    letter-spacing: 0.06em;
    opacity: 0;
    transition: opacity 0.3s ease;
    pointer-events: none;
    z-index: 10;
    border: 1px solid rgba(212, 175, 55, 0.15);
}

/* Show indicator only during active rotation (.guest-rotating is on parent) */
.book-desk-scene.guest-rotating > .book-cover-rotate-indicator {
    opacity: 1;
}

/* Disable CSS transitions on book frame during JS-driven rotation */
.book-desk-scene--cover.guest-rotating .book-frame {
    transition: none !important;
}

/* Cursor changes during guest rotation */
.book-desk-scene--cover.guest-rotating .book-desk-surface {
    cursor: grabbing;
}

/* Touch action: prevent scroll/zoom during guest rotation on mobile */
/* Grab cursor: shows the book is draggable in Cover state */
.book-desk-scene--cover .book-desk-surface {
    touch-action: pan-y;
    cursor: grab;
}

/* Reduced motion: disable rotation hints */
@media (prefers-reduced-motion: reduce) {
    .book-cover-hint,
    .book-cover-rotate-indicator {
        animation: none !important;
        transition: none !important;
    }
}

@media (max-width: 768px) {
    .book-cover-hint {
        white-space: normal;
        max-width: 85vw;
        bottom: 5%;
    }

    .book-cover-hint__text,
    .book-cover-hint__explore {
        font-size: clamp(0.6rem, 3vw, 0.85rem);
    }

    .book-cover-rotate-indicator {
        font-size: 0.7rem;
        padding: 5px 14px;
    }
}

/* ── Grab particle effect — brief gold sparkle burst on drag start ── */
.book-grab-particles {
    position: fixed;
    pointer-events: none;
    z-index: 99999;
    width: 0;
    height: 0;
}

.book-grab-particle {
    position: absolute;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(212, 175, 55, 0.9), rgba(212, 175, 55, 0.3));
    box-shadow:
        0 0 4px rgba(212, 175, 55, 0.6),
        0 0 8px rgba(212, 175, 55, 0.3),
        0 0 0 1px rgba(255, 255, 255, 0.5),    /* white ring — contrast on dark backgrounds */
        0 0 12px 2px rgba(255, 255, 255, 0.15); /* soft white halo */
    mix-blend-mode: screen; /* brightens on dark backgrounds, neutral on light */
    animation: grabParticleBurst 0.6s ease-out forwards;
}

/* Smaller variant for variety */
.book-grab-particle--sm {
    width: 3px;
    height: 3px;
    animation-duration: 0.5s;
}

/* Glow variant — larger, softer, enhanced halo for background visibility */
.book-grab-particle--glow {
    width: 8px;
    height: 8px;
    background: radial-gradient(circle, rgba(212, 175, 55, 0.6), transparent);
    box-shadow:
        0 0 6px rgba(212, 175, 55, 0.8),
        0 0 12px rgba(212, 175, 55, 0.4),
        0 0 0 1.5px rgba(255, 255, 255, 0.6),
        0 0 16px 3px rgba(255, 255, 255, 0.2);
    animation-duration: 0.7s;
}

@keyframes grabParticleBurst {
    0% {
        opacity: 1;
        transform: translate(var(--gp-x, 0px), var(--gp-y, 0px)) scale(1);
    }
    60% {
        opacity: 0.7;
    }
    100% {
        opacity: 0;
        transform: translate(
            calc(var(--gp-x, 0px) * 2.5),
            calc(var(--gp-y, 0px) * 2.5)
        ) scale(0.2);
    }
}

/* Reduced motion: disable grab particles */
@media (prefers-reduced-motion: reduce) {
    .book-grab-particle {
        animation: none !important;
        display: none;
    }
}

/* ══════════════════════════════════════════════════════════════════
   TABLE STATE: Book lying flat on the desk, viewed from above.
   Visitor sees a small closed book on the table with a pulsing
   golden glow inviting them to click. Clicking triggers the
   PickingUp transition to the Cover state.
   ══════════════════════════════════════════════════════════════════ */

/* ── Table state: flat book on desk ────────────────────────────── */

/* 3D perspective on desk surface for table rotation */
.book-desk-scene--table .book-desk-surface {
    perspective: var(--book-table-perspective);
    transform-style: preserve-3d;
}

/* Book frame flat on the desk — high rotateX tilts it nearly face-down */
.book-desk-scene--table .book-frame {
    transform-style: preserve-3d;
    overflow: visible;
    isolation: auto;
    cursor: pointer;
    transform:
        rotateX(var(--book-table-rotate-x))
        rotateY(var(--book-table-rotate-y))
        rotateZ(var(--book-table-rotate-z))
        scale(var(--book-table-scale))
        translateX(var(--book-table-translate-x))
        translateY(var(--book-table-translate-y))
        translateZ(var(--book-table-translate-z));
    transition: transform 0.3s ease;
}

/* Subtle lift on hover — book rises slightly off table.
   NOTE: Do NOT use filter here — filter creates an implicit stacking context
   that overrides transform-style:preserve-3d, flattening all 3D depth. */
.book-desk-scene--table .book-frame:hover {
    transform:
        rotateX(var(--book-table-rotate-x))
        rotateY(var(--book-table-rotate-y))
        rotateZ(var(--book-table-rotate-z))
        scale(var(--book-table-scale))
        translateX(var(--book-table-translate-x))
        translateY(var(--book-table-translate-y))
        translateZ(calc(var(--book-table-translate-z) + var(--book-table-hover-lift)));
}

/* Disable hover when admin is orbiting */
.book-desk-scene--table .book-frame.book-frame--no-hover:hover {
    transform:
        rotateX(var(--book-table-rotate-x))
        rotateY(var(--book-table-rotate-y))
        rotateZ(var(--book-table-rotate-z))
        scale(var(--book-table-scale))
        translateX(var(--book-table-translate-x))
        translateY(var(--book-table-translate-y))
        translateZ(var(--book-table-translate-z));
}

/* Maintain 3D context through DOM chain */
.book-desk-scene--table .book-viewport,
.book-desk-scene--table .book-page-stack,
.book-desk-scene--table .book-cover-page {
    transform-style: preserve-3d;
}

.book-desk-scene--table .book-viewport {
    perspective: none;
    background: transparent;
}

.book-desk-scene--table .book-frame-right {
    transform-style: preserve-3d;
    overflow: visible;
    width: 100%;
    flex: 1;
}

/* Front cover at top of page stack (same as Cover state) */
.book-desk-scene--table .book-cover-page {
    transform:
        translateX(var(--book-front-cover-extra-tx))
        translateY(var(--book-front-cover-extra-ty))
        translateZ(calc(var(--book-closed-page-depth) + 2px + var(--book-front-cover-extra-tz)))
        rotateX(var(--book-front-cover-extra-rx))
        rotateY(var(--book-front-cover-extra-ry))
        rotateZ(var(--book-front-cover-extra-rz));
    top: calc(-1 * var(--book-cover-overhang-top));
    left: 0;
    right: calc(-1 * var(--book-cover-overhang-right));
    bottom: calc(-1 * var(--book-cover-overhang-bottom));
}

/* Cover vignette */
.book-desk-scene--table .book-cover-page-front {
    box-shadow: inset 0 0 40px rgba(0, 0, 0, var(--book-cover-vignette-intensity));
}

/* Show cover content when book is flat on table — pointer-events disabled until pickup */
.book-desk-scene--table .book-cover-page-front > * {
    opacity: 1;
    pointer-events: none;
    transition: opacity 0.4s ease;
}

/* Hide elements not relevant in Table state */
.book-desk-scene--table .book-spine-3d {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none !important;
}

.book-desk-scene--table .book-frame::after {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none;
}

.book-desk-scene--table .book-3d-back-edge {
    display: none;
}

.book-desk-scene--table .book-nav,
.book-desk-scene--table .book-nav-ribbons {
    opacity: 0;
    pointer-events: none;
}

/* 3D depth elements fully visible (back cover, pages, spine wall, edges) */
.book-desk-scene--table .book-3d-depth {
    opacity: 1;
    visibility: visible;
    pointer-events: none;
    transition: opacity 0.6s ease, visibility 0s linear 0s;
}

/* Hide book pages (they'd peek behind the 3D cover) */
.book-desk-scene--table .book-page {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

/* ── Golden glow — pulsing aura around the flat book ──────────── */
.book-desk-scene--table .book-3d-depth::before {
    content: '';
    position: absolute;
    inset: -15px;
    transform: translateZ(-3px);
    border-radius: 8px;
    box-shadow:
        0 0 var(--book-table-glow-blur) var(--book-table-glow-spread) var(--book-table-glow-color);
    opacity: var(--book-table-glow-intensity);
    animation: tableGlowPulse var(--book-table-glow-pulse-speed) ease-in-out infinite alternate;
    pointer-events: none;
    z-index: -1;
}

@keyframes tableGlowPulse {
    0%   { opacity: calc(var(--book-table-glow-intensity) * 0.4); }
    100% { opacity: var(--book-table-glow-intensity); }
}

/* ── Table shadow — cast on the desk beneath the book ─────────── */
.book-desk-scene--table .book-3d-depth::after {
    content: '';
    position: absolute;
    inset: -4px;
    transform: translateZ(-4px);
    border-radius: 4px 10px 10px 4px;
    box-shadow:
        var(--book-table-shadow-offset-x)
        var(--book-table-shadow-offset-y)
        var(--book-table-shadow-blur)
        var(--book-table-shadow-spread)
        var(--book-table-shadow-color);
    opacity: var(--book-table-shadow-opacity);
    pointer-events: none;
    z-index: -2;
}

/* ── Per-surface rim glow — cel-shade edge lighting on each 3D surface ── */
/* Each surface gets its own box-shadow so the glow follows the 3D silhouette
   from every viewing angle, unlike the flat ::before floor halo. */
.book-desk-scene--table .book-3d-spine,
.book-desk-scene--table .book-3d-edge-right,
.book-desk-scene--table .book-3d-edge-top,
.book-desk-scene--table .book-3d-edge-bottom,
.book-desk-scene--table .book-3d-back-cover-face,
.book-desk-scene--table .book-cover-page-front {
    box-shadow:
        0 0 var(--book-table-rim-blur) var(--book-table-rim-spread) var(--book-table-rim-color);
    transition: box-shadow 0.3s ease;
}

/* Pulsing rim glow — uses its own pulse speed variable */
.book-desk-scene--table .book-3d-spine,
.book-desk-scene--table .book-3d-edge-right,
.book-desk-scene--table .book-3d-edge-top,
.book-desk-scene--table .book-3d-edge-bottom {
    animation: tableRimPulse var(--book-table-rim-pulse-speed) ease-in-out infinite alternate;
    opacity: var(--book-table-rim-intensity);
}

@keyframes tableRimPulse {
    0%   { box-shadow: 0 0 calc(var(--book-table-rim-blur) * 0.6) calc(var(--book-table-rim-spread) * 0.5) var(--book-table-rim-color); }
    100% { box-shadow: 0 0 var(--book-table-rim-blur) var(--book-table-rim-spread) var(--book-table-rim-color); }
}

/* Hover intensification — replaces the removed filter:brightness.
   Rim glow gets brighter + wider on hover, giving visual lift feedback. */
.book-desk-scene--table .book-frame:hover .book-3d-spine,
.book-desk-scene--table .book-frame:hover .book-3d-edge-right,
.book-desk-scene--table .book-frame:hover .book-3d-edge-top,
.book-desk-scene--table .book-frame:hover .book-3d-edge-bottom,
.book-desk-scene--table .book-frame:hover .book-3d-back-cover-face,
.book-desk-scene--table .book-frame:hover .book-cover-page-front {
    box-shadow:
        0 0 var(--book-table-rim-hover-blur) var(--book-table-rim-hover-spread) var(--book-table-rim-hover-color);
}

/* Intensify the floor halo on hover too */
.book-desk-scene--table .book-frame:hover .book-3d-depth::before {
    opacity: calc(var(--book-table-glow-intensity) * 1.4);
}

/* No-hover disables rim glow intensification for orbiting admin */
.book-desk-scene--table .book-frame.book-frame--no-hover:hover .book-3d-spine,
.book-desk-scene--table .book-frame.book-frame--no-hover:hover .book-3d-edge-right,
.book-desk-scene--table .book-frame.book-frame--no-hover:hover .book-3d-edge-top,
.book-desk-scene--table .book-frame.book-frame--no-hover:hover .book-3d-edge-bottom,
.book-desk-scene--table .book-frame.book-frame--no-hover:hover .book-3d-back-cover-face,
.book-desk-scene--table .book-frame.book-frame--no-hover:hover .book-cover-page-front {
    box-shadow:
        0 0 var(--book-table-rim-blur) var(--book-table-rim-spread) var(--book-table-rim-color);
}

.book-desk-scene--table .book-frame.book-frame--no-hover:hover .book-3d-depth::before {
    opacity: var(--book-table-glow-intensity);
}

/* ── Table particles — golden dust drifting upward ──────────────── */
.book-table-particles {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 2;
    overflow: visible;
}

.book-table-particle {
    position: absolute;
    width: calc(clamp(3px, 0.6vw, 8px) * var(--book-table-particle-size));
    height: calc(clamp(3px, 0.6vw, 8px) * var(--book-table-particle-size));
    border-radius: 50%;
    background: radial-gradient(circle, rgba(212, 175, 55, 0.9) 0%, rgba(212, 175, 55, 0) 70%);
    opacity: 0;
    pointer-events: none;
}

/* Only animate particles in Table state */
.book-desk-scene--table .book-table-particle {
    animation: tableParticleFloat calc(var(--p-duration) * var(--book-table-particle-speed)) ease-in-out var(--p-delay) infinite;
}

@keyframes tableParticleFloat {
    0%   { opacity: 0; transform: translateY(0) translateX(0) scale(0.5); }
    15%  { opacity: var(--book-table-particle-opacity); }
    50%  { opacity: calc(var(--book-table-particle-opacity) * 0.7);
           transform: translateY(calc(var(--book-table-particle-rise) * -0.5))
                      translateX(calc(var(--p-drift, 5px) * var(--book-table-particle-spread) / 12))
                      scale(1); }
    85%  { opacity: calc(var(--book-table-particle-opacity) * 0.3); }
    100% { opacity: 0;
           transform: translateY(calc(var(--book-table-particle-rise) * -1))
                      translateX(calc(var(--p-drift2, -3px) * var(--book-table-particle-spread) / 12))
                      scale(0.3); }
}

/* Per-particle positioning, timing, and drift randomization */
.book-table-particle:nth-child(1)  { left: 35%; bottom: 50%; --p-duration: 3.8s; --p-delay: 0s;   --p-drift: 8px;  --p-drift2: -5px; }
.book-table-particle:nth-child(2)  { left: 55%; bottom: 48%; --p-duration: 4.5s; --p-delay: 0.6s; --p-drift: -6px; --p-drift2: 4px; }
.book-table-particle:nth-child(3)  { left: 45%; bottom: 52%; --p-duration: 5.2s; --p-delay: 1.2s; --p-drift: 12px; --p-drift2: -8px; }
.book-table-particle:nth-child(4)  { left: 62%; bottom: 45%; --p-duration: 3.5s; --p-delay: 0.3s; --p-drift: -4px; --p-drift2: 7px; }
.book-table-particle:nth-child(5)  { left: 30%; bottom: 46%; --p-duration: 4.8s; --p-delay: 1.8s; --p-drift: 10px; --p-drift2: -3px; }
.book-table-particle:nth-child(6)  { left: 50%; bottom: 54%; --p-duration: 5.5s; --p-delay: 2.5s; --p-drift: -8px; --p-drift2: 6px; }
.book-table-particle:nth-child(7)  { left: 68%; bottom: 50%; --p-duration: 4.2s; --p-delay: 0.9s; --p-drift: 5px;  --p-drift2: -10px; }
.book-table-particle:nth-child(8)  { left: 40%; bottom: 44%; --p-duration: 5.8s; --p-delay: 1.5s; --p-drift: -10px;--p-drift2: 3px; }
.book-table-particle:nth-child(9)  { left: 58%; bottom: 52%; --p-duration: 3.2s; --p-delay: 2.1s; --p-drift: 7px;  --p-drift2: -6px; }
.book-table-particle:nth-child(10) { left: 42%; bottom: 48%; --p-duration: 4.0s; --p-delay: 0.4s; --p-drift: -12px;--p-drift2: 8px; }

/* Varied sizes via nth-child (multiplied by --book-table-particle-size) */
.book-table-particle:nth-child(2),
.book-table-particle:nth-child(6),
.book-table-particle:nth-child(10) {
    width: calc(clamp(4px, 0.8vw, 10px) * var(--book-table-particle-size));
    height: calc(clamp(4px, 0.8vw, 10px) * var(--book-table-particle-size));
}
.book-table-particle:nth-child(4),
.book-table-particle:nth-child(8) {
    width: calc(clamp(2px, 0.4vw, 6px) * var(--book-table-particle-size));
    height: calc(clamp(2px, 0.4vw, 6px) * var(--book-table-particle-size));
}

/* Hover: particles speed up ~1.5x */
.book-desk-scene--table .book-frame:hover ~ .book-table-particles .book-table-particle {
    animation-duration: calc(var(--p-duration) * var(--book-table-particle-speed) * 0.65);
}

/* No-hover disables particle speed-up for orbiting admin */
.book-desk-scene--table .book-frame.book-frame--no-hover:hover ~ .book-table-particles .book-table-particle {
    animation-duration: calc(var(--p-duration) * var(--book-table-particle-speed));
}

/* Fade out particles during pickup */
.book-desk-scene--pickingup .book-table-particles {
    opacity: 0;
    transition: opacity 0.4s ease;
}

/* Fade in particles during setdown */
.book-desk-scene--settingdown .book-table-particles {
    opacity: 0;
    animation: tableParticlesFadeIn 0.8s ease 0.6s forwards;
}

@keyframes tableParticlesFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Hide particles in all non-table states */
.book-desk-scene--cover .book-table-particles,
.book-desk-scene--opening .book-table-particles,
.book-desk-scene--settling .book-table-particles,
.book-desk-scene--book .book-table-particles,
.book-desk-scene--closing .book-table-particles {
    display: none;
}

/* Reduced motion: disable particles and rim glow pulsing */
@media (prefers-reduced-motion: reduce) {
    .book-table-particle {
        animation: none !important;
        opacity: 0 !important;
    }

    .book-desk-scene--table .book-3d-spine,
    .book-desk-scene--table .book-3d-edge-right,
    .book-desk-scene--table .book-3d-edge-top,
    .book-desk-scene--table .book-3d-edge-bottom {
        animation: none !important;
    }
}

/* ── Hint card — Table state interactive guide ──────────────────── */
.book-hint-card {
    position: absolute;
    left: 50%;
    top: 12%;
    transform: translateX(-50%);
    z-index: 10;
    width: clamp(220px, 18vw, 300px);
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-radius: 14px;
    border: 1px solid rgba(212, 175, 55, 0.15);
    border-bottom: 3px solid var(--book-gold-leaf, #D4AF37);
    padding: clamp(16px, 1.5vw, 24px);
    animation: hintCardSlideDown 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0.5s both;
    pointer-events: auto;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3),
                inset 0 1px 0 rgba(255, 255, 255, 0.04);
    text-align: center;
}

/* Hide card during guest rotation */
.book-desk-scene.guest-rotating > .book-hint-card {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
}

.book-hint-card__close {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 6px;
    color: rgba(255, 255, 255, 0.4);
    cursor: pointer;
    transition: color 0.2s, border-color 0.2s, background 0.2s;
    padding: 0;
}
.book-hint-card__close:hover {
    color: var(--book-gold-leaf, #D4AF37);
    border-color: rgba(212, 175, 55, 0.3);
    background: rgba(212, 175, 55, 0.08);
}

.book-hint-card__header {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-bottom: 0;
}

.book-hint-card__icon {
    color: var(--book-gold-leaf, #D4AF37);
    flex-shrink: 0;
    opacity: 0.8;
}

.book-hint-card__title {
    font-family: var(--font-heading);
    color: var(--book-gold-leaf, #D4AF37);
    font-size: clamp(0.8rem, 1.1vw, 1rem);
    text-transform: uppercase;
    letter-spacing: 0.12em;
    text-shadow: 0 1px 6px rgba(0, 0, 0, 0.3);
}

.book-hint-card__divider {
    height: 1px;
    background: linear-gradient(90deg, var(--book-gold-leaf, #D4AF37), transparent);
    opacity: 0.2;
    margin: clamp(10px, 1vw, 14px) 0;
}

.book-hint-card__body {
    display: flex;
    flex-direction: column;
    gap: clamp(8px, 0.8vw, 12px);
}

.book-hint-card__instruction {
    font-family: var(--font-body, 'Lato', sans-serif);
    color: rgba(255, 255, 255, 0.85);
    font-size: clamp(0.75rem, 1vw, 0.88rem);
    line-height: 1.5;
    margin: 0;
}

.book-hint-card__controls {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

/* Center controls inside the top-centered table card */
.book-hint-card .book-hint-card__controls {
    align-items: center;
}

.book-hint-card .book-hint-card__control {
    justify-content: center;
}

.book-hint-card__control {
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: var(--font-body, 'Lato', sans-serif);
    color: rgba(255, 255, 255, 0.55);
    font-size: clamp(0.68rem, 0.9vw, 0.8rem);
    letter-spacing: 0.02em;
}

.book-hint-card__control-icon {
    color: var(--book-gold-leaf, #D4AF37);
    opacity: 0.6;
    flex-shrink: 0;
    display: flex;
}

/* Animated click icon — gentle pulse to draw attention */
.book-hint-card__control-icon--click {
    animation: hintClickPulse 1.8s ease-in-out infinite;
}

/* Animated rotate icon — oscillating rotation to suggest drag motion */
.book-hint-card__control-icon--rotate {
    animation: hintRotateOscillate 2.2s ease-in-out infinite;
}

@keyframes hintClickPulse {
    0%, 100% { transform: scale(1); opacity: 0.6; }
    50%      { transform: scale(1.2); opacity: 1; }
}

@keyframes hintRotateOscillate {
    0%, 100% { transform: rotate(0deg); opacity: 0.6; }
    25%      { transform: rotate(-20deg); opacity: 0.9; }
    75%      { transform: rotate(20deg); opacity: 0.9; }
}

/* Table hint card arrow — bouncing down arrow pointing at the book */
.book-hint-card__arrow {
    display: flex;
    justify-content: center;
    margin-top: clamp(8px, 0.8vw, 14px);
    color: var(--book-gold-leaf, #D4AF37);
    animation: hintArrowBounce 1.5s ease-in-out infinite;
    filter: drop-shadow(0 2px 6px rgba(212, 175, 55, 0.4));
}

@keyframes hintArrowBounce {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(8px); }
}

@keyframes hintCardSlideDown {
    from {
        opacity: 0;
        transform: translateX(-50%) translateY(-20px);
    }
    to {
        opacity: 1;
        transform: translateX(-50%) translateY(0);
    }
}

/* ── Cover state hint card — left-aligned with drag-to-rotate ──── */
.book-cover-hint-card {
    position: absolute;
    left: 5%;
    top: 50%;
    transform: translateY(-50%);
    z-index: 10;
    width: clamp(220px, 18vw, 300px);
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-radius: 14px;
    border: 1px solid rgba(212, 175, 55, 0.15);
    border-right: 3px solid var(--book-gold-leaf, #D4AF37);
    padding: clamp(16px, 1.5vw, 24px);
    animation: coverHintCardSlideIn 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0.5s both;
    pointer-events: auto;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3),
                inset 0 1px 0 rgba(255, 255, 255, 0.04);
}

/* Hide cover hint card during guest rotation */
.book-desk-scene.guest-rotating > .book-cover-hint-card {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
}

@keyframes coverHintCardSlideIn {
    from {
        opacity: 0;
        transform: translateY(-50%) translateX(-20px);
    }
    to {
        opacity: 1;
        transform: translateY(-50%) translateX(0);
    }
}

@keyframes hintCardSlideIn {
    from {
        opacity: 0;
        transform: translateY(-50%) translateX(20px);
    }
    to {
        opacity: 1;
        transform: translateY(-50%) translateX(0);
    }
}

/* ── Hint card responsive ─────────────────────────────────────── */

/* 4K+ displays: more breathing room */
@media (min-width: 2560px) {
    .book-hint-card {
        width: clamp(260px, 16vw, 340px);
    }
    .book-cover-hint-card {
        left: 8%;
        width: clamp(260px, 16vw, 340px);
    }
}

/* Smaller laptops: keep top-center for table card, move cover card to bottom */
@media (max-width: 1400px) {
    .book-hint-card {
        width: clamp(260px, 40vw, 380px);
    }

    .book-cover-hint-card {
        left: auto;
        top: auto;
        bottom: 6%;
        left: 50%;
        transform: translateX(-50%);
        width: clamp(280px, 50vw, 420px);
        border-right: 1px solid rgba(212, 175, 55, 0.15);
        border-top: 3px solid var(--book-gold-leaf, #D4AF37);
        animation: hintCardSlideUp 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0.5s both;
    }

    .book-hint-card__controls,
    .book-cover-hint-card .book-hint-card__controls {
        flex-direction: row;
        gap: 16px;
    }
}

@keyframes hintCardSlideUp {
    from {
        opacity: 0;
        transform: translateX(-50%) translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateX(-50%) translateY(0);
    }
}

/* Cover state hint arrow — fix diagonal bounce direction */
@keyframes hintBounce {
    0%, 100% { transform: translateY(0) rotate(-45deg); }
    50%      { transform: translateY(6px) rotate(-45deg); }
}

@keyframes hintFadeIn {
    from {
        opacity: 0;
        transform: translateX(-50%) translateY(-10px);
    }
    to {
        opacity: 1;
        transform: translateX(-50%);
    }
}

/* ── PickingUp state: Table → Cover transition ─────────────────── */

.book-desk-scene--pickingup .book-desk-surface {
    perspective: var(--book-closed-perspective);
    transform-style: preserve-3d;
}

/* Animate from table rotation/scale to cover rotation/scale */
:not(.book-desk-scene--play).book-desk-scene--pickingup .book-frame {
    transform-style: preserve-3d;
    overflow: visible;
    isolation: auto;
    cursor: default;
    transform:
        rotateX(var(--book-closed-rotate-x))
        rotateY(var(--book-closed-rotate-y))
        rotateZ(var(--book-closed-rotate-z));
    transition: transform var(--book-table-pickup-duration) cubic-bezier(0.22, 0.68, 0.18, 1);
}

.book-desk-scene--pickingup .book-viewport,
.book-desk-scene--pickingup .book-page-stack,
.book-desk-scene--pickingup .book-cover-page {
    transform-style: preserve-3d;
}

.book-desk-scene--pickingup .book-viewport {
    perspective: none;
    background: transparent;
}

.book-desk-scene--pickingup .book-frame-right {
    transform-style: preserve-3d;
    overflow: visible;
    width: 100%;
    flex: 1;
}

/* Front cover position (same as Cover state) */
.book-desk-scene--pickingup .book-cover-page {
    transform:
        translateX(var(--book-front-cover-extra-tx))
        translateY(var(--book-front-cover-extra-ty))
        translateZ(calc(var(--book-closed-page-depth) + 2px + var(--book-front-cover-extra-tz)))
        rotateX(var(--book-front-cover-extra-rx))
        rotateY(var(--book-front-cover-extra-ry))
        rotateZ(var(--book-front-cover-extra-rz));
    top: calc(-1 * var(--book-cover-overhang-top));
    left: 0;
    right: calc(-1 * var(--book-cover-overhang-right));
    bottom: calc(-1 * var(--book-cover-overhang-bottom));
}

.book-desk-scene--pickingup .book-cover-page-front {
    box-shadow: inset 0 0 40px rgba(0, 0, 0, var(--book-cover-vignette-intensity));
}

/* Hidden elements (same as Cover) */
.book-desk-scene--pickingup .book-spine-3d {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none !important;
}

.book-desk-scene--pickingup .book-frame::after {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none;
}

.book-desk-scene--pickingup .book-3d-back-edge {
    display: none;
}

.book-desk-scene--pickingup .book-nav,
.book-desk-scene--pickingup .book-nav-ribbons {
    opacity: 0;
    pointer-events: none;
}

.book-desk-scene--pickingup .book-3d-depth {
    opacity: 1;
    visibility: visible;
    pointer-events: none;
    transition: opacity 0.6s ease, visibility 0s linear 0s;
}

.book-desk-scene--pickingup .book-page {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

/* Glow fades out during pickup */
.book-desk-scene--pickingup .book-3d-depth::before {
    content: '';
    position: absolute;
    inset: -15px;
    transform: translateZ(-3px);
    border-radius: 8px;
    box-shadow:
        0 0 var(--book-table-glow-blur) var(--book-table-glow-spread) var(--book-table-glow-color);
    opacity: 0;
    transition: opacity 0.4s ease;
    pointer-events: none;
    z-index: -1;
}

/* Rim glow fades out during pickup */
.book-desk-scene--pickingup .book-3d-spine,
.book-desk-scene--pickingup .book-3d-edge-right,
.book-desk-scene--pickingup .book-3d-edge-top,
.book-desk-scene--pickingup .book-3d-edge-bottom,
.book-desk-scene--pickingup .book-3d-back-cover-face,
.book-desk-scene--pickingup .book-cover-page-front {
    box-shadow: 0 0 0 0 transparent;
    animation: none;
    transition: box-shadow 0.4s ease;
}

/* Shadow persists during pickup (contact shadow) */
.book-desk-scene--pickingup .book-3d-depth::after {
    content: '';
    position: absolute;
    inset: -4px;
    transform: translateZ(-4px);
    border-radius: 4px 10px 10px 4px;
    box-shadow:
        var(--book-table-shadow-offset-x)
        var(--book-table-shadow-offset-y)
        var(--book-table-shadow-blur)
        var(--book-table-shadow-spread)
        var(--book-table-shadow-color);
    opacity: var(--book-table-shadow-opacity);
    transition: opacity 0.8s ease;
    pointer-events: none;
    z-index: -2;
}

/* ── SettingDown state: Cover → Table transition (admin) ───────── */

.book-desk-scene--settingdown .book-desk-surface {
    perspective: var(--book-table-perspective);
    transform-style: preserve-3d;
}

/* Animate from cover rotation to table flat rotation */
:not(.book-desk-scene--play).book-desk-scene--settingdown .book-frame {
    transform-style: preserve-3d;
    overflow: visible;
    isolation: auto;
    cursor: default;
    transform:
        rotateX(var(--book-table-rotate-x))
        rotateY(var(--book-table-rotate-y))
        rotateZ(var(--book-table-rotate-z))
        scale(var(--book-table-scale))
        translateX(var(--book-table-translate-x))
        translateY(var(--book-table-translate-y))
        translateZ(var(--book-table-translate-z));
    transition: transform var(--book-table-setdown-duration) cubic-bezier(0.22, 0.68, 0.18, 1);
}

.book-desk-scene--settingdown .book-viewport,
.book-desk-scene--settingdown .book-page-stack,
.book-desk-scene--settingdown .book-cover-page {
    transform-style: preserve-3d;
}

.book-desk-scene--settingdown .book-viewport {
    perspective: none;
    background: transparent;
}

.book-desk-scene--settingdown .book-frame-right {
    transform-style: preserve-3d;
    overflow: visible;
    width: 100%;
    flex: 1;
}

.book-desk-scene--settingdown .book-cover-page {
    transform:
        translateX(var(--book-front-cover-extra-tx))
        translateY(var(--book-front-cover-extra-ty))
        translateZ(calc(var(--book-closed-page-depth) + 2px + var(--book-front-cover-extra-tz)))
        rotateX(var(--book-front-cover-extra-rx))
        rotateY(var(--book-front-cover-extra-ry))
        rotateZ(var(--book-front-cover-extra-rz));
    top: calc(-1 * var(--book-cover-overhang-top));
    left: 0;
    right: calc(-1 * var(--book-cover-overhang-right));
    bottom: calc(-1 * var(--book-cover-overhang-bottom));
}

.book-desk-scene--settingdown .book-cover-page-front {
    box-shadow: inset 0 0 40px rgba(0, 0, 0, var(--book-cover-vignette-intensity));
}

.book-desk-scene--settingdown .book-spine-3d {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none !important;
}

.book-desk-scene--settingdown .book-frame::after {
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none;
}

.book-desk-scene--settingdown .book-3d-back-edge {
    display: none;
}

.book-desk-scene--settingdown .book-nav,
.book-desk-scene--settingdown .book-nav-ribbons {
    opacity: 0;
    pointer-events: none;
}

.book-desk-scene--settingdown .book-3d-depth {
    opacity: 1;
    visibility: visible;
    pointer-events: none;
    transition: opacity 0.6s ease, visibility 0s linear 0s;
}

.book-desk-scene--settingdown .book-page {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

/* Rim glow fades in as book settles on table */
.book-desk-scene--settingdown .book-3d-spine,
.book-desk-scene--settingdown .book-3d-edge-right,
.book-desk-scene--settingdown .book-3d-edge-top,
.book-desk-scene--settingdown .book-3d-edge-bottom,
.book-desk-scene--settingdown .book-3d-back-cover-face,
.book-desk-scene--settingdown .book-cover-page-front {
    box-shadow:
        0 0 var(--book-table-rim-blur) var(--book-table-rim-spread) var(--book-table-rim-color);
    animation: none;
    transition: box-shadow 0.8s ease 0.4s;
}

/* Floor halo fades in as book settles on table */
.book-desk-scene--settingdown .book-3d-depth::before {
    content: '';
    position: absolute;
    inset: -15px;
    transform: translateZ(-3px);
    border-radius: 8px;
    box-shadow:
        0 0 var(--book-table-glow-blur) var(--book-table-glow-spread) var(--book-table-glow-color);
    opacity: var(--book-table-glow-intensity);
    transition: opacity 0.8s ease 0.4s;
    pointer-events: none;
    z-index: -1;
}

.book-desk-scene--settingdown .book-3d-depth::after {
    content: '';
    position: absolute;
    inset: -4px;
    transform: translateZ(-4px);
    border-radius: 4px 10px 10px 4px;
    box-shadow:
        var(--book-table-shadow-offset-x)
        var(--book-table-shadow-offset-y)
        var(--book-table-shadow-blur)
        var(--book-table-shadow-spread)
        var(--book-table-shadow-color);
    opacity: var(--book-table-shadow-opacity);
    pointer-events: none;
    z-index: -2;
}

/* ── Desktop overrides ────────────────────────────────────────── */

@media (min-width: 1200px) {
    /* Closed book: single-page width */
    .book-desk-scene--cover .book-frame {
        width: min(800px, 42vw);
        height: min(88vh, 800px);
    }

    /* Opening: starts at single-page width, expands to spread when cover swings.
       The width transition happens DURING the cover swing while the frame is
       still at a 3D angle, hiding the lateral shift from the viewer.
       .book-frame--open triggers the expansion at the same time as the cover. */
    .book-desk-scene--opening .book-frame {
        width: min(800px, 42vw);
        height: min(88vh, 800px);
    }
    .book-desk-scene--opening .book-frame.book-frame--open {
        width: min(1600px, 85vw);
    }

    /* Settling: confirms spread width (already reached during Opening) */
    .book-desk-scene--settling .book-frame {
        width: min(1600px, 85vw);
        height: min(88vh, 800px);
    }

    /* Table: single-page width (scale handles visual size) */
    .book-desk-scene--table .book-frame,
    .book-desk-scene--pickingup .book-frame,
    .book-desk-scene--settingdown .book-frame {
        width: min(800px, 42vw);
        height: min(88vh, 800px);
    }

    /* Closing: shrink back to single-page width */
    .book-desk-scene--closing .book-frame {
        width: min(800px, 42vw);
        height: min(88vh, 800px);
    }

    /* Closing: right side back to 100% */
    .book-desk-scene--closing .book-frame-right {
        width: 100%;
        flex: 1;
        transition: width var(--book-closed-open-duration) cubic-bezier(0.22, 0.68, 0.18, 1);
    }

    /* Book state: subtle page-stack thickness visible along bottom edge.
       In the open book, the page stack has slight visible thickness at the edges,
       giving the book a grounded, physical presence rather than a flat panel. */
    .book-desk-scene--book .book-frame-right {
        box-shadow:
            3px 3px 0 0 rgba(200, 190, 170, 0.4),
            4px 4px 0 0 rgba(180, 170, 150, 0.3),
            5px 5px 2px 0 rgba(0, 0, 0, 0.06);
    }

    /* Opening: right side starts at 100%, transitions to 50% when cover swings.
       margin-left:auto keeps it anchored to the right side of the flex container. */
    .book-desk-scene--opening .book-frame-right {
        width: 100%;
        flex: 1;
        transition: width 0.6s cubic-bezier(0.22, 0.68, 0.18, 1),
                    flex 0.6s cubic-bezier(0.22, 0.68, 0.18, 1);
    }
    .book-desk-scene--opening .book-frame.book-frame--open .book-frame-right {
        width: 50%;
        flex: none;
        margin-left: auto;
    }

    /* Settling/Book: right side at 50%, anchored right via margin-left:auto.
       This ensures the right page stays in the right half of the frame. */
    .book-desk-scene--settling .book-frame-right,
    .book-desk-scene--book .book-frame-right {
        width: 50%;
        flex: none;
        margin-left: auto;
        /* Width transition removed — play mode animation handles width changes.
           A transition here would fire when play mode drops, causing visible sliding. */
        transition: none;
    }

    /* Gutter appears after settling — opacity transition instead of display toggle */
    .book-desk-scene--book .book-frame::after {
        opacity: 1;
        visibility: visible;
        animation: gutterFadeIn 0.6s ease 0.8s both;
    }

    @keyframes gutterFadeIn {
        0% { opacity: 0; }
        100% { opacity: 1; }
    }
}

/* ── Mobile/tablet closed book sizing ─────────────────────────── */

@media (max-width: 1199px) {
    .book-desk-scene--cover .book-frame,
    .book-desk-scene--opening .book-frame {
        width: min(var(--book-frame-max-w), 50vw);
    }

    .book-desk-scene--settling .book-frame {
        width: min(var(--book-frame-max-w), 50vw);
    }

    .book-desk-scene--closing .book-frame {
        width: min(var(--book-frame-max-w), 50vw);
    }

    .book-desk-scene--table .book-frame,
    .book-desk-scene--pickingup .book-frame,
    .book-desk-scene--settingdown .book-frame {
        width: min(var(--book-frame-max-w), 50vw);
    }
}

@media (max-width: 768px) {
    .book-desk-scene--cover .book-frame,
    .book-desk-scene--opening .book-frame {
        width: min(var(--book-frame-max-w), 70vw);
    }

    .book-desk-scene--settling .book-frame {
        width: min(var(--book-frame-max-w), 96vw);
    }

    .book-desk-scene--closing .book-frame {
        width: min(var(--book-frame-max-w), 70vw);
    }

    .book-desk-scene--table .book-frame,
    .book-desk-scene--pickingup .book-frame,
    .book-desk-scene--settingdown .book-frame {
        width: min(var(--book-frame-max-w), 70vw);
    }

    .book-hint-card__instruction {
        white-space: normal;
    }
}

@media (max-width: 480px) {
    .book-desk-scene--cover .book-frame,
    .book-desk-scene--opening .book-frame {
        width: 75vw;
    }

    .book-desk-scene--settling .book-frame {
        width: 98vw;
    }

    .book-desk-scene--closing .book-frame {
        width: 75vw;
    }

    .book-desk-scene--table .book-frame,
    .book-desk-scene--pickingup .book-frame,
    .book-desk-scene--settingdown .book-frame {
        width: 75vw;
    }
}


/* Debug colors removed — production textures active */
