/* ============================================================================
   STORYBOOK COMPONENT — 3D hardcover book with page-flip animations
   Scoped under `.storybook-scene` so it never touches the rest of the site.

   To embed: link this stylesheet, drop a `.storybook-scene` markup block, and
   include `/scripts/storybook.js` which auto-initializes every instance.
   Responds to `body.dark-mode` — no component-level theme state.
   ============================================================================ */

/* ---------------------------------------------------------------- SCENE ---- */
.storybook-scene {
    /* Responsive sizing — the book shrinks to fit any viewport so the open
       spread (2 × book-w + gutters) never clips. */
    --sb-max-book-w: 460px;
    --sb-aspect: 1.28;
    --sb-gutter: 36px;
    --sb-controls-space: 150px;

    /* Width constraint uses gutter × 2 (one gutter on each side of the open
       spread). The earlier × 4 was conservative and left too much dead space
       on mobile, which squeezed the book down to <150px and forced story
       text to overflow. × 2 lets the book occupy more of the viewport. */
    --sb-book-w: min(
        var(--sb-max-book-w),
        calc((100vw - var(--sb-gutter) * 2) / 2),
        calc((100vh - var(--sb-controls-space)) / var(--sb-aspect))
    );
    --sb-book-h: calc(var(--sb-book-w) * var(--sb-aspect));
    --sb-cover-thickness: max(8px, calc(var(--sb-book-w) * 0.028));

    /* Light mode palette : BLACK cover, CREAM pages */
    --sb-cover-bg: #0b0b0b;
    --sb-cover-deep: #000000;
    --sb-cover-sheen: rgba(255, 255, 255, 0.04);
    --sb-cover-ink: rgba(255, 255, 255, 0.92);
    --sb-cover-edge: rgba(255, 255, 255, 0.1);
    --sb-cover-frame: rgba(255, 255, 255, 0.14);

    --sb-page-bg: #faf7f0;
    --sb-page-bg-edge: #f1ead8;
    --sb-page-ink: #26221e;
    --sb-page-edge: #e4dbc5;
    --sb-page-shadow: rgba(60, 45, 20, 0.2);

    --sb-table-shadow: rgba(0, 0, 0, 0.22);

    --sb-logo-filter: invert(1);
    --sb-cover-transition: 1250ms cubic-bezier(0.68, 0.04, 0.26, 1);
    --sb-page-transition: 950ms cubic-bezier(0.55, 0.05, 0.3, 1);

    position: relative;
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 60px;
    padding: 40px var(--sb-gutter);
    box-sizing: border-box;
    perspective: 2600px;
    perspective-origin: 50% 40%;
    user-select: none;
    -webkit-user-select: none;
    overflow: hidden;
}

/* Dark mode palette : WHITE/CREAM cover, DARK PARCHMENT pages */
body.dark-mode .storybook-scene {
    --sb-cover-bg: #f4efe5;
    --sb-cover-deep: #e4dcca;
    --sb-cover-sheen: rgba(0, 0, 0, 0.03);
    --sb-cover-ink: rgba(10, 10, 10, 0.88);
    --sb-cover-edge: rgba(0, 0, 0, 0.1);
    --sb-cover-frame: rgba(0, 0, 0, 0.14);

    --sb-page-bg: #1c1a16;
    --sb-page-bg-edge: #14120f;
    --sb-page-ink: #e8e0cf;
    --sb-page-edge: #2a2720;
    --sb-page-shadow: rgba(0, 0, 0, 0.55);

    --sb-table-shadow: rgba(0, 0, 0, 0.65);

    --sb-logo-filter: none;
}

