/* =============================================================================
   components.css — the component layer BOTH pages render.

   Extracted from style.css so admin.html can stop loading it (CLAUDE.md §3b,
   "Known remaining coupling"). Everything here is reachable from the admin
   panel's DOM as well as the public app's, so it is a shared contract: an edit
   here changes both surfaces, and once the Tauri/Capacitor shells ship it
   changes installed copies that cannot be hot-fixed.

   Load order is base.css → components.css → style.css (public) and
   base.css → components.css → admin.css (admin). Rules appear below in their
   original style.css order, so the cascade among them is unchanged.

   Generated by the split; edit it directly from here on.
   ============================================================================= */

/* ─── UI text uses Inter ─── */

.nav-link,
.btn,
.form-label,
.form-input,
.form-select,
.admin-menu-item,
.badge,
.status-bar,
input,
select,
textarea,
button,
.admin-tab-content h2,
.auth-title,
.auth-card p,
.logo-text,
.confidence-badge {
    font-family: var(--font-ui);
}

/* ─── English / LTR overrides ─── */

.lang-en {
    font-family: var(--font-ui);
    direction: ltr;
    text-align: left;
}

/* ─── Focus ring (accessibility) ─── */

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {

/* Durations are neutralised to a very short NON-zero value rather than 0s
       so transitionend still fires — this codebase does hang timed follow-ups
       off transitions (e.g. the scroll-to-top FAB). */

*, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Public app: every scroll region scrolls (wheel, touch, keyboard, drag) but
   never paints a visible track. Scoped to body[data-display-mode] so the admin
   panel (bare <body>) keeps its native scrollbars. Individual components that
   already set `scrollbar-width: none` are now redundant but harmless. */

body[data-display-mode],
body[data-display-mode] * {
    scrollbar-width: none;          /* Firefox; also propagates body → viewport */
    -ms-overflow-style: none;       /* legacy Edge / IE */
}

body[data-display-mode]::-webkit-scrollbar,
body[data-display-mode] *::-webkit-scrollbar {
    width: 0;
    height: 0;
    display: none;                  /* Chrome, Safari, Chromium Edge */
}

/* The viewport (root) scrollbar — on mobile the page scroll lives on <html>,
   not on a descendant, so the rules above can't reach it. Kept in its own
   block: :has() paired with ::-webkit-scrollbar is rejected by some engines,
   which would drop the whole grouped rule if these shared one. */

html:has(> body[data-display-mode]) { scrollbar-width: none; -ms-overflow-style: none; }

html:has(> body[data-display-mode])::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* ======================== TOAST NOTIFICATIONS ========================
   Markup is built entirely by shared/components/toast.js:

     <div id="global-toast-container" class="toast-container-global">
       <div class="toast-message toast-{info|success|error} toast-visible">

   and on dismissal toast-visible is swapped for toast-hidden, 300ms before the
   node is removed.

   Those names replaced an earlier .toast-container/.toast pair and the
   stylesheet was never updated to follow, so EVERY toast in the app — both
   surfaces, all 20 modules that call showToast() — rendered as unstyled text at
   the end of <body>. The visual design below is the old .toast rule, retargeted.

   Logical properties mean this needs no [dir="ltr"] counterpart. The old
   .toast-container had one only because it positioned with `right`. */

.toast-container-global {
    position: fixed;
    bottom: var(--space-6);
    inset-inline-end: var(--space-6);
    z-index: var(--z-toast);
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    max-width: 380px;
    pointer-events: none;
}

.toast-message {
    background: var(--bg-surface);
    color: var(--text-primary);
    padding: 14px 20px;
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    border-inline-start: 4px solid var(--accent);
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-size: 14px;
    font-weight: 500;
    pointer-events: auto;
    /* Toast text is whatever the caller passed — Arabic from most of the admin
       UI, English from some of it. The container is dir="rtl", so an English
       message starting with a digit gets its number reordered to the far end
       ("3 volumes renumbered" reads as "volumes renumbered 3"). plaintext
       resolves each message's direction from its own first strong character,
       which is what dir="auto" does — done here because toast.js builds the
       node and is shared, guarded code. */
    unicode-bidi: plaintext;
    text-align: start;
    /* The resting, visible state. Kept here rather than on .toast-visible so the
       exit has something to transition FROM once that class is removed. */
    opacity: 1;
    transform: translateY(0);
    transition: opacity 300ms ease, transform 300ms ease;
}

/* Entry is an animation, not a transition: toast.js sets the whole class list
   before inserting the node, so the element is already in its visible state on
   first paint and a transition would have no start value to run from. */
.toast-message.toast-visible {
    animation: toastIn 300ms cubic-bezier(0.18, 0.89, 0.32, 1.28) both;
}

.toast-message.toast-hidden {
    opacity: 0;
    transform: translateY(20px);
}

/* toast-info is the default type and takes the accent border from the base rule. */
.toast-message.toast-error   { border-inline-start-color: #ef4444; }
.toast-message.toast-success { border-inline-start-color: #22c55e; }

@keyframes toastIn {
    from { transform: translateY(20px); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
}

/* ======================== STATUS BAR ======================== */

.status-bar {
    background: var(--bg-elevated);
    border-bottom: 1px solid var(--border);
    padding: var(--space-2) 0;
    font-size: 12px;
    color: var(--text-secondary);
    font-family: var(--font-ui);
}

.status-flex {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.status-badge {
    font-family: var(--font-ui);
    padding: 2px 8px;
    border-radius: var(--radius-full);
    background: var(--bg-page);
    font-size: 11px;
    font-weight: 600;
    color: var(--text-secondary);
}

.status-badge.connected {
    background: var(--accent-light);
    color: var(--accent);
}

/* ======================== CONTAINER ======================== */

.container {
    max-width: 1300px;
    margin: 0 auto;
    padding: 0 var(--space-6);
}

/* ======================== NAVBAR ======================== */

.navbar {
    background: var(--bg-elevated);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: var(--z-navbar);
    padding: 6px 0 0 0;
    max-height: 220px;
    overflow: visible;
    transition: background 300ms ease, border-color 300ms ease,
                max-height 280ms ease, padding 280ms ease, opacity 200ms ease;
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    box-shadow: 0 4px 14px -2px rgba(0, 0, 0, 0.08);
}

/* Set by switchLibraryTab() (app.js) whenever the active library tab is NOT
   All Books — those tabs (Author/Category/Recent) hide the shared
   .search-filter-panel and show their own local .search-grid header
   instead, so the shared bar contributes 0px of chrome here, not the usual
   80px baked into the default --chrome-offset above. */

.navbar-container {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: var(--space-4);
}

/* ─── Logo ─── */

.logo-section {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    text-decoration: none;
    color: var(--text-primary);
    flex-shrink: 0;
}

.logo-icon {
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    margin: 0;
    position: relative;
}

.logo-icon img,
.logo-icon svg {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: contain;
}

.logo-text {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 18px;
    font-weight: 700;
    letter-spacing: -0.03em;
    color: var(--accent);
    white-space: nowrap;
}

/* ─── Nav Links ─── */

.nav-links {
    display: flex;
    align-items: center;
    gap: var(--space-1);
}

.nav-link {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    padding: 6px 14px;
    border-radius: 6px;
    text-decoration: none;
    color: var(--text-secondary);
    font-weight: 500;
    font-size: 13.5px;
    transition: all var(--transition-fast);
    cursor: pointer;
    white-space: nowrap;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.nav-link:hover {
    color: var(--accent);
    background: rgba(15, 118, 110, 0.07);
}

.nav-link.active {
    color: var(--accent) !important;
    background: rgba(15, 118, 110, 0.10) !important;
    font-weight: 600;
    border-radius: 6px !important;
    position: relative;
    z-index: var(--z-navbar-active);
}

/* ======================== MAIN WRAPPER ======================== */

.main-wrapper {
    padding: 0;
}

.screen { display: none; }

.screen.active {
    display: block;
    animation: fadeSlideIn 300ms ease forwards;
}

/* ── Boot screen (pre-JS) ────────────────────────────────────────────────
   index.html hardcodes #screen-home as .active, so without these rules the
   homepage is what gets painted for every URL until app.js runs at the bottom
   of the page. The inline <head> script stamps data-boot-screen from the URL
   before the body is parsed; these rules make it win for that window only —
   preselectScreenFromPath() removes the attribute as soon as it has set the
   real .active class, so nothing here can fight the router afterwards.
   No animation: this is the first paint, there is nothing to transition. */

@keyframes fadeSlideIn {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ======================== PANEL ======================== */

.panel {
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--space-6);
    box-shadow: var(--shadow-md);
    margin-bottom: var(--space-6);
    transition: background-color var(--transition-base), border-color var(--transition-base),
                color var(--transition-base), box-shadow var(--transition-base);
}

/* ======================== BUTTONS ======================== */

.btn {
    font-family: var(--font-ui);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: 10px 20px;
    border-radius: var(--radius-md);
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    border: 1px solid var(--border);
    background: var(--bg-surface);
    color: var(--text-primary);
    transition: all var(--transition-fast);
    white-space: nowrap;
}

.btn:hover {
    background: var(--bg-page);
    border-color: var(--border-strong);
}

.btn:active {
    transform: scale(0.97);
    transition: transform 100ms ease;
}

/* Lucide icons inside buttons */

.btn i[data-lucide] {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
}

.btn-primary {
    background: var(--accent);
    color: #fff;
    border-color: var(--accent);
    box-shadow: 0 4px 12px rgba(45,106,79,0.15);
}

.btn-primary:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
}

.btn-accent {
    background: var(--accent);
    color: #fff;
    border-color: var(--accent);
}

.btn-accent:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
}

.btn-danger {
    background: #ef4444;
    color: #fff;
    border-color: #ef4444;
}

.btn-danger:hover {
    background: #dc2626;
    border-color: #dc2626;
}

.btn-sm {
    padding: 6px 14px;
    font-size: 13px;
    border-radius: var(--radius-sm);
}

.btn-icon {
    width: 40px;
    height: 40px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-md);
    border: 1px solid var(--border);
    background: var(--bg-surface);
    cursor: pointer;
    font-size: 18px;
    color: var(--text-secondary);
    transition: background var(--transition-fast), border-color var(--transition-fast),
                color var(--transition-fast), transform var(--transition-fast);
}

.btn-icon:hover {
    background: var(--accent-light);
    border-color: var(--accent);
    color: var(--accent);
}

.btn-icon:active {
    transform: scale(0.97);
    transition: transform 100ms ease;
}

/* ======================== FORMS ======================== */

.form-group { margin-bottom: 18px; }

.form-label {
    font-family: var(--font-ui);
    display: block;
    font-size: 13px;
    font-weight: 600;
    margin-bottom: 6px;
    color: var(--text-primary);
}

.form-input,
.form-select {
    width: 100%;
    padding: var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--bg-surface);
    color: var(--text-primary);
    font-family: var(--font-arabic);
    font-size: 15px;
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.form-input:focus,
.form-select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--focus-ring);
}

.form-input::placeholder { color: var(--text-muted); }

/* ======================== BADGES ======================== */

.badge {
    font-family: var(--font-ui);
    font-size: 11px;
    padding: 2px 8px;
    border-radius: var(--radius-full);
    font-weight: 500;
    background: var(--bg-page);
    color: var(--text-secondary);
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

/* Search box */

.search-icon {
    position: absolute;
    left: 14px;
    right: auto;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-muted);
    pointer-events: auto;
    cursor: pointer;
    transition: color 0.2s ease;
}

.search-icon:hover {
    color: var(--accent);
}

[dir="ltr"] .search-icon,
html[dir="ltr"] .search-icon {
    left: auto;
    right: 14px;
}

/* ======================== BOOK CARD (grid view) ======================== */

.book-card {
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    /* Grid items with overflow:hidden default their automatic minimum size to
       0 (instead of their content size), which lets CSS Grid's auto-sized rows
       collapse every card toward just its title line — squashing the
       aspect-ratio cover box and everything below it to ~0px height. Restoring
       an explicit min-content floor keeps the cover, author, and category
       visible at full size. */
    min-height: min-content;
    transition: transform var(--transition-base), box-shadow var(--transition-base);
    box-shadow: var(--shadow-sm);
    cursor: pointer;
}

.book-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
    border-color: var(--accent);
}

