/* ========================================
   Magazooms Reader v2 - Core Styles
   ======================================== */

:root {
    --color-bg: #1a1a1a;
    --color-surface: #242424;
    --color-toolbar: #2a2a2a;
    --color-text: #f0f0f0;
    --color-text-muted: #999;
    --color-accent: #c0392b;
    --color-accent-hover: #e74c3c;
    --color-border: #333;
    --toolbar-height: 48px;
    --transition: 0.2s ease;
    --radius: 6px;
    --shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
    height: 100%;
    overflow: hidden;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 14px;
    background: var(--color-bg);
    color: var(--color-text);
    -webkit-tap-highlight-color: transparent;
    -webkit-touch-callout: none;
}

/* ========================================
   Layout
   ======================================== */

.reader-app {
    display: grid;
    grid-template-rows: var(--toolbar-height) 1fr auto;
    height: 100vh;
    height: 100dvh; /* Dynamic viewport height — accounts for mobile browser chrome */
    width: 100vw;
}

/* ========================================
   Toolbars
   ======================================== */

.toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 12px;
    background: var(--color-toolbar);
    z-index: 100;
}

/* Bottom toolbar hosts the stacked page tracker (slider on top, page info
   below), so it grows a bit taller than the fixed top toolbar. */
.toolbar-bottom {
    min-height: var(--toolbar-height);
    padding-top: 6px;
    padding-bottom: 6px;
    align-items: center;
}
.toolbar-bottom .toolbar-left { align-items: stretch; }
.toolbar-bottom .toolbar-right { align-items: center; }

.toolbar-left,
.toolbar-center,
.toolbar-right {
    display: flex;
    align-items: center;
    gap: 8px;
}

.toolbar-left, .toolbar-right { flex: 1; }
.toolbar-right { justify-content: flex-end; }
.toolbar-center {
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    white-space: nowrap;
    flex: 2;                 /* let the tracker take more of the bar for many-page pubs */
    min-width: 0;
}
/* Slider on top, page-info label beneath it. */
.toolbar-center .slider-track { order: 1; }
.toolbar-center .page-indicator { order: 2; }

.toolbar-btn {
    background: none;
    border: none;
    color: var(--color-text);
    cursor: pointer;
    padding: 8px 12px;
    border-radius: var(--radius);
    font-size: 16px;
    transition: background var(--transition);
    position: relative;
}

.toolbar-btn:hover { background: rgba(255, 255, 255, 0.1); }
.toolbar-btn:active { background: rgba(255, 255, 255, 0.15); }

.pub-title {
    font-size: 13px;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
    min-width: 0;
    display: block;
}

.app-version {
    font-size: 10px;
    color: var(--color-text-muted);
    opacity: 0.5;
}

/* Stack version over the privacy/help icons to conserve horizontal space. */
.bottom-left-stack {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-end;   /* push content to the bottom, aligning version with page tracker text */
    gap: 3px;
    line-height: 1.1;
    height: 100%;
}
.bottom-left-stack .app-version { margin: 0; }
/* Row of Privacy / Help icons — give them breathing room + tap padding. */
.bottom-left-stack .icon-row { display: flex; align-items: center; gap: 14px; }
.bottom-left-stack .icon-row > a,
.bottom-left-stack .icon-row > button { padding: 4px 6px; }

.page-indicator {
    font-size: 12px;
    color: var(--color-text-muted);
    white-space: nowrap;
    min-width: 60px;
    max-width: 140px;
    text-align: center;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 4px;
    padding: 2px 8px;
    outline: none;
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s;
    font-family: inherit;
}
.page-indicator:hover {
    border-color: var(--color-border, #444);
}
.page-indicator:focus {
    border-color: var(--color-accent, #c0392b);
    background: var(--color-surface, #222);
    cursor: text;
    color: var(--color-text);
}

.slider-track {
    position: relative;
    width: 100%;
    max-width: 520px;
    height: 20px;
    display: flex;
    align-items: center;
    margin: 0 auto;
}

.slider-track::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    height: 2px;
    background: var(--color-border);
    border-radius: 1px;
    transform: translateY(-50%);
    pointer-events: none;
}

.slider-track::after {
    content: '';
    position: absolute;
    top: 3px;
    bottom: 3px;
    left: 0;
    right: 0;
    background-image: repeating-linear-gradient(
        to right,
        rgba(255, 255, 255, 0.4) 0px,
        rgba(255, 255, 255, 0.4) 1px,
        transparent 1px,
        transparent 12px
    );
    pointer-events: none;
    z-index: 0;
}

.page-slider {
    width: 100%;
    height: 14px;
    -webkit-appearance: none;
    appearance: none;
    background: transparent;
    outline: none;
    cursor: pointer;
    position: relative;
    z-index: 1;
    margin: 0;
}

.page-slider::-webkit-slider-runnable-track {
    height: 2px;
    background: transparent;
}

.page-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 12px;
    height: 12px;
    background: var(--color-accent);
    border-radius: 50%;
    cursor: pointer;
    margin-top: -5px;
}

.page-slider::-moz-range-track {
    height: 2px;
    background: transparent;
    border: none;
}

.page-slider::-moz-range-thumb {
    width: 12px;
    height: 12px;
    background: var(--color-accent);
    border-radius: 50%;
    cursor: pointer;
    border: none;
}

.cart-badge {
    position: absolute;
    top: 2px;
    right: 2px;
    background: var(--color-accent);
    color: #fff;
    font-size: 10px;
    min-width: 16px;
    height: 16px;
    line-height: 16px;
    text-align: center;
    border-radius: 8px;
    padding: 0 4px;
}

/* Search field */
.search-field {
    position: relative;
    display: flex;
    align-items: center;
    background: rgba(255,255,255,0.08);
    border: 1px solid rgba(255,255,255,0.15);
    border-radius: var(--radius);
    padding: 4px 10px;
    width: 200px;
}
#panelSearch .search-field {
    width: 100%;
}

.search-field .search-icon {
    color: rgba(255,255,255,0.5);
    font-size: 13px;
    margin-right: 8px;
}

.search-field input {
    background: none;
    border: none;
    color: #fff;
    font-size: 13px;
    outline: none;
    width: 100%;
}

.search-field input::placeholder {
    color: rgba(255,255,255,0.4);
}

.search-clear {
    background: none;
    border: none;
    color: var(--color-text-muted);
    font-size: 16px;
    cursor: pointer;
    padding: 0 4px;
}

/* Search results dropdown */
.search-results-dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    max-height: 300px;
    overflow-y: auto;
    z-index: 200;
    margin-top: 4px;
    display: none;
}

.search-results-dropdown.open {
    display: block;
}

.search-result-item {
    padding: 8px 12px;
    cursor: pointer;
    border-bottom: 1px solid var(--color-border);
    font-size: 12px;
}

.search-result-item:hover {
    background: rgba(255,255,255,0.05);
}

.search-result-item .result-page {
    color: var(--color-accent);
    font-weight: 500;
    margin-right: 8px;
}

.search-result-item .result-context {
    color: var(--color-text-muted);
}

/* ========================================
   Viewer / Page Display
   ======================================== */

.viewer {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    background: var(--color-bg);
}

.page-container {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    /* We handle all pinch/pan/zoom ourselves; tell the browser not to run its
       own native pinch-zoom or double-tap-zoom on the page surface (iOS Safari
       ignores user-scalable=no, so touch-action is the reliable lever). */
    touch-action: none;
}

