/* =============================================================================
   base.css — the SHARED style layer: @font-face, design tokens, reset.
   =============================================================================
   Loaded by BOTH public/index.html and public/admin.html, before their own
   stylesheet. This file is the public/admin CSS contract: admin.css makes 384
   var(--...) references, 43 of which resolve to custom properties declared
   here, and those tokens used to reach it only because admin.html happened to
   load the whole public stylesheet.

   RULES
   - A change here changes BOTH the public site and the admin panel. Treat it
     the way you treat src/shared/** on the server (CLAUDE.md, roadmap 2.3).
   - Public-only rules belong in style.css; admin-only rules in admin.css.
   - Content is style.css lines 1-753 moved verbatim and unreordered. Both
     pages load base.css immediately before their own sheet, so the cascade is
     byte-for-byte what it was: last rule still wins, in the same order.

   STILL COUPLED (not fixed by this file): admin.html also loads style.css,
   because 67 classes the admin panel renders -- modals, toasts, form controls,
   the Tiptap editor chrome -- are styled only there. Splitting those into a
   components.css is what lets admin.html drop style.css entirely; until then an
   admin-motivated style.css edit still reaches the public site.
   ============================================================================= */

/*
 * Islamic Digital Library — Redesigned UI
 * Warm parchment light mode, dark night-reading mode.
 * Design system: exact values from the brief. Do not deviate.
 */

/* Local font Jameel Noori Nastaleeq registered via @font-face.
   WOFF2 (Brotli-compressed) instead of the original TTF — same glyphs, ~48%
   smaller transfer. No TTF fallback needed: build.js already targets
   chrome100/firefox100/safari15, all of which have had WOFF2 support for
   years. Only downloads at all when a user actually switches to Urdu (these
   families are assigned to --font-urdu inside `[lang="ur"] { ... }`, and
   nothing outside that scope references them) — see docs/mobile-apps.md-era
   audit notes for why this isn't a "every visitor" cost. */
@font-face {
    font-family: 'Jameel Noori Nastaleeq';
    src: url('/fonts/Jameel Noori Nastaleeq Regular.woff2') format('woff2');
    font-weight: normal;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Jameel Noori Nastaleeq Regular';
    src: url('/fonts/Jameel Noori Nastaleeq Regular.woff2') format('woff2');
    font-weight: normal;
    font-style: normal;
    font-display: swap;
}

/* Kasheeda is NOT a stylistic alternate here — it is the only face in the stack
   that carries the Arabic-Indic digits ٠-٩ (U+0660-0669), the date separator,
   and the Bismillah / Jalla-Jalaluhu / Subhanahu-wa-Ta'ala / Azza-wa-Jall
   ligatures. 'Jameel Noori Nastaleeq Regular' has none of those 48 codepoints,
   so a single Hijri date or page number on the page made the browser fall
   through to Kasheeda and pull a SECOND 4.77 MB file on top of Regular's
   5.55 MB — 10.3 MB of fonts for one Urdu reader.

   Nothing else in Kasheeda was ever used, so it is subset to exactly the
   codepoints it uniquely provides: 4,773,104 -> 6,932 bytes, with no visual
   change whatsoever (these glyphs came from this font before and still do).
   The unicode-range makes that explicit, so the browser only fetches it when
   one of those characters is actually on the page instead of treating the face
   as a general fallback candidate.

   Regenerate with:
     python -m fontTools.subset "Jameel Noori Nastaleeq Kasheeda.woff2" \
       --flavor=woff2 --output-file="Jameel Noori Nastaleeq Kasheeda.subset.woff2" \
       --unicodes="U+060D,U+0660-0669,U+FDFB,U+FDFD,U+FDFE,U+FDFF" --layout-features='*'

   Regular is deliberately NOT subset: 19,306 of its 19,658 glyphs are reachable
   only through GSUB ligatures (that IS Nastaliq), so unicode-range subsetting
   saves 2.9% and dropping the ligatures saves 5.27 MB but stops it being
   Nastaliq at all. Its size is the calligraphy, not dead weight. */
@font-face {
    font-family: 'Jameel Noori Nastaleeq Kasheeda';
    src: url('/fonts/Jameel Noori Nastaleeq Kasheeda.subset.woff2') format('woff2');
    font-weight: normal;
    font-style: normal;
    font-display: swap;
    unicode-range: U+060D, U+0660-0669, U+FDFB, U+FDFD, U+FDFE, U+FDFF;
}

/* ======================== CSS CUSTOM PROPERTIES ======================== */