/* ======================== AUTH SCREEN ======================== */

.auth-container {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 60vh;
}

.auth-card {
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    padding: var(--space-10);
    width: 100%;
    max-width: 440px;
}

.auth-header {
    text-align: center;
    margin-bottom: 28px;
}

.auth-title {
    font-family: var(--font-ui);
    font-size: 24px;
    font-weight: 700;
    color: var(--accent);
}

/* .admin-grid / .admin-sidebar / .admin-menu-item layout now live entirely in
   admin.css (single-pane drill-down at every width — see that file). This
   used to duplicate a fixed-height, permanent-two-column version here, which
   silently won the cascade for any property admin.css didn't re-declare
   (height/overflow on .admin-grid, max-height/overflow-y on
   .admin-content-area below) since style.css loads first but these were
   never actually removed after the admin.css split — that's what caused the
   sidebar-menu-and-content-both-visible overlap bug. .admin-sidebar-header
   has no admin.css equivalent, so it stays. */

.admin-sidebar-header {
    text-align: center;
    margin-bottom: var(--space-6);
    border-bottom: 1px solid var(--border);
    padding-bottom: var(--space-4);
}

.admin-sidebar-header h3 {
    font-family: var(--font-ui);
    color: var(--accent);
    font-weight: 700;
    font-size: 16px;
}

