@import 'Bookary.Web.Client.uj95qy7mwv.bundle.scp.css';

/* /Components/Layout/MainLayout.razor.rz.scp.css */
/*
    DESIGN-PLAN §5 rule 1: this file is one of exactly two LAYOUTS allowed to
    name a viewport unit (the other is ImmersiveLayout). It said "exactly two
    places in the codebase" until 2026-08-28, and that was false when it was
    written: a census for phase 2 item (b) counted EIGHT component declarations
    naming one (§2.5 finding 11). Rule 1 now carries the carve-out that makes
    most of them legitimate — an element positioned against the viewport, which
    is `position: fixed` or a modal `<dialog>` in the top layer, is entitled to
    know how big the viewport is, because it has already told the browser its
    box is the screen's box.

    A component that has NOT said so gets nothing: it says `flex: 1` or
    `height: 100%` and takes what its parent gives. The reader once demanded its
    own 100vh inside this shell's 100vh, under a 3.5rem sticky header, and the
    bottom of the book sat below the fold by construction.

    `min-block-size`, not `block-size`: prose pages are as tall as their content
    and the document scrolls them. And `dvh`, not `vh` — `vh` is the LARGEST
    possible viewport on mobile, so a `vh` layout is clipped by the browser's
    URL bar before any other mistake gets a chance.

    The sizing and inset properties in this file are LOGICAL (§9.0, decided
    2026-08-28). They are the same properties under another name in a
    horizontal-tb LTR document, which every one of ours is; what they buy is
    that the day a locale is not, the layouts do not have to be rewritten. The
    four --bk-safe-* tokens are the deliberate exception and say so in app.css.
*/
.shell[b-art46jlujm] {
    min-block-size: 100dvh;
    display: flex;
    flex-direction: column;
}

/*
    DESIGN-PLAN §5A.1 and §5.2 rule 5: only a LAYOUT reserves a safe-area
    inset, for the same reason only a layout names a viewport unit — a
    component cannot know whether its edge is the screen's edge. The rule has
    two halves, and they are enforced differently. env(safe-area-inset-*) is
    written in exactly one place, app.css's token block, which is greppable.
    The var(--bk-safe-*) tokens it publishes are then read by a short
    allowlist: this file, ImmersiveLayout.razor.css, app.css's own page modes,
    and #blazor-error-ui — the last because position: fixed against the
    viewport IS the claim that an element's edge is the screen's edge, which
    is the one thing a component is entitled to know.

    The app installs with display: standalone, so on a notched phone the
    header used to run under the status bar and the Dynamic Island. Measured
    2026-08-27 at 390x844: nothing was reserved.

    The --bk-safe-* tokens this file reads each carry the 0px fallback,
    declared once in app.css, which is where env() itself is written — so a
    browser that has never heard of the function computes a length there
    instead of dropping the declaration here. On a device with no insets
    every value below is zero and the layout is exactly what it was.

    `min-block-size`, NOT `height`: a fixed height plus an inset is the
    arithmetic that put the bottom of the reader below the fold (§2.1) — the
    bar must be able to grow by the inset rather than absorb it.

    `max()` on the horizontal padding, not addition: the inset REPLACES the
    design padding when it is larger, rather than adding to it, so a
    landscape notch does not double the gutter.

    The tokens are PHYSICAL, because the env() functions behind them are —
    there is no logical form of safe-area-inset-left. The rest of this file
    uses logical properties per §9.0, so in an RTL document the two values in
    each padding-inline pair would need swapping. RTL is an explicit non-goal
    (§9); app.css's token block is the single seam where it would be picked
    up, which is most of why the tokens exist.

    None of this works without viewport-fit=cover on the viewport meta in
    App.razor: without it these values are all zero on iOS.
*/
.shell-header[b-art46jlujm] {
    position: sticky;
    inset-block-start: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 1rem;
    padding-block-start: var(--bk-safe-top);
    padding-inline: max(1rem, var(--bk-safe-left))
                    max(1rem, var(--bk-safe-right));
    min-block-size: calc(3.5rem + var(--bk-safe-top));
    box-sizing: border-box;
    background-color: var(--bk-surface-alt);
    border-block-end: var(--bk-edge-width) solid var(--bk-edge);
}

/*
    The wordmark is also the way home, so it is a target as well as an identity
    — measured 78 x 23 before phase 2 item (d), which is a link a thumb misses.
    `inline-flex` plus the block minimum rather than padding, because padding
    would push the brand off the header's optical left edge and the header has
    no room to give.
*/
.brand[b-art46jlujm] {
    display: inline-flex;
    align-items: center;
    min-block-size: 2.75rem;
    flex: 0 0 auto;
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--bk-text);
    text-decoration: none;
}

    .brand:hover[b-art46jlujm] {
        color: var(--bk-accent);
    }

/*
    NO max-width AND NO padding HERE, deliberately, since design phase 0. This
    used to be a centred 64rem prose box applied to every page — which is how
    the reader ended up paginating a book against a padded prose column built
    for the Terms page (DESIGN-PLAN §2.1). The containment now belongs to the
    page: its root element declares `.bk-prose` or `.bk-workspace` (app.css),
    and this element is only the flexible track between header and footer.

    `min-block-size: 0` is the flexbox trap's antidote: a flex item refuses to
    shrink below its content by default, so without this, any child that wants
    to FIT the shell rather than grow it can only clip. ShelfPanel learned the
    width half of this lesson; this is the height half, and it was missing.
*/
.shell-content[b-art46jlujm] {
    flex: 1;
    inline-size: 100%;
    min-block-size: 0;
}