:root {
    /* Height of navbar + search-filter-panel chrome above the library list
       views (used by #screen-library and #lib-view-all-books.active).
       Four explicit values instead of one flat number or a calc() of two
       separately-overridden variables — tried that first, but Chromium
       freezes a var()-of-var() chain's substitution at whichever element
       DECLARES the composed property (:root here), so overriding just the
       inner variable on a descendant (body.lib-searchbar-hidden) silently
       had no effect on the composed value. Explicit compound selectors for
       every combination sidesteps that: navbar visible/hidden (scroll
       auto-hide) × shared search bar visible/hidden (All Books vs.
       Author/Category/Recent, which show their own local search-grid
       instead and were wasting 80px of height for a bar that was never on
       screen for them). */
    --chrome-offset: 222px;   /* navbar + tab strip + shared search bar, all visible (All Books, resting) */

    /* Same idea as --chrome-offset above, but for the Offline Library screen
       (#lib-view-local-books), whose chrome stack is navbar + .offline-tabs-bar
       instead of navbar + .library-tabs-bar + search-filter-panel — different
       total height, so it needs its own pair rather than reusing --chrome-offset. */
    --offline-chrome-offset: 180px;
    --offline-chrome-offset-collapsed: 70px;

    /* ─── Spacing System ─── */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 20px;
    --space-6: 24px;
    --space-8: 32px;
    --space-10: 40px;
    --space-12: 48px;
    --space-16: 64px;

    /* ─── Typography ─── */
    /* Two Nastaliq faces, deliberately. A browser downloads a font when something
       USES it, so listing Jameel Noori anywhere site-wide cost every Urdu visitor
       5.55 MB just to paint the navbar. Jameel is therefore reserved for the two
       surfaces where a reader settles into long-form prose and the calligraphy is
       the point — the article reader and the article writer (see the
       --font-urdu-calligraphic rule near the end of this file). Everything else —
       chrome, book lists, titles, article list previews — uses Noto Nastaliq
       Urdu, which is ~239 KB against Jameel's 5.55 MB and is already fetched via
       the Google Fonts link in index.html.

       Side benefit: Jameel ships no bold face, so font-weight:700 on it was being
       synthesised by dilating the regular outlines (see the note further down).
       Noto Nastaliq has a real 700, so site chrome gets genuine bold. */
    --font-urdu: 'Noto Nastaliq Urdu', serif;
    --font-urdu-calligraphic: 'Jameel Noori Nastaleeq Regular', 'Jameel Noori Nastaleeq', 'Jameel Noori Nastaleeq Kasheeda', 'Noto Nastaliq Urdu', serif;
    --font-arabic: 'Tajawal', sans-serif;
    --font-ui: 'Inter', 'Segoe UI', system-ui, sans-serif;

    /* ─── Radii ─── */
    --radius-xs: 4px;
    --radius-sm: 6px;
    --radius-md: 10px;
    --radius-lg: 16px;
    --radius-xl: 20px;
    --radius-full: 9999px;

    /* ─── Shadows ─── */
    --shadow-sm: 0 1px 3px rgba(0,0,0,0.06);
    --shadow-md: 0 4px 12px rgba(0,0,0,0.06);
    --shadow-lg: 0 8px 24px rgba(0,0,0,0.08);

    /* ─── Transitions ─── */
    --transition-fast: 150ms ease;
    --transition-base: 200ms ease;
    --transition-slow: 240ms cubic-bezier(0.4,0,0.2,1);

    /* ─── Stacking ladder ───
       Every z-index in this file now references one of these names. The
       VALUES are exactly what each site used before this ladder existed, so
       introducing it changed no stacking whatsoever — the point was to give
       the numbers names, because previously each new layer was assigned
       whatever integer beat the last one and nothing recorded the intended
       order.

       Read top to bottom as "what sits above what". Note the deliberately
       tight clusters: 90/99/100/101 (tab bars vs. navbar vs. active nav item)
       and 120–250 (the PDF-viewer chrome family) are adjacent because those
       components genuinely interleave. Those clusters are the ones to leave
       alone unless you can visually verify the components afterwards; a
       "tidy-up" that collapses them onto round numbers WILL reorder real UI.
       Prefer reusing an existing rung over inventing a new integer. */
    --z-hero-bg:          0;    /* decorative hero backdrop, below content */
    --z-content:          1;    /* in-flow content lifted over a backdrop */
    --z-content-raised:   2;    /* active tab, small icon overlays */
    --z-overlay-local:   10;    /* overlay scoped to one panel */
    --z-popover-local:   50;    /* popover anchored inside a panel */
    --z-dropdown:        60;    /* nav dropdown panel */
    --z-tabs-bar:        90;    /* library tab strip */
    --z-tabs-bar-offline:99;    /* offline tab strip, tiptap toolbar */
    --z-navbar:         100;    /* site navbar */
    --z-navbar-active:  101;    /* active nav item, above the navbar ground */
    --z-viewer-float:   120;    /* PDF viewer floating toolbar */
    --z-viewer-sidebar: 150;    /* PDF viewer + reader TOC sidebars */
    --z-viewer-chrome:  180;    /* PDF viewer toolbar / status bar */
    --z-viewer-tabs:    190;    /* PDF viewer book tab strip */
    --z-viewer-header:  200;    /* PDF viewer top header */
    --z-bottom-nav:     200;    /* mobile bottom nav (same rung as above; the
                                   two never share a screen) */
    --z-viewer-dropdown:250;    /* PDF viewer "more" dropdown */
    --z-popover:        500;    /* book "more" popover */
    --z-drawer-overlay: 999;    /* scrim behind a slide-over drawer */
    --z-drawer:        1000;    /* slide-over drawer, thumbnail popup */
    --z-toast:         1100;    /* toasts, reader floating controls */
    --z-fullscreen:    2000;    /* fullscreen editor workspace */
    --z-sheet:         2110;    /* mobile bottom sheet */
    --z-sheet-scrim:   2150;    /* scrim above the sheet */
    --z-modal:         2200;    /* centered dialogs + the mobile bottom sheets
                                   that view-options / book-"…" / nav dropdowns
                                   turn into; same rung as the book sheets
                                   documented on .more-sheet below */
    --z-sheet-dropdown:2200;    /* dropdown opened from within a sheet */
    --z-sheet-top:     2300;    /* "more" sheet, above bottom nav + sheets */
    --z-editor-popover:5000;    /* tiptap link/footnote popovers, topmost */
}