.admin-sidebar-header span {
    font-size: 12px;
    color: var(--text-secondary);
}

.admin-content-area {
    min-width: 0;
}

.admin-tab-content { display: none; }

.admin-tab-content[style*="display: block"] { display: block !important; }

/* ─── Metadata Edit Grid ─── */

.meta-edit-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-3);
}

/* ─── Upload Dropzone ─── */

.upload-dropzone-icon {
    font-size: 48px;
    color: var(--accent);
    margin-bottom: var(--space-3);
    opacity: 0.8;
}

/* ─── Confidence badges ─── */

.confidence-badge {
    display: inline-block;
    padding: 2px 10px;
    border-radius: var(--radius-full);
    font-size: 11px;
    font-weight: 600;
}

/* ======================== RESPONSIVE ======================== */

@media (max-width: 1024px) {

.logo-icon {
        width: 55px;
        height: 48px;
        margin: 0;
    }

.logo-text,
    [lang="ar"] .logo-text,
    [lang="ur"] .logo-text {
        font-size: 22px;
    }
}

@media (max-width: 768px) {

/* Allow body to scroll on mobile only if the PDF reader is not active */

.container { padding: 0 var(--space-3); }

.main-wrapper { padding: 0; }

/* .library-tabs-bar .container's desktop padding-inline-start:240px (the
       sidebar clearance) has equal-or-higher specificity than the bare
       .container reset above for that one property, so `padding-inline-start`
       specifically stayed 240px on mobile even though top/bottom/inline-end
       correctly reset — 240px eats most of a 375px screen and squeezes the
       segmented tab track to one edge. Same selector here (matching
       specificity, later in the cascade) properly resets it. */

.navbar-container { flex-wrap: wrap; gap: var(--space-2); }

/* env() adds the notch/status-bar inset only in standalone PWA on notched
       devices; it resolves to 0 in normal browsers, so no visual change there. */

.navbar { padding: var(--space-2) 0; padding-top: calc(var(--space-2) + env(safe-area-inset-top, 0px)); }

.nav-links {
        width: 100%;
        overflow-x: auto;
        gap: 8px;
        flex-wrap: nowrap;
    }

.nav-link {
        font-size: 12px;
        padding: 6px 10px;
        flex-shrink: 0;
    }

.logo-icon {
        width: 46px;
        height: 40px;
        margin: 0;
    }

.logo-text,
    [lang="ar"] .logo-text,
    [lang="ur"] .logo-text { font-size: 19px; }

/* Urdu (Nastaliq) forces 21px / line-height 2.1 on all chrome controls for
       elderly legibility (the [lang="ur"] block near the top). On a phone that
       makes the navbar, its dropdown menu, the filter selects and the search box
       oversized and cramped, so scale them back to phone size here — still
       legible, just fitting the narrow screen. !important is required to beat
       those global rules. */

[lang="ur"] .nav-link {
        font-size: 14px !important;
        line-height: 1.7 !important;
        padding: 6px 10px !important;
    }

[lang="ur"] .logo-text { font-size: 18px !important; line-height: 1.4 !important; }

[lang="ur"] .form-select,
[lang="ur"] .form-input,
[lang="ur"] .search-input,
[lang="ur"] select {
        font-size: 14px !important;
        line-height: 1.6 !important;
    }

/* Centered dialogs (auth, volume picker, article preview, …): never let a
       tall modal overflow the screen with its buttons off-screen — cap the
       height and let the card scroll instead. (Widths stay as each modal sets
       them inline, which are already responsive: width:90%/max-width.) */

.modal-content {
        max-height: 90vh;
        overflow-y: auto;
    }

/* Dim the page behind the open sheet. pointer-events:none keeps the existing
       tap-outside-to-close behaviour working through the dim. */
}