/*
    THE FOOTER CLEARS THE BOTTOM BAR (phase 2 item d).

    Below 48rem the navigation is `position: fixed` to the bottom of the
    viewport (app.css, `.app-nav`), so it is out of the flow and would sit on
    top of the last thing on the page — which is this, and which carries the
    Terms, Privacy and Contact links a signed-out visitor is most likely to be
    reading when they reach the bottom.

    The bar's own height is `--bk-nav-block-size` rather than a number repeated
    here: a footer that cleared 3rem beside a bar that grew to 3.5 is a footer
    with its last line underneath the navigation, and that is a thing you
    discover from a screenshot rather than from a diff. The safe-area inset is
    added ONCE — the bar reserves it inside its own box, and this clears the
    bar's whole box including it.
*/
.shell-footer[b-art46jlujm] {
    padding-block: 1rem calc(1rem + var(--bk-safe-bottom) + var(--bk-nav-block-size));
    padding-inline: max(1.5rem, var(--bk-safe-left))
                    max(1.5rem, var(--bk-safe-right));
    border-block-start: var(--bk-edge-width) solid var(--bk-edge);
    color: var(--bk-muted);
    font-size: 0.85rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.5rem;
    align-items: baseline;
    justify-content: space-between;
}

/*
    THE LEGAL LINKS ARE NAVIGATION, so they take the 44px minimum like every
    other destination — measured 39, 46 and 50 px wide by 16 px tall before
    phase 2 item (d). WCAG 2.5.8 exempts a link sitting INSIDE a sentence,
    where making it 44px would wreck the line it is part of; these three are a
    row of their own with a `nav` element and an accessible name around them,
    which is not that case and should not borrow the excuse.
*/
.shell-footer-links[b-art46jlujm] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
}

.shell-footer-links a[b-art46jlujm] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-block-size: 2.75rem;
    /* "Terms" is 39px of text, so the inline minimum is doing real work here
       rather than restating the block one: 44 x 44 means both axes, and a
       39px-wide target is the axis nobody checks. */
    min-inline-size: 2.75rem;
}

.shell-footer-links a[b-art46jlujm] {
    color: inherit;
}

/*
    DESIGN-PLAN §5.3, mobile-first: the header's unqualified padding and gap are
    now the PHONE's, and this query adds the room a wider screen has. It used to
    be the other way round — a `max-width: 640.98px` block subtracting from a
    desktop default, with the `.98` a Bootstrap-era workaround for the
    off-by-one that only `max-width` has. There are two breakpoints in the whole
    app and this is the first: 48rem (768px), the width at which a tablet in
    portrait, and the four nav links, first fit. 64rem (1024px) is the other,
    and it is the library sidebar's. Custom properties cannot appear in a media
    query's condition, so the names live in this comment rather than as tokens.

    The narrow-viewport step for the CONTENT moved to `.bk-prose` /
    `.bk-workspace` in app.css, with the rest of the containment this element
    gave up in phase 0; app.css inverts its own copy of this query the same way.
*/
@media (min-width: 48rem) {
    .shell-header[b-art46jlujm] {
        padding-inline: max(1.5rem, var(--bk-safe-left))
                        max(1.5rem, var(--bk-safe-right));
        gap: 1.5rem;
    }

    /* No bar at this width — the links are back in the header — so there is
       nothing to clear and the footer returns to its own padding. */
    .shell-footer[b-art46jlujm] {
        padding-block-end: calc(1rem + var(--bk-safe-bottom));
    }
}
/* /Components/Layout/NavMenu.razor.rz.scp.css */
/*
    ALMOST EVERYTHING THIS FILE USED TO HOLD IS IN app.css NOW (phase 2 item d).

    `.app-nav` and `.nav-link` are laid out by the shell rather than by this
    component: below 48rem the nav is a bar fixed to the bottom of the viewport
    and `.shell-footer` in MainLayout.razor.css has to be padded clear of it,
    and those two files are in different assemblies' scoped stylesheets, which
    cannot see each other. Keeping the rules here would also have meant this
    file reading `var(--bk-safe-*)`, which §5.2 rule 5 confines to a four-file
    allowlist on purpose. app.css explains the arrangement where the arrangement
    is.

    What is left is the one thing that IS this component's: the header keeps a
    session corner at every width, and the ACCOUNT NAME inside it is the only
    part of the header that has no fixed upper bound — an address like
    somebody.with.a.long.name@a-long-domain.example is 24rem of text beside a
    brand and a Sign out button. It was capped at 14rem with an ellipsis, which
    is 224px, and on a 390px phone the header could not afford it: brand plus
    that cap plus Sign out is 372px before any padding. Below 48rem it is not
    shown at all, and nothing is lost — the account name is what the Account
    page opens with, and Account is one tap away in the bar.
*/
.nav-auth[b-jy3wd67w3v] {
    display: flex;
    align-items: center;
    gap: var(--bk-space-1);
    /* `auto` on the inline start, so the corner sits against the far edge with
       the brand at the near one. It used to be `margin-left` and it used to be
       INSIDE the nav being pushed away from the links; now the links are a
       sibling that leaves the flow entirely on a phone, and this pushes against
       the header itself. Logical per §9.0. */
    margin-inline-start: auto;
    min-inline-size: 0;
}
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
.components-reconnect-first-attempt-visible[b-75vo9hbe2f],
.components-reconnect-repeated-attempt-visible[b-75vo9hbe2f],
.components-reconnect-failed-visible[b-75vo9hbe2f],
.components-pause-visible[b-75vo9hbe2f],
.components-resume-failed-visible[b-75vo9hbe2f],
.components-rejoining-animation[b-75vo9hbe2f] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-75vo9hbe2f],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-75vo9hbe2f],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-75vo9hbe2f],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-75vo9hbe2f],
#components-reconnect-modal.components-reconnect-retrying[b-75vo9hbe2f],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-75vo9hbe2f],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-75vo9hbe2f],
#components-reconnect-modal.components-reconnect-failed[b-75vo9hbe2f],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-75vo9hbe2f] {
    display: block;
}


