@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');
@import url('https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,500;12..96,700;12..96,800&family=Nunito+Sans:ital,wght@0,400;0,600;0,700;1,400&display=swap');

/* ── Wondros App Tokens — After Lights-Out (night everywhere) ────
   The landing page scrolls dusk→dawn; the app is the night you read in.
   The whole app lives in the flashlight world's night sky (decided
   2026-07-22). Semantic tokens below are the NIGHT palette; components
   route through them, so the app themes dark cohesively. Book art, the
   cream reading pages, and the amber magic accents provide the light. */
:root {
    --night:    #0B0926;
    --night2:   #161240;
    --dusk:     #2E2468;
    --amber:    #FFC46B;
    --amber2:   #F0AD4E;
    --firefly:  #FFE9A8;
    --bg:       #0B0926;   /* night canvas */
    --surface:  #171441;   /* dark glass card / input */
    --surface2: #1E1955;   /* raised surface */
    --ink:      #ECE9FB;   /* primary text on night */
    --ink2:     #FFFFFF;   /* headings */
    --muted:    #B6ADDE;   /* secondary text */
    --dim:      #877FB0;   /* placeholders, disabled */
    --violet:   #8A6FEC;   /* workhorse — lifted for contrast on night */
    --violet2:  #A78BFA;
    --teal:     #4ECDC4;
    --lav:      #A78BFA;
    --rim:      #2E2A60;   /* borders on night */
    --rim2:     #201B4E;   /* subtle raised / alt background */
    --glow:     rgba(0, 0, 0, 0.5);   /* shadows go black on night */
    --amber-glow: rgba(255, 196, 107, 0.45);
    --spring:   cubic-bezier(0.32, 0.72, 0, 1);
}