@media (max-width: 480px) {

.logo-icon {
        width: 38px;
        height: 33px;
        margin: 0;
    }

.logo-text,
    [lang="ar"] .logo-text,
    [lang="ur"] .logo-text { font-size: 17px; }

.status-flex { flex-direction: column; gap: 6px; }

/* ─── OPFS local books (still uses .book-bar) ─── */

.book-card { flex-direction: column; align-items: flex-start; }

.meta-edit-grid { grid-template-columns: 1fr; }

.admin-sidebar {
        display: flex;
        overflow-x: auto;
        padding: var(--space-3);
        gap: 4px;
        flex-wrap: nowrap;
    }

.admin-sidebar .admin-sidebar-header { display: none; }

.admin-menu-item { white-space: nowrap; font-size: 12px; padding: var(--space-2) var(--space-3); margin-bottom: 0; flex-shrink: 0; }

.auth-card { padding: var(--space-6); margin: 0 var(--space-2); }

.book-card { padding: var(--space-2) var(--space-3); }

.btn { padding: 8px 14px; font-size: 13px; min-height: 44px; min-width: 44px; }

.btn-icon { min-height: 44px; min-width: 44px; }

/* .book-row's action icons are a vertical strip on mobile (sized 40px by
       the .book-row-actions rule in the ≤768px block — more specific, so it
       wins). Only .book-bar (OPFS local books) keeps the 44px min here. */

.upload-dropzone-icon { font-size: 32px; }

.panel { padding: var(--space-4); }
}