/* THE BANNER A READER SEES WHEN THE NETWORK IS WORST, WHICH IS WHEN THE PHONE
   IS IN SOMEBODY'S HAND (DESIGN-PLAN §2.5 finding 5).

   This box was 20rem + 2rem of padding on each side + a 1px border = 386px
   under content-box arithmetic, measured 2026-08-27. It fitted a 390px phone
   with 2px to spare and overflowed a 360px one by 26px — the modal that
   appears precisely when a reader cannot fix anything, running off the side of
   the screen. Nothing in this file changed to fix it: the universal
   `box-sizing: border-box` in app.css's base layer did, and 20rem is now 320px
   including its padding on every phone made. It is recorded here because the
   next person to widen this dialog needs to know which arithmetic they are
   working in.

   `20dvh`, not `20vh`, per §5.2 rule 2: `vh` is the tallest the viewport could
   be rather than the height it has, so a 20vh top margin under a URL bar
   pushes the dialog further down than intended on exactly the screen where
   there is least room. A modal <dialog> is in the top layer and positioned
   against the viewport by the user agent, which is what entitles it to name a
   viewport unit at all (§5.2 rule 1's top-layer carve-out); the margin and the
   `auto` centring are logical per §9.0. */
#components-reconnect-modal[b-75vo9hbe2f] {
    background-color: var(--bk-surface);
    color: var(--bk-text);
    inline-size: 20rem;
    margin-block: 20dvh;
    margin-inline: auto;
    padding: 2rem;
    border: var(--bk-edge-width) solid var(--bk-edge);
    border-radius: var(--bk-radius-lg);
    box-shadow: var(--bk-shadow-2);
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity-b-75vo9hbe2f 0.5s both;
    &[open]

{
    animation: components-reconnect-modal-slideUp-b-75vo9hbe2f 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity-b-75vo9hbe2f 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

}

#components-reconnect-modal[b-75vo9hbe2f]::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity-b-75vo9hbe2f 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-75vo9hbe2f {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-75vo9hbe2f {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-75vo9hbe2f {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container[b-75vo9hbe2f] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p[b-75vo9hbe2f] {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button[b-75vo9hbe2f] {
    border: 0;
    background-color: var(--bk-accent);
    color: var(--bk-accent-contrast);
    padding: 4px 24px;
    border-radius: var(--bk-radius-sm);
}

    #components-reconnect-modal button:hover[b-75vo9hbe2f] {
        background-color: var(--bk-muted);
    }

