/* Chapter reader. */

/* OpenDyslexic is not on Google Fonts, so it is self-hosted (SIL OFL, see
 * fonts/OpenDyslexic-OFL.txt). Upstream build; covers Latin + full Cyrillic. */
@font-face {
    font-family: OpenDyslexic;
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/OpenDyslexic-Regular.woff2") format("woff2");
}

@font-face {
    font-family: OpenDyslexic;
    font-style: italic;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/OpenDyslexic-Italic.woff2") format("woff2");
}

@font-face {
    font-family: OpenDyslexic;
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("../fonts/OpenDyslexic-Bold.woff2") format("woff2");
}

@font-face {
    font-family: OpenDyslexic;
    font-style: italic;
    font-weight: 700;
    font-display: swap;
    src: url("../fonts/OpenDyslexic-Bold-Italic.woff2") format("woff2");
}

.reader-body { background: var(--bg); }

/* Settings-driven typography. Font/width maps + defaults live here so the reader
 * is fully styled for anonymous users too; base.html overrides the vars inline
 * from saved prefs, and reader.js updates them live from the settings panel. */
.reader {
    /* Arial and Georgia are system faces, so nothing is downloaded for them.
     * Literata and Charis SIL come from Google Fonts (see base.html);
     * OpenDyslexic is self-hosted below. Quoted so stylelint's
     * value-keyword-case can't lowercase them — webfont family names are
     * case-sensitive. */
    --font-arial: arial, "Helvetica Neue", helvetica, sans-serif;
    --font-georgia: georgia, "Times New Roman", serif;
    --font-literata: "Literata", georgia, serif;
    --font-charis: "Charis SIL", georgia, serif;
    --font-dyslexic: "OpenDyslexic", arial, system-ui, sans-serif;
    --width-narrow: 30rem;
    --width-medium: 38rem;
    --width-wide: 46rem;
    --reader-font-size: 18px;
    --reader-line-height: 1.85;
    --reader-font: var(--font-georgia);
    --reader-align: left;
    --reader-hyphens: auto;
    --reader-width: var(--width-medium);
}

.reader-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-top: 10px;
    padding-bottom: 10px;
    position: sticky;
    top: 0;
    background: var(--bg);
}

.reader-tools {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.reader-novel {
    font-size: 13px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-soft);
}

.reader-chapter-title {
    text-align: center;
    font-size: 22px;
    margin: 24px 0 6px;
}

.reader-stats {
    text-align: center;
    color: var(--ink-soft);
    font-size: 13px;
    margin: 0 0 24px;
}

.reader-prose {
    font-size: var(--reader-font-size);
    line-height: var(--reader-line-height);
    font-family: var(--reader-font);
    text-align: var(--reader-align);

    /* No autoprefixer in the pipeline; mobile WebKit (iOS Telegram) needs the
         prefix or the hyphenation toggle is a no-op. */
    /* stylelint-disable-next-line property-no-vendor-prefix */
    -webkit-hyphens: var(--reader-hyphens);
    hyphens: var(--reader-hyphens);
    max-width: var(--reader-width);
    margin: 0 auto;

    /* Deter casual copying of chapter text. Not a hard block (DevTools/view-source
         still work); -webkit-touch-callout suppresses the iOS long-press copy menu. */
    /* stylelint-disable-next-line property-no-vendor-prefix */
    -webkit-user-select: none;
    user-select: none;
    /* stylelint-disable-next-line property-no-vendor-prefix */
    -webkit-touch-callout: none;
}
.reader-prose p { margin: 0 0 1em; }

.reader-prose h1,
.reader-prose h2,
.reader-prose h3 {
    font-family: var(--reader-font);
    font-weight: 600;
    line-height: 1.25;
    margin: 1.2em 0 0.6em;
}
.reader-prose h1 { font-size: 1.5em; }
.reader-prose h2 { font-size: 1.3em; }
.reader-prose h3 { font-size: 1.1em; }