/* ═══════════════════════════════════════════════════════════
   LTR Overrides (English mode)
   ═══════════════════════════════════════════════════════════ */

[dir="ltr"] .navbar-container {
  flex-direction: row;
}

/* Book listings (rows, cards, header) always read as Arabic/Urdu content —
   cover/title/metadata position must stay put regardless of which language
   the UI chrome is in, since an English interface doesn't mean the book data
   is in English. Forcing RTL here (rather than only patching individual
   text-align rules) keeps flex/grid child order, text alignment, and
   justify-content all consistent in one place instead of fighting the
   [dir="ltr"] cascade rule-by-rule as new row/card elements get added. */

[dir="ltr"] .nav-links {
  margin-right: auto;
  margin-left: 0;
}

[dir="ltr"] .accordion-bar-header {
  flex-direction: row;
}

[dir="ltr"] .confirm-dialog-actions {
  flex-direction: row;
}

[dir="ltr"] .form-group {
  text-align: left;
}

[dir="ltr"] .admin-sidebar {
  border-right: none;
  border-left: 1px solid var(--border);
  left: 0;
  right: auto;
}

[dir="ltr"] .modal-content {
  text-align: left;
}

/* Was capped at 1420px (barely above the 1300px base) so a maximized browser
   on a large/full-screen monitor still left large empty margins on both
   sides instead of using the extra width. */

@media (min-width: 1440px) {

.container {
        max-width: 1760px;
    }
}