.components-rejoining-animation[b-75vo9hbe2f] {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div[b-75vo9hbe2f] {
        position: absolute;
        border: 3px solid var(--bk-accent);
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation-b-75vo9hbe2f 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2)[b-75vo9hbe2f] {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation-b-75vo9hbe2f {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0px;
        left: 0px;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}
/* /Components/Pages/Home.razor.rz.scp.css */
/*
    ══════════════════════════════════════════════════════════════════════════
    THE FRONT DOOR (DESIGN-PLAN §6, phase 4)

    Scoped, and that is the point: this is the only page in the product shaped
    like a landing page, so none of it belongs in app.css. Nothing here declares
    a new token — every colour, space, radius, duration and type step is a
    `--bk-*` read from the token block, so the page follows light, dark and
    sepia without knowing they exist.

    ── THE THREE RULES THIS FILE IS WRITTEN UNDER ────────────────────────────

    1. MOBILE-FIRST. Every unqualified rule below is the PHONE. Width is added
       by `@container`, never subtracted by `max-width`.

    2. CONTAINER QUERIES, NOT MEDIA QUERIES (§5.5). The question this page keeps
       asking is "how wide is my column", and above 90rem of viewport that stops
       being the same question as "how wide is the screen" — `.bk-workspace`
       caps the column at 90rem, so on a 2560px monitor a viewport query would
       report 160rem for a column that is 90. The container is declared on the
       page root and named, so a nested container added later cannot silently
       capture these queries.

    3. NO `var(--bk-safe-*)`, NO `env()`, NO VIEWPORT UNITS. §5.2 rule 5 and
       rule 1 confine all three to the layouts, and SafeAreaTests enforces the
       first by reading this directory. The page mode's padding already carries
       the horizontal insets and MainLayout's footer already clears the bottom
       bar, so there is nothing left here to reserve.

    ── WHY THE BREAKPOINTS ARE THE APP'S TWO AND NOT NEW ONES ────────────────

    48rem and 64rem, the two §5.3 names. The handoff figure and the comparison
    table both want to change at the same width the nav does, and inventing a
    third number for a landing page would mean the product reflows twice on the
    way from a phone to a laptop for no reason a reader could see.
*/

.home[b-9p51uu9pa6] {
    /* Named, per rule 2 above. */
    container: home / inline-size;

    display: flex;
    flex-direction: column;
    /* The band gap IS the page rhythm: bands do not carry their own outer
       margins, so no two adjacent margins can collapse into an unintended
       gap and every seam on the page is this one number. */
    gap: var(--bk-space-6);
    padding-block-end: var(--bk-space-6);
}

@container home (min-width: 48rem) {
    .home[b-9p51uu9pa6] {
        gap: var(--bk-space-8);
    }
}

/* ── TYPE ──────────────────────────────────────────────────────────────────

   Literata (--bk-font-reading) for every heading on this page, and the UI face
   for everything else. §4.1 wants the product to feel like paper; the landing
   page is where a stranger forms that impression, and the headings are the
   only place a serif can carry it without costing legibility at small sizes.

   The h1 is BELOW the token scale's --bk-text-2xl on a phone (2.441rem = 39px)
   because 39px of Literata at 390px wide breaks "device." onto its own line
   under a two-word orphan. 2.1rem fits the sentence in three lines; the
   container query hands it the full step back as soon as there is room. */
.home-h1[b-9p51uu9pa6] {
    margin: 0;
    font-family: var(--bk-font-reading);
    font-size: 2.1rem;
    font-weight: 700;
    line-height: var(--bk-leading-tight);
    letter-spacing: -0.015em;
    text-wrap: balance;
}

.home-h2[b-9p51uu9pa6] {
    margin: 0;
    font-family: var(--bk-font-reading);
    font-size: var(--bk-text-lg);
    font-weight: 700;
    line-height: var(--bk-leading-tight);
    text-wrap: balance;
}

.home-lede[b-9p51uu9pa6] {
    margin: 0;
    font-size: var(--bk-text-base);
    line-height: var(--bk-leading-reading);
    color: var(--bk-muted);
    /* The lede is the one paragraph on the page a visitor certainly reads, so
       it gets a measure of its own rather than the workspace's full width —
       §7's 60-70 characters, applied where it matters most. */
    max-inline-size: 34rem;
    text-wrap: pretty;
}

.home-lede-sm[b-9p51uu9pa6] {
    font-size: var(--bk-text-sm);
}

/* Small caps-ish label above a heading. Letter-spaced because uppercase at
   0.8rem without tracking sets tight and reads as an abbreviation. */
.home-eyebrow[b-9p51uu9pa6] {
    font-size: var(--bk-text-xs);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--bk-muted);
}

.home-quiet[b-9p51uu9pa6] {
    color: var(--bk-muted);
}

@container home (min-width: 48rem) {
    .home-h1[b-9p51uu9pa6] {
        font-size: var(--bk-text-2xl);
        letter-spacing: -0.02em;
    }

    .home-h2[b-9p51uu9pa6] {
        font-size: var(--bk-text-xl);
    }

    .home-lede[b-9p51uu9pa6] {
        font-size: var(--bk-text-md);
    }

    .home-lede-sm[b-9p51uu9pa6] {
        font-size: var(--bk-text-base);
    }
}

/* ── HERO ─────────────────────────────────────────────────────────────────

   Left-aligned on a phone and left-aligned on a desktop. The wide mockup
   centres it; centring was dropped on measurement rather than on taste, because
   the h1 and the lede have different natural measures (a balanced three-word
   line over a 34rem paragraph), and centred, the two ragged edges make a shape
   that pulls the eye away from the button underneath them both. */
.home-hero[b-9p51uu9pa6] {
    display: flex;
    flex-direction: column;
    gap: var(--bk-space-3);
    padding-block-start: var(--bk-space-4);
}

.home-cta-row[b-9p51uu9pa6] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--bk-space-3);
    margin-block-start: var(--bk-space-2);
}

/* The primitive carries the 44px minimum, the colour and the focus ring
   (§4.5); this adds only what a landing page's primary action needs on top —
   it is the one control on the screen, so it is allowed the larger step. */
.home-cta[b-9p51uu9pa6] {
    font-size: var(--bk-text-base);
    font-weight: 600;
    padding-inline: var(--bk-space-5);
}

.home-cta-aside[b-9p51uu9pa6] {
    font-size: var(--bk-text-sm);
    color: var(--bk-muted);
}

/* An anchor in that slot is a real target, not a sentence fragment: it is a
   row of its own beside a button, so WCAG 2.5.8's inline-link exemption does
   not apply to it (the same argument MainLayout makes for the footer links). */
a.home-cta-aside[b-9p51uu9pa6] {
    display: inline-flex;
    align-items: center;
    min-block-size: 2.75rem;
    color: var(--bk-accent);
}

/* ── THE MOTIF (#158) ───────────────────────────────────────────────────────

   The shelf drawing under the CTA row. Sized in PX, deliberately against this
   file's own rem habit: the canvas's rule 01 renders the 32-unit module at an
   integer multiple — 96px (3x) on the phone, 192px (6x) once the container has
   room — and a rem size would break the integer under a reader's text zoom.
   The drawing is decoration beside the pitch, not text, so it does not scale
   with it. ::deep reaches the child component's <svg>; the query is this
   page's own named container, per rule 2 at the top of this file. */
.home-hero[b-9p51uu9pa6]  .pixel-art {
    inline-size: 96px;
    block-size: 96px;
    margin-block-start: var(--bk-space-2);
}

@container home (min-width: 48rem) {
    .home-hero[b-9p51uu9pa6]  .pixel-art {
        inline-size: 192px;
        block-size: 192px;
        margin-block-start: var(--bk-space-4);
    }
}

/* ── BANDS ────────────────────────────────────────────────────────────────

   The mockup's full-bleed stripes, as inset panels — Home.razor explains why
   at length (the page mode's gutter is carrying the landscape notch and this
   file is not entitled to re-declare it). A radius and a border say the same
   thing the stripe did: this is a section, and it ends here. */