/* -------------------------------------------------------- BOOK WRAPPER ---- */
.sb-book-float {
    transform-style: preserve-3d;
    animation: sb-float 6s ease-in-out infinite;
    will-change: transform;
    position: relative;
    /* This wrapper exists only to host the idle float animation — it has
       no visible content of its own, but its 2D bounding box sits at Z=0
       where the click-zones and the back-cover link live behind it in 3D.
       Letting it stay hit-testable means it intercepts clicks on the "here"
       link. Make it click-through; the `.sb-book` inside still takes clicks
       when closed (it defaults to pointer-events: auto), and its children
       (click-zones, in-page links, back-cover link) re-enable themselves
       when open. */
    pointer-events: none;
}
.storybook-scene.book-open .sb-book-float {
    animation-play-state: paused;
}
@keyframes sb-float {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-5px); }
}

.sb-book {
    position: relative;
    width: var(--sb-book-w);
    height: var(--sb-book-h);
    transform-style: preserve-3d;
    transform: var(--sb-book-rot, rotateX(8deg) rotateY(-22deg));
    transition: transform 1.1s cubic-bezier(0.22, 1, 0.36, 1);
    cursor: pointer;
    z-index: 2;
    /* Explicit auto so the closed book stays clickable even though its
       parent `.sb-book-float` is pointer-events: none (pointer-events does
       inherit, so without this the book would inherit none and the click-
       to-open handler would never fire). The `.is-open` rule below flips
       it back to none so open-state clicks fall through to the link and
       click-zones. */
    pointer-events: auto;
}
/* Closed state — keyboard focus ring for accessibility. */
.sb-book:not(.is-open):focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 20px;
    border-radius: 4px;
}
/* Open state — a hairline cover edge flush with the book, always on.
   Uses the theme's cover color (cream in dark, black in light) so it reads
   as the book's own cover showing at the perimeter of the spread, not as
   a floating focus ring. Decoupled from :focus-visible so it never flickers
   between navigation modes (arrow / page-click / keyboard). */
.sb-book.is-open,
.sb-book.is-open:focus,
.sb-book.is-open:focus-visible {
    outline: 1px solid var(--sb-cover-bg);
    outline-offset: 0;
    border-radius: 3px 6px 6px 3px;
}
.sb-book.is-open {
    transform: rotateX(4deg) rotateY(0deg) translateX(calc(var(--sb-book-w) / 2)) scale(0.95);
    cursor: default;
    /* Let clicks fall through the book's own surface to its children — the
       click-zones, in-page links, and back-cover link all opt back in with
       their own `pointer-events: auto`. */
    pointer-events: none;
}

/* Table shadow beneath the book — widens when open */
.sb-book::after {
    content: '';
    position: absolute;
    left: 50%;
    bottom: -30px;
    width: 120%;
    height: 30px;
    transform: translateX(-50%) rotateX(78deg) scaleX(1);
    background: radial-gradient(ellipse at center,
        var(--sb-table-shadow) 0%,
        transparent 65%);
    filter: blur(14px);
    opacity: 0.7;
    transition: width 1s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.6s ease;
    pointer-events: none;
    z-index: -1;
}
.sb-book.is-open::after {
    width: 210%;
    opacity: 0.85;
}

/* ------------------------------------------------------------------ SPINE ---- */
.sb-spine {
    position: absolute;
    left: 0;
    top: 0;
    width: var(--sb-cover-thickness);
    height: 100%;
    transform-origin: right center;
    transform: translateX(calc(var(--sb-cover-thickness) / -2)) rotateY(-90deg);
    background:
        linear-gradient(90deg,
            var(--sb-cover-deep) 0%,
            var(--sb-cover-bg) 22%,
            var(--sb-cover-bg) 78%,
            var(--sb-cover-deep) 100%);
    box-shadow: inset 0 0 18px rgba(0,0,0,0.45);
}
.sb-spine::before,
.sb-spine::after {
    content: '';
    position: absolute;
    left: 14%;
    right: 14%;
    height: 1px;
    background: var(--sb-cover-edge);
}
.sb-spine::before { top: 22%; }
.sb-spine::after  { bottom: 22%; }