/* ======================== ADVANCED MULTI-LINGUAL TYPOGRAPHY & STYLING SUITE ======================== */

/* --font-ui drives every UI-chrome element site-wide (buttons, nav links,
   menu items, form inputs, badges, tabs — see the broad selector list a few
   lines below and throughout admin.css/pm.css), but until now it was never
   redefined per language, so switching to Arabic/Urdu left all of that
   chrome in the English-oriented Inter/Segoe UI stack even though
   Noto Naskh Arabic/Noto Nastaliq Urdu were already loaded and used elsewhere. Setting
   it here on [lang="X"] (the <html> element — see i18n.js setLanguage())
   cascades to every var(--font-ui) reference in the app for free. */
[lang="ar"] {
    --font-ui: 'Tajawal', sans-serif;
}

/* English splits the two roles deliberately: Inter for UI chrome (it is what
   the [lang="en"] control rules below already ask for), Source Serif 4 for
   display and prose. Previously --font-ui was Source Serif 4 here while the
   individual .nav-link/.btn/.form-input rules hardcoded Inter — the two
   contradicted each other, and which one won depended on selector specificity
   rather than intent. Arabic and Urdu keep one face for both roles, which is
   correct for those scripts; Latin is the one that benefits from the split. */
[lang="en"] {
    --font-ui: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --font-display: 'Source Serif 4', Georgia, 'Times New Roman', serif;
}

/* ─── 1. Urdu (Nastaliq Poetic Calligraphy & Royal Scaling) ─── */
/* ─── 1. Urdu (Jameel Noori Nastaleeq Regular - Royal Scale Reading Experience) ─── */
[lang="ur"] {
    /* Noto Nastaliq, not Jameel — this rule lands on <html>, so naming Jameel
       here made the whole document use it and pulled 5.55 MB for every Urdu
       visitor before a single word of an article was opened. Jameel is
       re-applied to article prose only, at the end of this file. */
    --font-arabic: 'Noto Nastaliq Urdu', serif;
    --font-ui: 'Noto Nastaliq Urdu', serif;
    --font-urdu: 'Noto Nastaliq Urdu', serif;
    font-family: var(--font-urdu) !important;
    line-height: 2.6 !important;
    /* No root font-size bump here on purpose. This is set on <html>, so an
       earlier `font-size: 1.4rem` here didn't just enlarge the root — every
       rem value below (and elsewhere on the page) resolves against IT, so
       each already-tuned rem size in this section got multiplied by 1.4
       *again* on top of its own value. Proof: every rem figure below carries
       an inline "~Npx" comment, and every one of those N only matches when
       computed against a normal 16px root — e.g. 2.15rem is commented
       "~34px" (2.15 × 16), but with the 1.4rem root that was actually
       rendering at 48px. Confirmed live: .modal-body was measuring
       48.16px/135px line-height, and .btn/.badge controls were at 29px
       (should be ~21px). Removing this line alone restores every rule below
       to the size its own comment already promised. */
}