.home-band[b-9p51uu9pa6] {
    display: flex;
    flex-direction: column;
    gap: var(--bk-space-4);
}

.home-band-tinted[b-9p51uu9pa6] {
    padding: var(--bk-space-5) var(--bk-space-4);
    border: var(--bk-edge-width) solid var(--bk-edge);
    border-radius: var(--bk-radius-lg);
    background: var(--bk-surface-alt);
}

@container home (min-width: 48rem) {
    .home-band-tinted[b-9p51uu9pa6] {
        padding: var(--bk-space-6);
    }
}

.home-caption[b-9p51uu9pa6] {
    margin: 0;
    font-size: var(--bk-text-sm);
    line-height: var(--bk-leading-reading);
    color: var(--bk-muted);
    max-inline-size: 34rem;
}

.home-note[b-9p51uu9pa6] {
    margin: 0;
    border-inline-start: 3px solid var(--bk-border);
    padding: var(--bk-space-3) var(--bk-space-4);
    font-size: var(--bk-text-sm);
    line-height: var(--bk-leading-reading);
    color: var(--bk-muted);
}

/* ── THE HANDOFF FIGURE ───────────────────────────────────────────────────

   PHONE: a vertical stack. Each step is a row — the page plate on the left at a
   fixed width, the caption beside it — and the connectors are a vertical rule
   in the plate's column with a line of text beside it, so the whole figure
   reads down one axis under a thumb.

   ABOVE 48rem it becomes the horizontal three-panel figure the wide mockup
   draws, and the connectors rotate: the same element, one grid, no duplicated
   markup. The rule element is a plain box with a border rather than the
   mockup's inline SVG, because a 1px line and a dot do not need a vector and an
   SVG cannot pick up `currentColor` transitions across three themes for free. */
.home-handoff[b-9p51uu9pa6] {
    display: grid;
    gap: 0;
}

.home-step[b-9p51uu9pa6] {
    display: flex;
    gap: var(--bk-space-3);
    align-items: stretch;
}

.home-step-body[b-9p51uu9pa6] {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--bk-space-1);
    /* The horizontal half of the flexbox trap: without this the caption's
       longest word sets the row's width and the figure pushes the page
       sideways, which is exactly what HorizontalOverflowTests measures. */
    min-inline-size: 0;
}

.home-step-title[b-9p51uu9pa6] {
    font-family: var(--bk-font-reading);
    font-size: var(--bk-text-base);
    font-weight: 600;
    line-height: var(--bk-leading-tight);
}

.home-step-note[b-9p51uu9pa6] {
    font-size: var(--bk-text-sm);
    line-height: var(--bk-leading-normal);
    color: var(--bk-muted);
    text-wrap: pretty;
}

/* THE PLATE IS A PICTURE OF A PAGE, and the type size is what makes it read as
   one rather than as body copy nobody can see. It is `aria-hidden` in the
   markup for the same reason, and the caption beside it carries the claim in
   words — so this is decoration that argues, not text that has been shrunk.
   The size is in `rem`, so a reader who scales text still scales this. */
.home-page[b-9p51uu9pa6] {
    flex: 0 0 auto;
    inline-size: 7.25rem;
    padding: var(--bk-space-2) 0.55rem;
    border: var(--bk-edge-width) solid var(--bk-edge);
    border-radius: var(--bk-radius-lg);
    background: var(--bk-surface-raised);
    font-family: var(--bk-font-reading);
    font-size: 0.55rem;
    line-height: 1.7;
    color: var(--bk-muted);
}

.home-page p[b-9p51uu9pa6] {
    margin: 0;
}

/* The marked phrase. `<mark>` is the honest element — a run highlighted for
   reference elsewhere in the document — but its user-agent colours are a
   yellow that belongs to no theme here, so both are restated. --bk-accent-subtle
   is the same tint the active nav destination wears, which is deliberate: on
   this page it means "this exact spot", and that is what it means there too.
   The box-shadow is the highlighter's overshoot; padding would move the text. */
.home-mark[b-9p51uu9pa6] {
    background: var(--bk-accent-subtle);
    box-shadow: 0 0 0 2px var(--bk-accent-subtle);
    color: var(--bk-text);
}

.home-page-kindle[b-9p51uu9pa6] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--bk-space-2);
    background: var(--bk-surface-alt);
    font-family: var(--bk-font-ui);
    font-size: var(--bk-text-xs);
    line-height: var(--bk-leading-normal);
    text-align: center;
}

.home-page-kindle svg[b-9p51uu9pa6] {
    inline-size: 1.6rem;
    block-size: 1.6rem;
    color: var(--bk-accent);
}

/* The connector. On a phone it is a vertical rule sitting in the plate's
   column, so the figure has one spine; the note is set in the accent because it
   is the figure speaking rather than a caption. */
.home-link[b-9p51uu9pa6] {
    display: flex;
    align-items: center;
    gap: var(--bk-space-3);
    padding-block: var(--bk-space-2);
}

.home-link-rule[b-9p51uu9pa6] {
    flex: 0 0 auto;
    inline-size: 7.25rem;
    block-size: 2.5rem;
    /* A centred hairline drawn with a gradient rather than a child element:
       one box, one declaration, and it rotates with the container query below
       by swapping which axis the gradient runs along. */
    background:
        linear-gradient(var(--bk-accent), var(--bk-accent))
        center / 1.5px 100% no-repeat;
}

