/* Little Sprouts — the children's rooms.
 *
 * The hub reuses the study-hub card grid so the site does not fork into two
 * design languages. What changes inside the rooms is the reading surface: the
 * study rooms are built for an adult scanning a passage, these are built for a
 * child being read to, so the type is larger, the art leads, and there is only
 * ever one thing to press next.
 */

:root {
    /* Remapped for the dark marble build: names kept, values flipped so text
       tokens that sat on light paper now read on dark glass. */
    --sprout-green: #bfe0c8;
    --sprout-deep: #06241b;
    --sprout-gold: #c6a450;
    --sprout-paper: #fbf5e6;
    --sprout-ink: #e9e4d6;
    --sprout-muted: #a4b2a8;
}

.visually-hidden {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ================================================================
   THE KIDS' HUB
   ================================================================
   This page deliberately drops the dark study-centre chrome. Chunky
   rounded cards, hard offset shadows, big pill buttons, sky-to-meadow
   background: the look approved on the kids page of the live preview.

   The painted backdrop drops in the moment the file exists. Until then
   the gradient below shows on its own, so the page is never broken
   while the artwork is being made.
   ---------------------------------------------------------------- */

:root {
    --kid-green: #164c38;
    --kid-green-deep: #0a3024;
    --kid-gold: #f9c846;
    --kid-shadow: rgba(53, 111, 62, .20);
}

.kids-body { background: transparent; }

.kids {
    position: relative;
    padding: clamp(28px, 5vw, 70px) clamp(14px, 4vw, 54px) clamp(40px, 6vw, 88px);
    color: var(--ink);
    background: transparent;
}
/* The painted scene sits over the gradient and under the content. It is a
   separate layer rather than a background on .kids so it can be positioned
   and faded without disturbing the gradient underneath. */
.kids:before {
    content: "";
    position: absolute; inset: 0; z-index: 0;
    /* The painted backdrop never shipped; on the marble build the hub gets a
       soft warm glow instead so the kids' corner reads brighter than the rest
       of the site without painting the page light. */
    background:
        radial-gradient(720px 420px at 22% 12%, rgba(249, 200, 70, .13), transparent 65%),
        radial-gradient(640px 460px at 82% 20%, rgba(142, 216, 248, .10), transparent 65%),
        radial-gradient(900px 520px at 50% 105%, rgba(120, 200, 120, .12), transparent 70%);
    pointer-events: none;
}
.kids > * { position: relative; z-index: 1; }

.kids-grid {
    display: grid;
    grid-template-columns: minmax(240px, .7fr) minmax(320px, 1.3fr);
    gap: clamp(18px, 3vw, 38px);
    align-items: center;
    max-width: 1220px; margin: 0 auto;
}

/* ---- Sprout and his speech bubble ---- */

.sprout { position: relative; display: grid; place-items: center; }
.sprout-character {
    position: relative;
    display: grid; place-items: center;
    width: min(400px, 100%);
    animation: sproutHero 4s ease-in-out infinite alternate;
}
.sprout-character img { display: block; width: 100%; }
@keyframes sproutHero { to { transform: translateY(-10px) rotate(1deg); } }

.sprout-welcome {
    position: absolute; z-index: 2; top: 6px; right: -10px;
    width: min(245px, 70%); margin: 0;
    padding: .85rem 1rem;
    background: #fffdf6;
    border: 3px solid #c89a37;
    border-radius: 22px;
    color: #174735;
    font-size: .95rem; font-weight: 700; line-height: 1.42;
}
.sprout-welcome:after {
    content: "";
    position: absolute; left: 24px; bottom: -18px;
    border: 10px solid transparent;
    border-top-color: #c89a37;
    transform: rotate(18deg);
}

/* ---- the panel ---- */

.kids-intro {
    padding: clamp(1.1rem, 2.2vw, 1.7rem);
    border: 1px solid var(--glass-border);
    border-radius: 32px;
    background: linear-gradient(150deg, rgba(249, 200, 70, .10), var(--glass) 55%);
    box-shadow: 0 18px 50px rgba(0, 0, 0, .35);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
}
.kids-fun-strip { display: flex; gap: 10px; font-size: 1.35rem; margin-bottom: 6px; }
.kids-intro .eyebrow {
    display: inline-block; margin: 0 0 4px;
    padding: .35rem .8rem;
    border-radius: 999px;
    background: var(--kid-gold);
    color: #214d34;
    font-weight: 900; font-size: .72rem; letter-spacing: .12em;
    transform: rotate(-2deg);
}
.kids-intro h1 {
    margin: .2rem 0;
    font: 400 clamp(2.6rem, 6vw, 4.6rem)/1 var(--serif);
    color: var(--kid-gold);
    /* The layered offset still reads as a sticker, cut for the dark room. */
    text-shadow: 3px 3px 0 rgba(0, 0, 0, .45), 6px 6px 0 rgba(249, 200, 70, .22);
}
.kids-lede { margin: .3rem 0 1rem; font-size: 1.1rem; font-weight: 700; color: #cfe0d3; }

/* ---- the room cards ---- */

.kidcards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
.kidcards .card {
    display: flex; flex-direction: column; align-items: flex-start;
    padding: 1rem 1.1rem 1.1rem;
    border: 1px solid var(--glass-border); border-radius: 24px;
    background: var(--glass);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    box-shadow: 0 9px 0 rgba(0, 0, 0, .28), 0 16px 28px rgba(0, 0, 0, .32);
    transition: transform .2s ease, box-shadow .2s ease;
}
/* Alternating pastels and a degree of tilt, so the grid reads as a scatter of
   cards on a table rather than a spreadsheet. */
.kidcards .card:nth-child(1) { background: linear-gradient(145deg, rgba(249, 200, 70, .16), rgba(255, 130, 190, .09)); transform: rotate(-1deg); }
.kidcards .card:nth-child(2) { background: linear-gradient(145deg, rgba(150, 226, 120, .13), rgba(110, 190, 255, .09)); transform: rotate(1deg); }
.kidcards .card:nth-child(3) { background: linear-gradient(145deg, rgba(110, 190, 255, .13), rgba(200, 140, 255, .10)); transform: rotate(1deg); }
.kidcards .card:nth-child(4) { background: linear-gradient(145deg, rgba(255, 190, 92, .15), rgba(249, 200, 70, .07)); transform: rotate(-1deg); }
.kidcards .card:nth-child(5) { background: linear-gradient(145deg, rgba(120, 230, 180, .13), rgba(249, 200, 70, .09)); transform: rotate(-1deg); }
/* An odd card at the end runs the full width instead of leaving a hole. */
.kidcards .card:last-child:nth-child(odd) { grid-column: 1 / -1; }
.kidcards .card:hover, .kidcards .card:focus-within {
    transform: translateY(-7px) rotate(0deg);
    box-shadow: 0 13px 0 rgba(0, 0, 0, .32), 0 23px 34px rgba(0, 0, 0, .38);
}
.kidcards .card h2 { margin: .1rem 0 .4rem; font: 700 1.22rem var(--serif); color: var(--gold-pale); }
.kidcards .card p { flex: 1; margin: 0 0 .2rem; font-size: .94rem; line-height: 1.5; color: #c9d6cc; }

/* A big, obvious, child-sized target. The hard shadow is what makes it look
   pressable, and it collapses on :active so the button really goes down. */
.kid-action {
    width: 100%; margin-top: .8rem;
    padding: .8rem .9rem;
    border: 3px solid rgba(255, 255, 255, .28); border-radius: 999px;
    background: var(--kid-green); color: #fff;
    font: 900 .82rem var(--serif); letter-spacing: .04em;
    text-align: center; text-decoration: none; cursor: pointer;
    box-shadow: 0 5px 0 var(--kid-green-deep);
    transition: transform .12s ease, background .18s ease, box-shadow .12s ease;
}
.kid-action:hover, .kid-action:focus-visible {
    background: #c58924; color: #112d22; transform: translateY(-2px);
    box-shadow: 0 7px 0 var(--kid-green-deep);
}
.kid-action:active { transform: translateY(4px); box-shadow: 0 1px 0 var(--kid-green-deep); }

.kids-verse {
    max-width: 720px; margin: clamp(26px, 4vw, 46px) auto 0;
    text-align: center;
    font: italic 1.05rem/1.6 var(--serif); color: #cfe0d3;
}
.kids-verse span {
    display: block; margin-top: 6px;
    font-style: normal; font-weight: 900; font-size: .72rem;
    letter-spacing: .16em; text-transform: uppercase; color: #c3d67e;
}

@media (max-width: 860px) {
    .kids-grid { grid-template-columns: 1fr; }
    .sprout-character { width: min(300px, 76%); }
    .sprout-welcome { right: 0; }
    .kidcards { grid-template-columns: 1fr; }
    .kidcards .card { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .sprout-character { animation: none; }
    .kidcards .card { transition: none; }
    .kidcards .card:hover { transform: none; }
}

/* ================================================================
   SHARED CHROME FOR THE ROOMS
   ================================================================
   Every room — Colouring, Story Time, Theatre, Games, Friends — wears
   the same bright bar and heading as the hub, so a child never crosses
   into what looks like a different website. Each plaque on the hub
   opens one of these as its own page; nothing expands inline.
   ---------------------------------------------------------------- */

.kids-room-body { background: transparent; }

.kids-bar {
    display: flex; flex-wrap: wrap; gap: 10px;
    align-items: center; justify-content: space-between;
    padding: 12px clamp(14px, 4vw, 46px);
    background: linear-gradient(rgba(22, 76, 56, .78), rgba(14, 58, 41, .82));
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-bottom: 4px solid var(--kid-gold);
}
.kids-bar .back {
    display: inline-flex; align-items: center; gap: 8px;
    padding: .5rem .95rem;
    border: 3px solid rgba(255, 255, 255, .8); border-radius: 999px;
    background: #fffdf6; color: #174735;
    font: 900 .74rem var(--serif); text-decoration: none;
    box-shadow: 0 4px 0 #0a3024;
}
.kids-bar .back:hover { background: var(--kid-gold); transform: translateY(-2px); }
.kids-bar .back:active { transform: translateY(3px); box-shadow: 0 1px 0 #0a3024; }
.kids-bar strong { font: 400 1.3rem var(--serif); color: #fff7d6; }
.kids-bar nav { display: flex; flex-wrap: wrap; gap: 6px; }
.kids-bar nav a {
    padding: .42rem .8rem;
    border: 2px solid rgba(255, 255, 255, .35); border-radius: 999px;
    color: #fff7d6; text-decoration: none;
    font: 800 .72rem var(--serif);
}
.kids-bar nav a:hover,
.kids-bar nav a[aria-current="page"] {
    background: var(--kid-gold); color: #174735; border-color: var(--kid-gold);
}

.kids-room {
    padding: clamp(20px, 4vw, 48px) clamp(14px, 4vw, 54px) clamp(34px, 5vw, 70px);
    background: radial-gradient(760px 380px at 18% 0%, rgba(249, 200, 70, .08), transparent 65%);
}
.kids-room > header { max-width: 1180px; margin: 0 auto clamp(16px, 3vw, 30px); }
.kids-room > header .eyebrow {
    display: inline-block; margin: 0 0 6px;
    padding: .35rem .8rem; border-radius: 999px;
    background: var(--kid-gold); color: #214d34;
    font-weight: 900; font-size: .7rem; letter-spacing: .12em;
    transform: rotate(-2deg);
}
.kids-room > header h1 {
    margin: .1rem 0;
    font: 400 clamp(2.1rem, 4.6vw, 3.5rem)/1.02 var(--serif);
    color: var(--kid-gold);
    text-shadow: 3px 3px 0 rgba(0, 0, 0, .45), 6px 6px 0 rgba(249, 200, 70, .20);
}
.kids-room > header p { margin: .5rem 0 0; max-width: 62ch; font-size: 1rem; line-height: 1.6; color: #c9d6cc; }

/* A chunky panel used for anything that is not a card grid. */
.kids-panel {
    max-width: 1180px; margin: 0 auto;
    padding: clamp(1rem, 2.4vw, 1.6rem);
    border: 1px solid var(--glass-border); border-radius: 28px;
    background: var(--glass);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    box-shadow: 0 18px 50px rgba(0, 0, 0, .35);
}

/* ---- the games shelf ---- */

.game-shelf {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
    gap: 16px; max-width: 1180px; margin: 0 auto;
}
.game-tile {
    display: flex; flex-direction: column;
    border: 1px solid var(--glass-border); border-radius: 26px;
    overflow: hidden;
    background: var(--glass);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    box-shadow: 0 10px 0 rgba(0, 0, 0, .28), 0 18px 30px rgba(0, 0, 0, .32);
    transition: transform .2s ease, box-shadow .2s ease;
}
.game-tile:nth-child(1) { background: linear-gradient(145deg, rgba(150, 226, 120, .13), rgba(110, 190, 255, .09)); }
.game-tile:nth-child(2) { background: linear-gradient(145deg, rgba(249, 200, 70, .15), rgba(255, 130, 190, .09)); }
.game-tile:nth-child(3) { background: linear-gradient(145deg, rgba(110, 190, 255, .13), rgba(200, 140, 255, .10)); }
.game-tile:hover { transform: translateY(-7px); box-shadow: 0 15px 0 rgba(0, 0, 0, .32), 0 26px 38px rgba(0, 0, 0, .4); }
.game-art { aspect-ratio: 16 / 10; background: #1b3a2c; }
.game-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.game-art.is-blank { display: grid; place-items: center; font-size: 3.4rem;
                     background: linear-gradient(150deg, #2a5a41, #16382a); }
.game-body { display: flex; flex-direction: column; flex: 1; padding: 1rem 1.1rem 1.2rem; }
.game-body h2 { margin: 0 0 .35rem; font: 700 1.2rem var(--serif); color: var(--gold-pale); }
.game-body p { flex: 1; margin: 0; font-size: .92rem; line-height: 1.5; color: #c9d6cc; }
/* The piece counts on the puzzle tile, smallest to biggest. */
.game-levels {
    display: flex; flex-wrap: wrap; gap: 5px;
    margin: .7rem 0 0; padding: 0; list-style: none;
}
.game-levels li {
    display: flex; align-items: baseline; gap: 3px;
    padding: .22rem .55rem; border-radius: 999px;
    background: rgba(255, 255, 255, .10);
    font: 800 .68rem var(--serif); color: #d8e4da;
}
.game-levels b { font: 900 .82rem var(--serif); color: #ffe9a8; }
.game-levels span {
    font-size: .56rem; letter-spacing: .08em; text-transform: uppercase;
    color: #c3d67e;
}

.game-flag {
    align-self: flex-start; margin-top: .7rem;
    padding: .32rem .7rem; border-radius: 999px;
    background: rgba(249, 200, 70, .14); color: var(--gold-pale);
    font: 900 .62rem var(--serif); letter-spacing: .1em; text-transform: uppercase;
}

/* ---- picking a library ---- */

.shelf-cards {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
    gap: 16px; max-width: 1180px; margin: 0 auto;
}
.shelf-card {
    position: relative;
    display: grid; gap: 10px;
    padding: 16px 16px 18px;
    border: 1px solid var(--glass-border); border-radius: 26px;
    text-decoration: none; color: inherit;
    background: var(--glass);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    box-shadow: 0 10px 0 rgba(0, 0, 0, .28), 0 18px 30px rgba(0, 0, 0, .32);
    transition: transform .18s ease, box-shadow .18s ease;
}
.shelf-cards .shelf-card:nth-child(1) { background: linear-gradient(145deg, rgba(150, 226, 120, .13), rgba(110, 190, 255, .09)); }
.shelf-cards .shelf-card:nth-child(2) { background: linear-gradient(145deg, rgba(249, 200, 70, .15), rgba(255, 130, 190, .09)); }
.shelf-cards .shelf-card:nth-child(3) { background: linear-gradient(145deg, rgba(110, 190, 255, .13), rgba(200, 140, 255, .10)); }
.shelf-cards .shelf-card:nth-child(4) { background: linear-gradient(145deg, rgba(255, 190, 92, .15), rgba(249, 200, 70, .07)); }
.shelf-cards .shelf-card:nth-child(5) { background: linear-gradient(145deg, rgba(120, 230, 180, .13), rgba(249, 200, 70, .09)); }
.shelf-cards .shelf-card:nth-child(6) { background: linear-gradient(145deg, rgba(255, 140, 140, .12), rgba(249, 200, 70, .09)); }
.shelf-card:hover { transform: translateY(-7px); box-shadow: 0 15px 0 rgba(0, 0, 0, .32), 0 26px 38px rgba(0, 0, 0, .4); }

/* A colour picture of what is on the shelf.
 *
 * Not the line art. The line art is the thing the child is going to colour in,
 * and a row of white outlines makes every shelf look the same from the outside.
 * A finished picture tells a four-year-old which shelf they want before they
 * can read the label. */
.shelf-cover {
    display: block; height: 160px;
    border-radius: 18px; overflow: hidden;
    background: rgba(255, 255, 255, .10);
}
.shelf-cover img {
    width: 100%; height: 100%;
    object-fit: cover; display: block;
}
/* Shown when a cover has not been drawn yet, or fails to load. */
.shelf-cover.is-bare {
    display: grid; place-items: center;
    background: repeating-linear-gradient(45deg,
        rgba(255,255,255,.10) 0 12px, rgba(255,255,255,.05) 12px 24px);
}
.shelf-cover.is-bare:after {
    content: "picture to come";
    font: 900 .62rem var(--serif); letter-spacing: .12em;
    text-transform: uppercase; color: #8aa093;
}
.shelf-text { display: grid; gap: 3px; }
.shelf-text b { font: 700 1.16rem var(--serif); color: var(--gold-pale); }
.shelf-text em { font-style: normal; font-size: .88rem; line-height: 1.45; color: #c9d6cc; }
.shelf-count {
    justify-self: start; margin-top: 4px;
    padding: .22rem .7rem; border-radius: 999px;
    background: rgba(255, 255, 255, .10);
    font: 900 .64rem var(--serif); letter-spacing: .08em;
    text-transform: uppercase; color: #d8e4da;
}

/* ---- the colouring library shelves ---- */

.shelf { max-width: 1180px; margin: 0 auto clamp(22px, 4vw, 40px); }
.shelf h2 {
    display: flex; align-items: center; gap: 10px;
    margin: 0 0 4px; font: 400 1.7rem var(--serif); color: var(--gold-pale);
}
.shelf h2 b {
    padding: .18rem .6rem; border-radius: 999px;
    background: var(--kid-gold); color: #214d34;
    font: 900 .68rem var(--serif);
}
.shelf-blurb { margin: 0 0 14px; font-size: .95rem; color: #c9d6cc; }
.shelf-empty {
    padding: 18px 20px; border: 3px dashed rgba(255, 255, 255, .22); border-radius: 20px;
    background: var(--glass-soft); color: #b9c4bb; font-size: .92rem;
}

.color-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(196px, 1fr)); gap: 14px; }
.color-card {
    display: flex; flex-direction: column;
    border: 1px solid var(--glass-border); border-radius: 22px; overflow: hidden;
    background: var(--glass);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    box-shadow: 0 9px 0 rgba(0, 0, 0, .28), 0 16px 26px rgba(0, 0, 0, .3);
    transition: transform .18s ease, box-shadow .18s ease;
}
.color-card:hover { transform: translateY(-6px); box-shadow: 0 14px 0 rgba(0, 0, 0, .32), 0 24px 34px rgba(0, 0, 0, .38); }
.color-thumb { display: block; background: #fff; }
.color-thumb img { width: 100%; aspect-ratio: 1; object-fit: contain; display: block; padding: 8px; }
.color-body { display: flex; flex-direction: column; gap: 4px; padding: 10px 12px 12px; }
.color-body h3 { margin: 0; font: 700 1rem var(--serif); color: var(--gold-pale); }
.color-verse { margin: 0; font: 900 .6rem var(--serif); letter-spacing: .1em;
               text-transform: uppercase; color: #c3d67e; }
.color-actions { display: grid; gap: 6px; margin-top: 6px; }
.color-actions .kid-action { margin-top: 0; font-size: .7rem; padding: .6rem .5rem; }
.color-print {
    text-align: center; padding: .35rem;
    font: 800 .68rem var(--serif); color: #d8e4da; text-decoration: none;
    border-radius: 999px; border: 2px solid rgba(255, 255, 255, .25);
}
.color-print:hover { background: rgba(255, 255, 255, .08); }

/* ================================================================
   THE COLOURING DESK
   ================================================================
   Crayon box on the left, paper in the middle, tools on the right.
   The pointer carries the colour it is holding, so a child can see
   what they picked up before they touch the paper.
   ---------------------------------------------------------------- */

.desk {
    --held: #ffd23f;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: clamp(10px, 2vw, 24px);
    align-items: start;
    padding: clamp(14px, 2.5vw, 30px) clamp(10px, 3vw, 40px);
    background: radial-gradient(820px 420px at 50% 0%, rgba(249, 200, 70, .07), transparent 70%);
    min-height: calc(100vh - 66px);
}

/* ---- the crayon box ---- */

.crayon-box {
    display: grid; gap: 7px;
    padding: 12px 10px;
    border: 4px solid rgba(255, 255, 255, .75); border-radius: 24px;
    background: linear-gradient(160deg, #fff6d8, #ffe2a7);
    box-shadow: 0 10px 0 rgba(0, 0, 0, .3), 0 18px 30px rgba(0, 0, 0, .34);
}
/* A crayon: a pointed tip on a fat barrel with a paper wrap. */
.crayon {
    display: flex; align-items: center; gap: 0;
    width: clamp(58px, 7vw, 96px); padding: 0;
    border: 0; background: none; cursor: pointer;
    filter: drop-shadow(0 3px 2px rgba(60, 45, 15, .3));
    transition: transform .14s ease;
}
.crayon-tip {
    width: 0; height: 0; flex: 0 0 auto;
    border-top: 9px solid transparent;
    border-bottom: 9px solid transparent;
    border-right: 13px solid var(--crayon);
    filter: brightness(.82);
}
.crayon-body {
    flex: 1; min-width: 0;
    display: grid; place-items: center;
    height: 26px; padding: 0 4px;
    border-radius: 3px 7px 7px 3px;
    background:
        linear-gradient(180deg, rgba(255,255,255,.45), transparent 40%, rgba(0,0,0,.22)),
        var(--crayon);
}
.crayon-name {
    font: 900 .52rem var(--serif); letter-spacing: .04em;
    color: rgba(255, 255, 255, .95);
    text-shadow: 0 1px 1px rgba(0, 0, 0, .45);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.crayon:hover { transform: translateX(4px) rotate(-2deg); }
/* The chosen crayon pulls out of the box, the way it would in a real one. */
.crayon[aria-checked="true"] {
    transform: translateX(12px) rotate(-3deg) scale(1.06);
    filter: drop-shadow(0 5px 3px rgba(60, 45, 15, .45));
}

/* ---- the paper ---- */

.desk-middle { display: grid; gap: 10px; justify-items: center; }
.paper {
    position: relative;
    width: 100%; max-width: 720px;
    /* Replaced at load time with the artwork's real ratio - see the note in
       coloring-book.js. A fixed square here misaligns clicks. */
    aspect-ratio: 3 / 4;
    max-height: calc(100vh - 190px);
    border: 5px solid #fff; border-radius: 20px;
    background: #fff;
    box-shadow: 0 12px 0 rgba(0, 0, 0, .3), 0 22px 40px rgba(0, 0, 0, .38);
    overflow: hidden;
}
/* Both layers are letterboxed identically inside the sheet, so the paint and
   the lines always sit exactly on top of one another whatever shape the paper
   ends up. coloring-book.js undoes the letterbox when mapping clicks. */
.paper canvas, .paper img {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: contain;
    display: block;
}
/* The line art never takes the pointer, so a click always reaches the canvas.
 *
 * multiply is what makes this work at all. These sheets are opaque white with
 * black lines - no transparency - so sitting one on top of the paint hides
 * every stroke completely. Multiplying, white becomes invisible and the black
 * lines stay black, so the colour underneath shows through and the drawing
 * still sits on top of it. */
.paper img { pointer-events: none; mix-blend-mode: multiply; }
.paper canvas { touch-action: none; background: #fff; }
/* Keep the blend inside the sheet. */
.paper { isolation: isolate; }

/* The pointer carries the crayon. Two cursors: a bucket for fill, a fat nib
   for crayon, both tinted with the colour currently held. */
.desk[data-tool="fill"] .paper canvas { cursor: crosshair; }
.desk[data-tool="crayon"] .paper canvas { cursor: cell; }
.desk.is-holding .paper canvas { outline: none; }
.paper:after {
    content: ""; position: absolute; z-index: 3;
    right: 10px; top: 10px; width: 18px; height: 18px;
    border-radius: 50%; background: var(--held);
    border: 3px solid #fff;
    box-shadow: 0 2px 5px rgba(0, 0, 0, .3);
    pointer-events: none;
}

.paper-verse {
    margin: 0; font: 900 .72rem var(--serif); letter-spacing: .12em;
    text-transform: uppercase; color: #c3d67e;
}

/* ---- the tools ---- */

.desk-tools { display: grid; gap: 8px; width: clamp(140px, 17vw, 190px); }
.tool-group {
    display: grid; grid-template-columns: 1fr 1fr; gap: 6px;
    padding: 6px; margin-bottom: 4px;
    border: 1px solid var(--glass-border); border-radius: 20px;
    background: rgba(255, 255, 255, .10);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    box-shadow: 0 8px 0 rgba(0, 0, 0, .28);
}
.tool-group button {
    display: grid; gap: 2px; justify-items: center;
    padding: .55rem .3rem;
    border: 2px solid transparent; border-radius: 14px;
    background: transparent; color: #e4ead9;
    font: 900 .66rem var(--serif); cursor: pointer;
}
.tool-group button span { font-size: 1.3rem; }
.tool-group button[aria-pressed="true"] {
    background: var(--kid-gold); border-color: #fff; color: #174735;
}
/* Crayon size. Four dots that show the actual nib, tinted with the colour
   being held, so the choice is visible rather than a word to read. */
.size-group {
    display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px;
    padding: 7px; margin-bottom: 4px;
    border: 1px solid var(--glass-border); border-radius: 20px;
    background: rgba(255, 255, 255, .10);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    box-shadow: 0 8px 0 rgba(0, 0, 0, .28);
}
.size-group button {
    display: grid; place-items: center;
    aspect-ratio: 1; padding: 0;
    border: 2px solid transparent; border-radius: 14px;
    background: transparent; cursor: pointer;
}
.size-group button span {
    display: block; border-radius: 50%;
    background: var(--held, #22223b);
    box-shadow: inset 0 -2px 3px rgba(0, 0, 0, .25);
}
.size-group [data-size="s"]  span { width: 6px;  height: 6px; }
.size-group [data-size="m"]  span { width: 12px; height: 12px; }
.size-group [data-size="l"]  span { width: 19px; height: 19px; }
.size-group [data-size="xl"] span { width: 27px; height: 27px; }
.size-group button[aria-checked="true"] {
    background: var(--kid-gold); border-color: #fff;
}
.size-group button:hover { background: rgba(249, 200, 70, .45); }

.desk-tools .kid-action { margin-top: 0; font-size: .72rem; }
.desk-tools .kid-action:disabled { opacity: .45; cursor: default; box-shadow: 0 5px 0 var(--kid-green-deep); }

/* ---- more pages ---- */

.more-strip { padding: clamp(16px, 3vw, 30px) clamp(12px, 4vw, 46px) clamp(28px, 4vw, 50px); }
.more-strip h2 { margin: 0 0 12px; font: 400 1.5rem var(--serif); color: var(--gold-pale); }
.more-pages { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 12px; }
.more-page {
    display: grid; gap: 6px; justify-items: center;
    padding: 10px; text-decoration: none;
    border: 1px solid var(--glass-border); border-radius: 18px;
    background: var(--glass);
    box-shadow: 0 6px 0 rgba(0, 0, 0, .28);
}
.more-page img { width: 100%; aspect-ratio: 1; object-fit: contain; background: #fff; border-radius: 10px; }
.more-page span { font: 800 .68rem var(--serif); color: #d8e4da; text-align: center; }
.more-page:hover { transform: translateY(-4px); box-shadow: 0 10px 0 rgba(0, 0, 0, .32); }

@media (max-width: 900px) {
    .desk { grid-template-columns: 1fr; }
    .crayon-box { grid-auto-flow: column; grid-auto-columns: max-content;
                  overflow-x: auto; gap: 6px; }
    .crayon { width: 74px; }
    .crayon[aria-checked="true"] { transform: translateY(-6px) scale(1.06); }
    .desk-tools { width: 100%; grid-template-columns: repeat(2, 1fr); }
    .tool-group { grid-column: 1 / -1; }
}
@media print {
    .kids-bar, .crayon-box, .desk-tools, .more-strip, .paper-verse { display: none; }
    .desk { padding: 0; background: #fff; }
    .paper { border: 0; box-shadow: none; max-width: 100%; }
    .paper:after { display: none; }
}

/* ---- shared chrome for the rooms inside Little Sprouts ---- */

.sprouts-body-page { background: transparent; }

.sprouts-bar {
    display: flex; flex-wrap: wrap; gap: 14px;
    align-items: center; justify-content: space-between;
    padding: 14px clamp(18px, 5vw, 76px);
    background: var(--sprout-deep); color: white;
    border-bottom: 1px solid rgba(233, 213, 154, .22);
}
.sprouts-bar a.back {
    display: inline-flex; align-items: center; gap: 8px;
    color: #d9b95f; text-decoration: none;
    font-weight: 900; font-size: .72rem;
    text-transform: uppercase; letter-spacing: .12em;
}
.sprouts-bar a.back:hover { color: #fdf7e6; }
.sprouts-bar strong { font: 400 1.3rem var(--serif); color: #fdf7e6; }
.sprouts-bar nav { display: flex; flex-wrap: wrap; gap: 6px; }
.sprouts-bar nav a {
    padding: 7px 12px;
    border: 1px solid rgba(233, 213, 154, .3);
    color: rgba(255, 255, 255, .78);
    text-decoration: none; font-size: .69rem; font-weight: 800;
}
.sprouts-bar nav a:hover,
.sprouts-bar nav a[aria-current="page"] {
    background: var(--sprout-gold); color: var(--sprout-deep); border-color: var(--sprout-gold);
}

.sprouts-room > header {
    padding: clamp(40px, 5vw, 74px) clamp(20px, 6vw, 90px) clamp(26px, 3vw, 40px);
    background: transparent;
}
.sprouts-room > header .eyebrow { color: #8a6b2c; margin-bottom: 12px; }
.sprouts-room > header h1 {
    margin: 0;
    font: 400 clamp(2.6rem, 5vw, 4.6rem)/.95 var(--serif);
    color: var(--sprout-green);
}
.sprouts-room > header h1 em { font-style: italic; color: #8a6824; }
.sprouts-room > header p {
    margin: 14px 0 0; max-width: 62ch;
    font: 1.02rem/1.68 var(--serif); color: var(--sprout-muted);
}

/* A quiet line that says how much of something is finished. The ministry has
   said it will not pretend a thing is done, so the count is on the page. */
.sprouts-progress {
    margin: 18px 0 0; padding-left: 14px;
    border-left: 3px solid var(--sprout-gold);
    font-size: .82rem; line-height: 1.6; color: var(--sprout-muted);
}
.sprouts-progress b { color: var(--sprout-green); }

/* ---- volumes on the story shelf ---- */

.volume { max-width: 1180px; margin: 0 auto clamp(24px, 4vw, 42px); }
.volume-head {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px;
    margin: 0 0 12px; padding-bottom: 8px;
    border-bottom: 3px solid rgba(255, 255, 255, .12);
}
.volume-number {
    padding: .24rem .7rem; border-radius: 999px;
    background: var(--kid-gold); color: #214d34;
    font: 900 .64rem var(--serif); letter-spacing: .12em; text-transform: uppercase;
}
.volume-title { font: 400 1.5rem var(--serif); color: var(--gold-pale); }
.volume-count {
    margin-left: auto;
    font: 900 .64rem var(--serif); letter-spacing: .1em;
    text-transform: uppercase; color: #c3d67e;
}
.volume-books {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 14px;
}

/* ---- the story library ---- */

.book-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
    gap: clamp(14px, 2vw, 22px);
    padding: clamp(28px, 4vw, 52px) clamp(20px, 6vw, 90px) clamp(48px, 6vw, 84px);
}
.book-card {
    display: flex; flex-direction: column;
    background: var(--glass);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-sm);
    color: var(--sprout-ink); text-decoration: none;
    overflow: hidden;
    transition: transform .22s cubic-bezier(.2, .7, .2, 1), box-shadow .22s, border-color .22s;
}
.book-card:hover, .book-card:focus-visible {
    transform: translateY(-6px);
    border-color: rgba(201, 164, 92, .4);
    box-shadow: 0 22px 48px rgba(0, 0, 0, .45);
    outline: none;
}
.book-cover {
    position: relative;
    aspect-ratio: 1 / 1;
    background: linear-gradient(150deg, #16442f, #0a2a20);
}
/* Until a cover is drawn the card shows the book's scene mark rather than a
   broken image, so an unfinished shelf still looks deliberate. */
.book-plate {
    position: absolute; inset: 0;
    display: grid; place-items: center;
    font-size: clamp(2.4rem, 5vw, 3.4rem);
}
.book-cover img {
    position: relative; z-index: 1;
    width: 100%; height: 100%; object-fit: cover; display: block;
}
.book-number {
    position: absolute; z-index: 2; top: 0; left: 0;
    padding: 6px 12px;
    background: var(--sprout-deep); color: #e8d597;
    font-size: .64rem; font-weight: 900; letter-spacing: .14em;
}
.book-body { display: flex; flex-direction: column; gap: 8px; flex: 1; padding: 17px 19px 19px; }
.book-body h2 { margin: 0; font: 400 1.3rem/1.18 var(--serif); color: var(--sprout-green); }
.book-scripture {
    margin: 0;
    text-transform: uppercase; letter-spacing: .13em;
    font-size: .6rem; font-weight: 900; color: #d9b95f;
}
.book-truth { margin: 0; font-size: .85rem; line-height: 1.55; color: var(--sprout-muted); }
.book-meta {
    display: flex; flex-wrap: wrap; gap: 6px;
    margin-top: auto; padding-top: 12px;
}
.book-meta span {
    padding: 4px 9px;
    background: rgba(255, 255, 255, .08);
    font-size: .61rem; font-weight: 900;
    text-transform: uppercase; letter-spacing: .09em;
    color: #b9c4bb;
}
.book-meta span.is-listen { background: rgba(198, 164, 80, .2); color: #e9d5a3; }

/* ---- the storybook reader ----
 *
 * This is the approved reader from the live preview, carried over rather than
 * redesigned: a cover you open, then a real open book with the picture on the
 * left page and the words on the right, an edge arrow at each side, and a leaf
 * that actually turns between them. That layout is a rule of the book format —
 * LEFT is the picture, RIGHT is the text — not a style choice.
 *
 * The frame is the one piece of artwork the reader owns. Everything drawn
 * inside it comes from a book. Swap or drop the frame in one place:
 */
:root {
    --sprout-book-frame: url("../assets/kids/sprout-magical-open-storybook.png");
    --sprout-book-closed: url("../assets/kids/rooted-embossed-storybook-cover.png");
}

.reader-body { background: transparent; }

.story-screen { display: grid; place-items: center; padding: clamp(16px, 3vw, 28px); }
.story-screen[hidden] { display: none !important; }

/* ---- the cover you open ---- */

.story-cover-screen {
    min-height: calc(100vh - 88px);
    min-height: calc(100dvh - 88px);
    background: radial-gradient(circle at 50% 15%, #4b805e, #102f25 70%);
}
.story-cover-stage {
    display: grid;
    grid-template-columns: minmax(240px, 400px) minmax(280px, 520px);
    gap: clamp(24px, 5vw, 60px);
    align-items: center;
    color: white;
}

/* The cover stands behind; the friend who hosts the book stands in front of
   it, overlapping the bottom corner the way a presenter stands beside a
   poster. */
.story-cover-side { position: relative; }
/* Holds the book's cover once one is drawn. Until then it is an empty space
   with a quiet outline - NOT a painted green book. A fake cover competes with
   the real title beside it and makes an undrawn book look finished. */
.cover-plate {
    position: relative;
    aspect-ratio: 2 / 3;
    display: grid; place-content: center; gap: 10px;
    padding: 24px; text-align: center;
    border-radius: 10px;
    overflow: hidden;
}
/* With artwork it becomes a real cover, shadow and all. */
.cover-plate:not(.is-blank) {
    box-shadow: 0 26px 50px rgba(0, 0, 0, .45);
}
.cover-plate img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cover-plate-number {
    font: 900 .68rem var(--serif); letter-spacing: .22em;
    text-transform: uppercase; color: #f0cd75;
}
.cover-plate-title {
    font: 400 clamp(1.2rem, 2.2vw, 1.8rem)/1.15 var(--serif); color: #fff7d6;
}
/* An undrawn cover is an outline and a word, nothing more. The title and the
   verse are already set properly beside it; this only marks where the art will
   go, so Sprout still has something to stand against. */
.cover-plate.is-blank {
    border: 2px dashed rgba(240, 205, 117, .3);
    background: rgba(255, 255, 255, .03);
}
.cover-plate.is-blank .cover-plate-number,
.cover-plate.is-blank .cover-plate-title { display: none; }
.cover-plate.is-blank:after {
    content: "cover to come";
    position: absolute; left: 0; right: 0; top: 50%;
    transform: translateY(-50%);
    font: 900 .58rem var(--serif); letter-spacing: .2em;
    text-transform: uppercase; color: rgba(240, 205, 117, .45);
}
.cover-host {
    position: absolute; z-index: 2;
    right: -14%; bottom: -6%;
    width: 52%; max-height: 74%;
    object-fit: contain; object-position: bottom;
    filter: drop-shadow(0 12px 18px rgba(0, 0, 0, .5));
}

/* What the host says: the book's own introduction, in a speech panel. */
.cover-speech {
    margin: 14px 0 0; padding: 14px 16px;
    border-left: 4px solid #d5a43c;
    border-radius: 4px 16px 16px 4px;
    background: rgba(255, 250, 232, .1);
}
.cover-speech b {
    display: block; margin-bottom: 4px;
    font: 900 .6rem var(--serif); letter-spacing: .18em;
    text-transform: uppercase; color: #f0cd75;
}
.cover-speech p { margin: 0 0 .5em; font: 1rem/1.6 var(--serif); color: rgba(255, 247, 226, .88); }
.cover-speech p:last-child { margin-bottom: 0; }

.cover-scripture {
    margin: 2px 0 0;
    font: 900 .7rem var(--serif); letter-spacing: .14em;
    text-transform: uppercase; color: #e8c98a;
}

.cover-verse {
    margin: 14px 0 4px; padding: 14px 16px;
    border: 2px dashed rgba(240, 205, 117, .5); border-radius: 16px;
}
.cover-verse-label {
    margin: 0 0 6px;
    font: 900 .58rem var(--serif); letter-spacing: .18em;
    text-transform: uppercase; color: #f0cd75;
}
.cover-verse blockquote {
    margin: 0; font: italic 1.05rem/1.55 var(--serif);
    color: #fff7d6; white-space: pre-line;
}

@media (max-width: 820px) {
    .cover-host { right: -6%; width: 44%; }
    .cover-plate { transform: none; }
}
/* Until a cover is drawn the stage shows the ministry's embossed storybook
   rather than a gap, so an unfinished shelf still opens like a book. */
.story-cover-plate {
    aspect-ratio: 2 / 3;
    background: var(--sprout-book-closed) center/contain no-repeat;
    box-shadow: 18px 22px 0 #714717, 0 32px 70px rgba(0, 0, 0, .45);
    border-radius: 14px;
    transform: rotate(-1deg);
}
.story-cover-stage img {
    display: block; width: 100%;
    max-height: 74vh; object-fit: contain;
    border-radius: 14px;
    box-shadow: 18px 22px 0 #714717, 0 32px 70px rgba(0, 0, 0, .45);
    transform: rotate(-1deg);
}
.story-cover-intro .eyebrow { color: #f0cd75; margin-bottom: 6px; }
.story-cover-intro h1 {
    margin: .35rem 0;
    font: 400 clamp(2rem, 5vw, 4rem)/1.05 var(--serif);
    color: #fff7d6;
}
.story-cover-intro p { font: 1.08rem/1.6 var(--serif); color: #e8eedf; }
.story-open-button {
    border: 3px solid #f0cd75; border-radius: 999px;
    background: #d5a43c; color: #102f25;
    padding: .9rem 1.4rem;
    font: inherit; font-weight: 900; cursor: pointer;
    box-shadow: 0 8px 0 #76501d;
}
.story-open-button:hover { background: #e6b757; }
.story-open-button:active { transform: translateY(4px); box-shadow: 0 4px 0 #76501d; }

/* ---- the open book ---- */

/* The book sits on an old desk.
 *
 * The oak is lifted from the prayer room doors so the two rooms are plainly the
 * same building - but taken from a plain panel with no carving, no moulding and
 * no ironwork, then mirror-tiled into boards. It repeats without a seam in
 * either direction, so it covers any screen. */
.story-reader-wrap {
    position: relative;
    min-height: calc(100vh - 88px);
    min-height: calc(100dvh - 88px);
    overflow: hidden;
    background: #0d0703 url("../assets/images/desk-oak.jpg") top center / 520px auto repeat;
}
/* Waxed and worn: a sheen where the light falls, darker toward the edges, and
   a few knocks. Without this the tile reads as wallpaper rather than furniture. */
.story-reader-wrap:before {
    content: "";
    position: absolute; inset: 0; z-index: 0;
    background:
        radial-gradient(ellipse 60% 42% at 46% 20%, rgba(255, 228, 185, .07), transparent 70%),
        radial-gradient(circle 4px at 21% 63%, rgba(28, 13, 3, .5), transparent),
        radial-gradient(circle 6px at 74% 34%, rgba(28, 13, 3, .42), transparent),
        radial-gradient(ellipse 34px 4px at 61% 79%, rgba(28, 13, 3, .34), transparent),
        radial-gradient(ellipse 130% 100% at 50% 42%,
            transparent 34%, rgba(8, 3, 0, .72) 100%);
    pointer-events: none;
}

/* The tree seal carved into the boards, bottom right.
 *
 * Carving cuts through the dark stain into raw oak, so the mark is much LIGHTER
 * than the desk, not darker - that is what makes it read as cut rather than
 * printed. The two drop-shadows give the incision its depth: a hard dark edge
 * up and left where the cut is in shadow, and a warm highlight down and right
 * where the light catches the lower wall of the groove.
 *
 * The mark is cut to a stencil first - assets/brand-stencil.png, from
 * build_brand_stencil.py. The logo file itself is dark artwork on cream with no
 * alpha at all, so masking straight from it gives a solid square rather than
 * the shape of the mark.
 */
.story-reader-wrap:after {
    content: "";
    position: absolute; z-index: 0;
    right: clamp(14px, 3vw, 56px); bottom: clamp(10px, 3vh, 44px);
    width: clamp(140px, 17vw, 300px); aspect-ratio: 512 / 464;
    /* Raw oak under the stain, lit from the upper left. */
    background:
        linear-gradient(152deg, #d9b98a 0%, #c39f6d 34%, #a67f4d 66%, #8a6537 100%);
    -webkit-mask-image: url("../assets/images/brand-stencil.png");
            mask-image: url("../assets/images/brand-stencil.png");
    -webkit-mask-size: contain; mask-size: contain;
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
    -webkit-mask-position: center; mask-position: center;
    opacity: .92;
    filter:
        drop-shadow(-1.5px -1.5px 0 rgba(0, 0, 0, .92))
        drop-shadow(1.5px 2px 1px rgba(255, 226, 176, .3))
        drop-shadow(0 0 10px rgba(0, 0, 0, .6));
    pointer-events: none;
}

/* Everything on the desk sits above the wood and the brand. */
.story-book-stage, .story-reader-top { position: relative; z-index: 1; }
.story-book-stage {
    position: relative;
    width: min(1240px, 97vw);
    display: grid; justify-items: center; gap: 18px;
    padding: 38px 26px 12px;
}
.story-book-stage:before, .story-book-stage:after {
    content: "✦";
    position: absolute;
    color: #f8dda0; font-size: 1.4rem;
    text-shadow: 0 0 18px #ffe9a8;
    animation: storybookSparkle 2.4s ease-in-out infinite;
}
.story-book-stage:before { left: 2%; top: 4%; }
.story-book-stage:after { right: 3%; top: 15%; animation-delay: .9s; }
@keyframes storybookSparkle { 50% { opacity: .25; transform: translateY(-12px) rotate(35deg) scale(.7); } }

/* The book is sized by the height available, not by a locked ratio.
 *
 * It used to be aspect-ratio: 3/2, which tied the height of the text column to
 * the width of the book — about 40% of it. That left roughly 180px for pages
 * that carry up to 202 words, so the longest spreads simply overflowed. Now
 * the book fills the window and the width follows, and the text is fitted to
 * the page by measurement (see fitText in little-sprouts.js).
 *
 * --page-inset-* is the safe area: the paper curls toward the gutter and the
 * outer edge, so content is kept off the curve rather than printed across it.
 */
/* These are measured off the book artwork itself, not guessed. In
   kids-assets/sprout-magical-open-storybook.png the cream paper of the right
   page runs from 51.7% to 89.9% across and from 10% to 78% down — below that is
   the gold bottom board, and outside it the decorated border. Content set to
   the old figures printed across both. Each value leaves about two points of
   margin inside the paper so a descender never touches the edge. */
.story-open-book {
    --page-inset-top: 13%;
    --page-inset-bottom: 24%;
    --page-inset-outer: 12%;
    --page-inset-gutter: 5%;

    position: relative; z-index: 2;
    width: min(1180px, 100%);
    height: min(72vh, 660px);
    min-height: 360px;
    background: var(--sprout-book-frame) center/100% 100% no-repeat;
    filter: drop-shadow(0 30px 34px rgba(0, 0, 0, .5));
    transform-style: preserve-3d; perspective: 1800px;
}
/* The gutter highlight down the middle of the spread. */
.story-open-book:after {
    content: "";
    position: absolute; z-index: 2;
    left: 50%; top: 11%; bottom: 23%; width: 2px;
    background: linear-gradient(90deg, rgba(114, 71, 22, .28), #fff0b8, rgba(114, 71, 22, .25));
}

/* Each page keeps its content inside the flat part of the paper: tighter on
   the gutter side, where the curl is strongest. */
/* The two pages are placed on the artwork rather than laid out beside it.
   Percentage padding resolves against WIDTH even for top and bottom, so on a
   narrow window — where the book turns tall — padding-based insets collapse to
   a fraction of what they should be and the words print off the top and bottom
   of the paper. Percentage top/bottom offsets resolve against height, so these
   hold the text inside the paper whatever shape the book takes. */
.story-scene-page, .story-reading-page {
    position: absolute; background: transparent;
    top: var(--page-inset-top);
    bottom: var(--page-inset-bottom);
    min-height: 0;
}
.story-scene-page { left: var(--page-inset-outer); right: 53%; }
.story-reading-page { left: 53%; right: var(--page-inset-outer); }
.story-scene-page {
    overflow: hidden; display: grid; place-items: center;
    padding: 0 var(--page-inset-gutter) 0 0;
}

/* The page is curled, so a square picture dropped straight on it reads as a
   sticker. The frame below follows the page instead: it is inset from the
   gutter, rounded unevenly the way the paper is, and shaded darker toward the
   spine and lighter at the outer edge. */
/* Fill the printed picture area like a real full-page illustration. The source
   art is centered, so only its outer bleed may be trimmed at unusual ratios. */
.story-scene {
    position: relative;
    width: 100%; height: 100%; min-height: 0;
    display: grid; place-items: center; text-align: center;
    border-radius: 5px 10px 12px 6px;
    overflow: hidden;
    box-shadow: 0 5px 13px rgba(75, 48, 19, .12);
}
.story-scene:after {
    content: "";
    position: absolute; inset: 0; pointer-events: none;
    background:
        linear-gradient(90deg, rgba(255, 248, 222, .16) 0, transparent 10%, transparent 82%, rgba(100, 68, 28, .22) 98%),
        linear-gradient(0deg, rgba(87, 55, 20, .12), transparent 12%);
    mix-blend-mode: multiply;
}
.story-scene img {
    display: block;
    width: 100%; height: 100%; min-height: 0;
    object-fit: cover; object-position: center;
    border-radius: inherit;
}
/* No picture yet: name the spread quietly rather than showing a hole. */
.story-scene-plate {
    display: grid; gap: 10px; place-items: center;
    padding: 18px;
    color: rgba(93, 60, 22, .6);
    font-family: var(--serif);
}
.story-scene-plate b { font: 400 1.4rem var(--serif); color: rgba(93, 60, 22, .78); }
.story-scene-plate small {
    font-size: .62rem; font-weight: 900;
    text-transform: uppercase; letter-spacing: .16em;
}

/* No scrollbar: a page of a book does not scroll. Whatever is on this spread
   is fitted to it by fitText() instead. */
.story-reading-page {
    display: flex; flex-direction: column; justify-content: center;
    padding: 0 0 0 var(--page-inset-gutter);
    overflow: hidden;
}
.story-page-kicker {
    margin: 0;
    text-transform: uppercase; letter-spacing: .2em;
    font-size: .58rem; font-weight: 900; color: #8a6824;
}
.story-reading-page h2 {
    margin: calc(.3rem * var(--story-fit, 1)) 0;
    font: 400 calc(2.1rem * var(--story-fit, 1))/1.1 var(--serif);
    color: #5d3c16;
}
.story-reading-page .story-scripture { margin: 0 0 .6rem; font-weight: 800; color: #76501d; font-size: .85rem; }
/* --story-fit is set by fitText(): it starts at 1 and steps down until the
   words fit the page. Everything on the page scales with it, so the heading
   and the text shrink together instead of the text alone going small. */
.story-words {
    position: relative; z-index: 2;
    display: grid; gap: calc(.62em * var(--story-fit, 1));
    font-family: var(--serif);
    font-size: calc(1.28rem * var(--story-fit, 1));
    line-height: 1.62;
    color: #2e382e;
}
.story-words p { margin: 0; }
/* A tagged [SAY] line is a character speaking, and a [VERSE] is Scripture.
   They are set apart so a reading parent can see whose words they are. */
.story-words .said { font-style: italic; color: #3c5a3f; }
.story-words .said b {
    display: block;
    font: 900 .58rem/1 inherit; font-style: normal;
    text-transform: uppercase; letter-spacing: .16em;
    color: #8a6824; margin-bottom: .3em;
}
.story-words .verse {
    display: grid; gap: .5em;
    padding: .55em .8em;
    border-left: 3px solid #d5a43c;
    background: rgba(213, 164, 60, .12);
    font-style: italic;
}
/* pre-line keeps the reference on the line the writer put it on, without
   turning the whole block into preformatted text. */
.story-words .verse p { margin: 0; white-space: pre-line; }
/* The ROOTS spread is five named steps, not prose. */
.story-roots { display: grid; gap: .55em; margin: 0; padding: 0; list-style: none; }
.story-roots li { display: grid; gap: .15em; }
.story-roots b {
    font: 900 .58rem/1 var(--serif);
    text-transform: uppercase; letter-spacing: .15em; color: #8a6824;
}
.story-roots span { font-size: .92em; line-height: 1.6; }

/* ---- who is standing at the book ---- */

.book-watcher {
    position: absolute; z-index: 6; bottom: -2%;
    width: clamp(90px, 11vw, 168px);
    max-height: 46%;
    object-fit: contain; object-position: bottom;
    filter: drop-shadow(0 14px 16px rgba(0, 0, 0, .45));
    transition: opacity .4s ease, transform .4s ease;
    pointer-events: none;
}
.book-watcher[hidden] { display: none; }

/* Mirrored so both figures face in toward the book rather than away from it. */

/* Whoever is speaking on this spread leans in a little. */
/* The one who is talking leans in. */
.book-watcher.is-speaking { filter: drop-shadow(0 14px 18px rgba(0, 0, 0, .5)) brightness(1.06); }

@media (max-width: 900px) {
    /* On a narrow screen the book needs the width more than the company does. */
    .book-watcher { display: none; }
}

/* On a narrow window a two-column spread leaves each page a column barely a
   hundred pixels wide, which no amount of shrinking makes readable. The spread
   is stacked instead: the picture across the top of both pages and the words
   across the bottom, each using the full width of the paper. */
@media (max-width: 760px) {
    .story-scene-page, .story-reading-page {
        left: var(--page-inset-outer);
        right: var(--page-inset-outer);
    }
    /* Taller, because a stacked spread needs the room the second column gave
       up, and a phone has height to spare where it has no width. */
    .story-open-book { height: min(84vh, 780px); }
    /* Keep the picture at its intended 4:3 shape instead of squeezing it into
       a shallow strip. The words begin just below it on the lower paper. */
    .story-scene-page  {
        top: 12%;
        bottom: auto;
        aspect-ratio: 4 / 3;
        padding: 0;
    }
    .story-reading-page {
        top: 48%;
        bottom: 24%;
        padding: .35rem 0 0;
        justify-content: flex-start;
    }
    /* The gutter highlight would run straight through both. */
    .story-open-book:after { display: none; }
}

/* The last resort when a page will not fit even at the smallest readable size.
   The words scroll rather than being cut off, and a soft fade at the foot of
   the page shows there is more below. */
.story-reading-page.is-overfull {
    overflow-y: auto;
    scrollbar-width: thin;
    -webkit-mask-image: linear-gradient(180deg, #000 88%, transparent 100%);
            mask-image: linear-gradient(180deg, #000 88%, transparent 100%);
}

/* ---- read along ----
 *
 * The line being read lifts off the page in a warm highlight. Deliberately
 * strong: a child has to be able to find it at a glance from across a room,
 * and following the lit line is how listening turns into reading.
 */
.story-words [data-line] {
    border-radius: 6px;
    padding: 2px 6px; margin-left: -6px; margin-right: -6px;
    transition: background .25s ease, color .25s ease;
}
.story-words [data-line].is-reading {
    background: linear-gradient(180deg, #ffe9a8, #ffd76b);
    color: #3a2a08;
    box-shadow: 0 0 0 3px rgba(255, 215, 107, .35);
}
.story-words .said[data-line].is-reading { color: #33280c; }
.story-words .verse[data-line].is-reading { background: #ffe9a8; }

@media (prefers-reduced-motion: reduce) {
    .story-words [data-line] { transition: none; }
}

/* ---- turning the page ---- */

.story-edge-turn {
    position: absolute; z-index: 35; top: 50%;
    width: 38px; height: 54px;
    display: grid; place-items: center;
    border: 1px solid rgba(240, 205, 117, .7); border-radius: 999px;
    background: rgba(23, 71, 53, .45); color: rgba(255, 245, 205, .82);
    font-size: 1.65rem; line-height: 1; cursor: pointer;
    box-shadow: 0 7px 18px rgba(0, 0, 0, .2);
    transform: translateY(-50%);
    backdrop-filter: blur(5px);
    opacity: .58;
    transition: opacity .18s, transform .18s, background .18s;
}
.story-edge-turn:hover, .story-edge-turn:focus-visible {
    opacity: 1; background: rgba(197, 137, 36, .86); color: #17392c;
    transform: translateY(-50%) scale(1.06);
}
.story-edge-turn:disabled { opacity: .12; cursor: not-allowed; }
.story-edge-prev { left: 1.2%; }
.story-edge-next { right: 1.2%; }

.storybook-turn-leaf {
    display: none;
    position: absolute; z-index: 28;
    left: 50%; top: 10%; width: 42.5%; height: 76%;
    transform-style: preserve-3d; transform-origin: left center;
    pointer-events: none;
}
.storybook-turn-leaf.turning-next { display: block; animation: turnLeafNext .92s cubic-bezier(.22, .62, .18, 1) forwards; }
.storybook-turn-leaf.turning-prev {
    display: block; left: 7.5%; transform-origin: right center;
    animation: turnLeafPrev .92s cubic-bezier(.22, .62, .18, 1) forwards;
}
.turn-leaf-face {
    position: absolute; inset: 0;
    overflow: hidden; padding: 9%;
    backface-visibility: hidden;
    background: linear-gradient(90deg, #f4e2b9, #fff8df 12%, #fff9e8 88%, #e4c994);
    box-shadow: 0 5px 20px rgba(76, 48, 19, .24);
}
.turn-leaf-front { border-radius: 2% 8% 10% 2%; }
.turn-leaf-back { transform: rotateY(180deg); border-radius: 8% 2% 2% 10%; padding: 4%; }
.turn-leaf-back img {
    display: block; width: 92%; height: 84%; margin: 5% auto 0;
    object-fit: cover; border-radius: 5px 10px 12px 6px;
}
@keyframes turnLeafNext {
    0%   { transform: rotateY(0) skewY(0); filter: brightness(1); }
    28%  { transform: rotateY(-42deg) skewY(-1deg); filter: brightness(.94); }
    52%  { transform: rotateY(-96deg) skewY(-2deg); filter: brightness(.8); }
    76%  { transform: rotateY(-144deg) skewY(-1deg); filter: brightness(.92); }
    100% { transform: rotateY(-180deg) skewY(0); filter: brightness(1); }
}
@keyframes turnLeafPrev {
    0%   { transform: rotateY(0) skewY(0); }
    28%  { transform: rotateY(42deg) skewY(1deg); filter: brightness(.94); }
    52%  { transform: rotateY(96deg) skewY(2deg); filter: brightness(.8); }
    76%  { transform: rotateY(144deg) skewY(1deg); filter: brightness(.92); }
    100% { transform: rotateY(180deg) skewY(0); filter: brightness(1); }
}

/* ---- opening the book ---- */

.storybook-closed-shell {
    display: none;
    position: absolute; z-index: 45; top: 0; left: 50%;
    height: min(76vh, 760px); aspect-ratio: 2 / 3;
    transform: translateX(-50%);
    background: var(--sprout-book-closed) center/contain no-repeat;
    filter: drop-shadow(0 30px 34px rgba(0, 0, 0, .55));
    pointer-events: none;
}
.story-book-stage.book-is-opening .storybook-closed-shell { display: block; animation: closedBookYield 1.3s cubic-bezier(.22, .7, .2, 1) forwards; }
.story-book-stage.book-is-opening .story-open-book { animation: stableBookReveal 1.3s cubic-bezier(.22, .7, .2, 1) both; }
.story-book-stage.book-is-opening .story-scene-page,
.story-book-stage.book-is-opening .story-reading-page { animation: revealBookPages 1.3s cubic-bezier(.22, .7, .2, 1) both; }
.story-book-stage.book-is-opening .story-reader-toolbar { opacity: 0; pointer-events: none; }
.story-book-stage.book-opened .story-reader-toolbar { animation: showBookControls .45s ease both; }
@keyframes closedBookYield { from { opacity: 1; transform: translateX(-50%) scale(1); } to { opacity: 0; transform: translateX(-50%) scale(.96); } }
@keyframes stableBookReveal { from { opacity: 0; transform: scale(.94) translateY(10px); } to { opacity: 1; transform: scale(1) translateY(0); } }
@keyframes revealBookPages { from { opacity: 0; } to { opacity: 1; } }
@keyframes showBookControls { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* ---- the controls under the book ---- */

.story-reader-toolbar {
    display: flex; justify-content: center; align-items: center;
    gap: 10px; flex-wrap: wrap;
    width: min(1050px, 94vw);
    padding: .75rem 1rem;
    border: 2px solid rgba(240, 205, 117, .65); border-radius: 999px;
    background: rgba(11, 43, 32, .86);
    box-shadow: 0 12px 30px rgba(0, 0, 0, .25);
    backdrop-filter: blur(10px);
}
.story-reader-toolbar button {
    border: 2px solid #d5aa4c; border-radius: 999px;
    background: #fff8df; color: #143d2e;
    padding: .65rem .95rem;
    font: inherit; font-weight: 900; cursor: pointer;
}
.story-reader-toolbar button:disabled { opacity: .4; cursor: default; }
.story-reader-toolbar .listen { background: #d5a43c; }
.story-reader-toolbar .story-place { color: #fff7d6; font-size: .8rem; font-weight: 800; }
.story-reader-toolbar p { width: 100%; margin: 0; text-align: center; color: #fff7d6; font-size: .88rem; }

.story-reader-top {
    position: sticky; z-index: 10; top: 0;
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: .7rem clamp(1rem, 5vw, 2.5rem);
    background: #102f25; color: white;
    border-bottom: 3px solid #c89a37;
}
.story-reader-top strong { color: #f0cd75; font: 400 1.2rem var(--serif); }
.story-reader-close {
    border: 2px solid #f0cd75; border-radius: 999px;
    background: transparent; color: white;
    padding: .55rem .9rem;
    font: inherit; font-weight: 900; cursor: pointer; text-decoration: none;
}
.story-reader-close:hover { background: rgba(240, 205, 117, .18); }

/* ---- the end of the book ---- */

.story-reflection {
    min-height: calc(100vh - 88px);
    min-height: calc(100dvh - 88px);
    position: relative;
    background: radial-gradient(circle at 50% 15%, #4b805e, #102f25 70%);
}
.story-reflection-panel {
    position: relative; z-index: 1;
    width: min(940px, 94vw);
    padding: clamp(1.25rem, 4vw, 2.5rem);
    border: 4px solid #f0cd75; border-radius: 28px;
    background: rgba(255, 250, 232, .96);
    box-shadow: 0 30px 80px rgba(0, 0, 0, .42);
}
.story-reflection-panel .eyebrow { color: #8a6b2c; margin-bottom: 4px; }
.story-reflection-panel h2 { margin: .2rem 0 1rem; font: 400 clamp(2rem, 5vw, 3.2rem) var(--serif); color: #174735; }
.reflection-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.reflection-card { border-radius: 18px; padding: 1rem 1.15rem; background: #f7e7ae; }
.reflection-card h3 { margin: .1rem 0 .35rem; color: #76501d; font: 900 .95rem var(--serif); }
.reflection-card p { margin: 0; font: 1rem/1.6 var(--serif); color: #2e382e; }
.reflection-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 1.1rem; }
.reflection-actions a { text-decoration: none; display: inline-block; }

.gospel-for-kids {
    margin-top: 16px;
    padding: clamp(1.1rem, 3vw, 1.8rem);
    border: 3px solid #d5a43c; border-radius: 22px;
    background: linear-gradient(145deg, #fff8dd, #e7f1d9);
    box-shadow: inset 0 0 28px rgba(208, 167, 72, .14);
}
.gospel-for-kids .eyebrow { color: #8a6b2c; margin-bottom: 4px; }
.gospel-for-kids h3 { margin: .1rem 0 .45rem; color: #174735; font: 400 clamp(1.5rem, 3vw, 2.2rem) var(--serif); }
.gospel-for-kids > p { margin: .35rem 0 1rem; font: 1rem/1.6 var(--serif); }
.gospel-steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.gospel-step { padding: .85rem; border-radius: 16px; background: rgba(255, 255, 255, .72); color: #244638; }
.gospel-step b { display: block; color: #76501d; margin-bottom: .3rem; }
.gospel-step span { display: block; font-size: .93rem; line-height: 1.45; }
.gospel-invitation {
    margin-top: 12px; padding: .85rem 1rem;
    border-radius: 14px; background: #174735; color: white; line-height: 1.55;
}
.gospel-invitation strong { color: #f0cd75; }

/* ---- an empty shelf ---- */

.shelf-empty {
    margin: 0 auto; max-width: 720px;
    padding: clamp(30px, 5vw, 54px);
    text-align: center;
    background: var(--glass);
    border: 1px dashed rgba(255, 255, 255, .25);
    border-radius: var(--radius);
}
.shelf-empty h2 { margin: 0 0 12px; font: 400 1.9rem var(--serif); color: var(--sprout-green); }
.shelf-empty p { margin: 0 auto; max-width: 54ch; font: 1rem/1.7 var(--serif); color: var(--sprout-muted); }
.shelf-empty code {
    padding: 2px 6px;
    background: rgba(255, 255, 255, .08);
    font-size: .9em;
}


/* ---- meet the friends ---- */

.friend-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: clamp(14px, 2vw, 22px);
    padding: clamp(28px, 4vw, 52px) clamp(20px, 6vw, 90px) clamp(40px, 5vw, 64px);
}
.friend-card {
    display: flex; flex-direction: column;
    background: var(--glass);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-sm);
    overflow: hidden;
}
/* The master art is transparent PNG on no background, so the card supplies one.
   contain, not cover: these are character references and must not be cropped. */
.friend-figure {
    aspect-ratio: 1 / 1;
    display: grid; place-items: center;
    padding: 18px;
    background: radial-gradient(circle at 50% 62%, #14503c, #0a2a20 72%);
}
.friend-figure img { width: 100%; height: 100%; object-fit: contain; display: block; }
.friend-body { display: flex; flex-direction: column; gap: 9px; flex: 1; padding: 18px 20px 22px; }
.friend-body h2 { margin: 0; font: 400 1.55rem var(--serif); color: var(--sprout-green); }
.friend-role {
    margin: 0;
    text-transform: uppercase; letter-spacing: .13em;
    font-size: .6rem; font-weight: 900; color: #d9b95f;
}
.friend-traits { margin: 0; font-size: .88rem; line-height: 1.6; color: var(--sprout-muted); }
.friend-note {
    margin: auto 0 0; padding: 11px 13px;
    background: rgba(198, 164, 80, .12);
    border-left: 3px solid var(--sprout-gold);
    font-size: .8rem; line-height: 1.55; color: #cfc8b2;
}

/* The story rules are the reason the cast stays consistent, so they are not
   buried in a production document — they sit under the cast where an
   illustrator or writer will actually read them. */
.story-rules {
    padding: clamp(38px, 5vw, 68px) clamp(20px, 6vw, 90px);
    background: linear-gradient(150deg, #0a3125, #051f18);
    color: white;
}
.story-rules > div { max-width: 1180px; margin: 0 auto; }
.story-rules .authority-label {
    margin: 0 0 10px;
    text-transform: uppercase; letter-spacing: .17em;
    font-size: .6rem; font-weight: 950; color: #e8d597;
}
.story-rules h2 { margin: 0 0 8px; font: 400 clamp(2rem, 3.4vw, 3rem) var(--serif); color: #fdf7e6; }
.story-rules > div > p { margin: 0 0 24px; max-width: 62ch; font-size: .92rem; line-height: 1.66; color: rgba(255, 255, 255, .66); }
.story-rules ol { display: grid; gap: 12px; margin: 0; padding: 0; list-style: none; counter-reset: rule; }
.story-rules li {
    display: grid; grid-template-columns: 34px minmax(0, 1fr); gap: 14px;
    padding: 15px 18px;
    background: rgba(255, 250, 240, .06);
    border: 1px solid rgba(233, 213, 154, .22);
    font: 1rem/1.62 var(--serif); color: rgba(255, 255, 255, .85);
    counter-increment: rule;
}
.story-rules li:before {
    content: counter(rule);
    font: 400 1.4rem var(--serif); color: #e6c46b;
}

/* ---- colouring pages ---- */

.coloring-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
    gap: clamp(14px, 2vw, 22px);
    padding: clamp(28px, 4vw, 52px) clamp(20px, 6vw, 90px) clamp(40px, 5vw, 64px);
}
.coloring-card {
    display: flex; flex-direction: column;
    background: var(--glass);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    border: 1px solid var(--glass-border);
    border-radius: var(--radius-sm);
    overflow: hidden;
}
.coloring-card img {
    width: 100%; aspect-ratio: 1 / 1;
    object-fit: contain; display: block;
    background: white; padding: 10px;
}
.coloring-body { display: flex; flex-direction: column; gap: 8px; padding: 16px 19px 19px; }
.coloring-body h2 { margin: 0; font: 400 1.28rem var(--serif); color: var(--sprout-green); }
.coloring-body p { margin: 0; font-size: .84rem; line-height: 1.55; color: var(--sprout-muted); }
.coloring-actions { display: flex; gap: 8px; margin-top: 4px; }
.coloring-actions a {
    padding: 9px 15px;
    font-size: .66rem; font-weight: 900;
    text-transform: uppercase; letter-spacing: .1em;
    text-decoration: none;
}
.coloring-actions a.primary { background: #164c38; color: #f3e6c3; }
.coloring-actions a.primary:hover { background: #14503c; }
.coloring-actions a.ghost { border: 1px solid rgba(255, 255, 255, .25); color: var(--sprout-green); }
.coloring-actions a.ghost:hover { background: rgba(255, 255, 255, .08); }

.print-note {
    padding: 0 clamp(20px, 6vw, 90px) clamp(48px, 6vw, 80px);
}
.print-note > div {
    max-width: 1180px; margin: 0 auto; padding: 22px 24px;
    background: var(--glass);
    border-left: 3px solid var(--sprout-gold);
}
.print-note p { margin: 0; font-size: .86rem; line-height: 1.62; color: #b9c4bb; }

/* ---- narrow screens ---- */

@media (max-width: 820px) {
    .story-cover-stage { grid-template-columns: 1fr; text-align: center; }
    .story-cover-stage img, .story-cover-plate { max-height: 52vh; margin: auto; }
    .story-book-stage { width: 100%; padding: 24px 2px 8px; }
    .story-reading-page { padding: .6rem .6rem 3rem; }
    .story-words { font-size: clamp(.8rem, 2.2vw, 1rem); line-height: 1.5; }
    .story-reader-wrap { overflow: auto; }
}
@media (max-width: 720px) { .reflection-grid { grid-template-columns: 1fr; } }
@media (max-width: 760px) { .gospel-steps { grid-template-columns: 1fr 1fr; } }
@media (max-width: 480px) { .gospel-steps { grid-template-columns: 1fr; } }

/* The turning leaf and the opening book are the charm of this reader, but they
   are also large motion. Anyone who has asked for less gets the same book
   without the movement — the page still changes, it just does not swing. */
@media (prefers-reduced-motion: reduce) {
    .book-card { transition: none; }
    .book-card:hover, .book-card:focus-visible { transform: none; }
    .story-book-stage:before, .story-book-stage:after { animation: none; }
    .storybook-turn-leaf.turning-next, .storybook-turn-leaf.turning-prev { display: none; }
    .story-book-stage.book-is-opening .storybook-closed-shell,
    .story-book-stage.book-is-opening .story-open-book,
    .story-book-stage.book-is-opening .story-scene-page,
    .story-book-stage.book-is-opening .story-reading-page,
    .story-book-stage.book-opened .story-reader-toolbar { animation: none; }
    .story-edge-turn { transition: none; }
}

/* A colouring page is meant to leave the screen. Printing the reader or the
   library should give the art, not the site chrome. */
@media print {
    .site-header, .sprouts-bar, .coloring-actions, .print-note, .page-turn, .page-dots { display: none; }
    .coloring-grid, .book-grid, .sprout-reader { padding: 0; background: white; }
    .coloring-card, .book-card { border: 0; break-inside: avoid; }
}


/* ---- the shelf, level one: volumes ----
 *
 * Each volume is a boxed set of five, not a single book. It is drawn as a real
 * slipcase in CSS 3D: the cover art is the front face, and the five book spines
 * are the side face, turned ninety degrees and pushed out to the box's depth.
 * The whole thing is angled so both faces are visible at once, which is the
 * only way a flat card can say "there are five books in here".
 */
.volume-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: clamp(26px, 3.4vw, 44px);
    padding-right: 46px;                 /* the spines lean out to the right */
}

.volume-card {
    /* Spines on the RIGHT, so the turn is negative.
       rotateY moves +Z toward +X: a negative angle brings the RIGHT edge toward
       the viewer and pushes the left edge back, which is what puts the
       right-hand side face in view. Get the sign wrong and the side panel ends
       up hidden behind the front of the box.
       At rest the side projects to depth x sin(turn) wide, shared between five
       spines: 96px at 32 degrees is about 10px each. Hover opens it to 48
       degrees, where the titles become legible. */
    --box-depth: 96px;
    --box-turn: -32deg;
    --box-tilt: -7deg;
    display: flex; flex-direction: column; gap: 14px;
    text-decoration: none;
    transition: transform .25s ease;
}
.volume-card:hover, .volume-card:focus-visible { transform: translateY(-6px); }

.volume-set {
    perspective: 1100px;
    position: relative;
}
/* Sits it on the shelf. Without a contact shadow the box floats. */
.volume-set:after {
    content: "";
    position: absolute; z-index: -1;
    left: 4%; right: -6%; bottom: -14px; height: 26px;
    border-radius: 50%;
    background: radial-gradient(ellipse at center,
        rgba(4, 24, 15, .55) 0 45%, transparent 72%);
    filter: blur(5px);
}
.volume-set-3d {
    position: relative;
    transform-style: preserve-3d;
    transform: rotateX(var(--box-tilt)) rotateY(var(--box-turn));
    transition: transform .35s ease;
}
/* Turn further into the shelf on hover, so the spines become readable. */
.volume-card:hover .volume-set-3d,
.volume-card:focus-visible .volume-set-3d {
    transform: rotateX(var(--box-tilt)) rotateY(-48deg);
}

/* ---- the front of the box ---- */

/* Square, because the covers are square. This was 2/3, which with object-fit:
   cover sliced a vertical band out of the middle of every cover and took the
   ends off the longer titles - GOD'S COVENANT FAMILY read "OD'S COVENANT FAMIL"
   and INTO THE PROMISED LAND read "NTO THE PROMISED LAN". The box has to match
   the art it carries; the art cannot be re-cropped to fit the box. */
.volume-set-face {
    position: relative;
    aspect-ratio: 1 / 1;
    border-radius: 3px 0 0 3px;
    overflow: hidden;
    background: linear-gradient(160deg, #2f7d4f, #1c5a38);
    box-shadow: 0 24px 40px rgba(6, 34, 22, .45);
}
.volume-card-art {
    position: absolute; inset: 0;
    display: grid; place-items: center;
    background: rgba(255, 255, 255, .08);
}
.volume-card-art:before { content: "F4DA"; font-size: 2.6rem; line-height: 1; }
.volume-card-art img {
    position: absolute; inset: 0;
    width: 100%; height: 100%; object-fit: cover;
}
/* The lip of the slipcase, and a soft sheen across the board. */
.volume-set-face:after {
    content: "";
    position: absolute; inset: 0;
    background:
        linear-gradient(260deg, rgba(255, 255, 255, .3) 0 2%, transparent 18%),
        linear-gradient(80deg, rgba(0, 0, 0, .3) 0 3%, transparent 20%),
        linear-gradient(180deg, rgba(255, 255, 255, .1) 0 1.5%, transparent 6%);
    pointer-events: none;
}
.volume-card-number {
    position: absolute; left: 0; bottom: 12px;
    padding: .22rem .6rem .22rem .5rem;
    border-radius: 0 999px 999px 0;
    background: var(--sprout-sun, #ffd76b); color: #2a1f04;
    font: 900 .58rem var(--serif); letter-spacing: .12em; text-transform: uppercase;
}

/* The top of the case. Same trick as the side, hinged off the top edge. It is
   what makes this read as a box rather than a single book. */
.volume-set-top {
    position: absolute;
    left: 0; top: calc(-1 * var(--box-depth));
    width: 100%; height: var(--box-depth);
    transform-origin: bottom center;
    transform: rotateX(90deg);
    background: linear-gradient(180deg, #2b7048, #174b2f);
    box-shadow: inset 0 -6px 12px rgba(0, 0, 0, .35);
}

/* ---- the five spines, which are the side of the box ---- */

/* The side of the case. Sits immediately right of the front face and hinges
   backward about the edge they share, so the two meet at a clean corner. */
.volume-spines {
    position: absolute;
    top: 0; right: calc(-1 * var(--box-depth)); height: 100%;
    width: var(--box-depth);
    display: flex;
    transform-origin: left center;
    transform: rotateY(90deg);
    background: #123a25;
    overflow: hidden;
}
/* The case rim. A real slipcase only laps a few millimetres over the books, so
   this is a thin fixed band rather than a percentage - the books should read as
   very nearly the full height of the case. */
.volume-spines:before {
    content: "";
    position: absolute; inset: 0; z-index: 2;
    border-top: 5px solid #14472c;
    border-bottom: 5px solid #14472c;
    box-shadow:
        inset 0 6px 9px rgba(0, 0, 0, .5),          /* books recessed under the rim */
        inset 0 -6px 9px rgba(0, 0, 0, .5),
        inset -7px 0 12px rgba(0, 0, 0, .45);       /* depth into the case */
    pointer-events: none;
}
/* The cut edge of the board, catching the light along the opening. */
.volume-spines:after {
    content: "";
    position: absolute; z-index: 3;
    top: 0; bottom: 0; left: 0; width: 2px;
    background: linear-gradient(180deg, #4b9c6d, #2b7048 40%, #1a5236);
    pointer-events: none;
}

.volume-spine {
    position: relative;
    flex: 1; min-width: 0;
    display: flex; flex-direction: column-reverse; align-items: center;
    gap: 3px;
    padding: 7px 0;
    border-right: 1px solid rgba(0, 0, 0, .5);
    box-shadow: inset -2px 0 4px rgba(0, 0, 0, .28),
                inset 1px 0 0 rgba(255, 255, 255, .12);
}
/* Five books, not one striped block. Real sets are never all the same colour. */
.volume-spine:nth-child(1) { background: linear-gradient(180deg, #2f7d4f, #1f5c39); }
.volume-spine:nth-child(2) { background: linear-gradient(180deg, #7a5a1f, #553d12); }
.volume-spine:nth-child(3) { background: linear-gradient(180deg, #23606e, #17414c); }
.volume-spine:nth-child(4) { background: linear-gradient(180deg, #6d2f30, #4a1f20); }
.volume-spine:nth-child(5) { background: linear-gradient(180deg, #3d4a7a, #283154); }
.volume-spine:last-child { border-right: 0; }

/* The gold band across the foot of a spine, where a number usually sits. */
.volume-spine b {
    flex: 0 0 auto;
    width: 100%; text-align: center;
    padding: 2px 0;
    background: rgba(0, 0, 0, .3);
    border-top: 1px solid rgba(255, 214, 107, .45);
    font: 900 .56rem/1 var(--serif);
    color: var(--sprout-sun, #ffd76b);
}
/* The title runs up the spine, the way it does on a real book. */
.volume-spine i {
    flex: 1; min-height: 0;
    writing-mode: vertical-rl; transform: rotate(180deg);
    font: 600 .5rem/1 var(--serif); font-style: normal;
    letter-spacing: .02em;
    color: #f2f7f3;
    text-shadow: 0 1px 1px rgba(0, 0, 0, .6);
    overflow: hidden;
}
.volume-spine.is-blank {
    background: linear-gradient(180deg, #3a5546, #26382e);
}
.volume-spine.is-blank b,
.volume-spine.is-blank i { opacity: .3; }

/* ---- the caption under the box ---- */

/* Dark ink, not cream. These were #fffdf4 and #bfe6cd, written when the shelf
   sat on a dark green panel; the kids' room behind it is #d9f5ff, so the
   heading was running at about 1.05:1 against its background - present in the
   markup, readable by a screen reader, and invisible to the eye. */
.volume-card-body { display: flex; flex-direction: column; gap: 3px; }
.volume-card-body h2 {
    margin: 0; font: 400 1.14rem/1.2 var(--serif); color: #f4efe2;
}
.volume-card-count {
    margin: 0; font: 800 .66rem var(--serif); letter-spacing: .1em;
    text-transform: uppercase; color: #a8b5ac;
}

/* Planned but not written. Still shown, so the whole collection is visible. */
.volume-card.is-waiting { cursor: default; }
.volume-card.is-waiting:hover { transform: none; }
.volume-card.is-waiting .volume-set-3d {
    transform: rotateX(var(--box-tilt)) rotateY(var(--box-turn));
}
.volume-card.is-waiting .volume-set-top { background: linear-gradient(180deg, #33513f, #223629); }
.volume-card.is-waiting .volume-set-face {
    background: linear-gradient(160deg, #33513f, #243b2e);
    box-shadow: 0 14px 26px rgba(6, 34, 22, .3);
}
.volume-card.is-waiting .volume-card-art { opacity: .5; }
.volume-card-soon {
    align-self: flex-start;
    padding: .2rem .6rem; border-radius: 999px;
    background: rgba(0, 0, 0, .38); color: #dcefe2;
    font: 900 .54rem var(--serif); letter-spacing: .14em; text-transform: uppercase;
}

@media (prefers-reduced-motion: reduce) {
    .volume-card, .volume-set-3d { transition: none; }
}

/* A book in a volume that has not been written yet. */
.book-card.is-waiting { opacity: .45; cursor: default; }
.book-card.is-waiting:hover { transform: none; box-shadow: none; }

/* ---- walking from one volume to the next ---- */
.volume-walk {
    display: flex; flex-wrap: wrap; justify-content: center; gap: 10px;
    margin: clamp(24px, 4vw, 42px) 0 0;
}
.volume-step {
    padding: 11px 20px; border-radius: 999px;
    background: #fffaf0; color: #1c5a38;
    border: 2px solid rgba(255, 255, 255, .5);
    font: 900 .78rem var(--serif); letter-spacing: .04em;
    text-decoration: none;
}
.volume-step:hover { background: var(--sprout-sun, #ffd76b); }
.volume-step.is-up { background: transparent; color: #fffdf4; }
.volume-step.is-up:hover { background: rgba(255, 255, 255, .16); }

/* A game that is actually playable gets a button rather than a "coming soon"
   badge. The distinction has to be obvious at a glance on the games shelf. */
.game-play {
    display: inline-block; margin-top: auto;
    padding: 11px 22px; border-radius: 999px;
    background: var(--sprout-sun, #ffd76b); color: #3d2a06;
    font: 900 .82rem var(--serif); letter-spacing: .03em;
    text-decoration: none;
    box-shadow: 0 6px 0 rgba(0, 0, 0, .18);
    transition: transform .14s ease, box-shadow .14s ease;
}
.game-play:hover { transform: translateY(-2px); box-shadow: 0 8px 0 rgba(0, 0, 0, .2); }
.game-play:active { transform: translateY(3px); box-shadow: 0 2px 0 rgba(0, 0, 0, .2); }


/* ---- base pill for the game buttons ----
 *
 * The journey and match games were lifted out of the live preview, whose page
 * supplied the .btn base styles. That sheet did not travel, so the base pill
 * lives here where every sprouts page can reach it. */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: .5em;
    padding: .8rem 1.4rem; border-radius: 999px;
    border: 3px solid rgba(255, 255, 255, .35);
    background: rgba(255, 255, 255, .12); color: #fff7d6;
    font: 900 .8rem var(--serif); letter-spacing: .05em;
    cursor: pointer; text-decoration: none;
    transition: transform .14s ease, background .18s ease, box-shadow .14s ease;
}
.btn.primary {
    background: var(--kid-gold); color: #214d34;
    border-color: rgba(255, 255, 255, .75);
    box-shadow: 0 5px 0 #8a6b1d;
}
.btn.primary:hover { transform: translateY(-2px); box-shadow: 0 7px 0 #8a6b1d; }
.btn.primary:active { transform: translateY(3px); box-shadow: 0 1px 0 #8a6b1d; }