/* ---------------------------------------------------------- BACK COVER ---- */
.sb-back-cover {
    position: absolute;
    inset: 0;
    transform: translateZ(calc(var(--sb-cover-thickness) / -2));
    border-radius: 3px 6px 6px 3px;
    background:
        radial-gradient(ellipse at 70% 80%, var(--sb-cover-sheen) 0%, transparent 55%),
        linear-gradient(135deg, var(--sb-cover-bg) 0%, var(--sb-cover-deep) 100%);
    box-shadow:
        inset 0 0 0 1px var(--sb-cover-edge),
        inset 0 0 70px rgba(0,0,0,0.3);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 12% 14%;
    box-sizing: border-box;
}

/* Handwritten sign-off on the back cover. Revealed line-by-line once the
   book reaches the last spread (`.sb-book.at-end`), in the custom cursive
   used in the contact form. Lines start hidden and clip-path-reveal
   left-to-right so it reads like the text is being written in real time. */
.sb-back-note {
    position: relative;
    z-index: 4;
    width: 100%;
    pointer-events: none;
}
.sb-handwriting {
    font-family: 'Homemade Apple', 'Bruno Font', cursive;
    font-weight: 400;
    /* Cursive glyphs are wider than serif body text, so the scaling factor
       is a touch lower. 9px floor keeps the longest line ("If you'd like
       to learn") from wrapping on a 320px phone. */
    font-size: clamp(9px, calc(var(--sb-book-w) * 0.042), 22px);
    line-height: 1.6;
    letter-spacing: 0.005em;
    color: var(--sb-cover-ink);
    margin: 0;
    text-align: left;
}
.sb-handwriting .sb-line {
    display: block;
}
/* Each character gets wrapped in a `.sb-char` by storybook.js on init
   (spaces stay as plain text so line-wrap still works). Each char is
   invisible until the book reaches the end, then reveals in sequence
   with a stagger driven by the `--sb-char-i` index set in JS. */
.sb-handwriting .sb-char {
    display: inline-block;
    opacity: 0;
    transform: translateY(-1px);
    filter: blur(1.2px);
    will-change: opacity, filter, transform;
}
.sb-handwriting a {
    color: inherit;
    text-decoration: none;
    display: inline-block;
    pointer-events: auto;
    position: relative;
    z-index: 50;
    transition: opacity 0.25s ease;
}
/* The underline is drawn by a pseudo-element so it can animate as the
   last pen stroke AFTER all the characters have been written. */
.sb-handwriting a::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: -4px;
    height: 1px;
    background: currentColor;
    transform: scaleX(0);
    transform-origin: left center;
}
.sb-handwriting a:hover { opacity: 0.7; }


/* Writing cadence:
   - 0.5s initial pause lets the last page-flip settle before the pen starts
   - 55ms stagger between characters (~18 chars/sec — natural writing pace)
   - 140ms per-character fade/settle, so 2–3 chars are "in motion" at once
     and the reveal reads as a continuous pen stroke rather than a line-wipe. */
.sb-book.at-end .sb-handwriting .sb-char {
    animation: sb-char-write 140ms cubic-bezier(0.4, 0, 0.5, 1) forwards;
    animation-delay: calc(0.5s + var(--sb-char-i, 0) * 55ms);
}

@keyframes sb-char-write {
    0%   { opacity: 0; transform: translateY(-1px); filter: blur(1.2px); }
    60%  { opacity: 0.85; }
    100% { opacity: 1; transform: translateY(0); filter: blur(0); }
}

/* The final pen stroke: the underline under "here" draws in left-to-right
   right after the last character of the note is written. Timing:
   0.5s (initial) + 96 (last char index) × 55ms = 5.78s for the last char
   animation to start; +140ms for it to finish = 5.92s. Start the underline
   a hair later at 6.0s and let it sweep across in 520ms. */
.sb-book.at-end .sb-handwriting a::after {
    animation: sb-underline-stroke 520ms cubic-bezier(0.33, 0, 0.2, 1) forwards;
    animation-delay: 6s;
}