/* Primary Reading Prose: Extracted Text, Articles, Book Reader Body */
[lang="ur"] #extracted-text-body,
[lang="ur"] .article-reader-body,
[lang="ur"] .reader-content,
[lang="ur"] .reading-view,
[lang="ur"] .book-description,
[lang="ur"] .raw-text-container,
[lang="ur"] .modal-body,
[lang="ur"] .panel p {
    font-family: var(--font-urdu) !important;
    font-size: 2.15rem !important; /* ~34px - Royal & Crystal Clear Reading Experience */
    line-height: 2.8 !important;
    color: var(--text-primary) !important;
    word-spacing: 2px !important;
    letter-spacing: 0px !important;
}

[lang="ur"] .btn,
[lang="ur"] .btn-icon,
[lang="ur"] .nav-link,
[lang="ur"] .sidebar-tab-item,
[lang="ur"] .tab-text,
[lang="ur"] .form-input,
[lang="ur"] .form-select,
[lang="ur"] .badge,
[lang="ur"] .tab,
[lang="ur"] select,
[lang="ur"] option,
[lang="ur"] .filter-btn,
[lang="ur"] .filter-label,
[lang="ur"] .search-input {
    font-family: var(--font-urdu) !important;
    line-height: 2.2 !important;
    font-size: 1.25rem !important; /* ~20px for controls, inputs, and tabs */
    padding-top: 3px;
    padding-bottom: 5px;
}

/* Brand wordmark ("القلم") — deliberately NOT bundled with the generic
   Arabic/Urdu UI-text rules above: it's a brand mark, not a form control,
   and needs its own larger, bolder, calligraphic treatment to read as a
   logo rather than shrink to the same size as a tab label. Reuses
   Scheherazade New (already loaded for the body serif) instead of adding
   a new font just for the wordmark. */
[lang="ar"] .logo-text,
[lang="ur"] .logo-text {
    font-family: 'Tajawal', sans-serif;
    font-weight: 700;
    letter-spacing: 0;
}
[lang="ar"] .logo-text,
[lang="ur"] .logo-text {
    font-size: 26px;
    line-height: 1;
}

/* ─── Urdu weight policy: never above 400 ───
   The three Jameel Noori faces are each a SINGLE regular-weight file (see the
   @font-face block at the top — every one declares `font-weight: normal`).
   There is no bold Nastaliq here to reach, so `font-weight: 600/700` did not
   select a bolder face; it made the browser SYNTHESISE one by dilating the
   regular outlines. Measured on the live site: the same string at 400 and at
   700 came back with byte-identical advance widths (127.83203125px both),
   which is the signature of faux bold rather than a real second face.

   Faux bold hurts Nastaliq more than it hurts Latin. The script's beauty is
   in its modulated stroke contrast — heavy downstrokes meeting hairline
   connectors along a descending ligature cascade. Uniform dilation thickens
   the hairlines at the same rate as the thick strokes, so the contrast
   flattens and the joins smear, most visibly at the 18–25px sizes below.

   So weight is out as a hierarchy tool for Urdu, and SIZE plus COLOUR carry
   it instead. That is the stronger pairing anyway: previously titles and meta
   were only ~15% apart in size AND both sat on --text-primary AND both were
   bold, so the whole card read as one heavy block with no focal point. Now
   the title holds primary ink at the larger size and the metadata steps back
   to secondary — a clear two-tier read with nothing smeared.

   Sizes are deliberately unchanged: they were tuned for Nastaliq, which needs
   more size than Latin at equivalent legibility, and shrinking them to
   manufacture contrast would trade real legibility for hierarchy we now get
   from colour for free. Do not reintroduce a weight here unless a genuine
   bold Nastaliq file is added to /fonts and declared at font-weight: 700. */
[lang="ur"] .book-card-title {
    font-size: 1.45rem !important; /* ~23px */
    line-height: 2.2 !important;   /* extra room for tall ascenders & deep descenders */
    font-weight: 400 !important;
    padding-top: 4px !important;
    padding-bottom: 6px !important;
}

[lang="ur"] .book-row-title {
    font-size: 22px !important;
    line-height: 2.2 !important;
    font-weight: 400 !important;
    padding-top: 4px !important;
    padding-bottom: 6px !important;
}

[lang="ur"] .book-bar-title {
    font-size: 22px !important;
    line-height: 2.2 !important;
    font-weight: 400 !important;
    padding-top: 4px !important;
    padding-bottom: 6px !important;
}