html, body {
    font-family: 'Nunito Sans', sans-serif;
    background-color: var(--bg);
    background-image:
        radial-gradient(ellipse 90% 55% at 15% -5%, rgba(110, 79, 212, 0.20) 0%, transparent 55%),
        radial-gradient(ellipse 70% 50% at 95% 105%, rgba(255, 196, 107, 0.08) 0%, transparent 55%),
        linear-gradient(180deg, #0B0926 0%, #100C34 60%, #150F40 100%);
    background-attachment: fixed;
    color: var(--ink);
}

/* ── Typography ────────────────────────────────────────────────── */
h1, h2, h3, h4, h5, h6, .sb-heading {
    font-family: 'Bricolage Grotesque', sans-serif;
    font-weight: 800;
    color: var(--ink2);
    letter-spacing: -0.02em;
}

.text-muted { color: var(--muted) !important; }

/* ── Links ─────────────────────────────────────────────────────── */
a, .btn-link {
    color: var(--violet);
    transition: color 220ms var(--spring);
}

a:hover {
    color: var(--violet2);
}

/* ── Buttons ───────────────────────────────────────────────────── */
.btn {
    border-radius: 9999px;
    font-weight: 700;
    transition: transform 220ms var(--spring), box-shadow 220ms var(--spring),
                background 220ms var(--spring), color 220ms var(--spring),
                border-color 220ms var(--spring), opacity 220ms var(--spring);
}

.btn:active { transform: scale(0.98); }

/* Workhorse actions — violet */
.btn-primary {
    background: var(--violet);
    border-color: transparent;
    color: #fff;
}

.btn-primary:hover, .btn-primary:focus {
    background: var(--violet2);
    border-color: transparent;
    color: #fff;
    transform: translateY(-1px);
    box-shadow: 0 10px 24px -10px rgba(109, 79, 212, 0.55);
}

/* Magic actions (Generate, Send to Print) — amber, like every landing CTA.
   Pages use Bootstrap's .btn-success for these; restyled here on purpose. */
.btn-success {
    background: var(--amber);
    border-color: transparent;
    color: var(--night);
}

.btn-success:hover, .btn-success:focus, .btn-success:disabled {
    background: var(--amber);
    border-color: transparent;
    color: var(--night);
}

.btn-success:hover {
    transform: translateY(-2px);
    box-shadow: 0 0 34px var(--amber-glow);
}

.btn-secondary {
    background: var(--rim2);
    border: 1px solid var(--rim);
    color: var(--muted);
}

.btn-secondary:hover {
    background: var(--rim);
    color: var(--ink);
    border-color: var(--rim);
}

.btn-outline-primary {
    border-color: var(--violet);
    color: var(--violet);
}

.btn-outline-primary:hover {
    background: var(--violet);
    border-color: var(--violet);
    color: #fff;
}

.btn-outline-secondary {
    border-color: var(--rim);
    color: var(--muted);
    background: var(--surface);
}

.btn-outline-secondary:hover {
    background: var(--rim2);
    border-color: var(--dim);
    color: var(--ink);
}

.btn-outline-danger {
    border-color: #F3D2D8;
    color: #C2455E;
    background: var(--surface);
}

.btn-outline-danger:hover {
    background: #C2455E;
    border-color: #C2455E;
    color: #fff;
}

.btn-danger {
    background: #C2455E;
    border-color: transparent;
}

.btn-danger:hover {
    background: #A93750;
    border-color: transparent;
}

/* Bootstrap's text-primary spinner → violet */
.text-primary { color: var(--violet) !important; }

/* ── Focus rings ───────────────────────────────────────────────── */
.btn:focus,
.btn:active:focus,
.btn-link.nav-link:focus,
.form-control:focus,
.form-check-input:focus {
    box-shadow: 0 0 0 0.1rem var(--bg), 0 0 0 0.25rem rgba(138, 111, 236, 0.55);
    outline: none;
}

/* ── Forms ─────────────────────────────────────────────────────── */
.form-control,
.form-select {
    border: 1px solid var(--rim);
    border-radius: 12px;
    background: var(--surface);
    color: var(--ink);
    transition: border-color 220ms var(--spring), box-shadow 220ms var(--spring);
}

.form-control:focus,
.form-select:focus {
    border-color: var(--violet);
    box-shadow: 0 0 0 3px rgba(109, 79, 212, 0.15);
    /* Bootstrap's own .form-control:focus re-asserts the light-mode dark body
       color; without this the typed text goes near-black on the night surface
       while the field is focused. Keep it night-ink on focus. */
    background: var(--surface);
    color: var(--ink);
    caret-color: var(--amber);
}

.form-control::placeholder { color: var(--dim); }

.form-label {
    font-weight: 700;
    color: var(--muted);
    font-size: 0.85rem;
}

.form-check-input:checked {
    background-color: var(--violet);
    border-color: var(--violet);
}

/* Illustration-style radio tiles (btn-check + btn-outline-secondary labels) */
.btn-check:checked + .btn-outline-secondary {
    background: rgba(255, 196, 107, 0.14);
    border-color: var(--amber2);
    color: var(--ink);
    box-shadow: 0 0 0 1px var(--amber2);
}

/* ── Cards (Bootstrap .card, used across all pages) ────────────── */
.card {
    border: 1px solid var(--rim);
    border-radius: 18px;
    background: var(--surface);
    overflow: hidden;
}

.card.shadow-sm, .card.shadow {
    box-shadow: 0 14px 34px -18px var(--glow) !important;
}

.card-header {
    background: var(--rim2);
    border-bottom: 1px solid var(--rim);
    color: var(--ink2);
}

.card-footer {
    border-top: 1px solid var(--rim);
}

.bg-light {
    background-color: var(--rim2) !important;
}

.border { border-color: var(--rim) !important; }
.border-top { border-top-color: var(--rim) !important; }

/* Dashboard book cards get a lift + amber underline on hover */
.card.h-100 {
    transition: transform 400ms var(--spring), box-shadow 400ms var(--spring);
}

.card.h-100:hover {
    transform: translateY(-4px);
    box-shadow: 0 18px 40px -16px var(--glow) !important;
}

/* ── Status badges (Bootstrap classes, rethemed to the palette) ── */
.badge {
    font-weight: 700;
    letter-spacing: 0.05em;
    border-radius: 9999px;
    padding: 4px 12px;
}

.badge.bg-success {            /* Ready */
    background-color: rgba(78, 205, 196, 0.18) !important;
    color: #8CE8DE;
}

.badge.bg-warning {            /* Generating */
    background-color: rgba(255, 196, 107, 0.22) !important;
    color: var(--amber) !important;
}

.badge.bg-primary {            /* Ordered */
    background-color: rgba(139, 111, 236, 0.22) !important;
    color: var(--lav);
}

.badge.bg-secondary {          /* Draft */
    background-color: var(--rim2) !important;
    color: var(--muted);
}

/* ── Alerts ────────────────────────────────────────────────────── */
.alert { border-radius: 14px; }

.alert-danger {
    background: rgba(228, 87, 61, 0.14);
    border-color: rgba(228, 87, 61, 0.4);
    color: #FFC2B6;
}

.alert-warning {
    background: rgba(255, 196, 107, 0.13);
    border-color: rgba(240, 173, 78, 0.4);
    color: var(--firefly);
}

.alert-info {
    background: var(--rim2);
    border-color: var(--rim);
    color: var(--muted);
}

.alert-warning a, .alert-info a, .alert-danger a { color: var(--amber); font-weight: 700; }

/* ── Modals ────────────────────────────────────────────────────── */
.modal-content {
    border: 1px solid var(--rim);
    border-radius: 18px;
    background: var(--surface);   /* Bootstrap defaults this to white — force night */
    color: var(--ink);
}

/* ── Tables (admin) — Bootstrap defaults assume light; theme for night ── */
.table {
    color: var(--ink);
    --bs-table-bg: transparent;
    --bs-table-color: var(--ink);
    --bs-table-border-color: var(--rim);
    border-color: var(--rim);
}
.table > :not(caption) > * > * {
    background-color: transparent;
    color: var(--ink);
    border-bottom-color: var(--rim);
}
.table thead th { color: var(--muted); }
.table-hover > tbody > tr:hover > * {
    background-color: rgba(255, 255, 255, 0.04);
    color: var(--ink);
}

.modal-header, .modal-footer { border-color: var(--rim); }

/* ── Book/Page cards (sb-*) ────────────────────────────────────── */
.sb-page-card {
    border-radius: 18px;
    min-height: 380px;
    border: 1px solid var(--rim);
    background: var(--surface);
    overflow: hidden;
    transition: box-shadow 400ms var(--spring);
}

.sb-page-card:hover {
    box-shadow: 0 14px 34px -18px var(--glow);
}

.sb-page-img-full {
    width: 100%;
    max-height: 320px;
    object-fit: cover;
}

.sb-page-img-side {
    width: 100%;
    height: 100%;
    min-height: 320px;
    object-fit: cover;
}

/* ── Preview — the open book (two-page spread) ─────────────────────
   The reader holds the real printed book: two facing pages, a folded
   spine down the middle, and images bleeding to the page edges exactly
   as they will in print. The book itself stays light/cream; it is read
   inside the "After Lights-Out" night stage (.sb-night-reader, below). */
.sb-book {
    max-width: 880px;
    margin: 0 auto;
    perspective: 1800px;
    position: relative;   /* anchors the page-turn sheet overlay */
}

/* Closed-book view: the front/back cover shown alone, centered. Half the width
   of an open spread, and no gutter or fold shadow — it's a single panel. */
.sb-book--solo { max-width: 440px; }
.sb-spread--solo { justify-content: center; }
.sb-leaf--solo { box-shadow: none; }

/* ── Signature: the page-turn ──────────────────────────────────────
   A paper-tinted sheet hinged at the spine sweeps across when you turn.
   It's an overlay sibling of .sb-spread (which has ALREADY swapped to the
   new pages beneath it) and is keyed to the spread index in the markup, so
   each nav remounts it and the animation replays exactly once, then it fades
   out in its final frames leaving the fresh spread. Direction follows the
   nav: forward hinges on the left (the right page's spine edge), back hinges
   on the right. Under .sb-book's perspective the rotateY foreshortens like a
   real page. Transform + opacity only — GPU-friendly, no layout thrash. */
.sb-turn-sheet {
    position: absolute;
    top: 0;
    bottom: 0;
    width: calc(50% - 8px);   /* one page — half the spread minus half the 16px gutter */
    z-index: 5;
    pointer-events: none;     /* never blocks clicks on the spread beneath */
    border-radius: 14px;
    background:
        linear-gradient(105deg,
            rgba(255, 255, 255, 0) 30%,
            rgba(255, 255, 255, 0.5) 50%,
            rgba(255, 255, 255, 0) 66%),          /* sheen catch */
        linear-gradient(90deg, var(--surface), var(--rim2));
    box-shadow: 0 24px 50px -26px var(--glow);
    backface-visibility: visible;
    transform-style: preserve-3d;
    will-change: transform, opacity;
}

.sb-turn--fwd {
    right: 0;                       /* covers the right page */
    transform-origin: left center;  /* hinge on the spine */
    animation: sb-turn-fwd 520ms var(--spring) forwards;
}

.sb-turn--back {
    left: 0;                        /* covers the left page */
    transform-origin: right center; /* hinge on the spine */
    animation: sb-turn-back 520ms var(--spring) forwards;
}

@keyframes sb-turn-fwd {
    from { transform: rotateY(0deg);    opacity: 1; }
    82%  { transform: rotateY(-164deg); opacity: 1; }
    to   { transform: rotateY(-180deg); opacity: 0; }
}

@keyframes sb-turn-back {
    from { transform: rotateY(0deg);   opacity: 1; }
    82%  { transform: rotateY(164deg); opacity: 1; }
    to   { transform: rotateY(180deg); opacity: 0; }
}

.sb-spread {
    display: flex;
    align-items: stretch;
    border-radius: 14px;
    overflow: hidden;
    background: var(--surface);
    border: 1px solid var(--rim);
    box-shadow: 0 30px 64px -30px var(--glow), 0 2px 6px -3px var(--glow);
    animation: sb-spread-in 420ms var(--spring);
}

.sb-leaf {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    aspect-ratio: 1 / 1;   /* one printed page — standard 8.5"×8.5" square */
    overflow: hidden;
    background: var(--surface);
    display: flex;
}

/* Inner fold shadow — each page darkens slightly toward the gutter. */
.sb-leaf--left  { box-shadow: inset -26px 0 34px -28px var(--glow); }
.sb-leaf--right { box-shadow: inset  26px 0 34px -28px var(--glow); }
.sb-leaf--empty { background: linear-gradient(180deg, var(--surface), var(--rim2)); }

/* The spine — a thin folded gutter between the two pages. */
.sb-gutter {
    flex: 0 0 16px;
    position: relative;
    z-index: 2;
    background: linear-gradient(90deg,
        rgba(46, 36, 104, 0.02) 0%,
        rgba(46, 36, 104, 0.10) 40%,
        rgba(46, 36, 104, 0.18) 50%,
        rgba(46, 36, 104, 0.10) 60%,
        rgba(46, 36, 104, 0.02) 100%);
}

/* ── Leaf content ──────────────────────────────────────────────── */
.sb-leaf-img {
    width: 100%;
    height: 100%;
    object-fit: cover;   /* full-bleed illustration — shows the true print crop */
    display: block;
    cursor: zoom-in;
}

.sb-leaf-fill {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: clamp(1rem, 6%, 3rem);
    text-align: center;
}

.sb-leaf-story {
    margin: 0;
    max-width: 34ch;
    line-height: 1.62;
    color: var(--ink);
    font-weight: 600;
}

/* Shown on a StoryImage leaf when its illustration hasn't generated (or failed) —
   deliberately does NOT repeat the facing page's text (that's the bug this fixes). */
.sb-leaf-noimg {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px dashed var(--rim);
    border-radius: 12px;
    background: var(--bg);
}

.sb-leaf-noimg-text {
    color: var(--dim);
    font-size: 0.85rem;
    font-style: italic;
}

/* ── Front cover — title typeset over the art (mirrors ComposeFrontCover) ── */
/* container-type lets the title size track the cover's width like the PDF's
   panelWidth/N scaling; set on both the over-art cover and the no-art fallback. */
.sb-leaf-cover {
    position: relative;
    width: 100%;
    height: 100%;
    container-type: size;
}

/* Soft gradient feather over the bottom of the art (transparent → dark indigo).
   Height + color mirror the PDF ScrimPng (42% tall, #0A0820 at ~85%). */
.sb-leaf-cover-scrim {
    position: absolute;
    inset: auto 0 0 0;
    height: 42%;
    background: linear-gradient(180deg, transparent 0%, rgba(10, 8, 32, 0.85) 100%);
    pointer-events: none;
}

/* Bottom-anchored title band. pointer-events:none so a click still hits the
   art beneath and opens the lightbox, matching the other leaves. */
.sb-leaf-cover-band {
    position: absolute;
    inset: auto 0 0 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    padding: 6% 9% 7%;
    text-align: center;
    pointer-events: none;
}

.sb-leaf-cover-fallback {
    justify-content: center;
    gap: 0.5rem;
    container-type: size;
    background:
        radial-gradient(ellipse 90% 70% at 50% -10%, rgba(46, 36, 104, 0.9) 0%, transparent 70%),
        linear-gradient(180deg, var(--night) 0%, var(--night2) 100%);
}

.sb-leaf-cover-title {
    font-family: 'Bricolage Grotesque', sans-serif;
    font-weight: 800;                /* ExtraBold — matches the print cover */
    letter-spacing: -0.02em;
    line-height: 1.05;
    color: #FFF7EC;                  /* cream — identical to ComposeFrontCover */
    text-wrap: balance;
    text-shadow: 0 2px 14px rgba(10, 8, 32, 0.55);  /* echoes the PDF's indigo title cushion */
}

/* Length-bucketed title sizing — cqw fractions mirror panelWidth/{11,15,19,24}. */
.sb-cover-len-s  { font-size: clamp(1.5rem, 9.1cqw, 2.9rem); }
.sb-cover-len-m  { font-size: clamp(1.25rem, 6.7cqw, 2.1rem); }
.sb-cover-len-l  { font-size: clamp(1.1rem, 5.3cqw, 1.7rem); }
.sb-cover-len-xl { font-size: clamp(1rem, 4.2cqw, 1.45rem); }

.sb-leaf-end { gap: 1.1rem; }

.sb-leaf-end-img {
    width: 62%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: 12px;
    box-shadow: 0 16px 32px -18px var(--glow);
    cursor: zoom-in;
}

.sb-leaf-end-text {
    font-family: 'Bricolage Grotesque', sans-serif;
    font-style: italic;
    font-weight: 700;
    color: var(--muted);
    font-size: clamp(1.3rem, 3.6vw, 2rem);
}

.sb-leaf-ded { gap: 0.25rem; }

.sb-leaf-ded-photo {
    max-height: 46%;
    max-width: 72%;
    object-fit: contain;
    border-radius: 10px;
    margin-bottom: 1rem;
    box-shadow: 0 12px 26px -16px var(--glow);
    cursor: zoom-in;
}

.sb-leaf-ded-text {
    margin: 0;
    font-style: italic;
    color: var(--muted);
    line-height: 1.6;
    max-width: 30ch;
    font-size: 1.15rem;
}

.sb-leaf-ded-empty {
    margin: 0;
    font-style: italic;
    color: var(--dim);
    max-width: 28ch;
}

.sb-leaf-colophon { justify-content: flex-end; }

.sb-leaf-copy {
    margin: 0;
    font-size: 0.72rem;
    color: var(--dim);
    line-height: 1.5;
}

.sb-leaf-copy--dim { opacity: 0.8; }

/* Inside covers — a light endpaper: a faint diagonal weave over the page tint. */
.sb-leaf-endpaper {
    background:
        repeating-linear-gradient(45deg, rgba(231, 226, 246, 0.22) 0 9px, transparent 9px 18px),
        linear-gradient(160deg, var(--bg), var(--rim2));
}

/* Back cover — near-blank light panel with a small bottom credit, like the print back. */
.sb-leaf-back {
    justify-content: flex-end;
    background: linear-gradient(180deg, var(--surface), var(--rim2));
}

.sb-leaf-back-credit {
    font-family: 'Bricolage Grotesque', sans-serif;
    font-weight: 700;
    color: var(--dim);
    font-size: 0.8rem;
    letter-spacing: 0.02em;
}

@keyframes sb-spread-in {
    from { opacity: 0; transform: translateY(6px) scale(0.996); }
    to   { opacity: 1; transform: none; }
}

/* On narrow screens the spread stacks so both pages stay legible;
   the gutter turns into a horizontal fold. */
@media (max-width: 640px) {
    .sb-spread { flex-direction: column; }
    .sb-gutter {
        flex-basis: 14px;
        background: linear-gradient(180deg,
            rgba(46, 36, 104, 0.02) 0%,
            rgba(46, 36, 104, 0.10) 40%,
            rgba(46, 36, 104, 0.18) 50%,
            rgba(46, 36, 104, 0.10) 60%,
            rgba(46, 36, 104, 0.02) 100%);
    }
    .sb-leaf--left  { box-shadow: inset 0 -22px 30px -26px var(--glow); }
    .sb-leaf--right { box-shadow: inset 0  22px 30px -26px var(--glow); }
    /* Stacked layout: the half-width spine flip doesn't apply — swap instantly. */
    .sb-turn-sheet { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    .sb-spread { animation: none; }
    /* Instant swap — no page-turn under reduced motion. */
    .sb-turn-sheet { display: none; }
}

/* ══ After Lights-Out — the immersive night reading stage ═══════════════
   The reader is a sanctioned dark surface (like the sidebar + night panel):
   the finished book is read inside a pool of warm light within the dusk,
   directly echoing the landing hero. The book PAGES stay light/cream — night
   is the frame, never the story. All the night theming below is scoped under
   .sb-night-reader so the light editing cards floating on it (auth pattern)
   keep their normal daylight styling. */
/* Full-bleed: the reader fills the whole content column — no white frame — so
   the night meets the night-sky sidebar seamlessly as one continuous sky.
   :has() drops .content's padding + max-width only on the preview page. */
.content:has(.sb-night-reader) {
    max-width: none;
    padding: 0 !important;
}

.sb-night-reader {
    position: relative;
    overflow: hidden;
    min-height: 100vh;
    padding: clamp(1.6rem, 3vw, 3rem) clamp(1.1rem, 4vw, 3.25rem) clamp(2.5rem, 5vw, 4rem);
    color: #EDEAFF;
    background:
        radial-gradient(125% 80% at 50% 122%, rgba(46, 36, 104, 0.95) 0%, rgba(22, 18, 64, 0) 62%),
        radial-gradient(52% 42% at 50% 46%, rgba(255, 214, 120, 0.13) 0%, rgba(255, 214, 120, 0) 60%),
        linear-gradient(180deg, #0B0926 0%, #12103A 58%, #1B1550 100%);
}

/* Static star field — layered dots, no markup — plus the content sits above it. */
.sb-night-reader::before {
    content: "";
    position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background-image:
        radial-gradient(1.5px 1.5px at 12% 18%, rgba(207, 198, 255, 0.7) 50%, transparent 51%),
        radial-gradient(1px 1px at 27% 62%, rgba(207, 198, 255, 0.5) 50%, transparent 51%),
        radial-gradient(1.5px 1.5px at 46% 11%, rgba(255, 233, 168, 0.6) 50%, transparent 51%),
        radial-gradient(1px 1px at 66% 73%, rgba(207, 198, 255, 0.5) 50%, transparent 51%),
        radial-gradient(1.5px 1.5px at 82% 27%, rgba(207, 198, 255, 0.6) 50%, transparent 51%),
        radial-gradient(1px 1px at 90% 64%, rgba(255, 233, 168, 0.5) 50%, transparent 51%),
        radial-gradient(1px 1px at 58% 40%, rgba(207, 198, 255, 0.4) 50%, transparent 51%),
        radial-gradient(1px 1px at 36% 86%, rgba(207, 198, 255, 0.45) 50%, transparent 51%);
}
.sb-night-reader > * { position: relative; z-index: 1; }
/* Night fills the screen; the content stays a centered, readable column. */
.sb-night-reader .sb-reader-head,
.sb-night-reader .sb-reader {
    max-width: 1160px;
    margin-left: auto;
    margin-right: auto;
}

/* Fireflies — a few drifting amber motes behind the book. */
.sb-firefly {
    position: absolute; z-index: 0; width: 6px; height: 6px; border-radius: 50%;
    background: var(--firefly);
    box-shadow: 0 0 10px 3px rgba(255, 214, 120, 0.6);
    animation: sb-firefly-drift 9s ease-in-out infinite;
}
@keyframes sb-firefly-drift {
    0%, 100% { transform: translate(0, 0); opacity: 0.45; }
    50%      { transform: translate(14px, -12px); opacity: 1; }
}

/* Header, set into the night. */
.sb-reader-title { color: #FFF7EC; }
.sb-reader-sub { color: #B9B0E6; }
.sb-back-link { color: #A79FCB; }
.sb-back-link:hover { color: #EDEAFF; }
.sb-reader-hint { color: #8F86BB; }
/* Download PDF ghost button (Send to Print keeps the amber magic style). */
.sb-reader-head .btn-outline-secondary {
    color: #CFC9F6; border-color: rgba(167, 159, 203, 0.35); background: rgba(255, 255, 255, 0.03);
}
.sb-reader-head .btn-outline-secondary:hover {
    color: #FFE9A8; border-color: rgba(255, 214, 120, 0.5); background: rgba(255, 214, 120, 0.12);
}

/* The book, warmly lit: cream pages, page-stack depth, an amber halo. */
.sb-night-reader .sb-spread {
    background: #FBF4E4;
    border-color: rgba(255, 214, 120, 0.18);
    box-shadow:
        0 34px 66px -26px rgba(0, 0, 0, 0.7),
        0 0 0 1px rgba(255, 214, 120, 0.14),
        0 0 64px -8px rgba(255, 214, 120, 0.3);
}
.sb-night-reader .sb-leaf {
    background: #FBF4E4;
    /* The pages are light — the app-wide flipped tokens are for the dark chrome,
       but a book page is not chrome. Restore dark ink locally so story text,
       "The End", dedication and colophon stay readable on the cream page. */
    --ink:   #221D3D;
    --ink2:  #1A1533;
    --muted: #54497A;
    --dim:   #8B80AE;
}
.sb-night-reader .sb-leaf--empty { background: linear-gradient(180deg, #FBF4E4, #F1E6CE); }
/* Page-stack edges — the book has thickness. */
.sb-night-reader .sb-book::before,
.sb-night-reader .sb-book::after {
    content: ""; position: absolute; top: 2.5%; bottom: 2.5%; width: 7px; z-index: 0; border-radius: 6px;
}
.sb-night-reader .sb-book::before { left: -6px;  background: linear-gradient(90deg, #2A2350, #EFE0C2);  box-shadow: -4px 0 8px -4px rgba(0, 0, 0, 0.5); }
.sb-night-reader .sb-book::after  { right: -6px; background: linear-gradient(-90deg, #2A2350, #EFE0C2); box-shadow:  4px 0 8px -4px rgba(0, 0, 0, 0.5); }
/* The page-turn sheet becomes a cream leaf, not a white one. */
.sb-night-reader .sb-turn-sheet {
    background:
        linear-gradient(105deg, rgba(255, 255, 255, 0) 30%, rgba(255, 250, 240, 0.55) 50%, rgba(255, 255, 255, 0) 66%),
        linear-gradient(90deg, #FBF4E4, #F1E6CE);
}
/* Non-cover light leaves → warm cream so no page flashes stark white. */
.sb-night-reader .sb-leaf-noimg { background: #F3E9D2; border-color: rgba(120, 90, 40, 0.25); }
.sb-night-reader .sb-leaf-noimg-text { color: #8A7550; }
.sb-night-reader .sb-leaf-endpaper {
    background:
        repeating-linear-gradient(45deg, rgba(120, 90, 40, 0.1) 0 9px, transparent 9px 18px),
        linear-gradient(160deg, #FBF4E4, #F1E6CE);
}
.sb-night-reader .sb-leaf-back { background: linear-gradient(180deg, #FBF4E4, #F1E6CE); }

/* ── Star progress + arrows ── */
.sb-starnav { display: flex; align-items: center; justify-content: center; gap: 14px; margin-bottom: 1.2rem; }
.sb-starnav-arrow {
    width: 38px; height: 38px; border-radius: 50%;
    border: 1px solid rgba(167, 159, 203, 0.35); background: rgba(255, 255, 255, 0.04);
    color: #CFC9F6; display: grid; place-items: center;
    cursor: pointer; transition: all 0.22s var(--spring);
}
.sb-starnav-arrow:hover:not(:disabled) { background: rgba(255, 214, 120, 0.14); border-color: rgba(255, 214, 120, 0.5); color: #FFE9A8; }
.sb-starnav-arrow:disabled { opacity: 0.3; cursor: default; }
.sb-stars { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; justify-content: center; max-width: 420px; }
.sb-star { width: 8px; height: 8px; border-radius: 50%; background: rgba(167, 159, 203, 0.3); transition: all 0.35s var(--spring); }
.sb-star.lit  { background: var(--amber); box-shadow: 0 0 6px rgba(255, 214, 120, 0.55); }
.sb-star.here { background: var(--firefly); box-shadow: 0 0 12px 2px rgba(255, 214, 120, 0.85); transform: scale(1.5); }

/* ── Affordance row status text, set on the night ── */
.sb-reader-actions .text-muted { color: #B9B0E6 !important; }
.sb-reader-actions .text-success { color: var(--firefly) !important; }
.sb-reader-actions .btn-outline-secondary { color: #CFC9F6; border-color: rgba(167, 159, 203, 0.35); background: rgba(255, 255, 255, 0.05); }
.sb-reader-actions .btn-outline-secondary:hover { color: #FFE9A8; border-color: rgba(255, 214, 120, 0.5); background: rgba(255, 214, 120, 0.14); }
.sb-reader-actions .btn-outline-primary { color: #C4B4FF; border-color: rgba(167, 139, 250, 0.5); background: rgba(255, 255, 255, 0.05); }
.sb-reader-actions .btn-outline-primary:hover { color: #EDEAFF; border-color: rgba(167, 139, 250, 0.78); background: rgba(167, 139, 250, 0.2); }
.sb-reader-actions .btn-outline-danger { color: #FFC9BD; border-color: rgba(228, 87, 61, 0.6); background: rgba(228, 87, 61, 0.14); }
.sb-reader-actions .btn-outline-danger:hover { color: #FFFFFF; border-color: #E4573D; background: rgba(228, 87, 61, 0.32); }

/* ── Thumbnail pager, night-themed (active = amber, not violet) ── */
.sb-reader-pager .sb-page-thumb.btn-outline-secondary { color: #C4BCE6; border-color: rgba(167, 159, 203, 0.28); background: rgba(255, 255, 255, 0.03); }
.sb-reader-pager .sb-page-thumb.btn-outline-secondary:hover { color: #FFE9A8; border-color: rgba(255, 214, 120, 0.45); background: rgba(255, 214, 120, 0.12); }
.sb-reader-pager .sb-page-thumb.btn-primary { background: var(--amber); border-color: var(--amber); color: #3A2708; box-shadow: 0 0 14px -2px rgba(255, 214, 120, 0.6); }

@media (prefers-reduced-motion: reduce) {
    .sb-firefly { animation: none; }
}

/* ══ Cinematic first-read reveal ═══════════════════════════════════════════
   First time a finished book is opened: a flashlight beam finds the cover, the
   light pool blooms, the title glows on, then the cover opens to the dedication.
   Namespaced .sb-firstread so it never collides with the landing .sb-reveal.
   All motion is CSS keyed to .sb-firstread; Preview.razor only advances the
   spread and finalizes. Reduced-motion users never enter this state (JS gate). */
@property --sb-bx { syntax: '<percentage>'; inherits: false; initial-value: 50%; }
@property --sb-by { syntax: '<percentage>'; inherits: false; initial-value: 50%; }

/* The dark veil with a flashlight hole. Higher specificity than
   `.sb-night-reader > *` (which would otherwise pin it to z-index:1). */
.sb-night-reader > .sb-firstread-veil {
    position: absolute; inset: 0; z-index: 30; pointer-events: none;
    background: radial-gradient(circle 250px at var(--sb-bx) var(--sb-by),
        rgba(6, 4, 20, 0) 0%, rgba(6, 4, 20, 0) 34%, rgba(6, 4, 20, 0.965) 72%);
    animation: sb-fr-beam 2.7s var(--spring) forwards;
}
@keyframes sb-fr-beam {
    0%   { --sb-bx: 15%; --sb-by: 24%; opacity: 1; }   /* beam off to the side */
    26%  { --sb-bx: 50%; --sb-by: 50%; opacity: 1; }   /* settles on the cover */
    60%  { --sb-bx: 50%; --sb-by: 50%; opacity: 1; }   /* hold on the hero shot */
    100% { --sb-bx: 50%; --sb-by: 50%; opacity: 0; }   /* bloom to full light */
}
/* Title glows on as the beam lands. */
.sb-firstread .sb-leaf-cover-title { animation: sb-fr-title 2.7s ease forwards; }
@keyframes sb-fr-title {
    0%, 30% { opacity: 0; text-shadow: 0 0 0 rgba(255, 233, 168, 0); }
    60%     { opacity: 1; text-shadow: 0 2px 26px rgba(255, 233, 168, 0.6); }
    100%    { opacity: 1; }
}
/* Fireflies drift in during the bloom. */
.sb-firstread .sb-firefly { animation: sb-firefly-drift 9s ease-in-out infinite, sb-fr-fade 2.7s ease forwards; }
@keyframes sb-fr-fade { 0%, 42% { opacity: 0; } 100% { opacity: 1; } }

/* Chrome fades out during the reveal, back in when .sb-firstread is removed. */
.sb-night-reader .sb-starnav,
.sb-night-reader .sb-reader-pager,
.sb-night-reader .sb-reader-hint,
.sb-night-reader .sb-reader-actions,
.sb-night-reader .sb-reader-head { transition: opacity 0.5s var(--spring); }
.sb-firstread .sb-starnav,
.sb-firstread .sb-reader-pager,
.sb-firstread .sb-reader-hint,
.sb-firstread .sb-reader-actions,
.sb-firstread .sb-reader-head { opacity: 0; pointer-events: none; }

/* Full-stage click catcher + "tap to skip" hint. */
.sb-night-reader > .sb-firstread-skip {
    position: absolute; inset: 0; z-index: 31; width: 100%;
    display: flex; align-items: flex-end; justify-content: center; padding-bottom: 3.2rem;
    background: transparent; border: 0; cursor: pointer;
}
.sb-firstread-skip span { color: rgba(237, 234, 255, 0.5); font-size: 0.82rem; letter-spacing: 0.04em;
    animation: sb-fr-fade 2.7s ease forwards; }

.sb-replay-link { color: #A79FCB; text-decoration: none; }
.sb-replay-link:hover { color: #FFE9A8; }

/* The cover opens SLOWLY during the reveal — a graceful turn, not the brisk
   520ms navigation turn — so the first spread never feels rushed. */
.sb-firstread .sb-turn--fwd { animation-duration: 1200ms; }

@media (prefers-reduced-motion: reduce) {
    .sb-night-reader > .sb-firstread-veil { display: none; }
    .sb-firstread .sb-leaf-cover-title,
    .sb-firstread .sb-firefly { animation: none; }
}

/* ── Thumbnails ────────────────────────────────────────────────── */
.sb-thumb {
    width: 100%;
    height: 120px;
    object-fit: cover;
}

.sb-page-thumb {
    min-width: 48px;
    position: relative;
}

/* ── Redraw status badges on the thumbnail strip ──────────────────────
   A small corner chip on any spread whose illustration is queued for,
   undergoing, or finished with a redraw. */
.sb-thumb-badge {
    position: absolute;
    top: -6px;
    right: -6px;
    min-width: 16px;
    height: 16px;
    padding: 0 3px;
    border-radius: 8px;
    font-size: 10px;
    line-height: 16px;
    font-weight: 700;
    text-align: center;
    box-shadow: 0 1px 3px var(--glow);
    pointer-events: none;
}
.sb-badge-wait  { background: var(--rim);    color: var(--muted); }
.sb-badge-gen   { background: var(--amber);  color: var(--ink2);  animation: sb-badge-pulse 1.1s ease-in-out infinite; }
.sb-badge-ready { background: var(--amber);  color: var(--ink2);  }
.sb-badge-fail  { background: #E4573D;       color: #fff;         }

@keyframes sb-badge-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.35; }
}

/* Blocked "Send to Print" — pending redraws not yet reviewed. */
.sb-print-blocked {
    opacity: 0.55;
    pointer-events: none;
    cursor: not-allowed;
}

/* ── Redraw-ready toast stack ─────────────────────────────────────────
   Fixed, top-right; one card per finished-but-unviewed redraw. */
.sb-toast-stack {
    position: fixed;
    top: 84px;
    right: 20px;
    z-index: 1080;
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-width: min(360px, calc(100vw - 40px));
}
.sb-toast {
    display: flex;
    align-items: center;
    background: var(--surface);
    border: 1px solid var(--rim);
    border-left: 4px solid var(--amber);
    border-radius: 12px;
    padding: 10px 12px;
    box-shadow: 0 8px 24px var(--glow);
    font-size: 0.9rem;
    color: var(--ink);
    animation: sb-toast-in 0.4s var(--spring);
}
@keyframes sb-toast-in {
    from { opacity: 0; transform: translateX(16px); }
    to   { opacity: 1; transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
    .sb-badge-gen { animation: none; }
    .sb-toast     { animation: none; }
}

/* ── Night panel — the generation moment ───────────────────────────
   The one sanctioned piece of night sky inside the app: shown while
   the book is being written and illustrated. Echoes the landing hero. */
.sb-night-panel {
    position: relative;
    border-radius: 18px;
    background:
        radial-gradient(ellipse 90% 70% at 50% -10%, rgba(46, 36, 104, 0.9) 0%, transparent 70%),
        linear-gradient(180deg, var(--night) 0%, var(--night2) 100%);
    color: #EDEAFF;
    padding: 34px 28px 30px;
    overflow: hidden;
    text-align: center;
}

.sb-night-panel .sb-night-status {
    font-family: 'Bricolage Grotesque', sans-serif;
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--firefly);
    margin-bottom: 6px;
}

.sb-night-panel .sb-night-sub {
    font-size: 0.85rem;
    color: rgba(237, 234, 255, 0.55);
    font-style: italic;
    margin-bottom: 22px;
}

.sb-gen-stars {
    display: flex;
    justify-content: center;
    gap: 14px;
    margin-bottom: 24px;
    flex-wrap: wrap;
}

.sb-gen-star {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: rgba(198, 189, 242, 0.22);
    transition: background 500ms var(--spring), box-shadow 500ms var(--spring), transform 500ms var(--spring);
}

.sb-gen-star.lit {
    background: var(--amber);
    box-shadow: 0 0 12px 3px var(--amber-glow);
    transform: scale(1.15);
}

.sb-gen-star.writing {
    animation: sbStarPulse 1.6s ease-in-out infinite;
}

@keyframes sbStarPulse {
    0%, 100% { background: rgba(198, 189, 242, 0.22); box-shadow: none; }
    50%      { background: var(--firefly); box-shadow: 0 0 10px 2px var(--amber-glow); }
}

.sb-night-panel .btn-outline-secondary {
    background: transparent;
    border-color: rgba(237, 234, 255, 0.25);
    color: rgba(237, 234, 255, 0.75);
}

.sb-night-panel .btn-outline-secondary:hover {
    background: rgba(255, 255, 255, 0.08);
    border-color: rgba(237, 234, 255, 0.45);
    color: #fff;
}

/* ── Shelf cards — books that look like books ──────────────────── */
.sb-shelf-card {
    background: var(--surface);
    border: 1px solid var(--rim);
    border-radius: 18px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    height: 100%;
    transition: transform 400ms var(--spring), box-shadow 400ms var(--spring);
}

.sb-shelf-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 20px 44px -18px var(--glow);
}

.sb-cover-link {
    display: block;
    position: relative;
}

.sb-cover {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    display: block;
}

/* spine shadow along the left edge — reads as a book, not a photo */
.sb-cover-link::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, rgba(11, 9, 38, 0.25) 0%, rgba(11, 9, 38, 0.07) 3.5%, transparent 8%);
    pointer-events: none;
}

.sb-cover-link:focus-visible {
    outline: 3px solid var(--violet);
    outline-offset: -3px;
}

/* draft books haven't met their illustrator yet — a patch of night sky */
.sb-cover-draft {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    color: rgba(237, 234, 255, 0.6);
    background-image:
        radial-gradient(1.5px 1.5px at 22% 30%, rgba(207, 198, 255, 0.7) 50%, transparent 51%),
        radial-gradient(1px 1px at 68% 18%, rgba(255, 233, 168, 0.6) 50%, transparent 51%),
        radial-gradient(1.5px 1.5px at 80% 62%, rgba(207, 198, 255, 0.55) 50%, transparent 51%),
        radial-gradient(1px 1px at 38% 74%, rgba(207, 198, 255, 0.5) 50%, transparent 51%),
        linear-gradient(180deg, var(--night) 0%, var(--night2) 100%);
}

.sb-cover-moon {
    font-size: 2rem;
    filter: drop-shadow(0 0 14px rgba(255, 233, 168, 0.6));
}

.sb-cover-hint {
    font-size: 0.78rem;
    font-style: italic;
}

.sb-shelf-body {
    padding: 14px 16px 4px;
}

.sb-shelf-title {
    font-size: 1.05rem;
    line-height: 1.25;
}

.sb-shelf-meta {
    color: var(--dim);
    font-size: 0.82rem;
    margin: 6px 0 0;
}

.sb-shelf-actions {
    display: flex;
    gap: 8px;
    padding: 12px 16px 16px;
    margin-top: auto;
}

/* ── Staggered entrance — pure CSS, no observer needed ─────────── */
.sb-enter {
    opacity: 0;
    animation: sbEnter 600ms var(--spring) forwards;
}

@keyframes sbEnter {
    from { opacity: 0; transform: translateY(22px); filter: blur(5px); }
    to   { opacity: 1; transform: none; filter: none; }
}

/* ── Spark card — the Create page keeps the landing's promise ──── */
.sb-spark-card {
    background: var(--surface);
    border: 1px solid rgba(240, 173, 78, 0.45);
    border-radius: 18px;
    padding: 22px 24px 12px;
    box-shadow: 0 18px 44px -24px var(--amber-glow);
    margin-bottom: 30px;
}

.sb-spark-label {
    display: block;
    font-size: 0.74rem;
    font-weight: 800;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: #B97A1E;
    margin-bottom: 8px;
}

.sb-spark-card .form-control {
    border: none;
    box-shadow: none;
    padding: 0;
    font-size: 1.08rem;
    line-height: 1.55;
    background: transparent;
    resize: vertical;
}

.sb-spark-card .form-control:focus {
    border: none;
    box-shadow: none;
}

.sb-spark-card .form-text {
    color: var(--dim);
    font-style: italic;
}

.sb-details-heading {
    display: flex;
    align-items: center;
    gap: 14px;
    font-family: 'Nunito Sans', sans-serif;
    font-size: 0.76rem;
    font-weight: 800;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--dim);
    margin: 4px 0 18px;
}

.sb-details-heading::after {
    content: "";
    height: 1px;
    background: var(--rim);
    flex: 1;
}

/* ── Editor: header meta + spark quote ─────────────────────────── */
.sb-book-meta {
    color: var(--muted);
    font-size: 0.92rem;
}

.sb-spark-quote {
    font-style: italic;
    color: var(--muted);
    font-size: 1.02rem;
    line-height: 1.6;
    border-left: 3px solid var(--amber);
    padding-left: 14px;
    max-width: 68ch;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-bottom: 28px;
}

/* ── Editor: cast & places grid ────────────────────────────────── */
.sb-cast-card {
    position: relative;
    background: var(--surface);
    border: 1px solid var(--rim);
    border-radius: 16px;
    overflow: hidden;
    height: 100%;
    display: flex;
    flex-direction: column;
    transition: transform 220ms var(--spring), box-shadow 220ms var(--spring);
}

.sb-cast-card:hover {
    transform: translateY(-3px);
    box-shadow: 0 12px 28px -14px var(--glow);
}

.sb-cast-img {
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    display: block;
}

.sb-cast-body {
    padding: 10px 12px 12px;
}

.sb-cast-type {
    font-size: 0.66rem;
    font-weight: 800;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--dim);
}

.sb-cast-type.hero {
    color: #B97A1E;
}

.sb-cast-desc {
    font-size: 0.8rem;
    color: var(--muted);
    margin: 4px 0 0;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.sb-cast-delete {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: none;
    background: rgba(11, 9, 38, 0.55);
    color: #fff;
    font-size: 0.72rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0;
    transition: opacity 220ms var(--spring), background 220ms var(--spring);
}

.sb-cast-card:hover .sb-cast-delete,
.sb-cast-delete:focus-visible {
    opacity: 1;
}

.sb-cast-delete:hover {
    background: #C2455E;
}

@media (pointer: coarse) {
    .sb-cast-delete { opacity: 1; }
}

.sb-add-tile {
    width: 100%;
    height: 100%;
    min-height: 200px;
    border: 2px dashed var(--rim);
    background: transparent;
    border-radius: 16px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    color: var(--muted);
    font-weight: 700;
    cursor: pointer;
    padding: 18px;
    transition: border-color 220ms var(--spring), background 220ms var(--spring), color 220ms var(--spring);
}

.sb-add-tile:hover {
    border-color: var(--amber2);
    background: rgba(255, 196, 107, 0.08);
    color: var(--ink);
}

.sb-add-tile:focus-visible {
    outline: 3px solid var(--violet);
    outline-offset: 2px;
}

.sb-add-plus {
    font-size: 1.6rem;
    line-height: 1;
    color: var(--amber2);
}

.sb-add-hint {
    font-size: 0.72rem;
    font-weight: 400;
    font-style: italic;
    color: var(--dim);
    text-align: center;
}

.sb-upload-card {
    border: 1px solid rgba(240, 173, 78, 0.45);
    border-radius: 16px;
    background: var(--surface);
    padding: 18px 20px;
    box-shadow: 0 14px 34px -22px var(--amber-glow);
}

.sb-generated > summary {
    cursor: pointer;
    font-size: 0.88rem;
    font-weight: 700;
    color: var(--muted);
}

.sb-generated > summary:hover {
    color: var(--ink);
}

/* ── Editor: the finale card ───────────────────────────────────── */
.sb-finale {
    background: linear-gradient(180deg, var(--surface) 0%, #F5F1FF 100%);
}

/* ── Badges / Pills (custom) ───────────────────────────────────── */
.sb-badge {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border-radius: 9999px;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    background: var(--rim2);
    border: 1px solid var(--rim);
    color: var(--violet);
}

/* ── Scroll Reveal ─────────────────────────────────────────────── */
.sb-reveal {
    opacity: 0;
    transform: translateY(28px);
    filter: blur(6px);
    transition:
        opacity 600ms var(--spring),
        transform 600ms var(--spring),
        filter 600ms var(--spring);
}

.sb-reveal.in {
    opacity: 1;
    transform: none;
    filter: none;
}

/* ── Layout ────────────────────────────────────────────────────── */
h1:focus {
    outline: none;
}

.content {
    padding-top: 1.6rem;
    padding-bottom: 3rem;
    max-width: 1160px;
}

/* ── Validation ────────────────────────────────────────────────── */
.valid.modified:not([type=checkbox]) {
    outline: 1px solid var(--teal);
}

.invalid {
    outline: 1px solid #C2455E;
}

.validation-message {
    color: #C2455E;
    font-size: 0.82rem;
    margin-top: 4px;
}

@media (prefers-reduced-motion: reduce) {
    .sb-reveal { opacity: 1; transform: none; filter: none; }
    .sb-enter { animation: none; opacity: 1; }
    .sb-gen-star.writing { animation: none; }
    * { transition-duration: 0.01ms !important; }
}

/* ── Blazor Infrastructure (do not edit) ───────────────────────── */
#blazor-error-ui {
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2ZyA+) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.loading-progress {
    position: relative;
    display: block;
    width: 8rem;
    height: 8rem;
    margin: 20vh auto 1rem auto;
}

    .loading-progress circle {
        fill: none;
        stroke: #e0e0e0;
        stroke-width: 0.6rem;
        transform-origin: 50% 50%;
        transform: rotate(-90deg);
    }

        .loading-progress circle:last-child {
            stroke: var(--violet);
            stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
            transition: stroke-dasharray 0.05s ease-in-out;
        }

.loading-progress-text {
    position: absolute;
    text-align: center;
    font-weight: bold;
    inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
    color: var(--muted);
}

    .loading-progress-text:after {
        content: var(--blazor-load-percentage-text, "Loading");
    }

/* ── Auth — threshold screens between night landing and daylight app ──
   Full night sky (landing-hero gradient + star dots), a pool of amber
   flashlight glow, and a daylight card floating in the beam. */
.sb-auth-shell {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    background-image:
        radial-gradient(1.5px 1.5px at 18% 22%, rgba(207, 198, 255, 0.8) 50%, transparent 51%),
        radial-gradient(1px 1px at 72% 12%, rgba(207, 198, 255, 0.6) 50%, transparent 51%),
        radial-gradient(1.5px 1.5px at 84% 38%, rgba(255, 233, 168, 0.7) 50%, transparent 51%),
        radial-gradient(1px 1px at 32% 52%, rgba(207, 198, 255, 0.5) 50%, transparent 51%),
        radial-gradient(1.5px 1.5px at 62% 68%, rgba(207, 198, 255, 0.6) 50%, transparent 51%),
        radial-gradient(1px 1px at 8% 64%, rgba(255, 233, 168, 0.5) 50%, transparent 51%),
        radial-gradient(1px 1px at 88% 82%, rgba(207, 198, 255, 0.55) 50%, transparent 51%),
        radial-gradient(1.5px 1.5px at 44% 12%, rgba(207, 198, 255, 0.45) 50%, transparent 51%),
        radial-gradient(ellipse 60% 45% at 50% 62%, rgba(255, 196, 107, 0.14) 0%, transparent 65%),
        linear-gradient(180deg, var(--night) 0%, var(--night2) 62%, var(--dusk) 100%);
}

.sb-auth-brand {
    padding: 1.6rem 2rem 0;
    text-align: center;
}

.sb-auth-brand a {
    font-family: 'Bricolage Grotesque', sans-serif;
    font-weight: 800;
    font-size: 1.5rem;
    letter-spacing: -0.02em;
    color: #FDFCFF;
    text-decoration: none;
}

.sb-auth-brand a:hover { color: #fff; }
.sb-auth-brand a span { color: var(--amber); }

.sb-auth-main {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem 1rem;
}

.sb-auth-card {
    position: relative;
    width: 100%;
    max-width: 420px;
    background: var(--surface);
    border-radius: 22px;
    padding: 2.4rem 2.2rem 2rem;
    box-shadow:
        0 0 0 1px rgba(255, 255, 255, 0.06),
        0 0 80px 8px rgba(255, 196, 107, 0.16),
        0 24px 60px rgba(4, 2, 24, 0.55);
    animation: sb-auth-rise 500ms var(--spring);
}

@keyframes sb-auth-rise {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: translateY(0); }
}

.sb-auth-torch {
    font-size: 1.9rem;
    line-height: 1;
    margin-bottom: 0.9rem;
    display: inline-block;
    filter: drop-shadow(0 0 14px var(--amber-glow));
    animation: sb-auth-bob 2.6s ease-in-out infinite;
}

@keyframes sb-auth-bob {
    0%, 100% { transform: translateY(0) rotate(-8deg); }
    50%      { transform: translateY(-5px) rotate(6deg); }
}

.sb-auth-title {
    font-size: 1.5rem;
    margin-bottom: 0.4rem;
}

.sb-auth-sub {
    color: var(--muted);
    font-size: 0.95rem;
    margin-bottom: 1.5rem;
}

.sb-auth-label {
    display: block;
    font-weight: 700;
    font-size: 0.82rem;
    color: var(--ink2);
    margin: 0 0 0.35rem 0.1rem;
}

.sb-auth-input {
    width: 100%;
    border: 1.5px solid var(--rim);
    border-radius: 12px;
    padding: 0.65rem 0.9rem;
    font-size: 0.95rem;
    color: var(--ink);
    background: var(--bg);
    margin-bottom: 1rem;
    transition: border-color 220ms var(--spring), box-shadow 220ms var(--spring);
}

.sb-auth-input:focus {
    outline: none;
    border-color: var(--amber);
    box-shadow: 0 0 0 4px rgba(255, 196, 107, 0.22);
}

/* The magic action — same amber as Generate and the landing CTAs */
.sb-auth-btn {
    width: 100%;
    border: none;
    border-radius: 9999px;
    padding: 0.72rem 1rem;
    font-family: 'Nunito Sans', sans-serif;
    font-weight: 800;
    font-size: 1rem;
    color: var(--ink2);
    background: linear-gradient(180deg, var(--firefly) 0%, var(--amber) 55%);
    box-shadow: 0 6px 22px rgba(255, 196, 107, 0.35);
    margin-top: 0.25rem;
    transition: transform 220ms var(--spring), box-shadow 220ms var(--spring), opacity 220ms var(--spring);
}

.sb-auth-btn:hover:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: 0 8px 30px rgba(255, 196, 107, 0.5);
}

.sb-auth-btn:active:not(:disabled) { transform: scale(0.98); }

.sb-auth-btn:disabled { opacity: 0.6; }

.sb-auth-links {
    margin-top: 1.4rem;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    font-size: 0.88rem;
    color: var(--muted);
    text-align: center;
}

.sb-auth-links a { font-weight: 700; }

.sb-auth-error {
    background: rgba(255, 122, 107, 0.12);
    border: 1px solid rgba(255, 122, 107, 0.4);
    color: #B3402F;
    border-radius: 12px;
    padding: 0.6rem 0.9rem;
    font-size: 0.88rem;
    margin-bottom: 1rem;
}

.sb-auth-success {
    background: rgba(78, 205, 196, 0.12);
    border: 1px solid rgba(78, 205, 196, 0.45);
    color: #1F7A73;
    border-radius: 12px;
    padding: 0.6rem 0.9rem;
    font-size: 0.88rem;
    margin-bottom: 1rem;
}

.sb-auth-tagline {
    padding: 0 1rem 1.4rem;
    text-align: center;
    font-size: 0.75rem;
    font-style: italic;
    color: rgba(237, 234, 255, 0.4);
}

/* Fireflies — tiny wandering lights, same spirit as the landing hero */
.sb-auth-firefly {
    position: absolute;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--firefly);
    box-shadow: 0 0 10px 2px var(--amber-glow);
    opacity: 0.6;
    pointer-events: none;
    animation: sb-firefly-drift 11s ease-in-out infinite;
}

.sb-auth-firefly.f1 { top: 24%; left: 16%; animation-delay: 0s; }
.sb-auth-firefly.f2 { top: 62%; left: 78%; animation-delay: -4s; animation-duration: 14s; }
.sb-auth-firefly.f3 { top: 78%; left: 28%; animation-delay: -8s; animation-duration: 9s; }

@keyframes sb-firefly-drift {
    0%, 100% { transform: translate(0, 0); opacity: 0.55; }
    25%      { transform: translate(26px, -18px); opacity: 0.9; }
    50%      { transform: translate(-14px, -34px); opacity: 0.4; }
    75%      { transform: translate(-30px, 12px); opacity: 0.8; }
}

@media (prefers-reduced-motion: reduce) {
    .sb-auth-card { animation: none; }
    .sb-auth-torch { animation: none; }
    .sb-auth-firefly { animation: none; opacity: 0.4; }
}

/* ── Image lightbox — click-to-enlarge overlay (transient modal, dark scrim by design) ── */
.sb-lightbox {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(11, 9, 38, 0.86);
    backdrop-filter: blur(2px);
    outline: none;
    animation: sb-lightbox-fade 220ms var(--spring);
}

.sb-lightbox-img {
    max-width: 92vw;
    max-height: 92vh;
    object-fit: contain;
    border-radius: 12px;
    box-shadow: 0 30px 70px -20px rgba(0, 0, 0, 0.6), 0 0 0 1px var(--glow);
    animation: sb-lightbox-zoom 260ms var(--spring);
}

.sb-lightbox-close {
    position: fixed;
    top: 1.25rem;
    right: 1.5rem;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.3);
    background: rgba(11, 9, 38, 0.6);
    color: var(--ink);
    font-size: 1.1rem;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 220ms var(--spring), transform 220ms var(--spring);
}

.sb-lightbox-close:hover {
    background: rgba(255, 255, 255, 0.15);
    transform: scale(1.05);
}

@keyframes sb-lightbox-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes sb-lightbox-zoom {
    from { opacity: 0; transform: scale(0.96); }
    to   { opacity: 1; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .sb-lightbox { animation: none; }
    .sb-lightbox-img { animation: none; }
}

/* ── CreditWidget — balance banner + buy-credits pack picker ── */
.sb-credit-banner {
  display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
  background: var(--surface2); border: 1px solid var(--amber);
  border-radius: 14px; padding: .7rem 1rem; margin: 1rem 0; color: var(--ink);
}
.sb-credit-banner.sb-credit-blocked { border-color: var(--coral, #FF7A6B); }
.sb-credit-banner .btn { margin-left: auto; }
.sb-credit-modal-backdrop {
  position: fixed; inset: 0; background: rgba(6,4,20,.72);
  display: flex; align-items: center; justify-content: center; z-index: 1050;
}
.sb-credit-modal {
  background: var(--surface); border: 1px solid var(--rim); border-radius: 18px;
  padding: 1.5rem; max-width: 420px; width: 92%; color: var(--ink);
  box-shadow: 0 20px 60px var(--glow);
}
.sb-credit-packs { display: grid; gap: .6rem; margin: 1rem 0; }
.sb-credit-pack {
  display: flex; justify-content: space-between; align-items: center;
  background: var(--surface2); border: 1px solid var(--rim); border-radius: 12px;
  padding: .8rem 1rem; color: var(--ink); cursor: pointer; transition: all 220ms var(--spring, ease);
}
.sb-credit-pack:hover:not(:disabled) { border-color: var(--amber); transform: translateY(-2px); }
.sb-credit-pack-count { font-weight: 700; }
.sb-credit-pack-price { color: var(--firefly); font-weight: 700; }