@keyframes sb-underline-stroke {
    0%   { transform: scaleX(0); }
    100% { transform: scaleX(1); }
}

/* The "-Bruno" sign-off sits below the note, right-aligned like a real
   handwritten signature. Its characters use the same per-char reveal as
   the rest of the handwriting, but with an additional 1.1s offset so it
   only starts AFTER the underline finishes drawing (underline finishes
   at 6.52s; sign-off starts at ~6.94s). */
.sb-handwriting .sb-signoff {
    display: block;
    margin-top: 1.5em;
    text-align: right;
    padding-right: 4%;
}
.sb-book.at-end .sb-handwriting .sb-signoff .sb-char {
    animation-delay: calc(0.5s + var(--sb-char-i, 0) * 55ms + 1100ms);
}

@media (prefers-reduced-motion: reduce) {
    .sb-book.at-end .sb-handwriting .sb-char {
        animation: none;
        opacity: 1;
        transform: none;
        filter: none;
    }
    .sb-book.at-end .sb-handwriting a::after {
        animation: none;
        transform: scaleX(1);
    }
}

/* ---------------------------------------------------- PAGE-STACK EDGE ---- */
.sb-page-stack {
    position: absolute;
    top: 6px;
    bottom: 6px;
    width: 7px;
    right: -1px;
    transform: translateZ(0.1px);
    background:
        linear-gradient(to right, var(--sb-page-bg-edge) 0%, var(--sb-page-edge) 100%),
        repeating-linear-gradient(
            to bottom,
            var(--sb-page-edge) 0px,
            var(--sb-page-edge) 1px,
            color-mix(in srgb, var(--sb-page-edge) 78%, transparent) 1px,
            color-mix(in srgb, var(--sb-page-edge) 78%, transparent) 2.2px
        );
    background-blend-mode: multiply;
    border-radius: 0 2px 2px 0;
    box-shadow:
        1px 0 2px rgba(0,0,0,0.08),
        inset 0 0 3px rgba(0,0,0,0.12);
    opacity: 1;
    transition: opacity 0.6s ease;
}
.storybook-scene.book-open .sb-page-stack {
    opacity: 0.55;
}

/* -------------------------------------------------------- FRONT COVER ---- */
.sb-cover {
    position: absolute;
    inset: 0;
    transform-origin: left center;
    transform: translateZ(calc(var(--sb-cover-thickness) / 2));
    transform-style: preserve-3d;
    transition: transform var(--sb-cover-transition);
    z-index: 500;
}
.sb-book.is-open .sb-cover {
    transform: translateZ(calc(var(--sb-cover-thickness) / 2)) rotateY(-174deg);
    z-index: 10;
}

.sb-cover-face {
    position: absolute;
    inset: 0;
    border-radius: 3px 6px 6px 3px;
    overflow: hidden;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
    transition: background 0.6s ease, box-shadow 0.6s ease;
}

.sb-cover-front {
    background:
        radial-gradient(ellipse at 30% 24%, var(--sb-cover-sheen) 0%, transparent 60%),
        radial-gradient(ellipse at 72% 82%, color-mix(in srgb, var(--sb-cover-sheen) 50%, transparent) 0%, transparent 50%),
        linear-gradient(135deg, var(--sb-cover-bg) 0%, var(--sb-cover-deep) 100%);
    box-shadow:
        inset 0 0 0 1px var(--sb-cover-edge),
        inset 2px 0 10px rgba(0,0,0,0.4),
        inset 0 0 90px rgba(0,0,0,0.25);
    display: flex;
    align-items: center;
    justify-content: center;
}
.sb-cover-front::before {
    content: '';
    position: absolute;
    inset: 0;
    opacity: 0.38;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='cc'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' seed='13' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='discrete' tableValues='0 0.25 0.5 0.75 1'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23cc)'/%3E%3C/svg%3E");
    background-size: 200px 200px;
    mix-blend-mode: overlay;
    pointer-events: none;
}
.sb-cover-front::after {
    content: '';
    position: absolute;
    inset: 22px;
    border: 1px solid var(--sb-cover-frame);
    border-radius: 2px;
    box-shadow:
        inset 0 0 0 4px transparent,
        inset 0 0 0 5px var(--sb-cover-frame);
    pointer-events: none;
}