[lang="ur"] .book-card-author-row,
[lang="ur"] .book-row-author,
[lang="ur"] .book-bar-author,
[lang="ur"] .book-row-category,
[lang="ur"] .book-bar-category,
[lang="ur"] .split-list-item,
[lang="ur"] .author-card-name,
[lang="ur"] .category-card-name,
[lang="ur"] .author-name,
[lang="ur"] .category-name,
[lang="ur"] .book-row-death,
[lang="ur"] .book-card-death {
    color: var(--text-secondary) !important;
    font-weight: 400 !important;
    font-size: 19px !important; /* ~19px for high legibility */
    line-height: 2.4 !important;
    padding-top: 2px !important;
    padding-bottom: 4px !important;
}

[lang="ur"] .book-card-category {
    color: var(--text-secondary) !important;
    font-weight: 400 !important;
    font-size: 16px !important;
    padding: 4px 14px 6px 14px !important;
    line-height: 2.0 !important;
}

[lang="ur"] .hero-title {
    font-family: var(--font-urdu) !important;
    font-size: clamp(2.8rem, 7.5vw, 4.8rem);
    line-height: 2.0 !important;
    color: var(--accent);
    text-shadow: 0 4px 16px rgba(27, 67, 50, 0.16);
    padding-top: 10px;
    margin-bottom: var(--space-6);
}

[lang="ur"] .section-title {
    font-family: var(--font-urdu) !important;
    font-size: clamp(2.2rem, 5.5vw, 3.2rem);
    line-height: 2.3 !important;
    padding-top: 8px;
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

[lang="ur"] .info-card-title {
    font-family: var(--font-urdu) !important;
    font-size: 1.75rem;
    font-weight: 400;  /* no bold Nastaliq exists — see weight policy above */
    line-height: 2.1 !important;
    color: var(--text-primary);
}

[lang="ur"] .info-card-text {
    font-family: var(--font-urdu) !important;
    font-size: 20px;
    line-height: 2.4 !important;
}

/* ─── 2. Arabic (Classical Qur'anic Calligraphy & Modern Geometric Dignity) ─── */
[lang="ar"] body {
    font-family: 'Tajawal', sans-serif;
    font-size: 1.18rem;
    line-height: 2.15;
}

[lang="ar"] .hero-title {
    font-family: 'Tajawal', sans-serif;
    font-size: clamp(2.3rem, 6.5vw, 3.8rem);
    font-weight: 700;
    line-height: 1.35;
    color: var(--accent);
    text-shadow: 0 4px 18px rgba(27, 67, 50, 0.15);
    margin-bottom: var(--space-5);
}

[lang="ar"] .section-title {
    font-family: 'Tajawal', sans-serif;
    font-size: clamp(1.75rem, 4.2vw, 2.4rem);
    font-weight: 700;
    text-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
}

[lang="ar"] .info-card-title {
    font-family: 'Tajawal', sans-serif;
    font-size: 1.3rem;
    font-weight: 700;
}

[lang="ar"] .info-card-text {
    font-family: 'Tajawal', sans-serif;
    font-size: 15.5px;
    line-height: 1.85;
}

[lang="ar"] .btn,
[lang="ar"] .nav-link,
[lang="ar"] .tab-text {
    font-family: 'Tajawal', sans-serif;
    font-weight: 700;
}

/* Book listing typography — Naskh reads comfortably closer to Latin sizes
   than Nastaliq does, so this is a modest bump over the (Latin-tuned)
   unprefixed defaults, not Urdu's much larger jump. Was missing entirely
   before: Arabic book titles/authors/categories fell through to those
   English-proportioned defaults site-wide, the one component layer that
   never got Arabic-specific treatment even though hero/section/body text
   did. */
[lang="ar"] .btn,
[lang="ar"] .btn-icon,
[lang="ar"] .sidebar-tab-item,
[lang="ar"] .form-input,
[lang="ar"] .form-select,
[lang="ar"] .badge,
[lang="ar"] .tab,
[lang="ar"] select,
[lang="ar"] option,
[lang="ar"] .filter-btn,
[lang="ar"] .filter-label,
[lang="ar"] .search-input {
    font-family: 'Tajawal', sans-serif;
    line-height: 1.7;
    font-size: 1.05rem;
}

[lang="ar"] .book-card-title {
    font-size: 1.2rem;
    line-height: 1.55;
    font-weight: 700;
}

[lang="ar"] .book-row-title {
    font-size: 18px;
    line-height: 1.55;
    font-weight: 700;
}

[lang="ar"] .book-bar-title {
    font-size: 19px;
    line-height: 1.55;
    font-weight: 700;
}

[lang="ar"] .book-card-author-row,
[lang="ar"] .book-row-author,
[lang="ar"] .book-bar-author,
[lang="ar"] .book-row-category,
[lang="ar"] .book-bar-category,
[lang="ar"] .split-list-item,
[lang="ar"] .author-card-name,
[lang="ar"] .category-card-name,
[lang="ar"] .author-name,
[lang="ar"] .category-name,
[lang="ar"] .book-row-death,
[lang="ar"] .book-card-death {
    font-weight: 600;
    font-size: 15px;
    line-height: 1.7;
}

[lang="ar"] .book-card-category {
    font-weight: 600;
    font-size: 13px;
    line-height: 1.6;
}

/* ─── 3. English (Ultra-Modern Geometric Web App Hierarchy) ─── */
[lang="en"] body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 0.95rem;
    line-height: 1.6;
}

