/* Pop-up notebook — styles. Scene content lives in books/*.json */

/* =========================================================
   TOKENS
========================================================= */
:root {
    --paper: #f2eee3;
    --paper-3: #e0d7c6;
    --ink: #25231f;
    --accent: #b5452f;
    --cover: #2b3a4b;
}

* { box-sizing: border-box; }

html, body {
    width: 100%;
    height: 100%;
    margin: 0;
    overflow: hidden;
    background: #181715;
    color: var(--ink);
    font-family: Georgia, "Times New Roman", serif;
}

/* =========================================================
   STAGE / CAMERA
   IMPORTANT: nothing between .stage and the pop-up panels
   may use overflow:hidden, opacity<1 or filter — those
   flatten preserve-3d and kill the depth.
========================================================= */
.stage {
    position: fixed;
    inset: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    perspective: 2200px;
    perspective-origin: 50% 20%;
}

.scaler {
    transform-style: preserve-3d;
    /* zoom + pan: animated by the browser, not frame by frame in JS */
    transition: transform .45s cubic-bezier(.2, .7, .2, 1);
}

/* The camera rotates the world (desk + book) together */
.world {
    position: relative;
    width: 1200px;
    height: 760px;
    transform-style: preserve-3d;
}

.book {
    position: absolute;
    inset: 0;
    transform-style: preserve-3d;
    cursor: pointer;
}