.sb-cover-logo {
    width: 56%;
    max-width: 240px;
    aspect-ratio: 1;
    position: relative;
    z-index: 2;
    /* SVG's feColorMatrix strips the logo PNG's white background to alpha.
       --sb-logo-filter flips the silhouette color between themes. */
    filter: var(--sb-logo-filter) drop-shadow(0 2px 10px rgba(0,0,0,0.25));
    transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1), filter 0.6s ease;
    overflow: visible;
}
.sb-cover-logo image {
    filter: url(#sb-logo-alpha);
}
/* When the book opens, the cover-front rotates to face away — but the SVG
   logo's own filter compositing layer ignores `backface-visibility: hidden`
   on the parent face, so the silhouette ghosts through the cover-inner
   as soon as rotation passes 90° (edge-on).
   Gate the whole front face's visibility with a delay timed to the edge-on
   moment of the 1.25s rotation.
   Math: with transition timing `cubic-bezier(0.68, 0.04, 0.26, 1)` on the
   cover transform, rotation reaches ±90° (perpendicular, physically
   invisible) at ~0.58s of the 1.25s animation in both directions. Flipping
   visibility there is imperceptible — the cover is zero-area anyway — and
   it kills any ghosting on BOTH the open and close transitions. */
.sb-cover-front {
    visibility: visible;
    transition: visibility 0s linear 0.58s;
}
.sb-book.is-open .sb-cover-front {
    visibility: hidden;
    transition: visibility 0s linear 0.58s;
}
.sb-book:not(.is-open):hover .sb-cover-logo {
    transform: scale(1.04);
}

.sb-cover-inner {
    transform: rotateY(180deg);
    background:
        radial-gradient(ellipse at 50% 38%,
            color-mix(in srgb, var(--sb-page-bg) 96%, white) 0%,
            var(--sb-page-bg) 70%),
        var(--sb-page-bg);
    box-shadow: inset 4px 0 18px rgba(0,0,0,0.12);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 8%;
    box-sizing: border-box;
}
.sb-cover-inner::after {
    content: '';
    position: absolute;
    inset: 0;
    opacity: 0.14;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='420' height='420'%3E%3Cfilter id='pp'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.4' numOctaves='6' seed='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='420' height='420' filter='url(%23pp)'/%3E%3C/svg%3E");
    background-size: 160px 160px;
    mix-blend-mode: multiply;
    pointer-events: none;
}
body.dark-mode .sb-cover-inner::after { mix-blend-mode: screen; opacity: 0.08; }

.sb-bookplate {
    font-family: 'Cormorant Garamond', 'Playfair Display', Georgia, serif;
    font-size: 13px;
    font-style: italic;
    color: var(--sb-page-ink);
    opacity: 0.55;
    text-align: center;
    line-height: 1.7;
    max-width: 72%;
    position: relative;
    z-index: 2;
}
.sb-bookplate .sb-bookplate-rule {
    display: block;
    width: 28px;
    height: 1px;
    background: currentColor;
    opacity: 0.5;
    margin: 14px auto;
}
.sb-bookplate span.sb-bookplate-stamp {
    display: block;
    font-size: 9px;
    letter-spacing: 5px;
    text-transform: uppercase;
    margin-top: 4px;
    opacity: 0.75;
    font-style: normal;
}

/* ---- Text page (short story opposite the photo in every spread) ---- */
.sb-page-face.is-text,
.sb-cover-inner.is-text {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 13% 14% 13% 14%;
    box-sizing: border-box;
}
.sb-page-story {
    position: relative;
    z-index: 4;
    width: 100%;
    color: var(--sb-page-ink);
    text-align: left;
}
.sb-page-story .sb-story-num {
    display: block;
    font-family: 'Instrument Serif', 'Cormorant Garamond', Georgia, serif;
    font-style: italic;
    font-weight: 400;
    /* Scales with book size; falls as low as 18px so it still fits the
       tight content column on a 320–375px phone. */
    font-size: clamp(18px, calc(var(--sb-book-w) * 0.095), 46px);
    line-height: 1;
    letter-spacing: -0.01em;
    color: var(--sb-page-ink);
    opacity: 0.45;
    margin: 0 0 0.5em;
}
.sb-page-story h3 {
    font-family: 'Instrument Serif', 'Cormorant Garamond', Georgia, serif;
    font-weight: 400;
    font-size: clamp(12px, calc(var(--sb-book-w) * 0.055), 26px);
    line-height: 1.15;
    letter-spacing: -0.015em;
    margin: 0 0 0.65em;
    color: var(--sb-page-ink);
    opacity: 0.92;
}
.sb-page-story p {
    font-family: Georgia, 'Times New Roman', serif;
    font-weight: 400;
    /* 9.5px floor is small but still readable in Georgia at the
       ~120px column width a 320px phone ends up with. */
    font-size: clamp(9.5px, calc(var(--sb-book-w) * 0.032), 15px);
    line-height: 1.55;
    letter-spacing: 0.005em;
    margin: 0;
    color: var(--sb-page-ink);
    opacity: 0.72;
}
.sb-page-story p + p { margin-top: 0.9em; }

/* Make the story a "read-through" zone: clicks on body text fall through to
   the prev-page click zone beneath, but in-text links are promoted above
   the click zone so they remain clickable without flipping the page. */
.sb-page-story {
    pointer-events: none;
}
.sb-page-story a {
    pointer-events: auto;
    position: relative;
    z-index: 50;
    color: inherit;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
    text-decoration-color: currentColor;
    font-weight: 500;
    opacity: 1;
    transition: opacity 0.2s ease;
}
.sb-page-story a:hover { opacity: 0.7; }

/* -------------------------------------------------------------- PAGES ---- */
.sb-pages {
    position: absolute;
    inset: 0;
    transform-style: preserve-3d;
    /* The pages container is a transparent 3D stage; we don't want it to
       absorb clicks. Click-zones (siblings) and the links inside pages or
       on the back cover opt back in via their own `pointer-events: auto`. */
    pointer-events: none;
}

.sb-page {
    position: absolute;
    inset: 0;
    transform-origin: left center;
    transform-style: preserve-3d;
    transition: transform var(--sb-page-transition);
    will-change: transform;
}
.sb-page.is-flipped {
    transform: rotateY(-174deg);
}
.sb-page.is-flipping .sb-page-face {
    animation: sb-flip-shade var(--sb-page-transition) ease-in-out;
}
@keyframes sb-flip-shade {
    0%, 100% { filter: brightness(1); }
    50%      { filter: brightness(0.86); }
}

.sb-page-face {
    position: absolute;
    inset: 0;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
    background:
        radial-gradient(ellipse at 50% 40%,
            color-mix(in srgb, var(--sb-page-bg) 98%, white) 0%,
            var(--sb-page-bg) 80%),
        var(--sb-page-bg);
    border-radius: 2px 4px 4px 2px;
    overflow: hidden;
    box-shadow: inset 0 0 0 1px rgba(0,0,0,0.04);
    transition: background 0.6s ease;
}
.sb-page-face.back {
    transform: rotateY(180deg);
    border-radius: 4px 2px 2px 4px;
}
.sb-page-face::after {
    content: '';
    position: absolute;
    inset: 0;
    opacity: 0.13;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='500' height='500'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.5' numOctaves='8' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='discrete' tableValues='0 0.4 0.6 0.8 1'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='500' height='500' filter='url(%23g)'/%3E%3C/svg%3E");
    background-size: 170px 170px;
    mix-blend-mode: multiply;
    pointer-events: none;
    z-index: 5;
}
body.dark-mode .sb-page-face::after { mix-blend-mode: screen; opacity: 0.05; }

.sb-page-face::before {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    width: 42px;
    pointer-events: none;
    z-index: 3;
}
.sb-page-face.front::before {
    left: 0;
    background: linear-gradient(to right, var(--sb-page-shadow) 0%, transparent 100%);
    opacity: 0.5;
}
.sb-page-face.back::before {
    right: 0;
    background: linear-gradient(to left, var(--sb-page-shadow) 0%, transparent 100%);
    opacity: 0.5;
}

/* Photo frame — sits on the right page of a spread (front face of a sheet).
   Aspect ratio is tuned portrait-ish so most photos of Bruno crop cleanly. */
.sb-page-photo {
    position: absolute;
    inset: 8% 10% 10% 14%;
    border-radius: 2px;
    overflow: hidden;
    background: #0a0a0a;
    box-shadow:
        0 1px 2px rgba(0,0,0,0.12),
        0 6px 18px rgba(0,0,0,0.2),
        0 0 0 1px rgba(0,0,0,0.08);
    display: flex;
    align-items: center;
    justify-content: center;
}
.sb-page-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Default focus on the upper-center so portraits never lose hair/heads.
       Per-image overrides go inline on the <img> element. */
    object-position: 50% 30%;
    display: block;
    -webkit-user-drag: none;
}