.home-link-note[b-9p51uu9pa6] {
    font-size: var(--bk-text-sm);
    color: var(--bk-accent);
    text-wrap: pretty;
}

@container home (min-width: 48rem) {
    /* Three panels and two connectors, on one row. `align-items: start` so a
       longer caption in one column does not stretch the others' plates. */
    .home-handoff[b-9p51uu9pa6] {
        grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto minmax(0, 1fr);
        align-items: start;
        gap: 0 var(--bk-space-4);
    }

    .home-step[b-9p51uu9pa6] {
        flex-direction: column;
        gap: var(--bk-space-4);
    }

    .home-page[b-9p51uu9pa6] {
        inline-size: auto;
        min-block-size: 11rem;
        padding: var(--bk-space-4);
        font-size: 0.72rem;
    }

    .home-page-kindle[b-9p51uu9pa6] {
        justify-content: center;
        font-size: var(--bk-text-sm);
    }

    .home-page-kindle svg[b-9p51uu9pa6] {
        inline-size: 2.25rem;
        block-size: 2.25rem;
    }

    /* The connector turns with the figure: same element, the gradient now runs
       across instead of down, and the note goes under the rule so it does not
       compete with the panel captions for the row's width. */
    .home-link[b-9p51uu9pa6] {
        flex-direction: column;
        gap: var(--bk-space-2);
        /* 8.5rem: measured at 1280, "And when you want it off a screen…" set to
           four cramped lines in 7rem and two in this. The connector is a track
           in the grid, so widening it costs the three panels a few pixels each
           and buys the figure's own voice a readable line. */
        inline-size: 8.5rem;
        padding-block: 0;
        margin-block-start: 5rem;
        text-align: center;
    }

    .home-link-rule[b-9p51uu9pa6] {
        inline-size: 100%;
        block-size: 1.5px;
        background:
            linear-gradient(var(--bk-accent), var(--bk-accent))
            center / 100% 1.5px no-repeat;
    }

    .home-link-note[b-9p51uu9pa6] {
        font-size: var(--bk-text-xs);
    }

    .home-step-title[b-9p51uu9pa6] {
        font-size: var(--bk-text-md);
    }

    .home-step-note[b-9p51uu9pa6] {
        font-size: var(--bk-text-base);
        line-height: var(--bk-leading-reading);
    }
}

/* ── THE CARD ─────────────────────────────────────────────────────────────

   ONE RULE SET, TWO CALLERS: the signed-in reader's real "Continue reading"
   card, and the illustration of it on the landing page. Home.razor explains why
   they share markup — a picture of the product drawn in different CSS from the
   product is a picture that drifts. */
.home-card[b-9p51uu9pa6] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--bk-space-3);
    padding: var(--bk-space-3);
    border: var(--bk-edge-width) solid var(--bk-edge);
    border-radius: var(--bk-radius-lg);
    background: var(--bk-surface-raised);
    box-shadow: var(--bk-shadow-1);
}

.home-card-body[b-9p51uu9pa6] {
    flex: 1 1 10rem;
    min-inline-size: 0;
    display: flex;
    flex-direction: column;
    gap: var(--bk-space-1);
}

.home-card-title[b-9p51uu9pa6] {
    font-family: var(--bk-font-reading);
    font-size: var(--bk-text-md);
    font-weight: 600;
    line-height: var(--bk-leading-tight);
}

.home-card-meta[b-9p51uu9pa6] {
    font-size: var(--bk-text-sm);
    color: var(--bk-muted);
}

/* Full width on a phone, so Resume is a full-width target under the thumb
   rather than a button squeezed beside a title; `flex: 0 0 auto` at the width
   where the row has room for it. */
.home-card-action[b-9p51uu9pa6] {
    flex: 1 0 100%;
    font-weight: 600;
}

.home-progress[b-9p51uu9pa6] {
    margin-block-start: var(--bk-space-1);
    block-size: 4px;
    border-radius: var(--bk-radius-sm);
    background: var(--bk-surface-alt);
    overflow: hidden;
}

/* The fill is the ACCENT, not brass. #159 tried --bk-highlight here first and
   it failed its own contrast budget: 2.1-2.5:1 against the track in the light
   and sepia themes, where the accent measures 5.0-7.8:1. This bar has its
   percentage in text above it, but BookCard's twin meter has no number beside
   it — there the bar IS the carrier and owes 1.4.11's 3:1 — and the two
   meters stay one colour. The pixel canvas draws progress in oxblood for the
   same reason, and keeps brass for the spine bands. */
.home-progress-fill[b-9p51uu9pa6] {
    block-size: 100%;
    background: var(--bk-accent);
}

@container home (min-width: 34rem) {
    .home-card[b-9p51uu9pa6] {
        flex-wrap: nowrap;
        padding: var(--bk-space-4);
        gap: var(--bk-space-4);
    }

    .home-card-action[b-9p51uu9pa6] {
        flex: 0 0 auto;
    }
}

/* ── THE BOOK PLATE ───────────────────────────────────────────────────────

   The typeset fallback, which is the library's genuinely good idea reused: a
   book with no cover is still recognisably a book, set in the reading face with
   an oxblood spine. When a cover image exists it is laid over the top rather
   than swapped in, so a cover that 404s or is still being derived degrades to
   the plate instead of to a broken-image icon. */
.home-plate[b-9p51uu9pa6] {
    position: relative;
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--bk-space-1);
    inline-size: 3.875rem;
    aspect-ratio: 2 / 3;
    padding: var(--bk-space-2) 0.4rem;
    border: var(--bk-edge-width) solid var(--bk-edge);
    border-inline-start: 3px solid var(--bk-accent);
    border-radius: var(--bk-radius-sm);
    background: var(--bk-surface-alt);
    overflow: hidden;
}