/* Display type is Source Serif 4, not Inter. Inter is reserved for UI chrome
   (buttons, nav, forms) below; using it for the hero made the English site
   read as a generic web app, visually disconnected from the Naskh/Nastaliq
   display faces the Arabic and Urdu sites use. A serif display keeps all
   three languages in the same scholarly register. */
[lang="en"] .hero-title {
    font-family: 'Source Serif 4', Georgia, 'Times New Roman', serif;
    font-size: clamp(2.2rem, 5vw, 3.5rem);
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.15;
    color: var(--accent);
    margin-bottom: var(--space-5);
}

[lang="en"] .btn {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-weight: 600;
    letter-spacing: -0.01em;
}

[lang="en"] .section-title {
    font-family: 'Source Serif 4', Georgia, 'Times New Roman', serif;
    font-size: clamp(1.6rem, 3.5vw, 2.2rem);
    font-weight: 700;
    letter-spacing: -0.015em;
    line-height: 1.25;
}

[lang="en"] .info-card-title {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 1.2rem;
    font-weight: 600;
    letter-spacing: -0.015em;
}

[lang="en"] .info-card-text {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 14px;
    line-height: 1.6;
    color: var(--text-secondary);
}

[lang="en"] .nav-link,
[lang="en"] .tab-text,
[lang="en"] .form-input,
[lang="en"] .form-select {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

[lang="en"] .logo-text {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-weight: 700;
    letter-spacing: -0.03em;
}

/* ─── Light Mode (default) ─── */
/* ═══════════════════════════════════════════════════════════════
   Light mode — "Chalk & Ink" (default)
   Neutral, timeless, print/academic-press feeling.
   Value and warmth carry the design, not saturated hues.
   ═══════════════════════════════════════════════════════════════ */
:root,
[data-theme="light"] {
    /* Core palette — "Vellum & Ink"
       Warm ivory ground + forest ink-green, deliberately NOT the cool
       slate/teal SaaS default this used to be. Every text-on-background
       pair below is WCAG-verified; ratios noted inline. */
    --bg-page:       #FAF7F0;   /* Warm ivory vellum */
    --bg-surface:    #FFFFFF;   /* Pure white surface */
    --bg-elevated:   #FDFBF5;   /* Faintly warm elevated container */
    --child-bar-bg:  #F5F1E8;   /* Child bar header, one step down from page */
    --text-primary:  #1C1917;   /* Warm near-black ink (16.4:1 on page — AAA) */
    --text-secondary:#57534E;   /* Warm stone (7.5:1 — AAA) */
    --text-muted:    #6B645F;   /* (5.4:1 — AA). Was #78716C, which measured
                                   4.48:1 — just under the 4.5 AA floor. */
    --accent:        #1B4332;   /* Deep forest ink-green (10.4:1 as text — AAA) */
    --accent-light:  rgba(27, 67, 50, 0.08);
    --accent-hover:  #2D6A4F;
    --accent-warm:       #A6791F; /* Antique gold — FILLS/BORDERS ONLY (3.7:1) */
    --accent-warm-hover: #8A6318;
    --accent-gold:   #A6791F;   /* Gold for fills & borders (3:1 non-text AA) */
    --accent-gold-text: #8A6318;/* Darker gold for TEXT (4.7:1 — AA). Never
                                   use --accent-gold on text: it fails AA. */
    --accent-gold-light: rgba(166, 121, 31, 0.10);
    --border:        #E7DFCE;   /* Warm vellum border */
    --border-strong: #D8CCAE;   /* Divider border */
    --focus-ring:    rgba(27, 67, 50, 0.25);

    /* Primary Button Fill & Text */
    --btn-primary-bg:    #1B4332;
    --btn-primary-text:  #FFFFFF;  /* 11.1:1 Contrast Ratio — AAA */

    /* Semantic Badges & Feedback states */
    --badge-success-bg:    rgba(27, 67, 50, 0.10);
    --badge-success-text:  #1B4332;
    --badge-warning-bg:    rgba(166, 121, 31, 0.12);
    --badge-warning-text:  #8A6318;
    --badge-danger-bg:     rgba(190, 18, 60, 0.10);
    --badge-danger-text:   #BE123C;  /* 5.9:1. Was #E11D48 = 4.39:1, under AA. */
    --badge-info-bg:       rgba(27, 67, 50, 0.08);
    --badge-info-text:     #1B4332;
    --upload-hover-bg:     rgba(27, 67, 50, 0.06);

    /* Segmented control */
    --segmented-track-bg: #F0EBDF;        /* Warm track */
    --segmented-item-bg:  #FFFFFF;
    --segmented-item-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04);
}