/* =========================================================
   ROOM: wall, window, light
========================================================= */
.room {
    position: fixed;
    inset: 0;
    background: radial-gradient(ellipse at 30% 20%, #3b2f25, #17120e 70%);
}

/* The back wall stands up at the far edge of the desk */
.wall {
    position: absolute;
    left: -2200px;
    top: -1540px;
    width: 5600px;
    height: 1400px;
    transform-origin: 50% 100%;
    transform: translateZ(-10px) rotateX(-90deg);
    background:
        radial-gradient(ellipse 700px 600px at 2300px 880px, rgba(255,200,140,.30), transparent 70%),
        linear-gradient(180deg, #3d3128 0%, #4c3d30 70%, #3a2d23 100%);
}
.wall::before {               /* plaster grain */
    content: "";
    position: absolute;
    inset: 0;
    opacity: .3;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.7' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.5'/%3E%3C/svg%3E");
    mix-blend-mode: multiply;
}
.wall::after {                /* baseboard */
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 46px;
    background: linear-gradient(180deg, #2a2019, #1d1611);
}

.window {
    position: absolute;
    border: 16px solid #2b2119;
    border-radius: 3px;
    box-shadow:
        0 0 0 3px #1c150f,
        0 0 160px 60px rgba(255,190,120,.25),
        inset 0 0 30px rgba(255,220,170,.4);
    overflow: hidden;
}
.window .sky {
    position: absolute;
    inset: 0;
    background:
        radial-gradient(circle at 72% 40%, #fff6dc 0 4%, rgba(255,230,170,.9) 7%, rgba(255,200,130,.35) 22%, transparent 45%),
        linear-gradient(180deg, #9fc2d6 0%, #e9d2ad 55%, #f2b783 80%, #d98d64 100%);
}
.window .cloud {
    position: absolute;
    height: 22px;
    border-radius: 20px;
    background: rgba(255,247,235,.75);
    filter: blur(3px);
    animation: drift 90s linear infinite;
}
@keyframes drift { from { transform: translateX(-30%); } to { transform: translateX(700%); } }
.window .hills {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    width: 100%;
    height: 30%;
}
.window .mullions {
    position: absolute;
    inset: 0;
    background:
        linear-gradient(90deg, transparent calc(50% - 6px), #2b2119 calc(50% - 6px), #2b2119 calc(50% + 6px), transparent calc(50% + 6px)),
        linear-gradient(180deg, transparent calc(50% - 6px), #2b2119 calc(50% - 6px), #2b2119 calc(50% + 6px), transparent calc(50% + 6px));
}
.window .glass {
    position: absolute;
    inset: 0;
    background: linear-gradient(125deg, rgba(255,255,255,.18) 0%, transparent 30%, transparent 60%, rgba(255,255,255,.08) 75%, transparent 85%);
}
.sill {
    position: absolute;
    height: 22px;
    background: linear-gradient(180deg, #4a3826, #20180f);
    box-shadow: 0 12px 20px rgba(0,0,0,.4);
}

/* Shafts of light: flat sheets in 3D, placed by JS */
.beam {
    position: absolute;
    left: 0;
    top: 0;
    transform-origin: 0 0;
    pointer-events: none;
    background:
        linear-gradient(90deg, transparent calc(50% - 6px), rgba(0,0,0,0) calc(50% - 6px), rgba(0,0,0,0) calc(50% + 6px), transparent calc(50% + 6px)),
        linear-gradient(180deg, rgba(255,216,160,.16), rgba(255,216,160,.05) 60%, rgba(255,216,160,0));
    -webkit-mask-image: linear-gradient(90deg, #000 calc(50% - 6px), transparent calc(50% - 6px), transparent calc(50% + 6px), #000 calc(50% + 6px));
            mask-image: linear-gradient(90deg, #000 calc(50% - 6px), transparent calc(50% - 6px), transparent calc(50% + 6px), #000 calc(50% + 6px));
    opacity: var(--a, 1);
}

/* Sunlight printed onto a flat surface (desk or page), drawn by JS */
.sunlight {
    position: absolute;
    left: 0;
    top: 0;
    pointer-events: none;
    filter: blur(5px);
}

.dust {
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 6;
}
.motes {
    position: absolute;
    left: -5vw; top: -5vh;
    width: 62vw; height: 82vh;
    background-size: 100% 100%;
    will-change: transform, opacity;
}
.motes.a { animation: motes-a 19s ease-in-out infinite alternate; }
.motes.b { animation: motes-b 27s ease-in-out infinite alternate; }
@keyframes motes-a {
    0%   { transform: translate(0, 0); opacity: .9; }
    50%  { opacity: .45; }
    100% { transform: translate(34px, 26px); opacity: .9; }
}
@keyframes motes-b {
    0%   { transform: translate(18px, -10px); opacity: .5; }
    50%  { opacity: .9; }
    100% { transform: translate(-22px, 30px); opacity: .5; }
}

/* =========================================================
   DESK — a big flat plane under the book, same 3D space
========================================================= */
.desk {
    position: absolute;
    left: -2200px;
    top: -140px;
    width: 5600px;
    height: 2340px;
    overflow: hidden;
    transform: translateZ(-10px);
    background:
        radial-gradient(ellipse 45% 40% at 40% 40%, rgba(255,190,120,.18), transparent 70%),
        repeating-linear-gradient(90deg,
            rgba(0,0,0,0) 0px, rgba(0,0,0,.06) 3px, rgba(0,0,0,0) 9px,
            rgba(255,255,255,.03) 21px, rgba(0,0,0,0) 34px, rgba(0,0,0,.08) 47px, rgba(0,0,0,0) 61px),
        linear-gradient(90deg, #6b4a31, #7a5638 30%, #6e4d33 55%, #7b573a 80%, #66462e);
    border-top: 18px solid #4a3221;
    box-shadow: inset 0 40px 60px -20px rgba(0,0,0,.45);
}
.desk::before {                /* wood figure */
    content: "";
    position: absolute;
    inset: 0;
    opacity: .35;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='300'%3E%3Cfilter id='w'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.004 .09' numOctaves='3' seed='4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23w)' opacity='.6'/%3E%3C/svg%3E");
    mix-blend-mode: multiply;
}
.desk::after {                 /* falls off into shadow at the edges */
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(ellipse 50% 60% at 42% 25%, transparent 40%, rgba(15,10,6,.65) 100%);
}

/* Soft contact shadow under the open book */
.book-shadow {
    position: absolute;
    left: 2140px;
    top: 90px;
    width: 1320px;
    height: 860px;
    border-radius: 30px;
    background: rgba(10,6,3,.55);
    filter: blur(28px);
}

/* Back board (right half) — the front board is sheet 0 */
.back-board {
    position: absolute;
    left: 594px;
    top: -14px;
    width: 622px;
    height: 788px;
    border-radius: 0 8px 8px 0;
    background: linear-gradient(90deg, rgba(0,0,0,.3), transparent 5%, transparent 96%, rgba(0,0,0,.25)), var(--cover);
    transform: translateZ(-4px);
    box-shadow: 0 40px 80px rgba(0,0,0,.55);
}

/* =========================================================
   PAGES
========================================================= */
.face {
    position: absolute;
    top: 0;
    left: 0;
    width: 600px;
    height: 760px;
    overflow: hidden;            /* fine: faces are flat leaves */
    backface-visibility: hidden;
    background-color: var(--paper);
    background-image:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.18'/%3E%3C/svg%3E");
    background-blend-mode: multiply;
}
.face.lp, .face.rp { position: absolute; }
.face.lp::after,
.face.rp::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
}
.face.lp { border-radius: 5px 0 0 5px; }
.face.rp { border-radius: 0 5px 5px 0; }
.face.lp::after { background: linear-gradient(270deg, rgba(0,0,0,.16), transparent 9%, transparent 96%, rgba(0,0,0,.05)); }
.face.rp::after { background: linear-gradient(90deg,  rgba(0,0,0,.16), transparent 9%, transparent 96%, rgba(0,0,0,.05)); }

.base-right { left: 600px; }

/* Turning sheets — hinge on the gutter */
.sheet {
    position: absolute;
    left: 600px;
    top: 0;
    width: 600px;
    height: 760px;
    transform-style: preserve-3d;
    transform-origin: left center;
}
.sheet .face.back { transform: rotateY(180deg); }

/* Front cover = sheet 0 (front: cloth board, back: board + preface page) */
.board {
    position: absolute;
    left: 0;
    top: -14px;
    width: 616px;
    height: 788px;
    backface-visibility: hidden;
    background: var(--cover);
    overflow: hidden;
}
.board.front {
    border-radius: 0 8px 8px 0;
    background:
        linear-gradient(90deg, rgba(0,0,0,.35), rgba(255,255,255,.05) 4%, transparent 10%, transparent 96%, rgba(0,0,0,.25)),
        var(--cover);
    color: var(--paper);
}
.board.back {
    border-radius: 8px 0 0 8px;
    transform: rotateY(180deg);
}
.board.back .face { left: 16px; top: 14px; }

.cover-title {
    position: absolute;
    left: 70px;
    top: 120px;
    right: 70px;
}
.cover-title .rule { width: 60px; height: 3px; background: var(--accent); margin-bottom: 28px; }
.cover-title h1 {
    margin: 0;
    font-family: Arial, Helvetica, sans-serif;
    font-weight: 900;
    font-size: 64px;
    letter-spacing: .08em;
    line-height: 1;
}
.cover-title .sub {
    margin-top: 18px;
    font-size: 13px;
    letter-spacing: .35em;
    text-transform: uppercase;
    opacity: .6;
}
.cover-mark {
    position: absolute;
    right: 70px;
    bottom: 70px;
    font-size: 120px;
    line-height: 1;
    color: var(--accent);
}

.shade {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(90deg, rgba(0,0,0,.35), rgba(0,0,0,.08));
    opacity: 0;
}

/* =========================================================
   PAGE TYPOGRAPHY
========================================================= */
.label {
    position: absolute;
    top: 42px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 12px;
    letter-spacing: .25em;
    text-transform: uppercase;
    color: rgba(37,35,31,.45);
}
.lp .label { left: 50px; }
.rp .label { right: 50px; }

.copy {
    position: absolute;
    bottom: 70px;
    max-width: 330px;
}
.lp .copy { left: 55px; }
.rp .copy { right: 55px; }
.copy h2 { font-size: 34px; margin: 0 0 10px; font-weight: normal; }
.copy p  { font-size: 15px; line-height: 1.6; margin: 0 0 10px; }
.copy .small {
    font-family: Arial, Helvetica, sans-serif;
    font-size: 11px;
    letter-spacing: .2em;
    text-transform: uppercase;
    opacity: .5;
}

.num {
    position: absolute;
    bottom: 26px;
    font-size: 12px;
    letter-spacing: .15em;
    opacity: .4;
}
.lp .num { left: 36px; }
.rp .num { right: 36px; }

.hand {
    position: absolute;
    font-family: "Caveat", "Bradley Hand", cursive;
    font-size: 26px;
    opacity: .7;
    transform: rotate(-5deg);
}

.title-block { position: absolute; left: 55px; top: 90px; }
.title-block h1 {
    margin: 0;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 62px;
    font-weight: 900;
    letter-spacing: .06em;
    line-height: 1;
}
.title-block .sub {
    margin-top: 16px;
    font-size: 12px;
    letter-spacing: .35em;
    text-transform: uppercase;
    opacity: .45;
}

/* =========================================================
   POP-UP PANELS
   Every pop-up is a card folded down a centre crease.
   Each half is its own flat element placed with matrix3d.
========================================================= */
.half {
    position: absolute;
    left: 0;
    top: 0;
    transform-origin: 0 0;
    overflow: hidden;      /* clips the shared SVG to this half */
    visibility: hidden;
    pointer-events: none;
}
.half svg {
    position: absolute;
    top: 0;
    display: block;
    overflow: visible;
}

/* =========================================================
   UI
========================================================= */
.controls {
    position: fixed;
    left: 50%;
    bottom: 26px;
    transform: translateX(-50%);
    display: flex;
    gap: 14px;
    z-index: 10;
}
.control {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    border: 1px solid rgba(255,255,255,.3);
    background: rgba(30,29,26,.75);
    color: #fff;
    font-size: 22px;
    cursor: pointer;
    transition: background .2s, transform .2s;
}
.control:hover { background: rgba(70,67,60,.9); transform: translateY(-2px); }
.control:disabled { opacity: .25; cursor: default; transform: none; }

.page-label {
    position: fixed;
    top: 26px;
    left: 50%;
    transform: translateX(-50%);
    color: rgba(255,255,255,.6);
    font-family: Arial, Helvetica, sans-serif;
    font-size: 11px;
    letter-spacing: .3em;
    text-transform: uppercase;
    z-index: 10;
}

/* =========================================================
   LOADER UI (drop a book JSON, errors)
========================================================= */
.toast {
    position: fixed;
    left: 50%;
    bottom: 92px;
    transform: translateX(-50%);
    max-width: min(560px, 90vw);
    padding: 10px 16px;
    border-radius: 8px;
    background: rgba(20,18,16,.9);
    color: #f2eee3;
    font: 13px/1.5 Arial, Helvetica, sans-serif;
    z-index: 20;
    opacity: 0;
    transition: opacity .3s;
    pointer-events: none;
    white-space: pre-line;
}
.toast.show { opacity: 1; }
.toast.error { background: rgba(110,30,20,.92); }

.drop-hint {
    position: fixed;
    inset: 0;
    z-index: 30;
    display: none;
    align-items: center;
    justify-content: center;
    background: rgba(20,16,12,.6);
    color: #f2eee3;
    font: 16px Arial, Helvetica, sans-serif;
    letter-spacing: .2em;
    text-transform: uppercase;
    border: 3px dashed rgba(242,238,227,.5);
}
.drop-hint.show { display: flex; }

/* Free-placed handwritten note on a page */
.note { position: absolute; }

/* =========================================================
   STORY PAGES
========================================================= */
/* A short block of handwritten lines, bottom-right of a page */
.questions {
    position: absolute;
    right: 60px;
    bottom: 80px;
    width: 330px;
    font-family: "Caveat", "Bradley Hand", cursive;
    font-size: 27px;
    line-height: 1.15;
    color: var(--ink);
}
.questions p { margin: 0 0 16px; }
.questions .coda {
    margin-top: 22px;
    font-family: Georgia, "Times New Roman", serif;
    font-size: 16px;
    letter-spacing: .02em;
}

/* =========================================================
   POP-UP ANIMATION HOOKS
   Art groups carry a class (anim-*). They play once when a
   spread settles open (.half.is-open), then hold still.
   Nothing loops except a blinking cursor and faint steam.
========================================================= */
.half svg [class^="anim-"] { transform-box: fill-box; }

@media (prefers-reduced-motion: no-preference) {

    /* a screen catching up when the page lands */
    .half.is-open .anim-flicker { animation: flicker 1.1s ease-out 1; }
    @keyframes flicker {
        0%   { opacity: .55; }
        12%  { opacity: 1; }
        20%  { opacity: .8; }
        34%  { opacity: 1; }
        100% { opacity: 1; }
    }

    .half.is-open .anim-cursor { animation: cursor 1.1s steps(1) infinite; }
    @keyframes cursor { 50% { opacity: 0; } }

    /* the assembly page: the computer's front swings open */
    .half.is-open .anim-door { transform-origin: right center; animation: door 1.4s cubic-bezier(.2,.8,.2,1) .2s 1 both; }
    @keyframes door { from { transform: scaleX(.25); } to { transform: scaleX(1); } }

    /* one gear turns once */
    .half.is-open .anim-gear { transform-origin: center; animation: turn-once 2.6s cubic-bezier(.45,0,.2,1) .4s 1 both; }
    @keyframes turn-once { from { transform: rotate(0); } to { transform: rotate(360deg); } }

    /* the project that disappeared */
    .anim-ghost { opacity: 1; }
    .half.is-open .anim-ghost { animation: ghost 2.4s ease-in 1.2s 1 forwards; }
    @keyframes ghost { to { opacity: 0; } }

    /* paper settling into place */
    .half.is-open .anim-settle { transform-origin: bottom center; animation: settle .9s cubic-bezier(.2,1.4,.4,1) .3s 1 both; }
    @keyframes settle { from { transform: translateY(-6px) rotate(-1.5deg); } to { transform: none; } }

    /* hanging signs swing a little, then stop */
    .half.is-open .anim-sway { transform-origin: top center; animation: sway 2.6s ease-out .3s 1 both; }
    @keyframes sway {
        0%   { transform: rotate(0); }
        20%  { transform: rotate(3deg); }
        45%  { transform: rotate(-2deg); }
        70%  { transform: rotate(.8deg); }
        100% { transform: rotate(0); }
    }

    /* the λ appearing in the new editor */
    .half.is-open .anim-emerge { animation: emerge 1.6s ease-out .5s 1 both; }
    @keyframes emerge { from { opacity: 0; } to { opacity: .9; } }

    .anim-steam { opacity: .6; }
    .half.is-open .anim-steam { animation: steam 4s ease-in-out infinite alternate; }
    @keyframes steam { from { opacity: .35; } to { opacity: .75; } }
}

/* a handwritten underline that draws itself (hidden until the spread is open) */
.half svg .anim-underline { stroke-dasharray: 1; stroke-dashoffset: 1; }
.half.is-open svg .anim-underline { stroke-dashoffset: 0; transition: stroke-dashoffset .9s ease-out .6s; }
@media (prefers-reduced-motion: reduce) {
    .half svg .anim-underline { stroke-dashoffset: 0; }
}

/* =========================================================
   CONTENTS + LINKS
========================================================= */
.toc {
    position: absolute;
    left: 60px;
    right: 60px;
    bottom: 96px;
    font-family: Georgia, "Times New Roman", serif;
}
.toc a {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding: 9px 0;
    color: var(--ink);
    text-decoration: none;
    font-size: 26px;
    cursor: pointer;
}
.toc a span { white-space: nowrap; }
.toc a i {                                   /* dotted leader */
    flex: 1;
    border-bottom: 2px dotted rgba(37,35,31,.4);
    transform: translateY(-6px);
}
.toc a b { font-weight: normal; font-size: 20px; opacity: .7; }
.toc a.hover span,
.toc a:focus-visible span { color: var(--accent); }
.toc a.hover i { border-bottom-color: var(--accent); }
.toc .toc-sub {
    margin: 0 0 14px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 11px;
    letter-spacing: .25em;
    text-transform: uppercase;
    opacity: .45;
}

a.note.goto {
    color: var(--ink);
    text-decoration: none;
    cursor: pointer;
    font-size: 22px;
}
a.note.goto.hover { color: var(--accent); }

/* =========================================================
   LINKS OUT OF THE BOOK (mailto:, https:)
========================================================= */
.face a[href]:not([data-goto]) {
    color: var(--ink);
    text-decoration: none;
    border-bottom: 1.5px dotted rgba(37,35,31,.45);
}
.face a[href]:not([data-goto]).hover {
    color: var(--accent);
    border-bottom: 1.5px solid var(--accent);
}

.link-hint {
    position: fixed;
    left: 0;
    top: 0;
    z-index: 20;
    padding: 5px 10px;
    border-radius: 6px;
    background: rgba(20,18,16,.85);
    color: #f2eee3;
    font: 12px Arial, Helvetica, sans-serif;
    letter-spacing: .03em;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity .15s;
}
.link-hint.show { opacity: 1; }

/* =========================================================
   MUSIC TOGGLE
========================================================= */
.control.sound {
    position: fixed;
    right: 24px;
    bottom: 26px;
    z-index: 10;
    display: grid;
    place-items: center;
    color: rgba(255,255,255,.55);
}
.control.sound svg { width: 22px; height: 22px; }
.control.sound .wave { display: none; }
.control.sound.on { color: #fff; }
.control.sound.on .wave { display: inline; }
.control.sound.on .mute { display: none; }

/* =========================================================
   TIME OF DAY (the window cycles it; see js/toys.js)
========================================================= */
/* --sun (1 day → 0 night) is stepped by js/toys.js a few times per
   change. It is NOT animated every frame: every page inherits it, so
   a per-frame change would repaint the whole book 100 times. */
body { --sun: 1; }

/* Big things (desk sunlight, sunbeams, dust) fade with plain opacity,
   which the GPU does without repainting anything. Only the small
   per-page sunlight follows the stepped --sun. */
.face .sunlight polygon,
.face .sunlight path { fill-opacity: var(--sun, 1); }
.desk .sunlight,
.beam,
.dust { transition: opacity 1.6s ease; will-change: opacity; }
body.time-sunset .desk .sunlight { opacity: .5; }
body.time-night  .desk .sunlight { opacity: 0; }
body.time-sunset .beam { opacity: calc(var(--a, 1) * .5); }
body.time-night  .beam { opacity: 0; }
body.time-sunset .dust { opacity: .5; }
body.time-night  .dust { opacity: 0; }

.window { cursor: pointer; }
.window .sky.sky-sunset {
    background:
        radial-gradient(circle at 62% 80%, #ffe1a8 0 5%, rgba(255,170,110,.8) 9%, transparent 30%),
        linear-gradient(180deg, #4a4e8f 0%, #b5658a 45%, #f08a5d 75%, #f9b46b 100%);
}
.window .sky.sky-night { background: linear-gradient(180deg, #070d24 0%, #14214a 65%, #26386a 100%); }
.window .sky-sunset,
.window .sky-night { opacity: 0; transition: opacity 1.6s ease; }
body.time-sunset .sky-sunset,
body.time-night .sky-night { opacity: 1; }
.window .cloud { transition: opacity 1.6s ease; }
body.time-night .window .cloud { opacity: .1 !important; }
.moon {
    position: absolute; left: 22%; top: 16%;
    width: 44px; height: 44px; border-radius: 50%;
    background: #f4f1de;
    box-shadow: 0 0 26px 6px rgba(244,241,222,.35);
}
.star { position: absolute; width: 3px; height: 3px; border-radius: 50%; background: #fff; }
body.time-sunset .window {
    box-shadow: 0 0 0 3px #1c150f, 0 0 160px 60px rgba(255,140,80,.3), inset 0 0 30px rgba(255,180,120,.4);
}
body.time-night .window {
    box-shadow: 0 0 0 3px #1c150f, 0 0 120px 40px rgba(90,120,200,.12), inset 0 0 30px rgba(120,150,220,.15);
}

/* screen-space shading; the lamp's pool of light is cut out of it */
.shade {
    position: fixed; inset: 0; z-index: 5;
    pointer-events: none;
    opacity: 0;
    transition: opacity 1.6s ease;
    will-change: opacity;
    -webkit-mask-image: radial-gradient(ellipse var(--lrx, 1px) var(--lry, 1px) at var(--lx, 50%) var(--ly, 50%), transparent 0%, rgba(0,0,0,.35) 45%, #000 100%);
            mask-image: radial-gradient(ellipse var(--lrx, 1px) var(--lry, 1px) at var(--lx, 50%) var(--ly, 50%), transparent 0%, rgba(0,0,0,.35) 45%, #000 100%);
}
.shade.sunset { background: rgba(120,52,24,.24); }
.shade.night  { background: rgba(6,12,34,.74); }
body.time-sunset .shade.sunset,
body.time-night .shade.night { opacity: 1; }

.lamp-glow {
    position: fixed; inset: 0; z-index: 5;
    pointer-events: none;
    opacity: var(--lamp, 0);
    background:
        radial-gradient(circle var(--br, 1px) at var(--bx, 0) var(--by, 0), rgba(255,226,160,.75), rgba(255,226,160,0)),
        radial-gradient(ellipse var(--lrx, 1px) var(--lry, 1px) at var(--lx, 50%) var(--ly, 50%), rgba(255,196,120,.22), rgba(255,196,120,0));
}

/* =========================================================
   DESK PROPS (pen cup, lamp)
========================================================= */
.prop { position: absolute; left: 0; top: 0; transform-origin: 50% 100%; }
.prop img { display: block; width: 100%; height: 100%; pointer-events: none; user-select: none; -webkit-user-drag: none; }
.prop-shadow {
    position: absolute; left: 0; top: 0;
    border-radius: 50%;
    background: radial-gradient(closest-side, rgba(10,6,3,.4), rgba(10,6,3,0));
    pointer-events: none;
}
.marker { position: absolute; left: 0; top: 0; width: 1px; height: 1px; pointer-events: none; }
.pen { position: absolute; left: 0; top: 0; pointer-events: none; transition: opacity .35s; }
.pen.gone { opacity: 0; }
.pen svg { display: block; }
.lamp .bulb-glow {
    position: absolute;
    width: 130px; height: 130px; margin: -65px 0 0 -65px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255,232,160,.95) 0 12%, rgba(255,200,110,.45) 32%, rgba(255,200,110,0) 70%);
    opacity: 0;
    transition: opacity .4s;
    pointer-events: none;
}
.lamp.on .bulb-glow { opacity: 1; }
body.grabbing, body.grabbing * { cursor: grabbing !important; }

/* =========================================================
   PULL-TABS
   <div class="pull-tab" data-pull style="top:300px">pull →</div>
   (add data-pull-dir="left" and a left-hand position for a
   tab on a left page). Dragging sets --pull on the spread's
   pop-ups; the classes below decide what moves.
========================================================= */
.pull-tab {
    position: absolute;
    right: 100px;
    width: 82px; height: 32px;
    padding-right: 12px;
    text-align: right;
    white-space: nowrap;
    background: #f7f3ea;
    border: 2px solid rgba(37,35,31,.55);
    border-left: none;
    border-radius: 0 10px 10px 0;
    box-shadow: 2px 2px 0 rgba(0,0,0,.08);
    font-family: "Caveat", "Bradley Hand", cursive;
    font-size: 21px;
    line-height: 28px;
    color: var(--ink);
    user-select: none;
}
.pull-tab::before {               /* the slot it slides out of */
    content: "";
    position: absolute;
    left: -5px; top: -7px; bottom: -7px;
    width: 5px;
    border-radius: 2px;
    background: rgba(37,35,31,.75);
}
.pull-tab[data-pull-dir="left"] {
    padding: 0 0 0 12px;
    text-align: left;
    border: 2px solid rgba(37,35,31,.55);
    border-right: none;
    border-radius: 10px 0 0 10px;
}
.pull-tab[data-pull-dir="left"]::before { left: auto; right: -5px; }
@media (prefers-reduced-motion: no-preference) {
    .pull-tab { animation: tab-nudge 5s ease-in-out infinite; }
    @keyframes tab-nudge {
        0%, 84%, 100% { translate: 0; }
        88% { translate: 7px; }
        92% { translate: 0; }
        96% { translate: 3px; }
    }
}

/* PULL-TAB TARGETS: give an SVG group one of these classes */
.half .pull-hop    { transform: translateY(calc(var(--pull, 0) * -80px)); }
.half .pull-jump   { transform: translateY(calc(var(--pull, 0) * -80px)); }
.half .pull-lift   { transform: translateY(calc(var(--pull, 0) * -70px)); }
.half .pull-slide  { transform: translateX(calc(var(--pull, 0) * 110px)); }
.half .pull-out    { transform: translateX(calc(var(--pull, 0) * 110px)); }
.half .pull-letter { transform: translateY(calc(var(--pull, 0) * -120px)); }
.half .pull-spin   { transform-box: fill-box; transform-origin: center; transform: rotate(calc(var(--pull, 0) * 360deg)); }
.half .pull-lever  { transform-box: view-box; transform-origin: 352px 214px; transform: rotate(calc(var(--pull, 0) * 75deg)); }

/* =========================================================
   STICKY NOTES + the scrap of paper under them
========================================================= */
.sticky {
    position: absolute; left: 0; top: 0;
    width: 104px; height: 104px;
    padding: 14px 10px 10px;
    font-family: "Caveat", "Bradley Hand", cursive;
    font-size: 23px; line-height: 1;
    color: #2a2620;
    background-image: linear-gradient(180deg, rgba(0,0,0,.07), rgba(0,0,0,0) 24%);
    box-shadow: 0 1px 0 rgba(0,0,0,.08), 1px 4px 7px rgba(0,0,0,.18);
    pointer-events: none;
    user-select: none;
}
.sticky.lifted { box-shadow: 3px 14px 16px rgba(0,0,0,.26); }
.desk-scrap {
    position: absolute; left: 0; top: 0;
    display: flex; align-items: center; justify-content: center;
    background: #f4efe2;
    border-radius: 2px;
    box-shadow: 1px 2px 4px rgba(0,0,0,.28);
    font-family: "Caveat", "Bradley Hand", cursive;
    font-size: 30px;
    color: #2a2620;
    pointer-events: none;
}
.desk-scrap b { color: var(--accent); font-weight: 700; }
@media (prefers-reduced-motion: no-preference) {
    .desk-scrap.revealed { animation: scrap-glow 1.5s ease-in-out 2; }
    @keyframes scrap-glow { 50% { box-shadow: 0 0 22px 7px rgba(255,214,120,.9); } }
}

/* =========================================================
   RÉSUMÉ on the desk
========================================================= */
.resume-paper {
    position: absolute; left: 0; top: 0;
    box-shadow: 1px 3px 6px rgba(0,0,0,.22);
    transition: box-shadow .2s;
}
.resume-paper img { display: block; width: 100%; height: 100%; pointer-events: none; user-select: none; -webkit-user-drag: none; }
.resume-paper.hover { box-shadow: 3px 10px 14px rgba(0,0,0,.3); }