.sb-page-photo.is-empty {
    background:
        repeating-linear-gradient(
            45deg,
            color-mix(in srgb, var(--sb-page-bg) 90%, black) 0 12px,
            color-mix(in srgb, var(--sb-page-bg) 94%, black) 12px 24px
        );
    color: var(--sb-page-ink);
    opacity: 0.7;
    font-size: 10px;
    letter-spacing: 4px;
    text-transform: uppercase;
    font-family: 'Inter', sans-serif;
    font-weight: 500;
}

.sb-page-caption {
    position: absolute;
    bottom: 7%;
    left: 12%;
    right: 8%;
    font-family: 'Cormorant Garamond', 'Playfair Display', Georgia, serif;
    font-style: italic;
    font-size: 13px;
    color: var(--sb-page-ink);
    opacity: 0.68;
    line-height: 1.45;
    text-align: left;
    z-index: 6;
}
.sb-page-face.back .sb-page-caption {
    left: 8%;
    right: 12%;
    text-align: right;
}

.sb-page-num {
    position: absolute;
    bottom: 7%;
    font-family: 'Inter', sans-serif;
    font-size: 9px;
    letter-spacing: 3px;
    color: var(--sb-page-ink);
    opacity: 0.4;
    z-index: 6;
}
.sb-page-face.front .sb-page-num { right: 8%; }
.sb-page-face.back  .sb-page-num { left:  8%; }

