/* =============================================================================
   SudaHub redesign — Reader (CLAUDE.md §7.4)
   Phase 5d. The one deliberate brand-free zone: no gradient, no glass, no
   lattice, no rail/ticker/status-strip. Its own light/sepia/dark themes are
   fixed values (--reader-*-bg/text in tokens.css), independent of the app's
   [data-theme]. Chrome (header/footer) floats over the content and auto-hides
   — it is not part of the reading surface itself.
   ========================================================================== */

.reader-modal {
    position: fixed;
    inset: 0;
    /* Above the premiere room (bookclub.css, also 150) — the reader can now be
       opened from inside that room via "Read Now", and at equal z-index the
       room won and the reader rendered invisibly behind it. Stays below
       toasts (primitives.css, 200), which must be able to speak over §7.4's
       full-screen reading mode. */
    z-index: 160;
    display: flex;
    flex-direction: column;
}
/* Every reader surface (chrome, dropdown, bookmark rows) derives its neutral
   tints from these three, purely from currentColor/reader background — never
   from the app's own --surface/--line/--text-muted/--accent tokens. A reader
   theme must look identical regardless of whether the app itself is in dark
   or light mode; that coupling is exactly the bug this exists to prevent. */
.reader-modal.reader-theme-light {
    background: var(--reader-light-bg); color: var(--reader-light-text);
    --reader-line: var(--reader-light-line); --reader-line-strong: var(--reader-light-line-strong);
    --reader-surface: var(--reader-light-surface); --reader-shadow: var(--reader-light-shadow);
}
.reader-modal.reader-theme-sepia {
    background: var(--reader-sepia-bg); color: var(--reader-sepia-text);
    --reader-line: var(--reader-sepia-line); --reader-line-strong: var(--reader-sepia-line-strong);
    --reader-surface: var(--reader-sepia-surface); --reader-shadow: var(--reader-sepia-shadow);
}
.reader-modal.reader-theme-dark {
    background: var(--reader-dark-bg); color: var(--reader-dark-text);
    --reader-line: var(--reader-dark-line); --reader-line-strong: var(--reader-dark-line-strong);
    --reader-surface: var(--reader-dark-surface); --reader-shadow: var(--reader-dark-shadow);
}

/* ---------- Chrome: floats over the content, auto-hides ---------- */
.reader-chrome {
    position: absolute;
    inset-inline: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-inline: 16px;
    padding-block: 12px;
    background: inherit;
    border-color: var(--reader-line);
    transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}
.reader-chrome-top { inset-block-start: 0; border-block-end: 1px solid; }
.reader-chrome-bottom { inset-block-end: 0; border-block-start: 1px solid; }

.reader-modal.reader-chrome-hidden .reader-chrome-top { transform: translateY(-100%); opacity: 0; }
.reader-modal.reader-chrome-hidden .reader-chrome-bottom { transform: translateY(100%); opacity: 0; }
/* The chrome still exists for screen readers/keyboard focus while visually hidden
   only in the sense of sliding off — fully remove from the a11y tree when hidden
   so it can't be tabbed into invisibly. */
.reader-modal.reader-chrome-hidden .reader-chrome { pointer-events: none; }

.reader-title-block { flex: 1; min-width: 0; padding-inline: 8px; text-align: center; }
.reader-title-block p { margin: 0; }
#reader-title { font-size: var(--fs-label); font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#reader-author { font-size: var(--fs-meta); opacity: 0.6; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.reader-header-actions { display: flex; align-items: center; gap: 6px; }

.reader-icon-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    min-width: 44px;
    min-height: 44px;
    border-radius: var(--r-md);
    background: var(--reader-surface);
    border: none;
    font-family: var(--font-label);
    font-weight: 700;
    font-size: var(--fs-body-s);
    color: inherit;
    cursor: pointer;
    transition: transform var(--dur-micro) var(--ease-out), opacity var(--dur-micro) var(--ease-out);
}
.reader-icon-btn:active { transform: scale(0.94); }
.reader-icon-btn:disabled { opacity: 0.3; cursor: default; }
.reader-icon-btn[aria-pressed="true"] { background: var(--reader-line-strong); }

.reader-page-indicator { font-family: var(--font-mono); font-size: var(--fs-meta); opacity: 0.6; font-variant-numeric: tabular-nums; }

