/* Reader: one column of pages, or dual-page spreads (body.dual).
   Page width (--page-w) is set by reader.js from the zoom and fit mode. */
.pages_container {
    padding: 48px 70px 80px 50px; /* room for the contents bar and toolbar */
    overflow-x: clip; /* a spread slid aside for a thread must not widen the page */
}

.chapter-block {
    position: relative;
}

/* =========================
   Single page: [spacer][page][comment margin]
   The spacer mirrors the margin so the page sits centred at any zoom.
   A zoomed page leaves the margin room for bubbles only; opening a
   thread there slides the row left (--shift), as in a spread.
   ========================= */

.page-row {
    position: relative;
    display: flex;
    justify-content: center;
    align-items: stretch;
    margin-bottom: var(--gap-between-pages);
    transform: translateX(var(--shift, 0px));
    transition: transform 460ms var(--ease-out);
}

.row-spacer {
    flex: 1 1 0;
    min-width: 0;
    margin-right: var(--gap);
}

.page-paper {
    position: relative;
    flex: none;
    width: var(--page-w);
    aspect-ratio: var(--ar);
    background: #fff;
    user-select: none;
    -webkit-user-select: none;
}

.page-paper img {
    display: block;
    width: 100%;
    height: 100%;
    -webkit-touch-callout: none;
    -webkit-user-drag: none;
}

.comment-margin {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    margin-left: var(--gap);
}

/* A row or spread with an open thread rises above its neighbours,
   so a long thread can run past the page's bottom edge */
.page-row.has-open,
.page-spread.has-open {
    z-index: 20;
}

/* =========================
   Dual page: [margin][left page][right page][margin]
   Paired as printed: even pages left, odd right. Comments live in the
   outer margins; opening one slides the spread aside (--shift).
   ========================= */

.page-spread {
    --gap: 10px;
    --thread-w: 300px;
    position: relative;
    display: flex;
    justify-content: center;
    align-items: stretch;
    margin-bottom: var(--gap-between-pages);
    transform: translateX(var(--shift, 0px));
    transition: transform 460ms var(--ease-out);
}

body:not(.dual) .page-spread,
body.dual .page-row {
    display: none;
}

.page-slot {
    flex: none;
    width: var(--page-w);
}

.slot-l {
    margin-right: 1px;
}

.page-spread .comment-margin {
    flex: 0 0 44px;
    margin: 0;
}

.page-spread .margin-l {
    margin-right: var(--gap);
}

.page-spread .margin-r {
    margin-left: var(--gap);
}

/* Lifted above the others while gliding between layouts */
.page-paper.moving {
    z-index: 6;
}

/* =========================
   Line highlight: ties a comment to its line
   --y is the line's position on the page (0–1). Only the line is marked;
   a comment's x is stored but not drawn.
   ========================= */

.page-anchor {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
}

.anchor-band,
.anchor-bridge {
    position: absolute;
    top: calc(var(--y, 0) * 100%);
    height: var(--line-glow);
    margin-top: calc(var(--line-glow) / -2);
    opacity: 0;
    transition: opacity 180ms;
}

/* Soft band across the whole line, like a highlighter (multiply keeps the text dark) */
.anchor-band {
    left: 0;
    right: 0;
    mix-blend-mode: multiply;
    transform-origin: right center;
}

/* Crosses the gap between the page and the bubble */
.anchor-bridge {
    left: 100%;
    width: var(--gap);
}

/* Left pages of a spread: the bubble sits in the outer (left) margin */
.page-paper.side-l .anchor-band {
    transform-origin: left center;
}

.page-paper.side-l .anchor-bridge {
    left: auto;
    right: 100%;
}

/* is-trace: the line under the pointer, where a click would comment.
   It moves with the pointer at once and fades out once the pointer rests. */
.page-anchor.is-trace .anchor-band { opacity: 0.22; transition: opacity 80ms; }
.page-anchor.is-trace.is-idle .anchor-band { opacity: 0; transition: opacity 220ms var(--ease-out); }

/* is-preview: a hovered bubble, or the pointer on its line */
.page-anchor.is-preview .anchor-band { opacity: 0.3; }
.page-anchor.is-preview .anchor-bridge { opacity: 0.45; }

/* is-on: an open thread or comment form */
.page-anchor.is-on .anchor-band { opacity: 0.42; }
.page-anchor.is-on .anchor-bridge { opacity: 0.8; }

/* is-draw: the glow leaves the bubble and sweeps across the line */
.page-anchor.is-draw .anchor-bridge { animation: anchor-fade 200ms both; }
.page-anchor.is-draw .anchor-band { animation: anchor-draw 560ms 80ms var(--ease-out) both; }

@keyframes anchor-draw { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes anchor-fade { from { opacity: 0; } }

/* =========================
   Phones: full-width pages, comments as dots on the page edge
   ========================= */

@media (max-width: 760px) {
    .pages_container {
        padding: 24px 16px 96px;
    }

    .row-spacer,
    .page-row > .comment-margin {
        display: none;
    }

    .page-row {
        margin-bottom: 12px;
    }

    .anchor-bridge {
        display: none;
    }
}