.sb-page-face.is-endplate {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 8%;
    box-sizing: border-box;
}
.sb-page-face.is-endplate .sb-bookplate {
    max-width: 72%;
}

/* ------------------------------------------------- CLICK ZONES & HINT ---- */
.sb-click-zone {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 50%;
    z-index: 40;
    cursor: pointer;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.3s ease;
}
.storybook-scene.book-open .sb-click-zone { pointer-events: auto; }
/* On the final spread, disable BOTH click-zones so the "here" link in the
   back-cover note gets the click instead of triggering a page flip. The
   link sits near the spine on the right page, which falls inside the
   left (prev) zone's footprint, so disabling just .next isn't enough.
   Nav bar arrow buttons still handle flipping back. */
.storybook-scene.book-open .sb-book.at-end .sb-click-zone { pointer-events: none; }
.sb-click-zone.prev { left: 0; cursor: w-resize; }
.sb-click-zone.next { right: 0; cursor: e-resize; }
.sb-click-zone:hover {
    opacity: 1;
    background: radial-gradient(ellipse at center, rgba(0,0,0,0.035) 0%, transparent 60%);
}
body.dark-mode .sb-click-zone:hover {
    background: radial-gradient(ellipse at center, rgba(255,255,255,0.025) 0%, transparent 60%);
}