/* ═══════════════════════════════════════════════════════════════
   Dark mode — "Slate & Ash"
   ═══════════════════════════════════════════════════════════════ */
[data-theme="dark"] {
    /* Core palette — "Ink & Ember"
       Walnut/espresso ground kept from the previous dark mode (it was already
       the most distinctive of the three); accent pulled from orange-amber
       toward a richer ember gold so it reads as gilt on a manuscript rather
       than a notification badge. */
    --bg-page:       #15130F;   /* Deep espresso night */
    --bg-surface:    #211E1B;   /* Elevated dark walnut surface */
    --bg-elevated:   #2C2824;
    --child-bar-bg:  #1C1916;   /* slightly darker than navbar for visual distinction */
    --text-primary:  #ECE4D4;   /* Softer warm parchment, less stark than pure
                                   white (14.7:1 — still AAA). Was #F5F1E8. */
    --text-secondary:#B7AFA0;   /* Lighter/warmer stone for legibility
                                   (8.5:1 — AAA, up from 7.0). Was #A8A29E. */
    --text-muted:    #928A83;   /* (5.5:1 — AA). Was #78716C = 3.87:1 on the
                                   darkened page ground — under the AA floor. */
    --accent:        #BE8B3E;   /* Desaturated brass gold, less raw-yellow
                                   than the previous ember gold (6.1:1 as
                                   text — AA). Was #D4A017. */
    --accent-light:  rgba(190, 139, 62, 0.14);
    --accent-hover:  #D0A052;
    --accent-warm:       #EA580C;
    --accent-warm-hover: #F97316;
    --accent-gold:   #BE8B3E;
    --accent-gold-text: #BE8B3E; /* 6.1:1 on dark ground — clears AA as text */
    --accent-gold-light: rgba(190, 139, 62, 0.14);
    --border:        #3C3631;
    --border-strong: #4F4741;
    --focus-ring:    rgba(190, 139, 62, 0.25);

    --shadow-sm: 0 1px 3px rgba(0,0,0,0.35);
    --shadow-md: 0 4px 12px rgba(0,0,0,0.45);
    --shadow-lg: 0 8px 24px rgba(0,0,0,0.55);

    /* Semantic Badges & Feedback states */
    --badge-success-bg:    rgba(190, 139, 62, 0.14);
    --badge-success-text:  #BE8B3E;
    --badge-warning-bg:    rgba(234, 88, 12, 0.15);
    --badge-warning-text:  #EA580C;
    --badge-danger-bg:     rgba(246, 92, 126, 0.15);
    --badge-danger-text:   #F65C7E;  /* 6.0:1. Was #E11D48 = 3.95:1 on dark. */
    --badge-info-bg:       rgba(190, 139, 62, 0.12);
    --badge-info-text:     #D0A052;
    --upload-hover-bg:     rgba(190, 139, 62, 0.08);

    /* Segmented control */
    --segmented-track-bg: #3C3631;
    --segmented-item-bg:  #211E1B;
    --segmented-item-shadow: 0 1px 3px rgba(0,0,0,0.4);
}