/* ─── Tablet & iPad Screens (769px to 1024px) ─── */

@media (min-width: 769px) and (max-width: 1024px) {

.container {
        padding: 0 var(--space-4);
    }

.nav-link {
        padding: 8px 12px;
        font-size: 13.5px;
    }
}

@media (max-width: 768px) {

/* Hide horizontal scrollbar on mobile nav links for clean UI */

.nav-links {
        -ms-overflow-style: none;
        scrollbar-width: none;
    }

.nav-links::-webkit-scrollbar {
        display: none;
    }
}

/* Clickable elements get pointer cursor and user-select: none to prevent I-beam selection cursor */

.btn,
.btn-icon,
.nav-link,
.logo-section,
.admin-menu-item {
    cursor: pointer !important;
    user-select: none;
    -webkit-user-select: none;
}

/* Premium Brand Logo Micro-Animation */

.logo-section .logo-icon img,
.logo-section .logo-icon svg {
    transition: transform var(--transition-base), filter var(--transition-base);
}

.logo-section:hover .logo-icon img,
.logo-section:hover .logo-icon svg {
    transform: rotate(-4deg) scale(1.06);
    filter: drop-shadow(0 2px 6px rgba(180, 140, 80, 0.45));
}

/* Buttons Hover Elevation & Click Press */

.btn:hover {
    transform: translateY(-1.5px);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
}

.btn:active {
    transform: translateY(0) scale(0.97) !important;
}

/* Book Card Hover Elevation scale */

.book-card {
    transition: all var(--transition-slow) !important;
}

.book-card:hover {
    transform: translateY(-3px) scale(1.01);
    box-shadow: var(--shadow-lg);
    border-color: var(--accent);
}

/* Language-specific font classes for article blocks */

.font-naskh {
  font-family: 'Noto Naskh Arabic', serif;
  line-height: 1.9;
  font-size: 18px;
}

/* Select dropdowns in toolbar */

.toolbar-select {
  font-size: 13px;
  padding: 6px 28px 6px 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-surface) url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23475569' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat right 8px center/14px;
  color: var(--text-primary);
  cursor: pointer;
  font-weight: 600;
  outline: none;
  appearance: none;
  transition: all 0.15s ease;
}

.toolbar-select:hover {
  border-color: var(--accent);
}

/* Autosave Pill */

.editor-autosave-status-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border-radius: 9999px;
  background-color: var(--accent-light);
  color: var(--accent);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.1px;
}

.editor-autosave-status-pill .status-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background-color: currentColor;
}

.editor-autosave-status-pill.saving {
  background-color: #fef3c7;
  color: #b45309;
}

.editor-autosave-status-pill.offline {
  background-color: #fef2f2;
  color: #dc2626;
}

/* Canvas + Sidebar Split */

.fullscreen-editor-canvas-container {
  flex: 1;
  display: flex;
  position: relative;
  overflow-y: auto;
  overflow-x: hidden;
  height: calc(100vh - 104px);
}

.fullscreen-editor-canvas {
  flex: 1;
  max-width: 740px;
  width: 100%;
  margin: 0 auto;
  padding: 40px 24px 120px 24px;
  overflow: visible;
}

/* Link and Footnote Popovers */

.tiptap-link-popover, .tiptap-footnote-popover, .tiptap-image-bubble {
  position: absolute;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.15);
  padding: 10px;
  z-index: var(--z-editor-popover);
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 250px;
}

.tiptap-link-popover input, .tiptap-footnote-popover textarea, .tiptap-image-bubble input {
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 13px;
  background: var(--bg-body);
  color: var(--text-primary);
  outline: none;
}

.popover-actions, .bubble-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}

.btn-xs {
  padding: 4px 8px;
  font-size: 11px;
  font-weight: 700;
  border-radius: 4px;
  cursor: pointer;
}

.btn-icon-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 4px;
  border-radius: 4px;
  color: var(--text-muted);
  transition: color 0.15s;
}

.btn-icon-link:hover {
  color: var(--accent);
}

/* Footnotes rendering */