/* 6rem AT EVERY WIDTH, and the number was measured rather than chosen. The
   plate has to hold an ordinary one-word title without breaking it: at 5rem the
   content box is 62px and "Middlemarch" sets to 64, which broke to
   "Middlemarc / h" and read as a rendering bug rather than as a cover. 6rem
   gives 79px of content, and the card still has 218px for its text on a 390px
   phone. A title longer than that is clamped and ellipsised, which is the
   honest treatment; a title one character over is not. */
.home-plate-lg[b-9p51uu9pa6] {
    inline-size: 6rem;
}

.home-plate-title[b-9p51uu9pa6] {
    font-family: var(--bk-font-reading);
    font-size: 0.62rem;
    font-weight: 600;
    line-height: var(--bk-leading-tight);
    color: var(--bk-text);
    /* Three lines and then an ellipsis: a long title must not push the author
       out of a 3:2 plate, and clamping is the only thing that holds the plate's
       aspect ratio against arbitrary user data.

       AND THE CLAMP ALONE DOES NOT HELP A SINGLE LONG WORD: measured at 1280,
       "Middlemarch" rendered as "Middlemarc" in a 6rem plate, because there was
       no break opportunity in it to take. `hyphens: auto` rather than
       `overflow-wrap: anywhere`, which was tried first and broke it as
       "Middlema / rch" — a hyphenation dictionary breaks at syllables and shows
       the hyphen, which is what a book spine does. It needs the document
       language, and App.razor's <html lang="en"> supplies it; `break-word` is
       the floor under it for a title with no syllables to break, which is
       usually a URL or a scanning artefact. */
    overflow-wrap: break-word;
    hyphens: auto;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
}