/* ─── Legacy variable aliases (backward compat with existing JS) ─── */
:root {
    --primary: var(--accent);
    --primary-hover: var(--accent-hover);
    --primary-light: var(--accent-light);
    --bg-base: var(--bg-page);
    --bg-card: var(--bg-surface);
    --bg-panel: var(--bg-elevated);
    --bg-input: var(--bg-page);
    --text-light: var(--text-muted);
    --text-color: var(--text-primary);  /* admin.html accordion titles, dropdowns, dialogs */
    --red: #dc2626;                    /* admin.html .btn-danger + admin.js error/delete text */
    --border-glow: var(--focus-ring);
    --radius: var(--radius-md);

    /* ─── Names the stylesheets referenced but nobody ever declared ───
       Twelve custom properties were used across admin.css and style.css and
       declared NOWHERE — not here, not in either sheet, not from JS. They split
       into two failure modes.

       WITH a hardcoded fallback (`var(--bg-secondary, #f3f4f6)`) they rendered,
       but in the cool-slate palette this design deliberately moved away from,
       and outside the token system entirely: restyling the theme left them
       behind, and a dark admin theme would never reach them.

       WITHOUT one they were dead. An undefined var() and no fallback is invalid
       at computed-value time, so the whole declaration computes to `unset` —
       and it still WINS the cascade first, suppressing whatever lower-specificity
       rule would otherwise have applied. Seven declarations were in this state:
         · --bg-surface-hover — `.accordion-bar:hover .accordion-bar-header`
           (0,3,0) beat admin.html's `.accordion-bar-header:hover` (0,2,0), so
           accordion bars in the queue had NO hover feedback at all.
         · --bg-hover — five dead hover/active states on the PUBLIC app:
           `.reading-list-tab:hover`, `.add-books-mode-tab:hover`, `.tab:hover`,
           `.tab-scroll-btn:hover` (which is `!important`, so it also overrode
           whatever else might have painted there) and `.more-sheet-item:active`.
         · --bg-body — the Tiptap popover inputs had no background.

       Each is mapped to the closest semantic token rather than to a literal
       colour, so they follow the palette from here on. The now-dead fallbacks
       left in admin.css/style.css are harmless and were not touched.

       NEW CODE SHOULD USE THE CANONICAL NAMES on the right-hand side. These
       exist so two large stylesheets did not have to be rewritten to gain them.

       Deliberately NOT aliased:
         · --accent-rgb — it had exactly one appearance, as the unreachable
           fallback of a var() whose own variable is always declared. The dead
           fallback was removed from style.css rather than given a value here.
         · --progress, --split-sidebar-width — set per-element from JS
           (save-offline.js, navigation.js). A :root default would be wrong. */

    /* admin.css */
    --accent-color: var(--accent);              /* .admin-page-input:focus — matches .form-input:focus */
    --bg-primary: var(--bg-surface);            /* .pill-current, .admin-page-input */
    --bg-secondary: var(--segmented-track-bg);  /* .pill-nav track, card cover ground, icon-button hover */
    --bg-surface-hover: var(--accent-light);    /* .accordion-bar hover tint */
    --border-color: var(--border);              /* pill nav, .admin-page-input — matches .form-input */
    --border-light: var(--border);              /* .autocomplete-item separator */
    --green: var(--badge-success-text);         /* .btn-approve:hover text + border */
    --green-bg: var(--badge-success-bg);        /* .btn-approve:hover fill */
    --red-bg: var(--badge-danger-bg);           /* .btn-flag:hover fill — pairs with --red above */

    /* style.css */
    --bg-hover: var(--accent-light);            /* tab + sheet-item hover/active tint */
    --bg-body: var(--bg-surface);               /* Tiptap popover inputs — matches .form-input */
    --danger: var(--badge-danger-text);         /* .clear-history-btn:hover. Its #ef4444 fallback
                                                   measured under AA; this token is 5.9:1. */
}

/* ======================== BASE STYLES ======================== */
*,
*::before,
*::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    -webkit-tap-highlight-color: transparent;
}

html {
    font-size: 16px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    max-width: 100vw;
    overflow-x: hidden;
    text-size-adjust: 100%;
    -webkit-text-size-adjust: 100%;
}

img, video, canvas, iframe {
    max-width: 100%;
    height: auto;
    display: block;
}
svg {
    max-width: 100%;
    height: auto;
}

body {
    font-family: var(--font-arabic);
    font-size: 1.15rem;
    line-height: 2.1;
    font-weight: 400;
    letter-spacing: 0;
    background-color: var(--bg-page);
    color: var(--text-primary);
    overflow-x: hidden;
    min-height: 100dvh;
    transition: background-color 300ms ease, color 300ms ease;
}

[dir="ltr"] body {
    direction: ltr;
    text-align: left;
}

[dir="rtl"] body {
    direction: rtl;
    text-align: right;
}

/* Content whose own script may differ from the page's UI language (e.g. an
   English article title on the Arabic site, or vice versa) uses dir="auto"
   so the browser resolves its bidi direction from its own text. Without this
   rule, text-align would still inherit the page-wide left/right above and
   visually misalign even though the character ordering was already correct. */
[dir="auto"] {
    text-align: start;
}