.footnote-marker {
  color: var(--accent);
  cursor: pointer;
  font-weight: 700;
  padding: 0 2px;
}

.footnote-marker:hover {
  text-decoration: underline;
}

/* Footnotes Section at the bottom */

.footnotes-section {
  margin-top: 48px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

.footnotes-section-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--text-secondary);
  margin-bottom: 8px;
}

.footnotes-list {
  padding-inline-start: 20px;
  margin: 0;
}

.footnotes-list-item {
  font-size: 12.5px;
  color: var(--text-muted);
  line-height: 1.6;
  margin-bottom: 6px;
}

/* Mobile responsive horizontal carousel toolbar */

@media (max-width: 768px) {

.tiptap-toolbar {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none; /* Firefox */
    padding: 6px 16px;
    height: 48px;
    top: 56px;
  }

.tiptap-toolbar::-webkit-scrollbar {
    display: none; /* Safari / Chrome */
  }

.toolbar-divider {
    height: 16px;
    flex-shrink: 0;
  }

.toolbar-group {
    flex-shrink: 0;
  }

.toolbar-select {
    padding-top: 4px;
    padding-bottom: 4px;
    font-size: 12px;
  }

.fullscreen-editor-canvas-container {
    height: calc(100vh - 96px);
  }

.fullscreen-editor-header {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none; /* Hide scrollbar Firefox */
    justify-content: flex-start;
    gap: 12px;
    padding: 0 16px;
    -webkit-overflow-scrolling: touch;
  }

.fullscreen-editor-header::-webkit-scrollbar {
    display: none; /* Hide scrollbar Safari/Chrome */
  }

.editor-header-left,
  .editor-header-center,
  .editor-header-right {
    flex-shrink: 0;
  }
}

/* Fullscreen Immersive Article Writer Workspace */

.fullscreen-editor-workspace {
  position: fixed !important;
  top: 0 !important;
  left: 0 !important;
  right: 0 !important;
  bottom: 0 !important;
  width: 100vw !important;
  height: 100vh !important;
  height: 100dvh !important;
  background-color: var(--bg-surface) !important;
  z-index: var(--z-fullscreen) !important;
  overflow-y: auto !important;
  display: flex;
  flex-direction: column;
}

.fullscreen-editor-header {
  position: sticky;
  top: 0;
  left: 0;
  height: 56px;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 24px;
  z-index: var(--z-navbar);
}

.editor-header-left, .editor-header-right {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* Sticky Toolbar */

.tiptap-toolbar {
  position: sticky;
  top: 56px;
  left: 0;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 24px;
  z-index: var(--z-tabs-bar-offline);
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.tiptap-toolbar::-webkit-scrollbar {
  display: none;
}

.toolbar-group {
  display: flex;
  align-items: center;
  gap: 4px;
}

.toolbar-divider {
  width: 1px;
  height: 20px;
  background-color: var(--border);
  margin: 0 4px;
}

.toolbar-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--text-primary);
  cursor: pointer;
  transition: all 0.15s ease;
}

.toolbar-btn i, .toolbar-btn svg {
  width: 16px;
  height: 16px;
}

.toolbar-btn:hover {
  background-color: var(--border);
  color: var(--accent);
}

.toolbar-btn.active {
  background-color: var(--accent-light);
  color: var(--accent);
  border-color: var(--accent);
}

/* Centered writing canvas */

.fullscreen-editor-canvas {
  flex: 1;
  max-width: 740px;
  width: 100%;
  margin: 0 auto;
  padding: 40px 24px 120px 24px;
  display: flex;
  flex-direction: column;
}

.write-article-title-input {
  width: 100%;
  font-family: inherit;
  font-size: 2.4rem;
  font-weight: 800;
  line-height: 1.2;
  border: none;
  background: transparent;
  color: var(--text-primary);
  outline: none;
  margin-bottom: 24px;
  padding: 0;
  box-sizing: border-box;
}

.write-article-title-input::placeholder {
  color: var(--text-muted);
  opacity: 0.5;
}

/* Tiptap Container & Editor Canvas */

.tiptap-container {
  flex: 1;
  outline: none;
  min-height: 400px;
}