.home-plate-author[b-9p51uu9pa6] {
    font-size: 0.5rem;
    line-height: var(--bk-leading-tight);
    color: var(--bk-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.home-plate-image[b-9p51uu9pa6] {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
}

@container home (min-width: 48rem) {
    .home-plate-lg .home-plate-title[b-9p51uu9pa6] {
        /* 0.7rem, not 0.8: at 0.8rem "Middlemarch" sets to 82px inside the
           79px content box the 6rem plate above gives, and broke. The plate
           does not get wider again to fix it — the type does, because past
           6rem the plate starts eating the card's text column on a phone. */
        font-size: 0.7rem;
    }

    .home-plate-lg .home-plate-author[b-9p51uu9pa6] {
        font-size: 0.65rem;
    }
}

/* ── SIGNED IN ────────────────────────────────────────────────────────────

   The heading is smaller than the landing page's h1 and that is deliberate:
   "Continue reading" is a label over the one thing on the screen, not a pitch.
   §6's own words — a reading app's home is the book you are in the middle of —
   and the book should be the largest thing on it. */
.home-continue[b-9p51uu9pa6] {
    display: flex;
    flex-direction: column;
    gap: var(--bk-space-4);
    padding-block-start: var(--bk-space-4);
}

.home-continue-heading[b-9p51uu9pa6] {
    margin: 0;
    font-family: var(--bk-font-reading);
    font-size: var(--bk-text-md);
    font-weight: 700;
    line-height: var(--bk-leading-tight);
}

.home-recent-heading[b-9p51uu9pa6] {
    margin-block-start: var(--bk-space-3);
    font-size: var(--bk-text-md);
}

.home-recent[b-9p51uu9pa6] {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--bk-space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Four on a phone even when the strip loaded more: the page renders up to
   eight so the wide layout has covers to fill with, and the phone keeps the
   row it was proportioned for. Hidden rather than not rendered, because this
   page is static SSR and cannot know the container's width on the server —
   the container query below is what reveals the rest. */
.home-recent li:nth-child(n+5)[b-9p51uu9pa6] {
    display: none;
}

/* The plate fills its grid cell here rather than keeping the fixed width it has
   inside a card — same component, sized by its container, which is the whole
   argument of §5.5. */
.home-recent .home-plate[b-9p51uu9pa6] {
    inline-size: 100%;
    text-decoration: none;
}

.home-recent .home-plate:focus-visible[b-9p51uu9pa6] {
    outline: 2px solid var(--bk-focus);
    outline-offset: 2px;
}

.home-recent .home-plate:hover[b-9p51uu9pa6] {
    border-color: var(--bk-accent);
}

@container home (min-width: 48rem) {
    .home-recent[b-9p51uu9pa6] {
        /* auto-fill off a 7.5rem floor — the plate that shipped at this
           width, not .home-plate-lg's 6rem, which was measured as the
           smallest that holds a one-word title and reads cramped under cover
           art. NOT a fixed count. The repeat(4, …) this replaces was the
           phone's proportion worn at every width, and at 1280px it left the
           strip a third of the container with empty paper under it (#156); a
           6rem floor made the same mistake from the other side — eleven
           tracks in the ~76rem container, eight covers at ~110px and three
           empty. At 7.5rem the container holds nine tracks, so the eight
           covers render at ~135px and fill the width the strip was meant to
           fill. auto-fill rather than auto-fit so a short library keeps the
           same plate size instead of stretching three covers across a laptop;
           the empty tracks absorb the leftover width. */
        grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr));
        gap: var(--bk-space-4);
    }

    .home-recent li:nth-child(n+5)[b-9p51uu9pa6] {
        display: list-item;
    }
}

/* ── WHAT HAPPENS TO A FILE ───────────────────────────────────────────────

   A real <ol>, so the numbers are the list's and not three hand-set glyphs a
   screen reader reads as body text. The marker is styled through ::marker,
   which is the one property set on it that all three engines honour. */
.home-steps[b-9p51uu9pa6] {
    display: flex;
    flex-direction: column;
    gap: 0;
    margin: 0;
    padding: 0;
    list-style: decimal;
}

.home-steps li[b-9p51uu9pa6] {
    margin-inline-start: var(--bk-space-5);
    padding-block: var(--bk-space-3);
    padding-inline-start: var(--bk-space-1);
    border-block-start: 1px solid var(--bk-border);
    font-size: var(--bk-text-sm);
    line-height: var(--bk-leading-reading);
    text-wrap: pretty;
}

.home-steps li:last-child[b-9p51uu9pa6] {
    border-block-end: 1px solid var(--bk-border);
}

.home-steps li[b-9p51uu9pa6]::marker {
    font-family: var(--bk-font-reading);
    font-size: var(--bk-text-base);
    color: var(--bk-accent);
}

@container home (min-width: 48rem) {
    .home-steps[b-9p51uu9pa6] {
        flex-direction: row;
        gap: var(--bk-space-6);
    }

    .home-steps li[b-9p51uu9pa6] {
        flex: 1 1 0;
        padding-block: var(--bk-space-4) 0;
        font-size: var(--bk-text-base);
    }

    .home-steps li:last-child[b-9p51uu9pa6] {
        border-block-end: 0;
    }
}

/* Capability pills. A list, because that is what they are; the bullets are
   removed rather than the element being a row of spans, so the count reaches a
   screen reader ("list, 4 items") without any ARIA. */
.home-pills[b-9p51uu9pa6] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bk-space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.home-pills li[b-9p51uu9pa6] {
    padding: var(--bk-space-2) var(--bk-space-3);
    border: var(--bk-edge-width) solid var(--bk-edge);
    border-radius: var(--bk-radius-pill);
    background: var(--bk-surface);
    font-size: var(--bk-text-sm);
    color: var(--bk-text);
}

/* ── THE COMPARISON TABLE ─────────────────────────────────────────────────

   `table-layout: fixed` with percentage columns, and the wrapper scrolls if it
   ever has to. Fixed layout is what makes the phone case safe: an intrinsic
   table sizes itself from its longest cell, and "The next upload waits until
   you make room or move up" is a cell — that sentence alone would take the
   table past 360px and fail HorizontalOverflowTests. */
.home-table-wrap[b-9p51uu9pa6] {
    overflow-x: auto;
    border: var(--bk-edge-width) solid var(--bk-edge);
    border-radius: var(--bk-radius-lg);
    background: var(--bk-surface-raised);
}

.home-table[b-9p51uu9pa6] {
    inline-size: 100%;
    table-layout: fixed;
    border-collapse: collapse;
    font-size: var(--bk-text-sm);
}

/* The h2 above already names the section; the caption exists for a screen
   reader arriving at the table out of context, which is what a table caption
   is for, so it is hidden from sight and not from the accessibility tree.
   `clip-path` rather than `display: none` for exactly that reason. */
.home-table-caption[b-9p51uu9pa6] {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.home-table thead th[b-9p51uu9pa6],
.home-table thead td[b-9p51uu9pa6] {
    padding: var(--bk-space-3);
    background: var(--bk-surface-alt);
    border-block-end: 1px solid var(--bk-border);
    font-family: var(--bk-font-reading);
    font-size: var(--bk-text-base);
    font-weight: 700;
    text-align: start;
}

.home-table tbody th[b-9p51uu9pa6] {
    /* 34% on a phone: enough for "Reading, search, Kindle" to wrap to two
       lines rather than three, without starving the two value columns. */
    inline-size: 34%;
    font-weight: 400;
    font-size: var(--bk-text-xs);
    color: var(--bk-muted);
    text-align: start;
}

.home-table th[b-9p51uu9pa6],
.home-table td[b-9p51uu9pa6] {
    padding: var(--bk-space-3);
    border-block-start: 1px solid var(--bk-border);
    vertical-align: top;
    line-height: var(--bk-leading-normal);
    text-wrap: pretty;
}

.home-table thead th[b-9p51uu9pa6],
.home-table thead td[b-9p51uu9pa6] {
    border-block-start: 0;
}

.home-table-pro[b-9p51uu9pa6] {
    color: var(--bk-accent);
}

/* The row where the two plans are the same, tinted so the eye finds it: it is
   the section's thesis ("both plans read the same") stated as data. The tint is
   --bk-accent-subtle, and the row also SAYS "Everything" twice, because §4.0's
   rule holds here as everywhere — colour never carries a fact alone. */
.home-table-same[b-9p51uu9pa6] {
    background: var(--bk-accent-subtle);
}

@container home (min-width: 48rem) {
    .home-table[b-9p51uu9pa6] {
        font-size: var(--bk-text-base);
    }

    .home-table tbody th[b-9p51uu9pa6] {
        inline-size: 26%;
        font-size: var(--bk-text-sm);
    }

    .home-table th[b-9p51uu9pa6],
    .home-table td[b-9p51uu9pa6] {
        padding: var(--bk-space-4);
    }

    .home-table thead th[b-9p51uu9pa6],
    .home-table thead td[b-9p51uu9pa6] {
        padding: var(--bk-space-4);
        font-size: var(--bk-text-md);
    }
}