.page-layer {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: opacity 0.25s ease;
    transform-origin: 0 0;
}

/* Cover title placeholder while image loads */
.cover-title-placeholder {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    /* Sit in the upper portion of the page so the splash logo/title clears the
       vertically-centered "Not For Public Release" preview banner (which is
       centered at ~50vh). Raised from 25vh so there is no overlap. */
    padding-top: 8vh;
    z-index: 10;
    pointer-events: none;
}

.cover-title-placeholder .cover-logo {
    display: block;
    max-width: 220px;
    max-height: 72px;
    width: auto;
    height: auto;
    margin: 0 0 22px 0;
    object-fit: contain;
    opacity: 0.95;
}

@media (max-width: 640px) {
    .cover-title-placeholder .cover-logo {
        max-width: 60vw;
        max-height: 56px;
        margin-bottom: 16px;
    }
}

.cover-title-placeholder h1 {
    font-size: 24px;
    font-weight: 300;
    letter-spacing: 1px;
    margin: 0;
    color: var(--color-text);
    text-align: center;
}

.cover-title-placeholder .cover-account {
    font-size: 24px;
    color: var(--color-text);
    margin: 0 0 6px 0;
    font-weight: 300;
    opacity: 0.7;
}

.cover-title-placeholder .cover-publication {
    font-size: 24px;
    color: var(--color-text);
    margin: 0 0 16px 0;
    font-weight: 300;
    opacity: 0.85;
}

.cover-title-placeholder p {
    margin: 0;
}

.cover-title-placeholder.fade-out {
    animation: titleFadeOut 0.5s ease forwards;
}

@keyframes titleFadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

@keyframes titleFadeOut {
    from { opacity: 1; }
    to { opacity: 0; pointer-events: none; }
}

/* Cover entrance animation — no longer used, cover fades via JS */

.page-layer.active {
    opacity: 1;
    z-index: 2;
    transition: opacity 0.6s ease;
    visibility: visible;
}

.page-layer.buffer {
    opacity: 0;
    z-index: 1;
    transition: none;
    visibility: hidden;
}

.page-layer.revealing {
    opacity: 1;
    z-index: 1;
    transition: none;
    visibility: visible;
}

.page-layer.dissolving {
    opacity: 0;
    z-index: 2;
    transition: opacity 0.6s ease;
}

.page-layer.spread-mode {
    gap: 0;
}
.page-layer.spread-mode .page-left {
    justify-content: flex-end;
}
.page-layer.spread-mode .page-right {
    justify-content: flex-start;
}
.page-layer.spread-mode .page-canvas {
    box-shadow: none;
}


.page-slot {
    position: relative;

    display: flex;
    align-items: center;
    justify-content: center;
}

/* The COVER must always mask whatever sits behind it in its slot — the page-1
   canvas can render a hair larger than the WebP cover from sub-pixel rounding,
   letting the canvas's WHITE page background peek past the darker cover art on
   the right/bottom edges. Painting the cover's single slot with the dark reader
   background makes any such overhang dark-on-dark (invisible) without touching
   the cover fade/transition. Scoped to the cover layer so ordinary spread pages
   (which legitimately show white pages) are unaffected. */
#layerA .page-slot.page-single {
    background: var(--color-bg);
}


/* A freshly-created .page-canvas is empty with the HTML default 300x150
   footprint. Inside the cover slot (which paints the dark reader background)
   that default box shows as a dark ~300x150 rectangle BEFORE the cover image
   or page bitmap renders — the "empty container" artifact. Collapse the
   unrendered canvas to zero size (not just visibility:hidden, which keeps the
   300x150 layout box and still drives the slot's painted area) until
   drawPageToCanvas() paints real pixels and adds .rendered. */
.page-canvas:not(.rendered) {
    width: 0 !important;
    height: 0 !important;
    visibility: hidden;
}

.page-canvas {
    display: block;
    max-width: 100%;
    /* dvh (dynamic viewport height), NOT vh: on iOS Safari 100vh includes the
       address-bar chrome, so a vh-based cap over-estimated the visible area and
       let a landscape page render taller than the screen (breaking fit +
       centering). dvh tracks the actual visible height. This is only a SAFETY
       cap — drawPageToCanvas sets the authoritative inline width/height from
       computeBaseScale; the cap must never be tighter than that fit. */
    max-height: calc(100dvh - var(--toolbar-height) * 2);
    object-fit: contain;
    width: auto;
    height: auto;
}

/* Loading — circular bubble spinner */
.page-slot.loading,
.page-container.loading {
    position: relative;
}