.sb-hint {
    position: absolute;
    bottom: -44px;
    left: 50%;
    transform: translateX(-50%);
    font-family: 'Inter', sans-serif;
    font-size: 10px;
    letter-spacing: 5px;
    text-transform: uppercase;
    color: var(--text-color, currentColor);
    opacity: 0.42;
    white-space: nowrap;
    pointer-events: none;
    transition: opacity 0.5s ease;
}
.storybook-scene.book-open .sb-hint { opacity: 0; }

/* ----------------------------------------------------------- NAV BAR ---- */
.sb-nav {
    position: relative;
    display: flex;
    align-items: center;
    gap: 16px;
    opacity: 0;
    pointer-events: none;
    transform: translateY(12px);
    transition: opacity 0.5s ease 0.6s, transform 0.6s cubic-bezier(0.22, 1, 0.36, 1) 0.6s;
    z-index: 100;
    min-height: 44px;
}
.storybook-scene.book-open .sb-nav {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
}

.sb-nav-btn {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: 1px solid rgba(0,0,0,0.14);
    background: rgba(255,255,255,0.7);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    color: inherit;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.25s cubic-bezier(0.22, 1, 0.36, 1);
    font-family: inherit;
    padding: 0;
}
body.dark-mode .sb-nav-btn {
    border-color: rgba(255,255,255,0.16);
    background: rgba(20,20,20,0.7);
}
.sb-nav-btn svg { width: 16px; height: 16px; }
.sb-nav-btn:hover:not(:disabled) {
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(0,0,0,0.14);
}
.sb-nav-btn:active:not(:disabled) { transform: translateY(0); }
.sb-nav-btn:disabled { opacity: 0.28; cursor: not-allowed; }
.sb-nav-btn.sb-close { width: 38px; height: 38px; }
.sb-nav-btn.sb-close svg { width: 12px; height: 12px; }

.sb-page-indicator {
    font-family: 'Inter', sans-serif;
    font-size: 10px;
    letter-spacing: 4px;
    text-transform: uppercase;
    opacity: 0.55;
    min-width: 76px;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------- RESPONSIVE ---- */
@media (max-width: 720px) {
    .storybook-scene {
        /* Narrower gutter + taller aspect + extra vertical space below the
           book give the phone-sized book a real usable content column. */
        --sb-gutter: 14px;
        --sb-controls-space: 120px;
        --sb-aspect: 1.5;
        padding: 32px 12px;
        gap: 40px;
    }
    /* On mobile the 5% scale-down cost us ~8px of usable width, which we
       can't spare. Drop it. */
    .sb-book.is-open {
        transform: rotateX(4deg) rotateY(0deg) translateX(calc(var(--sb-book-w) / 2));
    }
    /* Tighter padding on text-heavy faces gives the story and handwriting
       more room to breathe before wrapping. */
    .sb-page-face.is-text,
    .sb-cover-inner.is-text {
        padding: 7% 8% 7% 8%;
    }
    .sb-back-cover {
        padding: 8% 9%;
    }
    .sb-nav { gap: 12px; }
    .sb-page-caption { font-size: 11px; }
}

/* -------------------------------------------------- REDUCED MOTION ---- */
@media (prefers-reduced-motion: reduce) {
    .sb-book-float { animation: none; }
    .sb-book, .sb-cover, .sb-page, .sb-nav {
        transition-duration: 0.25s !important;
    }
    .sb-page.is-flipping .sb-page-face { animation: none; }
}