/* Status badges */

.status-badge {
  font-size: 11px;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 9999px;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}

/* ═══════════════════════════════════════════════════════════════════
   iOS Safari zoom-jump fix — any focused input under 16px font-size
   makes Safari zoom the whole viewport in, forcing the user to manually
   pinch back out. Desktop sizing (13-15px, deliberately compact) is left
   alone since the bug is mobile-Safari-only; this only overrides the
   affected inputs at the same ≤768px breakpoint the rest of the mobile
   layout already switches on.
   ═══════════════════════════════════════════════════════════════════ */

@media (max-width: 768px) {

.form-input,
.form-select,
[lang="ur"] .form-select,
[lang="ur"] .form-input {
        font-size: 16px !important;
    }
}

/* Medium-Style Writer Canvas Override */

.fullscreen-editor-canvas {
  background: var(--bg-surface);
  border: none;
  border-radius: 0;
  box-shadow: none;
  margin: 0 auto;
  padding: 48px 40px;
  max-width: 780px;
}

/* Media Query Responsive Adjustments */

@media (max-width: 640px) {

.fullscreen-editor-canvas {
    padding: 24px 16px;
    margin: 0;
    border-radius: 0;
  }
}

/* ======================== KEYBOARD FOCUS RING (BUTTONS) ========================
   The bare `:focus-visible` rule near the top of this file gives every element a
   2px --accent outline, but buttons are what a keyboard user actually traverses
   — four icon buttons per book card, fifty cards per page — and against this
   palette a plain outline alone reads as barely more than the browser default.
   This adds the same soft --focus-ring halo the text inputs already render
   (.form-input:focus, .search-box-wrapper input:focus, .primary-search-input:focus),
   so focus looks consistent whichever control you land on.

   Lives at the END of the file on purpose: the many `.btn:hover` /
   `.btn-icon:hover` box-shadow rules above are the same specificity, and at a
   tie the later rule wins. Patching this in near the top would have been
   silently overridden — the exact trap CLAUDE.md warns about.

   `:focus-visible`, never `:focus`, so a mouse click leaves no ring. No
   `outline: none` anywhere here: the outline IS the indicator, the box-shadow
   only thickens it.

   Visible in all three themes without a per-theme override — the outline is
   drawn in --accent, offset 2px so it sits on the page background rather than
   on the control's own fill (which matters for accent-filled .btn-primary):
     light  --accent #1B4332 on #F6F4EF -> 10.4:1
     dark   --accent #D4A017 on #1C1B19 ->  7.8:1
     sepia  --accent #7A2E1D on #DDD4C0 ->  6.8:1
   all far above the 3:1 WCAG asks of a non-text focus indicator. The halo
   colour --focus-ring is a low-alpha tint (0.25 / 0.25 / 0.20) and is
   decorative only, so sepia's slightly lower alpha needs no special-casing. */

button:focus-visible,
a.btn:focus-visible,
.btn:focus-visible,
.btn-icon:focus-visible,
[role="button"]:focus-visible,
summary:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    box-shadow: 0 0 0 4px var(--focus-ring);
}

/* ─── Modal Dialog Overlay System (createModal) ─── */

.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    z-index: 2500;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
    box-sizing: border-box;
}

.modal-content {
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.2), 0 10px 10px -5px rgba(0, 0, 0, 0.1);
    width: 100%;
    max-width: 540px;
    max-height: 88vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    margin: auto;
}

.modal-content.modal-wide {
    max-width: 740px;
}

.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px;
    border-bottom: 1px solid var(--border);
    background: var(--bg-elevated, var(--bg-surface));
}

.modal-header h3 {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--accent);
}

.modal-close {
    background: transparent;
    border: none;
    font-size: 1.5rem;
    line-height: 1;
    color: var(--text-muted);
    cursor: pointer;
    padding: 4px 10px;
    border-radius: var(--radius-md);
    transition: color 0.15s ease, background 0.15s ease;
}

.modal-close:hover {
    color: var(--text-primary);
    background: var(--bg-elevated);
}

.modal-body {
    padding: 20px;
    overflow-y: auto;
    flex: 1;
}