/* Prev/next are direction-carrying (CLAUDE.md §2) — they point at where the
   page physically goes, which flips under RTL since the book paginates
   right-to-left. Close and bookmark are neutral and never mirror. */
[dir="rtl"] #reader-prev-btn svg, [dir="rtl"] #reader-next-btn svg { transform: rotate(180deg); }

/* ---------- Settings / bookmarks panel ---------- */
.reader-settings-wrap { position: relative; }
.reader-settings-panel {
    position: absolute;
    inset-inline-end: 0;
    top: calc(100% + 8px);
    width: 240px;
    max-height: 60vh;
    overflow-y: auto;
    border: 1px solid var(--reader-line-strong);
    border-radius: var(--r-lg);
    box-shadow: 0 24px 64px var(--reader-shadow);
    padding: 14px;
    z-index: 3;
}
/* Explicit per-theme background/text rather than `inherit` — the panel sits
   several DOM levels below .reader-modal (wrap > header-actions > header),
   and background-color doesn't inherit through elements that don't
   themselves re-declare it, so `inherit` here would only reach its
   immediate (transparent) parent. */
.reader-modal.reader-theme-light .reader-settings-panel { background: var(--reader-light-bg); color: var(--reader-light-text); }
.reader-modal.reader-theme-sepia .reader-settings-panel { background: var(--reader-sepia-bg); color: var(--reader-sepia-text); }
.reader-modal.reader-theme-dark  .reader-settings-panel { background: var(--reader-dark-bg);  color: var(--reader-dark-text); }
.reader-settings-section + .reader-settings-section { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--reader-line); }
.reader-settings-label { font-family: var(--font-label); font-size: var(--fs-micro); font-weight: 700; letter-spacing: 0.08em; opacity: 0.65; margin-bottom: 8px; }
[lang="en"] .reader-settings-label { text-transform: uppercase; }
[lang="ar"] .reader-settings-label { letter-spacing: 0; }

.reader-fontsize-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.reader-fontsize-btn { padding-block: 8px; border-radius: var(--r-sm); background: var(--reader-surface); border: none; color: inherit; cursor: pointer; }
/* Selected state inverts fg/bg using only reader tokens (not --accent) so it
   never shifts with the app's own dark/light toggle. Background and text are
   set from two DIFFERENT tokens (this theme's own text colour and its own bg
   colour) rather than `background: currentColor` plus a `color` override on
   the same selector — those resolve against the same final `color` and
   collapse into one indistinguishable value instead of inverting. */
.reader-modal.reader-theme-light .reader-fontsize-btn[aria-pressed="true"] { background: var(--reader-light-text); color: var(--reader-light-bg); }
.reader-modal.reader-theme-sepia .reader-fontsize-btn[aria-pressed="true"] { background: var(--reader-sepia-text); color: var(--reader-sepia-bg); }
.reader-modal.reader-theme-dark  .reader-fontsize-btn[aria-pressed="true"] { background: var(--reader-dark-text);  color: var(--reader-dark-bg); }

.reader-theme-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.reader-theme-btn { padding-block: 8px; border-radius: var(--r-sm); font-size: var(--fs-meta); font-weight: 700; cursor: pointer; border: 1px solid var(--reader-swatch-border); }
.reader-theme-btn[data-theme="light"] { background: var(--reader-light-bg); color: var(--reader-light-text); }
.reader-theme-btn[data-theme="sepia"] { background: var(--reader-sepia-bg); color: var(--reader-sepia-text); }
.reader-theme-btn[data-theme="dark"]  { background: var(--reader-dark-bg);  color: var(--reader-dark-text); }
.reader-theme-btn[aria-pressed="true"] { outline: 2px solid currentColor; outline-offset: 1px; }

.reader-bookmark-list { display: flex; flex-direction: column; gap: 4px; }
.reader-bookmark-empty { font-size: var(--fs-caption); opacity: 0.65; }
.reader-bookmark-item {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px;
    border-radius: var(--r-sm);
    background: var(--reader-surface);
    border: 1px solid var(--reader-line);
}
/* Two sibling buttons, not one nested inside the other — nested interactive
   elements break click-target resolution and screen-reader semantics. */