.page-slot.loading::after,
.page-container.loading::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 10px;
    height: 10px;
    margin: -5px 0 0 -5px;
    border-radius: 50%;
    background: transparent;
    box-shadow:
        0 -24px 0 0 var(--color-accent, #c0392b),
        17px -17px 0 0 var(--color-accent, #c0392b),
        24px 0 0 0 var(--color-accent, #c0392b),
        17px 17px 0 0 var(--color-accent, #c0392b),
        0 24px 0 0 var(--color-accent, #c0392b),
        -17px 17px 0 0 var(--color-accent, #c0392b),
        -24px 0 0 0 var(--color-accent, #c0392b),
        -17px -17px 0 0 var(--color-accent, #c0392b);
    animation: pulsingRing 1.2s ease-in-out infinite;
    z-index: 50;
}

.page-slot.loading canvas {
    opacity: 0;
}

@keyframes pulsingRing {
    0%   { box-shadow: 0 -24px 0 0 var(--color-accent,#c0392b), 17px -17px 0 -3px rgba(192,57,43,0.2), 24px 0 0 -3px rgba(192,57,43,0.2), 17px 17px 0 -3px rgba(192,57,43,0.2), 0 24px 0 -3px rgba(192,57,43,0.2), -17px 17px 0 -3px rgba(192,57,43,0.2), -24px 0 0 -3px rgba(192,57,43,0.2), -17px -17px 0 -3px rgba(192,57,43,0.2); }
    12.5%{ box-shadow: 0 -24px 0 -3px rgba(192,57,43,0.2), 17px -17px 0 0 var(--color-accent,#c0392b), 24px 0 0 -3px rgba(192,57,43,0.2), 17px 17px 0 -3px rgba(192,57,43,0.2), 0 24px 0 -3px rgba(192,57,43,0.2), -17px 17px 0 -3px rgba(192,57,43,0.2), -24px 0 0 -3px rgba(192,57,43,0.2), -17px -17px 0 -3px rgba(192,57,43,0.2); }
    25%  { box-shadow: 0 -24px 0 -3px rgba(192,57,43,0.2), 17px -17px 0 -3px rgba(192,57,43,0.2), 24px 0 0 0 var(--color-accent,#c0392b), 17px 17px 0 -3px rgba(192,57,43,0.2), 0 24px 0 -3px rgba(192,57,43,0.2), -17px 17px 0 -3px rgba(192,57,43,0.2), -24px 0 0 -3px rgba(192,57,43,0.2), -17px -17px 0 -3px rgba(192,57,43,0.2); }
    37.5%{ box-shadow: 0 -24px 0 -3px rgba(192,57,43,0.2), 17px -17px 0 -3px rgba(192,57,43,0.2), 24px 0 0 -3px rgba(192,57,43,0.2), 17px 17px 0 0 var(--color-accent,#c0392b), 0 24px 0 -3px rgba(192,57,43,0.2), -17px 17px 0 -3px rgba(192,57,43,0.2), -24px 0 0 -3px rgba(192,57,43,0.2), -17px -17px 0 -3px rgba(192,57,43,0.2); }
    50%  { box-shadow: 0 -24px 0 -3px rgba(192,57,43,0.2), 17px -17px 0 -3px rgba(192,57,43,0.2), 24px 0 0 -3px rgba(192,57,43,0.2), 17px 17px 0 -3px rgba(192,57,43,0.2), 0 24px 0 0 var(--color-accent,#c0392b), -17px 17px 0 -3px rgba(192,57,43,0.2), -24px 0 0 -3px rgba(192,57,43,0.2), -17px -17px 0 -3px rgba(192,57,43,0.2); }
    62.5%{ box-shadow: 0 -24px 0 -3px rgba(192,57,43,0.2), 17px -17px 0 -3px rgba(192,57,43,0.2), 24px 0 0 -3px rgba(192,57,43,0.2), 17px 17px 0 -3px rgba(192,57,43,0.2), 0 24px 0 -3px rgba(192,57,43,0.2), -17px 17px 0 0 var(--color-accent,#c0392b), -24px 0 0 -3px rgba(192,57,43,0.2), -17px -17px 0 -3px rgba(192,57,43,0.2); }
    75%  { box-shadow: 0 -24px 0 -3px rgba(192,57,43,0.2), 17px -17px 0 -3px rgba(192,57,43,0.2), 24px 0 0 -3px rgba(192,57,43,0.2), 17px 17px 0 -3px rgba(192,57,43,0.2), 0 24px 0 -3px rgba(192,57,43,0.2), -17px 17px 0 -3px rgba(192,57,43,0.2), -24px 0 0 0 var(--color-accent,#c0392b), -17px -17px 0 -3px rgba(192,57,43,0.2); }
    87.5%{ box-shadow: 0 -24px 0 -3px rgba(192,57,43,0.2), 17px -17px 0 -3px rgba(192,57,43,0.2), 24px 0 0 -3px rgba(192,57,43,0.2), 17px 17px 0 -3px rgba(192,57,43,0.2), 0 24px 0 -3px rgba(192,57,43,0.2), -17px 17px 0 -3px rgba(192,57,43,0.2), -24px 0 0 -3px rgba(192,57,43,0.2), -17px -17px 0 0 var(--color-accent,#c0392b); }
    100% { box-shadow: 0 -24px 0 0 var(--color-accent,#c0392b), 17px -17px 0 -3px rgba(192,57,43,0.2), 24px 0 0 -3px rgba(192,57,43,0.2), 17px 17px 0 -3px rgba(192,57,43,0.2), 0 24px 0 -3px rgba(192,57,43,0.2), -17px 17px 0 -3px rgba(192,57,43,0.2), -24px 0 0 -3px rgba(192,57,43,0.2), -17px -17px 0 -3px rgba(192,57,43,0.2); }
}
.annotations-layer {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 20;
    opacity: 0;
    transition: opacity 0.3s ease 0.5s;
}

.page-layer.active .annotations-layer {
    pointer-events: auto;
    opacity: 1;
}

.annotations-layer > * {
    position: absolute;
    pointer-events: auto;
    cursor: pointer;
    -webkit-tap-highlight-color: rgba(192, 57, 43, 0.3);
    touch-action: manipulation;
}

.annotations-layer > *:active {
    background: rgba(192, 57, 43, 0.3) !important;
    outline: 2px solid rgba(192, 57, 43, 0.6);
}

/* ========================================
   Navigation Arrows
   ======================================== */

.nav-arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background: rgba(0, 0, 0, 0.4);
    border: none;
    color: #fff;
    font-size: 36px;
    width: 44px;
    height: 80px;
    cursor: pointer;
    z-index: 50;
    transition: background var(--transition), opacity var(--transition);
    /* Always visible (previously only on .viewer:hover, which never triggers on
       touch and was easy to miss on desktop). Subtle by default, darker on
       hover. */
    opacity: 1;
    border-radius: var(--radius);
}

.viewer:hover .nav-arrow { opacity: 1; }
.nav-arrow:hover { background: rgba(0, 0, 0, 0.7); }
.nav-prev { left: var(--page-gutter, 8px); }
.nav-next { right: var(--page-gutter, 8px); }

/* ========================================
   Side Panel
   ======================================== */

/* Side panel (Search / AI Search). On DESKTOP it docks on the RIGHT at a
   reading-companion width (not full screen) so the page stays visible behind
   it; a shadow separates it from the page. On MOBILE it stays a full-width
   slide-in (see the <=768px override below), which is the right call on a phone.
   Slides via `right` so the open/close transition is unchanged in feel. */
.side-panel {
    position: fixed;
    top: var(--toolbar-height);
    left: 0;
    right: auto;
    width: min(440px, 92vw);
    transform: translateX(-100%);
    height: calc(100% - var(--toolbar-height));
    background: var(--color-surface);
    z-index: 200;
    transition: transform 0.3s ease;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    box-shadow: 8px 0 28px rgba(0, 0, 0, 0.4);
    border-right: 1px solid var(--color-border, rgba(255,255,255,0.1));
}

.side-panel.open { transform: translateX(0); }


.panel-header {
    display: flex;
    flex-direction: column;
    
    
    padding: 16px;
    border-bottom: none;
}

.panel-header h3 {
    font-size: 16px;
    font-weight: 500;
}

.panel-close {
    background: none;
    border: none;
    color: var(--color-text-muted);
    font-size: 24px;
    cursor: pointer;
}

.panel-content {
    overflow-y: auto;
    padding: 12px;
    flex: 1;
    min-height: 0;
}

/* ========================================
   AI Chat (multi-turn) — Chat Sheet
   ======================================== */

/* #panelAi is toggled to display:flex by panel-tabs.js when the AI tab is
   active; make it a column that fills the side panel. */
#panelAi {
    flex: 1;
    min-height: 0;
    flex-direction: column;
    overflow: hidden;
}

#aiChat {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}

#aiChatHeader {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 10px 12px;
    border-bottom: 1px solid var(--color-border);
    background: var(--color-surface);
    flex: 0 0 auto;
}

#aiChatTitle {
    font-size: 13px;
    font-weight: 600;
    color: var(--color-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

#aiChatTitle i { color: var(--color-accent); margin-right: 4px; }

#aiSavedBtn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 36px;
    padding: 6px 12px;
    background: rgba(255,255,255,0.08);
    border: 1px solid var(--color-border);
    border-radius: 6px;
    color: var(--color-text);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}

#aiSavedBtn:hover { background: rgba(255,255,255,0.14); }

/* Saved-prompt icon reflects state:
   - empty  -> muted outline bookmark, no badge
   - has saved -> accent-colored bookmark + count badge */
#aiSavedBtn i.fa-bookmark { color: rgba(255,255,255,0.55); transition: color .15s ease; }
#aiSavedBtn.has-saved { border-color: var(--color-primary, #e11d2a); }
#aiSavedBtn.has-saved i.fa-bookmark { color: var(--color-primary, #e11d2a); }

.ai-saved-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 16px;
    height: 16px;
    padding: 0 5px;
    border-radius: 8px;
    background: var(--color-primary, #e11d2a);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
}

#aiTranscript {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Turn rows control bubble alignment */
.ai-turn {
    display: flex;
    flex-direction: column;
    max-width: 100%;
}
.ai-turn.user { align-items: flex-end; }
.ai-turn.assistant { align-items: flex-start; }

.ai-bubble {
    max-width: 85%;
    padding: 8px 12px;
    border-radius: 14px;
    font-size: 13px;
    line-height: 1.6;
    word-wrap: break-word;
    overflow-wrap: anywhere;
    white-space: normal;
}

.ai-turn.user .ai-bubble {
    background: var(--color-accent);
    color: #fff;
    border-bottom-right-radius: 4px;
}

/* Edit & re-run affordance under each user prompt (persists so any prompt —
   saved or not — can be tweaked and re-sent). Subtle by default, clearer on
   hover; visible fill so it's a real button, not a ghost. */
.ai-turn-edit {
    margin-top: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    font-size: 11px;
    line-height: 1;
    padding: 4px 8px;
    border-radius: 6px;
    background: rgba(255,255,255,0.06);
    border: 1px solid var(--color-border);
    color: var(--color-text-muted);
    cursor: pointer;
    opacity: 0.6;
    transition: opacity .15s ease, background .15s ease, color .15s ease;
}
.ai-turn:hover .ai-turn-edit { opacity: 1; }
.ai-turn-edit:hover {
    opacity: 1;
    background: var(--color-primary, #e11d2a);
    border-color: var(--color-primary, #e11d2a);
    color: #fff;
}

@media (pointer: coarse) {
    /* Always visible on touch (no hover) and a real touch target. */
    .ai-turn-edit { opacity: 1; min-height: 32px; padding: 6px 10px; font-size: 12px; }
}

.ai-turn.assistant .ai-bubble {
    background: rgba(255,255,255,0.06);
    border: 1px solid var(--color-border);
    color: var(--color-text);
    border-bottom-left-radius: 4px;
}

.ai-bubble h2, .ai-bubble h3, .ai-bubble h4 { color: var(--color-text); }

.ai-bubble .ai-page-link {
    color: var(--color-accent);
    text-decoration: underline;
    cursor: pointer;
}

/* Runnable sample-query suggestion (sample-ai-query feature).
   Shown in the empty transcript; clicking the chip runs the query. */
.ai-sample-suggestion {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    padding: 12px 4px 4px;
}
.ai-sample-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: var(--color-text-muted);
}
.ai-sample-chip {
    max-width: 100%;
    text-align: left;
    padding: 10px 14px;
    min-height: 44px;                 /* touch target */
    border-radius: 18px;
    border: 1px solid var(--color-accent, #c0392b);
    background: rgba(192,57,43,0.14);  /* visible fill, not ghost/outline-only */
    color: var(--color-text);
    font-size: 13px;
    line-height: 1.5;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}
.ai-sample-chip:hover {
    background: rgba(192,57,43,0.28);
    border-color: var(--color-accent-hover, #e74c3c);
}
.ai-sample-chip:active { background: rgba(192,57,43,0.36); }

/* Loading indicator on the pending assistant turn */
.ai-loading {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--color-text-muted);
    font-size: 13px;
}

/* Inline citations footer within an assistant bubble */
.ai-citations {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--color-border);
}
.ai-citations .ai-cite-label {
    font-size: 10px;
    text-transform: uppercase;
    color: var(--color-text-muted);
    margin-bottom: 6px;
}
.ai-citations .ai-page-link {
    display: inline-block;
    min-height: 28px;
    line-height: 20px;
    font-size: 12px;
    padding: 4px 10px;
    margin: 2px 4px 2px 0;
    background: rgba(255,255,255,0.08);
    border: 1px solid var(--color-border);
    border-radius: 14px;
    color: var(--color-accent);
    text-decoration: none;
    cursor: pointer;
    font-weight: 600;
}

/* Assistant turn actions (Save) */
.ai-turn-actions {
    margin-top: 6px;
    display: flex;
    gap: 8px;
}
.ai-save-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 32px;
    padding: 4px 10px;
    background: rgba(255,255,255,0.08);
    border: 1px solid var(--color-border);
    border-radius: 6px;
    color: var(--color-text-muted);
    font-size: 12px;
    cursor: pointer;
}
.ai-save-btn:hover { color: var(--color-text); background: rgba(255,255,255,0.14); }
.ai-save-btn.saved { color: var(--color-accent); border-color: var(--color-accent); }

/* Generate/Download PDF: accent (brand-red) primary action next to Save. */
.ai-pdf-btn {
    background: var(--color-accent);
    border-color: var(--color-accent);
    color: #fff;
    font-weight: 600;
}
.ai-pdf-btn:hover {
    background: var(--color-accent-hover);
    border-color: var(--color-accent-hover);
    color: #fff;
}
.ai-pdf-btn:disabled { opacity: 0.7; cursor: default; }

/* Share: brand-red primary action (visible fill, not ghost/outline-only) */
.ai-share-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 32px;
    padding: 4px 10px;
    background: var(--color-accent);
    border: 1px solid var(--color-accent);
    border-radius: 6px;
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
}
.ai-share-btn:hover { background: var(--color-accent-hover); border-color: var(--color-accent-hover); }

/* Share modal */
.ai-share-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10000;
    padding: 16px;
}
.ai-share-panel {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 10px;
    width: 100%;
    max-width: 420px;
    padding: 20px;
    box-shadow: 0 8px 30px rgba(0,0,0,0.5);
}
.ai-share-title { margin: 0 0 16px; font-size: 16px; color: var(--color-text); }
.ai-share-field { margin-bottom: 14px; display: flex; flex-direction: column; gap: 6px; }
.ai-share-field label { font-size: 12px; color: var(--color-text-muted); }
.ai-share-field input,
.ai-share-field textarea {
    min-height: 44px;                 /* touch target */
    padding: 10px 12px;
    background: #1e1e1e;
    border: 1px solid var(--color-border);
    border-radius: 6px;
    color: var(--color-text);
    font-size: 14px;
    font-family: inherit;
    resize: vertical;
}
.ai-share-field input:focus,
.ai-share-field textarea:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(192,57,43,0.25);
}
.ai-share-error { color: #e74c3c; font-size: 13px; margin: 0 0 12px; }
.ai-share-footer { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
.ai-share-cancel,
.ai-share-send {
    min-height: 44px;                 /* touch target */
    padding: 10px 20px;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
}
.ai-share-cancel {
    background: rgba(255,255,255,0.08);  /* subtle dark fill, not ghost-only */
    border: 1px solid var(--color-border);
    color: var(--color-text);
}
.ai-share-cancel:hover { background: rgba(255,255,255,0.14); }
.ai-share-send {
    background: var(--color-accent);
    border: 1px solid var(--color-accent);
    color: #fff;
}
.ai-share-send:hover { background: var(--color-accent-hover); border-color: var(--color-accent-hover); }
.ai-share-send:disabled { opacity: 0.6; cursor: default; }

/* Sign-in prompt inside a turn */
.ai-signin { text-align: center; padding: 16px 8px; }
.ai-signin .ai-signin-icon { font-size: 22px; color: var(--color-text-muted); margin-bottom: 10px; }
.ai-signin p { font-size: 13px; color: var(--color-text); margin-bottom: 14px; }
.ai-signin a.ai-signin-link {
    display: inline-block;
    background: var(--color-accent);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    padding: 10px 20px;
    border-radius: 6px;
    text-decoration: none;
}

/* Retry error affordance */
.ai-error { color: #e74c3c; font-size: 13px; }
.ai-retry-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 32px;
    margin-top: 8px;
    padding: 4px 12px;
    background: rgba(255,255,255,0.08);
    border: 1px solid var(--color-border);
    border-radius: 6px;
    color: var(--color-text);
    font-size: 12px;
    cursor: pointer;
}

/* Composer (docked input) */
#aiComposer {
    position: sticky;
    bottom: 0;
    z-index: 2;
    display: flex;
    gap: 8px;
    align-items: flex-end;
    padding: 12px;
    /* Visually lift the composer off the transcript so the input is obvious. */
    border-top: 1px solid var(--color-border);
    background: var(--color-bg, #111);
    box-shadow: 0 -6px 16px rgba(0,0,0,0.35);
    flex: 0 0 auto;
}

#aiComposer textarea {
    flex: 1;
    resize: none;
    max-height: 180px;
    min-height: 72px;
    padding: 12px 14px;
    /* Clearly readable input: brighter fill + visible border. */
    background: rgba(255,255,255,0.14);
    border: 1.5px solid rgba(255,255,255,0.35);
    border-radius: 10px;
    color: #fff;
    font-size: 14px;
    line-height: 1.4;
    outline: none;
    font-family: inherit;
    transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}
#aiComposer textarea:hover { border-color: rgba(255,255,255,0.5); }
#aiComposer textarea:focus {
    background: #1e1e1e;
    border-color: var(--color-accent, #c0392b);
    box-shadow: 0 0 0 3px rgba(192,57,43,0.25);
}
#aiComposer textarea::placeholder { color: rgba(255,255,255,0.55); }

#aiComposer #aiSearchBtn {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-accent);
    border: none;
    border-radius: 8px;
    color: #fff;
    font-size: 15px;
    cursor: pointer;
}
#aiComposer #aiSearchBtn:hover { background: var(--color-accent-hover); }
#aiComposer #aiSearchBtn:disabled { opacity: 0.5; cursor: default; }
.voice-input-btn { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; flex: 0 0 44px; background: rgba(192,57,43,0.16); border: 1px solid rgba(231,76,60,0.7); border-radius: 8px; color: #ffb4ab; font-size: 15px; cursor: pointer; box-shadow: 0 0 0 2px rgba(192,57,43,0.08); }
.voice-input-btn:hover { color: #fff; background: rgba(192,57,43,0.3); border-color: var(--color-accent-hover); }
.voice-input-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.voice-input-btn.is-listening { color: #fff; background: var(--color-accent); border-color: var(--color-accent-hover); }
.voice-input-status { min-height: 18px; padding: 4px 2px 0; color: var(--color-text-muted); font-size: 11px; }

/* Saved-prompts list overlay */
#aiSavedList {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 12px;
}
.ai-saved-item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px;
    margin-bottom: 8px;
    background: rgba(255,255,255,0.05);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    cursor: pointer;
}
.ai-saved-item:hover { background: rgba(255,255,255,0.1); }
.ai-saved-item .ai-saved-body { flex: 1; min-width: 0; }
.ai-saved-item .ai-saved-query {
    font-size: 13px;
    font-weight: 600;
    color: var(--color-text);
    margin-bottom: 3px;
}
.ai-saved-item .ai-saved-snippet {
    font-size: 12px;
    color: var(--color-text-muted);
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.ai-saved-actions {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 6px;
}
.ai-saved-edit, .ai-saved-del {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255,255,255,0.08);
    border: 1px solid var(--color-border);
    color: var(--color-text-muted);
    font-size: 13px;
    cursor: pointer;
    border-radius: 6px;
}
.ai-saved-edit:hover { color: #fff; background: var(--color-primary, #e11d2a); border-color: var(--color-primary, #e11d2a); }
.ai-saved-del:hover { color: #fff; background: #c0392b; border-color: #c0392b; }

@media (pointer: coarse) {
    .ai-saved-edit, .ai-saved-del { width: 44px; height: 44px; font-size: 15px; }
}
.ai-saved-empty { color: var(--color-text-muted); font-size: 13px; text-align: center; padding: 24px 8px; }

/* Mobile: full-screen Chat Sheet with docked composer above the keyboard */
@media (max-width: 768px), (pointer: coarse) {
    #panelAi { height: 100%; }
    #aiChat {
        height: 100%;
        /* dvh keeps the sheet correct when iOS Safari toolbars/keyboard resize */
        height: 100dvh;
        max-height: calc(100dvh - var(--toolbar-height));
    }
    #aiTranscript {
        flex: 1;
        min-height: 0;
    }
    #aiComposer {
        padding-bottom: calc(12px + env(safe-area-inset-bottom));
    }
    #aiComposer #aiSearchBtn { width: 44px; height: 44px; }
    .ai-bubble { font-size: 14px; }
}

/* Keyboard-up reflow (touch/iPad): when the on-screen keyboard is up the
   bottom-docked composer would sit behind it. ai-chat.js adds .kbd-open to
   #aiChat (via visualViewport detection); we then move the composer to the
   TOP of the chat column and reverse the transcript so the newest turn
   stays adjacent to the input and reads naturally. The composer sticks to
   the top instead of the bottom while in this state. */
#aiChat.kbd-open #aiComposer {
    order: -1;
    position: sticky;
    top: 0;
    bottom: auto;
    border-top: none;
    border-bottom: 1px solid var(--color-border);
    box-shadow: 0 6px 16px rgba(0,0,0,0.35);
}
#aiChat.kbd-open #aiTranscript {
    /* Newest bubble renders nearest the (now top) composer. */
    flex-direction: column-reverse;
}
#aiChat.kbd-open #aiSavedList { order: 0; }

/* ========================================
   Modals
   ======================================== */

.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.7);
    z-index: 500;
    display: flex;
    align-items: center;
    justify-content: center;
}

.modal-box {
    background: var(--color-surface);
    border-radius: var(--radius);
    padding: 24px;
    max-width: 90vw;
    max-height: 85vh;
    overflow-y: auto;
    position: relative;
    box-shadow: var(--shadow);
}

.modal-close {
    position: absolute;
    top: 12px;
    right: 16px;
    background: none;
    border: none;
    color: var(--color-text-muted);
    font-size: 24px;
    cursor: pointer;
}

.product-modal { width: 400px; }
.search-modal { width: 500px; }

/* Cart reuses the product modal box but needs more room so line items
   (SKU | Qty | Unit Price | Line Total | remove) lay out on one line
   without wrapping. Widen on desktop only; mobile stays capped by the
   .modal-box max-width:90vw so it still fits small screens. */
@media (min-width: 769px) {
    .product-modal.cart-wide { width: 640px; }
}

/* --- Mobile cart: stacked-card layout (<=768px) -------------------------
   The desktop cart is a multi-column table (SKU | Location | Qty | Unit
   Price | Line Total | remove) that overflows a narrow phone viewport. On
   mobile we collapse each row into a self-contained card: the header row is
   hidden and every cell becomes a label/value line using the cell's
   data-label. Desktop is untouched — these rules live entirely inside the
   max-width:768px query. !important is required only here because the cart
   cells carry inline styles (rendered by shopping.js); the desktop layout,
   being outside this query, keeps those inline styles verbatim. Matches the
   project's mobile breakpoint convention (max-width:768px OR coarse pointer)
   so it also applies on touch devices regardless of exact width. */
@media (max-width: 768px), (pointer: coarse) {
    /* Give the cart modal the full phone width. */
    .product-modal.cart-wide,
    .product-modal { width: auto !important; }
    .modal-box.product-modal,
    .product-modal.cart-wide.modal-box { width: auto !important; }

    .cart-table { display: block !important; width: 100% !important; }
    .cart-table thead { display: none !important; }        /* labels move onto each cell */
    .cart-table tbody { display: block !important; width: 100% !important; }

    .cart-table tr {
        display: block !important;
        width: 100% !important;
        box-sizing: border-box;
        border: 1px solid var(--color-border);
        border-radius: 8px;
        padding: 6px 10px;
        margin-bottom: 10px;
        background: var(--color-surface, #1b1b1d);
    }

    .cart-table td {
        display: flex !important;
        width: auto !important;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        padding: 6px 0 !important;
        border-bottom: 1px solid rgba(255,255,255,0.06) !important;
        text-align: right !important;
        white-space: normal !important;
    }
    .cart-table tr td:last-child { border-bottom: none !important; }

    /* Left-side label from data-label (skip cells with an empty label, e.g.
       the remove cell, which then right-aligns its button alone). */
    .cart-table td[data-label]:not([data-label=""])::before {
        content: attr(data-label);
        flex: 0 0 auto;
        text-align: left;
        font-size: 11px;
        letter-spacing: 0.5px;
        text-transform: uppercase;
        color: var(--color-text-muted);
        font-family: inherit;
    }

    /* The SKU cell reads better full-width stacked (label above value). */
    .cart-table td[data-label="SKU"] {
        flex-direction: column !important;
        align-items: stretch !important;
        text-align: left !important;
        gap: 2px;
    }

    /* Qty stepper: keep its controls together, pushed to the right. */
    .cart-table td[data-label="Qty"] { justify-content: space-between; }

    /* The remove cell: no label, button aligned right, a touch bigger for
       a comfortable touch target. */
    .cart-table td[data-label=""] { justify-content: flex-end; }
    .cart-table td[data-label=""] .remove-item {
        font-size: 22px !important;
        padding: 4px 6px !important;
        min-width: 44px;
        min-height: 44px;
    }

    /* tfoot (subtotal) as its own emphasized card row. */
    .cart-table tfoot { display: block !important; }
    .cart-table tfoot tr { background: transparent; border: none; }
    .cart-table tfoot td {
        border-bottom: none !important;
        font-size: 14px !important;
    }
    .cart-table tfoot td[colspan] { display: none !important; }  /* drop the empty 'Subtotal' spacer td */
    .cart-table tfoot td:not([colspan])::before {
        content: "Subtotal";
        flex: 0 0 auto;
        text-align: left;
        text-transform: uppercase;
        font-size: 12px;
        letter-spacing: 0.5px;
        color: var(--color-text-muted);
    }
}

.search-modal input {
    width: 100%;
    padding: 10px 14px;
    margin-top: 12px;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    color: var(--color-text);
    font-size: 14px;
}

.search-modal input:focus {
    outline: none;
    border-color: var(--color-accent);
}

.search-results {
    margin-top: 16px;
    max-height: 400px;
    overflow-y: auto;
}

/* ========================================
   Responsive
   ======================================== */

@media (max-width: 768px) {
    :root { --toolbar-height: 40px; }
    .pub-title { font-size: 11px; }

    /* On a phone the Search / AI Search panel is full-width (the docked
       desktop width would leave too little room). Restore the full-bleed
       slide-in; it still animates via transform. */
    .side-panel {
        width: 100%;
        box-shadow: none;
        border-right: none;
    }

    /* Keep the page tracker visible on mobile — drag-to-scrub with thumbnail
       preview is the primary jump-to-page control on touch. */
    .slider-track { display: flex; }
    .page-indicator { font-size: 10px; }

    /* Nav arrows stay visible on mobile too (finger swipe still works); just
       make them smaller per the mobile sizing rule. */
    .nav-arrow { display: block; opacity: 1; font-size: 24px; width: 34px; height: 60px; background: rgba(0, 0, 0, 0.35); }

    /* Canvas fit/gutter is computed in JS (computeBaseScale). Do NOT cap width
       or add margins here — that fights the JS-set inline size and pushes the
       page/annotation layer out of alignment on iPhone. */

    .search-field { width: 100px; padding: 3px 8px; }
    .search-field input { font-size: 12px; }
    .toolbar-btn { padding: 6px 8px; font-size: 14px; }

    /* Hide zoom buttons on mobile — pinch-to-zoom handles it */
    #zoomInBtn, #zoomOutBtn { display: none; }

    /* Icons only on mobile — hide text labels next to icons in toolbar buttons,
       the account name in the bottom toolbar, and the Privacy text label. */
    .btn-label { display: none; }

    /* ----------------------------------------------------------------------
       iPhone bottom toolbar: two rows. Row 1 = full-width page scroller
       (raised); row 2 = account + all utility icons evenly spaced beneath.
       Scoped to the #toolbarBottom ID so it decisively beats the base
       `.toolbar` row layout, and child flex is reset so nothing grows in-row.
       The .reader-app grid bottom row is `auto`, so a taller bar just shrinks
       the page area; there is ample space above the page bottom.
       ---------------------------------------------------------------------- */
    #toolbarBottom.toolbar-bottom {
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;                  /* center wraps to line 1; left+right share line 2 */
        align-items: center;
        justify-content: space-between;
        row-gap: 4px;
        min-height: 88px;
        padding-top: 8px;
        padding-bottom: calc(8px + env(safe-area-inset-bottom));
    }
    /* Row 1: page scroller takes the ENTIRE first line (forces the wrap). */
    #toolbarBottom .toolbar-center {
        order: 0;
        flex: 1 0 100%;
        width: 100%;
        flex-direction: column;
        padding: 0 12px;
    }
    #toolbarBottom .toolbar-center .slider-track { width: 100%; }
    /* Row 2: account (left) + utility icons (right) sit SIDE BY SIDE on the
       wrapped second line, vertically centered on one 44px baseline. */
    #toolbarBottom .toolbar-left {
        order: 1;
        flex: 0 0 auto;
        height: 44px;
        align-items: center;
        justify-content: center;
        gap: 0;
        padding-left: 8px;
    }
    #toolbarBottom .toolbar-right {
        order: 2;
        flex: 1 1 auto;
        height: 44px;
        align-items: center;
        justify-content: space-around;
        gap: 0;
        padding-right: 8px;
    }
    /* All row-2 controls share the same 44px-tall centered baseline. */
    #toolbarBottom .toolbar-left .account-link,
    #toolbarBottom .toolbar-right .util-btn,
    #toolbarBottom .toolbar-right .dq-brand,
    #toolbarBottom .toolbar-right .app-version {
        display: inline-flex;
        align-items: center;
        height: 44px;
        margin: 0;
        flex: 0 0 auto;
    }
}

/* Tablets (iPad, Android tablets, other touch tablets): hide ALL toolbar
   button labels (top and bottom) so the toolbars are icon-only, matching the
   phone treatment. A tablet lands at a wide viewport (1024–1366px) in
   landscape, so the width-only `@media (max-width: 768px)` rule above never
   hits it — instead we key off the `is-tablet` device class that app.js sets
   on <body> from device detection (per the "detect device type, not just
   screen width" UI rule). Covers .btn-label everywhere plus the account-name
   label in the bottom toolbar. (`is-ipad` is also set for any iPad-only
   tweaks, but the label hiding is shared across all tablets.) */
body.is-tablet .btn-label { display: none; }
/* Tablet: collapse the data-sensitivity indicator to its single level icon too
   (same reason as the touch rule above) so it never overflows the icon-only
   toolbar. Keyed on the is-tablet device class to match the label-hiding
   convention; the (pointer:coarse) rule also covers most tablets, this makes it
   decisive for the is-tablet landscape case. */
body.is-tablet #sensitivityIndicator .sens-marker { display: none; }

@media (min-width: 1200px) {
    .slider-track { max-width: 640px; }
}

/* Preview badge — small indicator just BELOW the top toolbar, top-left.
   Top offset (56px) sits clear of the 48px top toolbar (var(--toolbar-height))
   with a slight 8px gap. pointer-events:auto so the Approve button is
   clickable; z-index above page content. Contains a status pill and, when a
   valid proof-decision approve token is present, an Approve Proof button. */
.preview-badge {
    position: fixed;
    top: 56px;
    left: 12px;
    z-index: 1200;
    pointer-events: auto;
    user-select: none;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 4px;
    border-radius: 8px;
    background: rgba(20, 20, 20, 0.85);
    box-shadow: 0 2px 8px rgba(0,0,0,0.45);
}
.preview-badge-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 1px;
    color: #fff;
    background: rgba(230, 145, 30, 0.95);  /* amber pill, readable on dark */
    color: #1a1a1a;
    padding: 4px 10px;
    border-radius: 999px;
    white-space: nowrap;
}
.preview-approve-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 700;
    color: #fff;
    background: #2ea043;                   /* visible green — no ghost */
    padding: 6px 12px;
    border-radius: 6px;
    text-decoration: none;
    line-height: 1;
    min-height: 32px;
    box-sizing: border-box;
    transition: background 0.15s ease;
}
.preview-approve-btn:hover,
.preview-approve-btn:active {
    background: #268239;                   /* darken slightly on hover */
    text-decoration: none;
}
@media (max-width: 768px) {
    .preview-badge { top: 48px; left: 8px; padding: 3px; gap: 6px; }
    .preview-badge-label { font-size: 10px; padding: 3px 8px; }
    .preview-approve-btn { font-size: 11px; padding: 6px 10px; min-height: 30px; }
}

/* When the fixed Preview/Draft badge is showing (top-left, over the side
   panel), push the Search + AI panel contents down so the search input is not
   hidden underneath the badge. Scoped to #app.has-preview-badge so normal
   (published) reading is unaffected. The badge sits ~34px tall starting near
   the toolbar; ~44px of extra top padding clears it with margin. */
#app.has-preview-badge #panelSearch { padding-top: 52px; }
#app.has-preview-badge #panelAi { padding-top: 52px; }
@media (max-width: 768px) {
    /* Mobile badge sits a touch higher/smaller; a little less clearance. */
    #app.has-preview-badge #panelSearch { padding-top: 46px; }
    #app.has-preview-badge #panelAi { padding-top: 46px; }
}


/* AI Search panel - scrollable results */
#panelAi {
    display: none;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    padding: 12px 16px;
}
#panelAi .search-field {
    flex-shrink: 0;
}
#aiSearchResults {
    margin-top: 10px;
    flex: 1;
    overflow-y: auto;
    min-height: 0;
    font-size: 13px;
    line-height: 1.7;
    padding: 0 4px;
}
#panelSearch {
    display: none;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    padding: 12px 16px;
}
#searchResults {
    margin-top: 8px;
    flex: 1;
    overflow-y: auto;
    min-height: 0;
    font-size: 12px;
}


/* ========================================
   Touch scrubber affordances (iPhone / iPad)
   ======================================== */
@media (pointer: coarse) {
    /* Give the track a real 44px touch target and own the horizontal gesture
       so iOS doesn't steal the drag for page pan/zoom. */
    .slider-track {
        min-height: 44px;
        display: flex;
        align-items: center;
        touch-action: none;
    }
    .page-slider {
        height: 44px;
        touch-action: none;
    }
    /* Larger, easier-to-see thumb on touch. */
    .page-slider::-webkit-slider-thumb {
        width: 18px;
        height: 18px;
        margin-top: -8px;
    }
    .page-slider::-moz-range-thumb {
        width: 18px;
        height: 18px;
    }
    /* The preview thumbnail is the primary affordance on touch — make it a bit
       larger so it reads well under a fingertip. */
    .slider-preview-canvas { width: 96px; max-height: 138px; }
}

/* ========================================
   Account / login-status indicator (top toolbar)
   ======================================== */
.acct-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--color-primary, #e11d2a);
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    text-transform: uppercase;
    flex-shrink: 0;
}

/* Sign-in / account buttons inherit the standard .toolbar-btn look so they are
   visually consistent with the other top-toolbar buttons (AI, Search, Share,
   Cart). The avatar chip provides the login-status recognizability. */

.acct-dropdown {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 220px;
    background: var(--color-surface, #1b1b1d);
    border: 1px solid var(--color-border, rgba(255,255,255,0.12));
    border-radius: 8px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
    padding: 6px;
    z-index: 3000;
}
.acct-dropdown .acct-email {
    font-size: 12px;
    color: var(--color-text-muted, rgba(255,255,255,0.7));
    padding: 8px 10px;
    border-bottom: 1px solid var(--color-border, rgba(255,255,255,0.10));
    margin-bottom: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.acct-signout {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    background: rgba(255, 255, 255, 0.06);
    border: none;
    border-radius: 6px;
    color: #fff;
    font-size: 13px;
    padding: 10px 10px;
    cursor: pointer;
    text-align: left;
}
.acct-signout:hover { background: rgba(255, 255, 255, 0.14); }

/* Touch targets ≥44px on coarse pointers. */
@media (pointer: coarse) {
    #signInBtn, #acctBtn { min-height: 44px; min-width: 44px; }
    .acct-signout { min-height: 44px; }
    .acct-dropdown { min-width: 240px; }
}

/* ========================================
   Utility toolbar buttons (Help, Privacy) — bottom-right.
   Moved from the bottom-left text links; larger icons for recognition.
   ======================================== */
.toolbar-bottom .toolbar-right { display: flex; align-items: center; gap: 4px; }

.util-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 36px;
    padding: 0 12px;                 /* room for icon + label on desktop */
    font-size: 15px;
    color: rgba(255, 255, 255, 0.72);
    background: none;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background var(--transition), color var(--transition);
}
.util-btn .btn-label { font-size: 12px; }
.util-btn:hover  { color: #fff; background: rgba(255, 255, 255, 0.12); }
.util-btn:active { background: rgba(255, 255, 255, 0.18); }

/* Data-sensitivity risk markers (PII / PHI / pending) sit after the level
   label inside #sensitivityIndicator. The button chrome follows the sibling
   util-btn pattern (single level icon + .btn-label); these markers KEEP their
   semantic colors (owner decision Y) via inline color, which wins over the
   util-btn:hover recolor, so no color rule is needed here. This rule only
   handles layout: a small left gap and a slightly smaller size keep them
   visually subordinate to the primary level icon. */
#sensitivityIndicator .sens-marker { font-size: 0.85em; margin-left: 4px; }

/* CTA variant for the reader "Upload Your PDF" button. Tasteful brand-accent
   tint + hairline accent border so it invites without shouting; brightens to
   solid accent on hover. Visible background per UI rules (no ghost/outline).
   On touch it collapses to the same 44px icon-only target as other util-btns
   (see the mobile override in the media query below). */
.util-btn.upload-cta {
    color: var(--color-accent-hover, #e74c3c);
    background: rgba(192, 57, 43, 0.14);
    border: 1px solid rgba(192, 57, 43, 0.5);
}
.util-btn.upload-cta .btn-label { font-weight: 600; }
.util-btn.upload-cta:hover {
    color: #fff;
    background: var(--color-accent, #c0392b);
    border-color: var(--color-accent, #c0392b);
}
.util-btn.upload-cta:active { background: var(--color-accent-hover, #e74c3c); }

/* Mobile / touch: icon-only (label hidden by the .btn-label rule), square target. */
@media (max-width: 768px), (pointer: coarse) {
    .util-btn { width: 44px; height: 44px; padding: 0; gap: 0; font-size: 18px; }
    /* Data-sensitivity indicator collapses to a SINGLE level icon on touch so
       it fits the 44px square like every other util-btn — the extra PII/PHI/
       pending markers would overflow the fixed-width box and could wrap/disrupt
       the toolbar. The full detail is preserved in the button's title/aria-label
       and in the intro-modal Data Sensitivity row, so nothing is lost. */
    #sensitivityIndicator .sens-marker { display: none; }
    /* Upload CTA on touch: same 44px square as sibling icon buttons; keep the
       subtle accent tint but drop the label (hidden by .btn-label rule). */
    .util-btn.upload-cta { border-radius: 6px; }
}

/* ========================================
   Digital Quire brand mark (bottom-right, before version)
   ======================================== */
.dq-brand {
    display: inline-flex;
    align-items: center;
    margin: 0 6px 0 4px;
    opacity: 0.75;
    transition: opacity var(--transition);
    text-decoration: none;
}
.dq-brand:hover { opacity: 1; }
.dq-brand img {
    height: 18px;
    width: auto;
    display: block;
}
@media (max-width: 768px), (pointer: coarse) {
    .dq-brand img { height: 16px; }
    .dq-brand { margin: 0 4px; }
}

/* Cart button pulse when a SKU is added straight to the cart (cart productView). */
@keyframes cartBump { 0%{transform:scale(1);} 30%{transform:scale(1.18);} 100%{transform:scale(1);} }
.cart-bump { animation: cartBump 0.35s ease; }

/* ========================================
   Add-to-cart ALERT popover — bright, coachmark-style, points at the cart icon.
   ======================================== */
.cart-alert {
    position: fixed;
    z-index: 3200;
    max-width: 280px;
    display: flex;
    align-items: center;
    background: var(--color-primary, #e11d2a);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    padding: 11px 15px;
    border-radius: 10px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.45);
    opacity: 0;
    transform: translateY(-6px);
    transition: opacity .2s ease, transform .2s ease;
    pointer-events: none;
}
.cart-alert.show { opacity: 1; transform: translateY(0); }
.cart-alert strong { font-weight: 800; }

/* Upward-pointing arrow (cart sits above, in the top toolbar). */
.cart-alert-arrow {
    position: absolute;
    top: -7px;
    width: 14px;
    height: 14px;
    background: var(--color-primary, #e11d2a);
    transform: rotate(45deg);
    border-radius: 2px;
}

/* ── PDF page-picker modal (reader) ───────────────────────────────────────── */
.pdf-modal-overlay {
    position: fixed; inset: 0; z-index: 2000;
    background: rgba(0,0,0,0.6);
    display: flex; align-items: center; justify-content: center;
    padding: 20px;
}
.pdf-modal {
    background: var(--color-surface, #1f1f1f);
    border: 1px solid var(--color-border, rgba(255,255,255,0.12));
    border-radius: 10px;
    width: 100%; max-width: 640px;
    max-height: 85vh; display: flex; flex-direction: column;
    box-shadow: 0 12px 40px rgba(0,0,0,0.5);
}
.pdf-modal-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 16px 20px; border-bottom: 1px solid var(--color-border, rgba(255,255,255,0.1));
}
.pdf-modal-header h3 { font-size: 15px; font-weight: 600; color: var(--color-text, #fff); display: flex; align-items: center; gap: 8px; }
.pdf-modal-header h3 i { color: var(--color-accent, #c0392b); }
.pdf-modal-close {
    background: none; border: none; color: var(--color-text-muted, rgba(255,255,255,0.6));
    font-size: 24px; line-height: 1; cursor: pointer; padding: 0 4px;
}
.pdf-modal-close:hover { color: var(--color-text, #fff); }
.pdf-modal-intro { padding: 14px 20px 4px; font-size: 13px; line-height: 1.6; color: var(--color-text, rgba(255,255,255,0.75)); }
.pdf-modal-counter { padding: 4px 20px 12px; font-size: 12px; color: var(--color-text-muted, rgba(255,255,255,0.55)); }
.pdf-modal-counter strong { color: var(--color-text, #fff); }

.pdf-modal-grid {
    padding: 0 20px; overflow-y: auto;
    display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px;
}
@media (max-width: 520px) { .pdf-modal-grid { grid-template-columns: 1fr; } }
.pdf-modal-cell {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 12px; border-radius: 6px;
    background: rgba(255,255,255,0.05); border: 1px solid var(--color-border, rgba(255,255,255,0.1));
    cursor: pointer; min-height: 44px;
}
.pdf-modal-cell:hover { background: rgba(255,255,255,0.09); }
.pdf-modal-cell input[type="checkbox"] { width: 16px; height: 16px; flex: 0 0 auto; accent-color: var(--color-accent, #c0392b); }
.pdf-modal-cell input[type="checkbox"]:disabled { opacity: 0.4; }
.pdf-modal-cell-meta { display: flex; flex-direction: column; min-width: 0; }
.pdf-modal-cell-title { font-size: 13px; color: var(--color-text, #eee); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pdf-modal-cell-page { font-size: 11px; color: var(--color-text-muted, rgba(255,255,255,0.5)); margin-top: 2px; }

.pdf-modal-footer {
    display: flex; align-items: center; gap: 12px;
    padding: 16px 20px; border-top: 1px solid var(--color-border, rgba(255,255,255,0.1)); margin-top: 14px;
}
.pdf-modal-msg { flex: 1; font-size: 12px; min-width: 0; }
.pdf-modal-cancel {
    background: rgba(255,255,255,0.08); border: 1px solid var(--color-border, rgba(255,255,255,0.12));
    color: var(--color-text, rgba(255,255,255,0.8)); padding: 8px 16px; border-radius: 6px;
    font-size: 13px; cursor: pointer;
}
.pdf-modal-cancel:hover { color: #fff; background: rgba(255,255,255,0.14); }
.pdf-modal-confirm { display: inline-flex; align-items: center; gap: 6px; }
@media (pointer: coarse) {
    .pdf-modal-cancel, .pdf-modal-confirm { min-height: 44px; }
}