.reader-prose ul,
.reader-prose ol {
    margin: 0 0 1em;
    padding-left: 1.5em;
}
.reader-prose li { margin: 0 0 0.3em; }

/* Block alignment set in the editor. An unaligned block inherits --reader-align,
 * the reader's own preference; these classes override it. */
.reader-prose .align-left { text-align: left; }
.reader-prose .align-center { text-align: center; }
.reader-prose .align-right { text-align: right; }

/* Two admin-chosen footnote types. Inline blocks render in-flow; modal notes are
 * hidden and surfaced by reader.js when their [n] marker is tapped. */
.reader-prose aside.footnote-inline {
    display: block;
    border-left: 3px solid var(--olive);
    padding-left: 10px;
    color: var(--olive);
    font-style: italic;
    font-size: 15px;
    margin: 1em 0;
}
.reader-prose aside.footnote-modal { display: none; }

.reader-prose sup.fn {
    color: var(--accent);
    cursor: pointer;

    /* margin-left: -0.15em; */
    font-size: 0.7em;
}

/* Book-like horizontal paging (scroll_direction=horizontal). The whole flow
 * box paginates: title/stats fall on page 1, prose fragments across columns,
 * and reactions flow to the chapter's end. Height comes from --reader-prose-h
 * and column width from --reader-prose-w, both set by reader.js from the box's
 * actual layout (percentages/vw are unreliable: column-width:100% degenerates
 * to a single unbounded column, and 100vw overflows a centered/padded container
 * on desktop). overflow-y stays hidden so an over-tall column pages instead of
 * scrolling. */
.reader.reading-horizontal .reader-flow {
    position: relative;
    height: var(--reader-prose-h, 80vh);
    column-width: var(--reader-prose-w, 100vw);
    column-gap: 0;
    overflow: auto hidden;

    /* Paging is driven per-column by reader.js touch handlers; native mandatory
     * snap points sit only on flow-child starts, so a flung swipe would skip
     * several columns. Proximity keeps keyboard/desktop paging tidy without
     * fighting the JS scrollTo target. */
    scroll-snap-type: x proximity;
    scrollbar-width: none;
}
.reader.reading-horizontal .reader-flow::-webkit-scrollbar { display: none; }
.reader.reading-horizontal .reader-flow > * { scroll-snap-align: start; }

/* Inner prose fills the column here — its vertical measure/centering is off. */
.reader.reading-horizontal .reader-prose { max-width: none; }

/* In horizontal mode the header is a fixed overlay, so it can't push text clear
 * of Telegram's fullscreen controls — the flow box starts at y=0 and columns
 * run under them. Pad the box itself instead; box-sizing:border-box keeps
 * --reader-prose-h (set from its measured top offset) correct. */
.reader.is-fullscreen.reading-horizontal .reader-flow {
    padding-top: var(--tg-inset-top, 0);
}

.reader-foot {
    position: sticky;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 0;
    background: var(--bg);
    border-top: 1px solid var(--line);
    color: var(--accent);
}

.reader-nav-off {
    color: var(--ink-soft);
    opacity: 0.5;
}

.reader-pct {
    color: var(--olive);
    font-size: 14px;
}

/* Telegram fullscreen (Bot API 8.0): the Mini App covers the whole screen, so
 * the device notch and Telegram's floating close/menu controls now overlap our
 * header, and the home indicator overlaps the footer. reader.js mirrors
 * tg.safeAreaInset + tg.contentSafeAreaInset into these vars — the content
 * inset already accounts for the height of Telegram's own controls. */
.reader.is-fullscreen .reader-head {
    padding-top: calc(10px + var(--tg-inset-top, 0px));
}

.reader.is-fullscreen .reader-foot {
    padding-bottom: calc(12px + var(--tg-inset-bottom, 0px));
}