.reader-bookmark-item-main {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px;
    border: none;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: start;
    cursor: pointer;
}
.reader-bookmark-item-text { flex: 1; min-width: 0; font-size: var(--fs-caption); line-height: 1.4; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.reader-bookmark-item-meta { font-family: var(--font-label); font-size: var(--fs-micro); opacity: 0.65; flex-shrink: 0; }
.reader-bookmark-remove { flex-shrink: 0; width: 28px; height: 28px; min-width: 28px; display: flex; align-items: center; justify-content: center; opacity: 0.65; border: none; background: transparent; color: inherit; cursor: pointer; font-size: var(--fs-caption); }

/* ---------- Reading viewport: tap zones + content pane ---------- */
/* touch-action: none is what makes the reader's gestures work on a touch
   screen at all.

   Chromium — which is the Android WebView — ignores preventDefault() on
   pointermove for the purposes of scrolling. touch-action is the ONLY way to
   stop the compositor claiming a drag, and once it claims one it fires
   pointercancel, which gestures.js correctly treats as "gesture aborted".
   That is why page-turn swipes and swipe-down-to-close worked with a mouse on
   desktop and did nothing at all in the APK: with a mouse there is no pan to
   claim and no cancel to abort them.

   Safe to take the whole gesture surface here: this element holds only the
   tap zones and the paginated pane (overflow: hidden, never scrolls). The
   settings panel, bookmark list and header are all outside it and keep their
   own scrolling. */
.reader-viewport { position: relative; flex: 1; overflow: hidden; touch-action: none; }

/* These sit above the pane, so they are the element a swipe actually starts
   on. The ancestor intersection would resolve them to none anyway, but this
   is the hit target the whole gesture depends on — stated outright rather
   than inferred. Panning only; taps still generate clicks normally. */
.reader-tap-zone { position: absolute; inset-block: 0; z-index: 1; touch-action: none; }
.reader-tap-zone-prev { inset-inline-start: 0; width: 25%; cursor: w-resize; }
.reader-tap-zone-next { inset-inline-end: 0; width: 25%; cursor: e-resize; }
.reader-tap-zone-center { inset-inline-start: 25%; width: 50%; }
[dir="rtl"] .reader-tap-zone-prev { cursor: e-resize; }
[dir="rtl"] .reader-tap-zone-next { cursor: w-resize; }

.reader-content-pane {
    /* Explicit rather than relying on inheriting the viewport's value: the
       effective touch-action is intersected UP the ancestor chain only as far
       as the nearest scroll container, and overflow:hidden makes this element
       one. Stating it here removes the ambiguity. */
    touch-action: none;
    position: absolute;
    inset: 0;
    overflow: hidden;
    padding-inline: 24px;
    padding-block: 24px;
    max-width: 640px;
    margin-inline: auto;
    font-size: var(--reader-fontsize, 18px);
    line-height: 1.6;
    transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}
.reader-content-pane p { margin: 0 0 1em; }

/* ---- Book formatting (see parseBlocks in library.js) ----
   Sizes are relative to --reader-fontsize, so they scale with the reader's
   own text-size control instead of fighting it. */
.reader-content-pane .reader-h1,
.reader-content-pane .reader-h2 {
    text-align: center;
    font-weight: 700;
    line-height: 1.35;
    /* A heading needs air above it far more than below — the space belongs
       between it and what came before. */
    margin: 1.6em 0 0.8em;
}
.reader-content-pane .reader-h1:first-child,
.reader-content-pane .reader-h2:first-child { margin-block-start: 0; }
.reader-content-pane .reader-h1 { font-size: 1.5em; }
.reader-content-pane .reader-h2 { font-size: 1.2em; }

.reader-content-pane .reader-centre { text-align: center; margin: 0 0 1em; }

.reader-content-pane .reader-quote {
    margin: 0 0 1em;
    padding-inline-start: 1em;
    /* Logical, so the rule sits on the correct side under RTL (§2). */
    border-inline-start: 2px solid currentColor;
    opacity: 0.78;
    font-style: italic;
}
/* Arabic has no italic — §3 forbids faking one. Emphasis falls back to weight,
   which is how Arabic typography actually marks it. */
.reader-content-pane[lang="ar"] .reader-quote { font-style: normal; font-weight: 500; }
.reader-content-pane[lang="ar"] em { font-style: normal; font-weight: 600; }

/* A scene break, not a divider: centred, short, and quiet. */
.reader-content-pane .reader-break {
    border: 0;
    margin: 1.6em auto;
    width: 42%;
    height: 1px;
    background: currentColor;
    opacity: 0.28;
}
.reader-content-pane[lang="en"], .reader-content-pane[lang]:not([lang="ar"]) { font-family: var(--font-brand); }
.reader-content-pane[lang="ar"] {
    font-family: var(--font-reading);
    line-height: 1.9;
    /* Word-spacing justification only — CLAUDE.md §7.4 explicitly forbids
       kashida stretching without a real Arabic justification engine. Browsers'
       default `justify` behaviour on Arabic text expands inter-word spacing,
       never kashida, so a plain `justify` is exactly the safe behaviour. */
    text-align: justify;
    text-justify: inter-word;
}
.reader-content-pane * { font-variant-numeric: tabular-nums; }

/* Slide-transition states, direction-aware. JS toggles these classes for one
   frame around a page turn rather than animating layout directly. */
.reader-content-pane.reader-page-turn-out-forward { transform: translateX(-24px); opacity: 0; }
.reader-content-pane.reader-page-turn-out-back { transform: translateX(24px); opacity: 0; }
[dir="rtl"] .reader-content-pane.reader-page-turn-out-forward { transform: translateX(24px); }
[dir="rtl"] .reader-content-pane.reader-page-turn-out-back { transform: translateX(-24px); }
.reader-content-pane.reader-page-turn-notransition { transition: none !important; }

.reader-empty-state, .reader-loading-state {
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 8px;
    padding: 24px;
    opacity: 0.7;
}
.reader-empty-state p, .reader-loading-state p { font-size: var(--fs-body-s); font-weight: 700; max-width: 40ch; }

/* A page image is not a column of prose. The pane's 640px cap and 24px
   padding exist for line length (§3); on a PDF they letterbox the page and
   waste the screen, so PDF mode drops both and centres the page instead. */
.reader-content-pane.is-pdf {
    max-width: none;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Zooming past fit makes the page larger than the pane; without this it
       would be clipped by the pane's `overflow: hidden` with no way to reach
       the rest. */
    overflow: auto;
}

/* `height: auto` is deliberately NOT set here any more. renderPdfPage() sizes
   the canvas explicitly — a dense backing store shown at logical size — and a
   stylesheet `height: auto` fighting that inline height is how a
   high-DPI canvas ends up stretched. */
.reader-content-pane canvas {
    display: block;
    margin-inline: auto;
    max-width: 100%;
    border-radius: var(--r-sm);
    transition: filter var(--dur-base) var(--ease-out);
}

/* ---- Reader themes on a PDF page ----
   A PDF page is an image carrying its own white paper and black ink, so the
   theme buttons changed the surface around it and left the page glaring white
   in dark mode. A filter is the only lever available.

   The numbers are derived, not eyeballed: each maps the page's white and black
   onto the LUMINANCE of that theme's actual --reader-*-bg / --reader-*-text
   token, solving contrast(c) then brightness(b) for both endpoints at once.
   Dark lands white->0.082 and black->0.862, matching #12151C on #D8DCE4 —
   which is also why it never produces pure #000, forbidden by §10.

   `hue-rotate(180deg)` after `invert` is what keeps coloured ink coloured: a
   plain inversion turns red headings cyan.

   LIMITATION, worth stating: this is a heuristic that suits text. A page that
   is mostly photograph renders as a negative in dark mode. Every PDF reader
   that offers a dark mode has this same trade; the alternative is not
   offering one. */
.reader-modal.reader-theme-dark .reader-content-pane canvas {
    filter: invert(1) hue-rotate(180deg) contrast(0.83) brightness(0.94);
}
.reader-modal.reader-theme-sepia .reader-content-pane canvas {
    filter: sepia(0.55) contrast(0.65) brightness(1.12);
}
/* Light needs nothing — the page is already paper-on-white. Declared anyway so
   switching back from dark actually clears the filter. */
.reader-modal.reader-theme-light .reader-content-pane canvas {
    filter: none;
}

@media (prefers-reduced-motion: reduce) {
    .reader-chrome, .reader-content-pane { transition-duration: 0.01ms; }
}