/* Immersive chrome: in horizontal mode the head and foot leave layout (so the
 * flow box owns the full height) and float as fixed overlays, toggled by a
 * center-third tap (reader.js sets .chrome-visible). Because they never resize
 * the flow box, toggling them triggers no reflow and the reader keeps their
 * page. */
.reader.reading-horizontal .reader-head,
.reader.reading-horizontal .reader-foot {
    position: fixed;
    left: 0;
    right: 0;
    z-index: 5;
    padding-inline: max(var(--gutter), calc((100% - var(--reader-width)) / 2));
    transition: transform 0.2s ease;
}

.reader.reading-horizontal .reader-head {
    top: 0;
    transform: translateY(-100%);
}

.reader.reading-horizontal .reader-foot {
    bottom: 0;
    transform: translateY(100%);
}

.reader.reading-horizontal.chrome-visible .reader-head,
.reader.reading-horizontal.chrome-visible .reader-foot {
    transform: none;
}

/* Quiet end-of-chapter marker that introduces the reactions. */
.chapter-end {
    text-align: center;
    color: var(--ink-soft);
    font-size: 13px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin: 32px 0 12px;
}

/* End-of-chapter reaction pool (docs/Reader Directions.html: «конец главы +
     реакции»). In both scroll modes reactions are ordinary flow content at the
     chapter's end; horizontal mode paginates them onto the last page for free.
     Pills tint on the user's own reactions; the icon inherits currentColor so it
     tints with them. */
.reactions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 9px;
    margin: 24px 0 8px;
}

/* Keep atomic blocks from splitting across a column boundary; keep the end
 * marker on the same page as the reactions it introduces. */
.reader.reading-horizontal .reader-chapter-title,
.reader.reading-horizontal .reader-stats,
.reader.reading-horizontal .reactions {
    break-inside: avoid;
}

.reader.reading-horizontal .chapter-end {
    break-inside: avoid;
    break-after: avoid;
}

.reaction {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 13px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface);
    color: var(--ink-soft);
    font: 600 12px/1 var(--font-arial);
    cursor: pointer;
}
.reaction:disabled { cursor: default; }

.reaction.is-active {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 16%, transparent);
    color: var(--ink);
}

/* The .webp is opaque black art on a transparent ground; only its alpha is
 * used, as a mask over currentColor, so the glyph inherits the pill's colour
 * in every theme and on the active state. */
.reaction-icon {
    width: 16px;
    height: 16px;
    flex: none;
    background-color: currentcolor;
    mask: var(--icon) center / contain no-repeat;
}
.reaction-count { color: var(--ink-soft); }
.reaction.is-active .reaction-count { color: var(--olive); }

/* ---------- desktop ----------
 * Deliberately almost nothing. The measure is already right: --reader-width is
 * driven by the reader's own setting (narrow/medium/wide), not the viewport, so
 * a wide window must not widen the text. Only the chrome gets breathing room.
 *
 * .reader-prose's box is off limits — reader.js measures it for progress and
 * horizontal paging (see .reading-horizontal above).
 */

@media (width >= 900px) {
    /* Like the admin editor: the outer box spans the viewport so the themed
     * background fills it (no gutter frame), while each row re-centers on the
     * reading measure so chrome stays aligned with the text column. */
    .reader {
        max-width: none;
        padding-inline: 0;
    }

    /* The flow box (multicol container in horizontal mode) centres on the reading
     * measure; the columns and vertical text follow it. */
    .reader-flow {
        max-width: var(--reader-width);
        margin-inline: auto;
        width: 100%;
    }

    /* Head/foot span the viewport (their themed/sticky background must too), but
     * their inner content is centred on the measure via a max-width child. */
    .reader-head,
    .reader-foot {
        padding-inline: max(var(--gutter), calc((100% - var(--reader-width)) / 2));
    }

    .reader-head { padding-block: 16px 12px; }
    .reader-chapter-title { margin-top: 40px; }
    .reader-foot { padding-block: 16px; }
}
