/* ============================================================
   Phantom Shelf — UI
   ============================================================ */

/* Design Tokens — Phantom Shelf reskin (slate + pastel) */
:root {
    --bg:             #F7FAFB;
    --surface:        #FFFFFF;
    --surface-alt:    #EEF4F1;
    --border:         #E2E9EC;
    --border-strong:  #C2CDD1;
    --lane:           #EEF3F5;   /* kanban lane panel */
    --lane-line:      #DEE7EA;
    --text:           #16232A;
    --text-2:         #5E6B71;
    --text-3:         #9AA7AC;
    --accent:         #B4533A;
    --accent-dim:     #F6E7E1;
    --accent-hover:   #9C4632;
    --navy:           #16232A;   /* ink — brand / primary / active */
    --navy-light:     #2E4A56;
    --success:        #4A6B5C;
    --success-dim:    #DCEBE2;
    --danger:         #B85C4A;
    --danger-dim:     #F7E7E2;
    --info:           #3D5A73;
    --info-dim:       #E2E9EC;

    /* Typography */
    --font-display:   'Bricolage Grotesque', 'Segoe UI', system-ui, sans-serif;
    --font-mono:      'IBM Plex Mono', ui-monospace, 'SFMono-Regular', monospace;

    /* Media-type pastels (chip) + cover-placeholder tints — per design KEY */
    --type-book:      #BFE6D2;   /* mint  */
    --type-comic:     #BFDCF2;   /* blue  */
    --type-screen:    #F6D3BE;   /* peach — movies & TV */
    --type-game:      #EFC9DA;   /* pink  */
    /* Orchid. The other five pastels plus the two Venn tints leave no room at
       this lightness — every candidate hue landed within ΔE 11 of something
       already spoken for, which is confusable at chip size. This sits ΔE 22
       from its nearest neighbour (game pink) and ΔE 53 from book mint, the
       pair that actually has to be told apart, while keeping 8.2:1 against the
       navy label. Slightly more saturated than its neighbours as the price. */
    --type-audiobook: #DDA8DD;   /* orchid — audiobooks */

    /* Library-overlap Venn: two PEOPLE, not two media types. This used to
       borrow --type-comic and --type-screen, which made a library comparison
       look exactly like a comics-vs-film split.
       Lavender and butter are the two pastel families nothing else in the app
       claims, so neither can be mistaken for a category. Both stay light
       enough for the dark count labels, and multiplied together they give the
       lens a warm taupe (~#C4B3A7) that reads as a genuine blend of the two
       rather than as a third colour. */
    --overlap-mine:   #D3CCEB;   /* lavender */
    --overlap-theirs: #EDE0B5;   /* butter   */

    --radius-sm:      4px;
    --radius:         10px;
    --radius-lg:      14px;
    --radius-pill:    999px;
    --shadow-sm:      0 1px 3px rgba(22,35,42,0.10);
    --shadow:         0 5px 14px rgba(22,35,42,0.12);
    --shadow-lg:      0 18px 40px rgba(22,35,42,0.20);
    --transition:     140ms ease;
}

/* Reset */
*, *::before, *::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* Base */
body {
    font-family: var(--font-display);
    background: var(--bg);
    min-height: 100vh;
    color: var(--text);
    font-size: 15px;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    padding: 32px 20px;
}

.page-frame {
    max-width: 820px;
    margin: 0 auto;
    border: 1.5px solid var(--navy);
    border-radius: 20px;
    overflow: hidden;
    box-shadow: 0 0 0 1px rgba(28, 46, 74, 0.06), var(--shadow-lg);
}

.container {
    padding: 0 24px 56px;
}

/* ── Header ─────────────────────────────────────────── */
header {
    background: var(--navy);
    padding: 40px 20px 36px;
    margin-bottom: 32px;
    text-align: center;
}

.settings-btn {
    margin-top: 16px;
    padding: 6px 16px;
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: var(--radius);
    color: rgba(255, 255, 255, 0.6);
    font-size: 0.78rem;
    font-family: inherit;
    font-weight: 500;
    letter-spacing: 0.04em;
    cursor: pointer;
    transition: border-color var(--transition), color var(--transition);
}

.settings-btn:hover {
    border-color: rgba(255, 255, 255, 0.5);
    color: rgba(255, 255, 255, 0.9);
}

header h1 {
    font-family: var(--font-display);
    font-size: 2rem;
    font-weight: 400;
    letter-spacing: 0;
    color: #fff;
    margin-bottom: 6px;
}

.subtitle {
    font-size: 0.875rem;
    color: rgba(255, 255, 255, 0.45);
    font-weight: 400;
}

/* ── Panels ─────────────────────────────────────────── */
.panel {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 28px;
    margin-bottom: 16px;
    box-shadow: var(--shadow-sm);
}

.panel h2 {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-3);
    margin-bottom: 24px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--border);
}

/* ── Configuration ──────────────────────────────────── */
.config-group {
    margin-bottom: 20px;
}

.config-group label {
    display: block;
    font-size: 0.83rem;
    font-weight: 500;
    color: var(--text-2);
    margin-bottom: 6px;
}

.config-group input {
    width: 100%;
    padding: 9px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    font-size: 0.875rem;
    font-family: inherit;
    color: var(--text);
    background: var(--bg);
    transition: border-color var(--transition), box-shadow var(--transition);
}

.config-group input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-dim);
}

.config-group small {
    display: block;
    margin-top: 5px;
    color: var(--text-3);
    font-size: 0.78rem;
}

.help-link {
    display: inline-block;
    margin-top: 6px;
    color: var(--accent);
    text-decoration: none;
    font-size: 0.82rem;
    font-weight: 500;
}

.help-link:hover {
    text-decoration: underline;
}

.status-text {
    margin-left: 10px;
    font-size: 0.83rem;
    color: var(--text-2);
    font-weight: 500;
}

/* ── Buttons ─────────────────────────────────────────── */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 9px 18px;
    border: none;
    border-radius: var(--radius-pill);
    font-size: 0.85rem;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: background var(--transition), box-shadow var(--transition), opacity var(--transition);
    white-space: nowrap;
    letter-spacing: 0.01em;
}

.btn:disabled {
    opacity: 0.35;
    cursor: not-allowed;
    pointer-events: none;
}

.btn-primary {
    background: var(--navy);
    color: #fff;
}

.btn-primary:hover:not(:disabled) {
    background: var(--navy-light);
    box-shadow: var(--shadow);
}

.btn-secondary {
    background: var(--surface-alt);
    color: var(--text);
    border: 1px solid var(--border);
}

.btn-secondary:hover:not(:disabled) {
    background: var(--border);
}

/* Ink, mono, uppercase — the same treatment the redesign gave the diary Save
   pill and then never generalised. This rule was the last survivor of the
   pre-redesign button set: solid terracotta sans-serif in a UI otherwise built
   from mono-uppercase pills, on --accent, which nothing else uses structurally. */
.btn-success {
    background: var(--navy);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.btn-success:hover:not(:disabled) {
    background: var(--navy-light);
    box-shadow: var(--shadow);
}

/* .btn-sm sets font-size after this in the cascade, which would put the small
   variants back to 0.8rem sans-serif proportions. */
.btn-success.btn-sm {
    font-size: 0.64rem;
    padding: 6px 13px;
}

/* ── Scanner ─────────────────────────────────────────── */
#scanner-container {
    position: relative;
    width: 100%;
    margin: 0 0 16px;
    background: #0a0a0a;
    border-radius: var(--radius);
    overflow: hidden;
    border: 1px solid var(--border);
}

.viewport {
    position: relative;
    width: 100%;
    height: 400px;
}

.viewport video,
.viewport canvas {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.viewport canvas.drawingBuffer {
    z-index: 2;
}

#scanner-overlay {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 82%;
    height: 52%;
    border: 1.5px solid rgba(255, 255, 255, 0.5);
    border-radius: var(--radius);
    pointer-events: none;
    z-index: 3;
    box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.35);
}

.scan-line {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 2px;
    background: var(--accent);
    box-shadow: 0 0 10px var(--accent), 0 0 24px var(--accent-dim);
    animation: scan 2.2s ease-in-out infinite;
}

@keyframes scan {
    0%, 100% { top: 0; opacity: 1; }
    50% { top: calc(100% - 2px); opacity: 0.85; }
}

.scanner-controls {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

/* ── Result Box ──────────────────────────────────────── */
.result-box {
    background: var(--surface-alt);
    padding: 14px 16px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
}

.barcode-display {
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--text-2);
    margin-bottom: 3px;
}

#barcode-value {
    color: var(--accent);
    font-family: 'SF Mono', 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;
    font-size: 0.875rem;
}

/* ── Manual Entry ────────────────────────────────────── */
.manual-entry-section {
    margin-top: 24px;
    padding-top: 22px;
    border-top: 1px solid var(--border);
}

.or-divider {
    text-align: center;
    color: var(--text-3);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin-bottom: 16px;
}

.manual-entry-controls {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-bottom: 8px;
}

#manual-barcode-input {
    flex: 1;
    padding: 9px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    font-size: 0.875rem;
    font-family: 'SF Mono', 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;
    color: var(--text);
    background: var(--bg);
    transition: border-color var(--transition), box-shadow var(--transition);
}

#manual-barcode-input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-dim);
}

#manual-barcode-input::placeholder {
    font-family: inherit;
    color: var(--text-3);
}

.help-text {
    display: block;
    color: var(--text-3);
    font-size: 0.78rem;
}

/* ── Comic Info ──────────────────────────────────────── */
.comic-details {
    display: flex;
    gap: 24px;
    margin-bottom: 24px;
}

.comic-cover {
    flex-shrink: 0;
    width: 150px;
}

.comic-cover img {
    width: 100%;
    height: auto;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    box-shadow: var(--shadow);
    display: block;
}

.comic-metadata {
    flex: 1;
    min-width: 0;
}

.info-row {
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
    display: flex;
    gap: 16px;
    align-items: baseline;
}


.info-row strong {
    min-width: 100px;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text-3);
    flex-shrink: 0;
}

.info-row span {
    color: var(--text);
    font-size: 0.875rem;
}

.action-buttons {
    display: flex;
    gap: 10px;
    padding-top: 8px;
}

/* ── Scan History ────────────────────────────────────── */
.history-list {
    max-height: 300px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.history-item {
    background: var(--surface-alt);
    padding: 14px 16px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    border-left: 3px solid var(--accent);
}

.history-item .barcode {
    font-family: 'SF Mono', 'Fira Code', 'Courier New', monospace;
    color: var(--text-3);
    font-size: 0.75rem;
    margin-bottom: 3px;
}

.history-item .title {
    font-weight: 500;
    font-size: 0.875rem;
    color: var(--text);
}

.history-item .timestamp {
    font-size: 0.75rem;
    color: var(--text-3);
    margin-top: 4px;
}

.empty-state {
    text-align: center;
    color: var(--text-3);
    font-size: 0.85rem;
    padding: 24px;
}

/* ── Loading Overlay ─────────────────────────────────── */
.overlay {
    position: fixed;
    inset: 0;
    background: rgba(28, 46, 74, 0.65);
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    z-index: 1000;
    backdrop-filter: blur(3px);
}

.spinner {
    width: 32px;
    height: 32px;
    border: 2.5px solid rgba(255, 255, 255, 0.2);
    border-top-color: #fff;
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
}

.spinner-small {
    width: 11px;
    height: 11px;
    border: 1.5px solid rgba(0, 0, 0, 0.15);
    border-top-color: #92400E;
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

#loading-message {
    color: rgba(255, 255, 255, 0.8);
    margin-top: 14px;
    font-size: 0.875rem;
    font-weight: 500;
}

/* ── Toast Notifications ─────────────────────────────── */
#toast-container {
    position: fixed;
    top: 20px;
    right: 20px;
    z-index: 2000;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.toast {
    background: var(--surface);
    padding: 13px 16px;
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    min-width: 260px;
    max-width: 340px;
    border: 1px solid var(--border);
    animation: toastIn 0.18s ease-out;
    display: flex;
    align-items: center;
    gap: 10px;
}

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

.toast.success { border-left: 3px solid var(--success); }
.toast.error   { border-left: 3px solid var(--danger); }
.toast.info    { border-left: 3px solid var(--navy); }

.toast-icon {
    font-size: 0.7rem;
    font-weight: 800;
    width: 17px;
    height: 17px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.toast.success .toast-icon { background: var(--success-dim); color: var(--success); }
.toast.error   .toast-icon { background: var(--danger-dim);  color: var(--danger); }
.toast.info    .toast-icon { background: var(--info-dim);    color: var(--info); }

.toast-message {
    flex: 1;
    font-size: 0.85rem;
    color: var(--text);
    line-height: 1.4;
}

/* ── Focus ───────────────────────────────────────────── */
.btn:focus-visible,
input:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* ── Utilities ───────────────────────────────────────── */
.hidden { display: none !important; }

/* ── Responsive ──────────────────────────────────────── */
@media (max-width: 600px) {
    header {
        padding: 32px 20px 28px;
    }

    header h1 {
        font-size: 1.3rem;
    }

    .panel {
        padding: 20px 16px;
    }

    .comic-details {
        flex-direction: column;
        align-items: center;
    }

    .comic-cover {
        width: 130px;
    }

    .action-buttons {
        flex-direction: column;
    }

    .scanner-controls .btn {
        flex: 1;
    }

    #toast-container {
        left: 12px;
        right: 12px;
        top: 12px;
    }

    .toast {
        min-width: auto;
    }

    .viewport {
        height: 280px;
    }

    .info-row {
        flex-direction: column;
        gap: 2px;
    }

    .manual-entry-controls {
        flex-direction: column;
    }

    #manual-barcode-input {
        width: 100%;
    }

    /* ── View padding ── */
    .view {
        padding: 16px 16px 32px;
    }

    /* ── Overlay body ── */
    .overlay-body {
        padding: 16px 16px 48px;
    }

    /* ── Item detail hero: stack cover above metadata ── */
    .item-detail-hero {
        flex-direction: column;
        align-items: center;
        gap: 16px;
    }

    .item-detail-cover {
        width: 160px;
    }

    .item-detail-head {
        width: 100%;
        text-align: left;
    }

    .item-detail-title {
        font-size: 1.15rem;
    }

    /* ── Book rating summary ── */
    .book-rating-summary {
        gap: 10px;
    }

    .book-rating-avg {
        font-size: 2rem;
    }
}

/* ============================================================
   Unit 7 — App Shell Layout
   ============================================================ */

body {
    padding: 0;
}

@media (min-width: 820px) {
    body { padding: 32px 20px; }
}

.app-shell {
    max-width: 820px;
    margin: 0 auto;
    height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--bg);
    position: relative;
    /* `clip`, not `hidden`. A closed dialog is still laid out, and a transform
       still contributes scrollable overflow. `hidden` stops the user scrolling
       to it but not the browser: any scrollIntoView() deep in the page would
       drag a parked dialog into view, where it sat looking like a blank popup
       that could not be dismissed, because it was never actually open. `clip`
       makes the container genuinely unscrollable. (This was written when the
       dialogs were bottom sheets parked at translateY(100%); centring them
       shrinks the overflow but does not remove the hazard.)
       `hidden` first as the fallback: clip is Safari 16+, and a browser that
       drops the declaration would otherwise land on `visible` and spill. */
    overflow: hidden;
    overflow: clip;
}

@media (min-width: 820px) {
    .app-shell {
        height: calc(100vh - 64px);
        border: 1.5px solid var(--navy);
        border-radius: 20px;
        box-shadow: 0 0 0 1px rgba(28,46,74,0.06), var(--shadow-lg);
    }
}

/* ── App Header ────────────────────────────────────────── */
.app-header {
    flex-shrink: 0;
    background: var(--bg);
    border-bottom: 1px solid var(--border);
    padding: 12px 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

/* Logo highlighted with the sidebar's layered-pastel selection block */
.app-logo {
    position: relative;
    isolation: isolate;
    display: inline-flex;
    align-items: center;
    padding: 4px 12px;
    border-radius: 8px;
    background: var(--type-book);
    font-family: var(--font-display);
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--text);
    letter-spacing: -0.01em;
    white-space: nowrap;
}
.app-logo::before,
.app-logo::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 8px;
    mix-blend-mode: multiply;
    z-index: 0;
}
.app-logo::before { background: var(--type-comic); transform: translate(4px, 3px); }
.app-logo::after  { background: var(--type-screen); transform: translate(8px, 5px); }
.app-logo > span { position: relative; z-index: 1; }

.user-email-text {
    font-size: 0.8rem;
    color: var(--text-2);
}

/* ── Views ─────────────────────────────────────────────── */
.views-container {
    flex: 1;
    position: relative;
    overflow: hidden;
    min-height: 0;
}

.view {
    position: absolute;
    inset: 0;
    height: 100%;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 20px 20px 32px;
    box-sizing: border-box;
    opacity: 0;
    pointer-events: none;
    /* keep views GPU-composited to avoid repaint flash on switch */
    will-change: opacity;
}

.view.view-active {
    opacity: 1;
    pointer-events: auto;
}

.view-title {
    font-family: var(--font-display);
    font-size: clamp(2.2rem, 5.5vw, 3.4rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.02;
    color: var(--text);
}

/* ── Bottom Nav ────────────────────────────────────────── */
.bottom-nav {
    flex-shrink: 0;
    display: flex;
    gap: 4px;
    background: var(--surface);
    border-top: 1px solid var(--border);
    padding: 8px 8px calc(env(safe-area-inset-bottom) + 16px);
}

.nav-btn {
    flex: 1;
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 9px 4px;
    border: none;
    border-radius: 12px;
    background: transparent;
    color: var(--text-3);
    cursor: pointer;
    font-family: inherit;
    overflow: visible;
    transition: color var(--transition);
}

.nav-btn:hover:not(.active) { color: var(--text-2); }

.nav-icon {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    position: relative;
    z-index: 1;
}

.nav-label {
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    position: relative;
    z-index: 1;
}

/* Active tab: layered pastel selection pill, mirroring the desktop sidebar */
.nav-btn.active { color: var(--text); background: var(--type-book); }
.nav-btn.active .nav-label { font-weight: 700; color: var(--text); }
.nav-btn.active::before,
.nav-btn.active::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 12px;
    mix-blend-mode: multiply;
    z-index: 0;
}
.nav-btn.active::before { background: var(--type-comic); transform: translate(4px, 3px); }
.nav-btn.active::after  { background: var(--type-screen); transform: translate(8px, 6px); }

/* ── Sidebar (desktop only) ────────────────────────────── */
.sidebar { display: none; }

@media (min-width: 900px) {
    .sidebar {
        display: flex;
        flex-direction: column;
        position: fixed;
        top: 0; left: 0; bottom: 0;
        width: 232px;
        background: var(--navy);
        padding: 26px 16px;
        z-index: 50;
    }
    .sidebar-logo {
        font-family: var(--font-display);
        font-weight: 700;
        font-size: 1.3rem;
        color: #fff;
        padding: 0 10px 22px;
        letter-spacing: -0.01em;
    }
    .sidebar-nav { display: flex; flex-direction: column; gap: 4px; }
    .sidebar .nav-btn {
        flex: none;
        flex-direction: row;
        justify-content: flex-start;
        gap: 12px;
        padding: 11px 12px;
        border-radius: var(--radius);
        color: rgba(255,255,255,0.60);
    }
    .sidebar .nav-btn .nav-label {
        font-family: var(--font-mono);
        font-size: 0.72rem;
        font-weight: 500;
        text-transform: uppercase;
        letter-spacing: 0.08em;
    }
    .sidebar .nav-btn.active { color: var(--navy); background: #fff; }
    .sidebar .nav-btn:hover:not(.active) { color: #fff; background: rgba(255,255,255,0.09); }

    /* Full-width desktop layout: sidebar offset, drop the phone frame */
    .app-shell {
        max-width: none;
        margin: 0 0 0 232px;
        height: 100vh;
        border: none !important;
        border-radius: 0 !important;
        box-shadow: none !important;
    }
    .app-header {
        background: var(--surface);
        border-bottom: 1px solid var(--border);
    }
    .app-header .app-logo { display: none; }
    .app-header .user-email-text { color: var(--text-2); }
    .bottom-nav { display: none; }

    /* Center + constrain content on wide screens */
    .view {
        padding-left:  max(32px, calc((100% - 1440px) / 2));
        padding-right: max(32px, calc((100% - 1440px) / 2));
    }
}

/* ── Detail Overlays ───────────────────────────────────── */
.detail-overlay {
    position: absolute;
    inset: 0;
    background: var(--surface);
    z-index: 200;
    overflow-y: auto;
    overflow-x: hidden;
    opacity: 0;
    pointer-events: none;
    transition: opacity 200ms ease-out;
    -webkit-overflow-scrolling: touch;
}

.detail-overlay.open { opacity: 1; pointer-events: auto; }

@media (prefers-reduced-motion: reduce) { .detail-overlay { transition: none; } }
.detail-overlay.open.overlay-stacked { z-index: 270; }

/* The list detail is the one overlay that is a dialog rather than a page: a
   list of three titles full-bleed on a desktop viewport is mostly white. The
   overlay element becomes the scrim and the card inside it holds the content.
   _openOverlay sets display:block inline, so the card centres on absolute
   positioning rather than flex — an inline style would win over `display`. */
#overlay-list {
    background: rgba(0, 0, 0, 0.32);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    overflow: hidden;
}
#overlay-list .list-dialog-card {
    position: absolute;
    top: 50%;
    left: 50%;
    /* Percentages of #overlay-list, which is inset:0 of .views-container — the
       viewport less the header and the bottom nav. A vh cap overshoots that,
       and the container's overflow:hidden would clip the card's edges with no
       way to scroll to them. */
    width: min(920px, calc(100% - 32px));
    max-height: calc(100% - 32px);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 26px;
    box-shadow: var(--shadow-lg);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transform: translate(-50%, -50%) scale(0.97);
    transition: transform 200ms ease-out;
}
#overlay-list.open .list-dialog-card { transform: translate(-50%, -50%) scale(1); }
@supports (corner-shape: squircle) {
    #overlay-list .list-dialog-card {
        corner-shape: squircle;
        border-radius: 34px;
    }
}
@media (prefers-reduced-motion: reduce) {
    #overlay-list .list-dialog-card { transition: none; }
}
/* Same breakpoint as the sidebar: past it the shell is the viewport less 224px,
   and a card sized to a short list sits marooned in all that room. Fixed height
   rather than a cap, so the dialog does not change size per list — the white
   space under a two-item list is the lesser cost. The body scrolls past it.
   Below 900px the card stays content-sized: the phone has no room to spare, and
   a near-fullscreen card is the full-bleed page this replaced. */
@media (min-width: 900px) {
    #overlay-list .list-dialog-card { height: min(680px, calc(100% - 48px)); }
}
/* The card clips its own corners, so the bar only needs to stop shrinking —
   and hold the ✕ against the right edge, where every other dialog puts it.
   No rule under it: holding one small button, a full-width bordered band read
   as an empty strip. The list's own <h1> is the header here. */
#overlay-list .overlay-top-bar {
    flex-shrink: 0;
    display: flex;
    justify-content: flex-end;
    padding: 10px 12px 0;
    border-bottom: none;
}
#overlay-list .overlay-body {
    overflow-y: auto;
    padding: 4px 20px 24px;
}

/* ── Top-slide overlay (Settings) ─────────────────────── */
.top-overlay {
    position: absolute;
    inset: 0;
    background: var(--surface);
    z-index: 200;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    transform: translateY(-100%);
    transition: transform 260ms cubic-bezier(0.4, 0, 0.2, 1);
    padding: 20px 20px 32px;
    box-sizing: border-box;
}
.top-overlay.open { transform: translateY(0); }

/* ── Social bottom sheet ───────────────────────────────── */
.social-sheet-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.32);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    /* Above the overlays (200, or 270 stacked, plus the per-open bump in
       _openOverlay), because a dialog is always raised *from* one — Edit on a
       list detail opens this over #overlay-list. At 250 it rendered behind the
       list and could not be reached. Still below the toast layer at 1000. */
    z-index: 300;
    opacity: 0;
    pointer-events: none;
    transition: opacity 260ms cubic-bezier(0.4, 0, 0.2, 1);
}
.social-sheet-backdrop.open {
    opacity: 1;
    pointer-events: auto;
}

/* A centered squircle card, not a bottom sheet. The sheet was a phone
   convention: full-bleed and edge-anchored, it strands itself across a wide
   viewport. One centered card sized in `min()` reads correctly at both ends,
   so there is a single treatment rather than a breakpoint fork. */
.social-sheet {
    position: absolute;
    top: 50%;
    left: 50%;
    width: min(440px, calc(100% - 28px));
    background: var(--surface);
    border-radius: 26px;
    /* Percentage, not vh: the containing block is .app-shell, which is shorter
       than the viewport on desktop and clips (overflow: clip), so a vh cap
       taller than it would put the edges somewhere unscrollable. */
    max-height: min(640px, calc(100% - 32px));
    display: flex;
    flex-direction: column;
    overflow: hidden;
    z-index: 310;
}
/* Belt and braces: a parked dialog must not be tappable even if something does
   surface it. Delayed so the fade-out still plays before it disappears. */
.social-sheet {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.96);
    visibility: hidden;
    pointer-events: none;
    transition: transform 220ms cubic-bezier(0.4, 0, 0.2, 1),
                opacity   220ms cubic-bezier(0.4, 0, 0.2, 1),
                visibility 0s linear 220ms;
}
.social-sheet.open {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
    visibility: visible;
    pointer-events: auto;
    transition: transform 220ms cubic-bezier(0.4, 0, 0.2, 1),
                opacity   220ms cubic-bezier(0.4, 0, 0.2, 1),
                visibility 0s;
}
/* Actual superellipse corners where the browser has them; the plain radius
   above is the fallback everywhere else. */
@supports (corner-shape: squircle) {
    .social-sheet {
        corner-shape: squircle;
        border-radius: 34px;
    }
}

/* The grab handle was affordance for a sheet you could swipe down. Nothing
   drags now, so it would be a promise the dialog doesn't keep. */
.social-sheet-handle { display: none; }

.social-sheet-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 16px 12px;
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    background: var(--surface);
}

.social-sheet-title {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text);
}

.social-sheet-body .friend-row {
    padding: 12px 16px;
    display: flex;
    align-items: center;
    border-bottom: 1px solid var(--border);
}
.social-sheet-body .friend-row:last-child {
    border-bottom: none;
}
.social-sheet-body .empty-state {
    padding: 24px 16px;
    margin: 0;
}

/* The item overlay's bar carries the back button on the left and the flip
   controls on the right; every other overlay has only the button. */
#overlay-item .overlay-top-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.item-nav {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

.item-nav-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border: 1px solid var(--border-strong);
    border-radius: 50%;
    background: var(--surface);
    color: var(--text-2);
    cursor: pointer;
    padding: 0;
}
.item-nav-btn:hover:not(:disabled) {
    border-color: var(--navy);
    color: var(--navy);
}
/* Kept in place rather than hidden at the ends of a run: the pair jumping
   sideways as you reach the last issue is more distracting than a dim arrow. */
.item-nav-btn:disabled {
    opacity: 0.3;
    cursor: default;
}

/* The count is the point. An arrow alone does not tell you a run has eleven
   more issues in it. */
.item-nav-count {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    letter-spacing: 0.04em;
    color: var(--text-3);
    min-width: 54px;
    text-align: center;
}

.overlay-top-bar {
    position: sticky;
    top: 0;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    padding: 12px 16px;
    z-index: 10;
}

.back-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border: none;
    background: transparent;
    color: var(--text-2);
    font-size: 0.875rem;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    padding: 4px 0;
    transition: color var(--transition);
}

.back-btn:hover { color: var(--text); }

.overlay-body {
    padding: 20px 20px 48px;
}

/* ── Item Detail ───────────────────────────────────────── */
.item-detail-hero {
    display: flex;
    gap: 20px;
    margin-bottom: 24px;
}

.item-detail-cover {
    flex-shrink: 0;
    width: 300px;
}

.item-detail-cover img {
    width: 100%;
    height: auto;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    box-shadow: var(--shadow);
    display: block;
}

/* ── Book Rating Summary ───────────────────────────────── */
.book-rating-summary {
    display: flex;
    align-items: center;
    gap: 14px;
    border-top: 1px solid var(--border);
    padding-top: 16px;
}

.book-rating-avg {
    font-family: var(--font-display);
    font-size: 2.4rem;
    font-weight: 400;
    color: var(--text);
    line-height: 1;
}

.book-rating-detail {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.book-rating-count {
    font-size: 0.78rem;
    color: var(--text-3);
}

.book-rating-histogram {
    flex: 1;
    display: flex;
    align-items: flex-end;
    gap: 3px;
    height: 44px;
}

.book-rating-bar {
    flex: 1;
    background: var(--accent);
    border-radius: 2px 2px 0 0;
    opacity: 0.75;
    min-height: 0;
}

/* ── Item Personal Section ─────────────────────────────── */
.item-personal-section {
    border-top: 1px solid var(--border);
    padding-top: 4px;
}

.item-detail-head { flex: 1; min-width: 0; }

.item-detail-title-row {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 3px;
}

.item-detail-title {
    font-family: var(--font-display);
    font-size: 1.3rem;
    font-weight: 400;
    line-height: 1.3;
    color: var(--text);
    margin-bottom: 0;
}

.item-detail-issue {
    font-size: 0.95rem;
    color: var(--text-3);
    font-weight: 500;
    white-space: nowrap;
}

.item-detail-sub {
    font-size: 0.85rem;
    color: var(--text-2);
    margin-bottom: 8px;
}

.item-classification {
    display: flex;
    flex-wrap: wrap;
    gap: 0;
}
.classification-pill {
    font-size: 0.78rem;
    font-weight: 400;
    letter-spacing: 0;
    color: var(--text-3);
    background: none;
    border: none;
    border-radius: 0;
    padding: 0;
}
.classification-pill::after {
    content: ' · ';
}
.classification-pill:last-child::after {
    content: '';
}

.info-rows { display: flex; flex-direction: column; }

/* ── Series Detail ─────────────────────────────────────── */
.series-detail-title {
    font-family: var(--font-display);
    font-size: 1.6rem;
    font-weight: 400;
    color: var(--text);
    margin-bottom: 3px;
}

.series-detail-publisher {
    font-size: 0.85rem;
    color: var(--text-2);
    margin-bottom: 3px;
}

.series-detail-completion {
    font-size: 0.85rem;
    color: var(--text-2);
    margin: 4px 0 24px;
}

.series-issue-list { display: flex; flex-direction: column; gap: 8px; }

.series-issue-card {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    cursor: pointer;
    transition: box-shadow var(--transition);
}

.series-issue-card:hover { box-shadow: var(--shadow); }

.series-issue-cover {
    width: 40px;
    height: 58px;
    border-radius: 3px;
    overflow: hidden;
    background: var(--border);
    flex-shrink: 0;
}

.series-issue-cover img { width: 100%; height: 100%; object-fit: cover; }

.series-issue-info { flex: 1; }

.series-issue-num {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text);
}

/* ── Search ────────────────────────────────────────────── */
.search-type-toggle {
    display: flex;
    gap: 4px;
    margin-bottom: 12px;
}

.search-type-btn {
    padding: 6px 16px;
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    background: transparent;
    color: var(--text-2);
    font-size: 0.85rem;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}

.search-type-btn.active {
    background: var(--navy);
    border-color: var(--navy);
    color: #fff;
}

/* .search-type-scan's margin-left:auto removed — it lived in the type-chip
   row and pushed Scan to the far end. It now has .search-scan-row to itself. */

.search-input-row {
    display: flex;
    gap: 8px;
    margin-bottom: 20px;
}

.search-input {
    flex: 1;
    padding: 10px 12px;
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    font-size: 0.9rem;
    font-family: inherit;
    color: var(--text);
    background: var(--bg);
    transition: border-color var(--transition);
}

.search-input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-dim);
}

.search-results { display: flex; flex-direction: column; gap: 8px; }

.search-result-card {
    display: flex;
    gap: 14px;
    align-items: flex-start;
    padding: 12px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    cursor: pointer;
    transition: box-shadow var(--transition);
}

.search-result-card:hover { box-shadow: var(--shadow); }

.search-result-cover {
    flex-shrink: 0;
    width: 46px;
    height: 66px;
    border-radius: 4px;
    overflow: hidden;
    background: var(--border);
    border: 1px solid var(--border-strong);
}

.search-result-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }

.search-result-info { flex: 1; min-width: 0; }

.search-result-title {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 2px;
}

.search-result-sub { font-size: 0.78rem; color: var(--text-2); }
.search-result-pub { font-size: 0.75rem; color: var(--text-3); margin-top: 2px; }

.no-upc { color: var(--danger); }

.in-library-badge {
    display: inline-block;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--accent);
    background: var(--accent-dim);
    border-radius: 20px;
    padding: 1px 7px;
    margin-left: 6px;
    vertical-align: middle;
}

/* "DLC", "Bundle", "Expansion" — what kind of thing a Games tab result is.
   Deliberately quieter than .in-library-badge, and outlined rather than
   filled: the two can sit side by side on one row, and "In Library" is the
   one worth noticing. This is a footnote, not an alert. */
.result-kind-chip {
    display: inline-block;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-3);
    border: 1px solid var(--border-strong);
    border-radius: 20px;
    padding: 0 6px;
    margin-left: 6px;
    vertical-align: middle;
}

/* ── Profile / Stats ───────────────────────────────────── */
.profile-view-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}

.settings-view-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 20px;
}
.settings-view-header .view-title {
    margin: 0;
}

.profile-social-row {
    display: flex;
    gap: 12px;
    margin-bottom: 8px;
}

.social-count-btn {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 12px 8px;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}
.social-count-btn:hover {
    background: var(--surface-alt);
    border-color: var(--border-strong);
}

.social-count {
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--text);
}

.social-label {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text-2);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}


.profile-email {
    font-size: 0.85rem;
    color: var(--text-2);
    margin-bottom: 20px;
}

.stats-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    margin-bottom: 28px;
}

.stat-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 16px 12px;
    text-align: center;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.stat-card.stat-accent {
    background: var(--navy);
    border-color: var(--navy);
}

.stat-value {
    font-family: var(--font-mono);
    font-size: 1.9rem;
    font-weight: 500;
    color: var(--text);
    line-height: 1;
}

.stat-accent .stat-value { color: #fff; }

.stat-label {
    font-family: var(--font-mono);
    font-size: 0.66rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text-3);
}

.stat-accent .stat-label { color: rgba(255,255,255,0.55); }

.stat-card.stat-see-stats {
    cursor: pointer;
    justify-content: center;
    align-items: center;
}
.stat-card.stat-see-stats:active { opacity: 0.7; }
.stat-see-stats-arrow {
    font-size: 1.5rem;
    color: var(--text-2);
    line-height: 1;
}

.section-label {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-3);
    margin-bottom: 12px;
}

.currently-reading-section { margin-bottom: 28px; }

.cr-section-header {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 14px;
}

.cr-header-title {
    font-family: var(--font-display);
    font-size: 1.4rem;
    font-weight: 400;
    color: var(--text);
}

.cr-count-badge {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--surface-alt);
    border: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text-2);
}

.cr-grid {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    padding-bottom: 4px;
    scrollbar-width: none;
}
.cr-grid::-webkit-scrollbar { display: none; }

.cr-card {
    flex-shrink: 0;
    width: 100px;
}

.cr-card-cover {
    width: 100px;
    height: 144px;
    object-fit: cover;
    border-radius: var(--radius);
    display: block;
    margin-bottom: 6px;
    background: var(--border);
}

.cr-card-title {
    font-size: 0.82rem;
    color: var(--text-2);
    line-height: 1.35;
}

.cr-item-clickable { cursor: pointer; }
.cr-card.cr-item-clickable:hover .cr-card-cover {
    opacity: 0.85;
    transition: opacity var(--transition);
}

.currently-reading-list { display: flex; flex-direction: column; gap: 8px; }

.cr-item {
    display: flex;
    gap: 12px;
    align-items: center;
    padding: 10px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.cr-cover {
    width: 36px;
    height: 52px;
    object-fit: cover;
    border-radius: 3px;
    flex-shrink: 0;
    background: var(--border);
}

.cr-info { flex: 1; min-width: 0; }

.cr-title {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cr-page { font-size: 0.75rem; color: var(--text-3); margin-top: 2px; }

.settings-section { padding-top: 8px; }

/* ============================================================
   Auth Modal
   ============================================================ */

.auth-modal {
    position: fixed;
    inset: 0;
    background: var(--surface);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    padding: 20px;
}

.auth-card {
    background: var(--surface);
    border: 1.5px solid var(--border-strong);
    border-radius: var(--radius-lg);
    padding: 40px 36px;
    width: 100%;
    max-width: 400px;
    box-shadow: var(--shadow-lg);
}

.auth-logo {
    font-family: var(--font-display);
    font-size: 1.8rem;
    color: var(--navy);
    text-align: center;
    margin-bottom: 3px;
}

.auth-tagline {
    color: var(--text-2);
    text-align: center;
    font-size: 0.9rem;
    margin-bottom: 28px;
}

.auth-tabs {
    display: flex;
    gap: 0;
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    margin-bottom: 24px;
}

.auth-tab {
    flex: 1;
    padding: 8px 0;
    border: none;
    background: transparent;
    color: var(--text-2);
    font-size: 0.9rem;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}

.auth-tab.active {
    background: var(--navy);
    color: #fff;
}

#auth-form .form-group,
#forgot-password-panel .form-group,
#reset-password-panel .form-group {
    margin-bottom: 16px;
}

#auth-form label,
#forgot-password-panel label,
#reset-password-panel label {
    display: block;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--text-2);
    margin-bottom: 6px;
}

#auth-form input,
#forgot-password-panel input,
#reset-password-panel input {
    width: 100%;
    padding: 10px 12px;
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    font-size: 0.95rem;
    background: var(--bg);
    color: var(--text);
    transition: border-color var(--transition);
}

#auth-form input:focus,
#forgot-password-panel input:focus,
#reset-password-panel input:focus {
    outline: none;
    border-color: var(--navy);
}

.auth-error {
    font-size: 0.85rem;
    min-height: 20px;
    margin-bottom: 12px;
    color: var(--danger);
}

.auth-link {
    background: none;
    border: none;
    padding: 0;
    color: var(--accent);
    font-size: 0.85rem;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.auth-link:hover {
    opacity: 0.75;
}

.btn-full {
    width: 100%;
}

/* User bar in header */
#user-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 0.85rem;
    color: var(--text-2);
}

.btn-sm {
    padding: 4px 12px;
    font-size: 0.8rem;
}

/* ============================================================
   Library & Shelf — Unit 5
   ============================================================ */

/* ── Status Badges ──────────────────────────────────── */
.status-badge {
    display: inline-flex;
    align-items: center;
    padding: 3px 9px;
    border-radius: 99px;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.status-badge.want    { background: var(--info-dim);    color: var(--info); }
.status-badge.to_read { background: #2d1f5e;            color: #b39ddb; }
.status-badge.reading { background: var(--accent-dim);  color: var(--accent); }
.status-badge.paused  { background: #f4e6c8;            color: #8a6a1c; }
.status-badge.read    { background: var(--success-dim); color: var(--success); }
.status-badge.dnf     { background: var(--surface-alt); color: var(--text-3); border: 1px solid var(--border); }

/* ── Description ─────────────────────────────────────── */
.item-description-section {
    padding-top: 16px;
    margin-top: 4px;
}

.desc-ai-label {
    display: inline-block;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--text-3);
    background: var(--surface-2);
    border-radius: 4px;
    padding: 2px 6px;
    margin-bottom: 8px;
}

.item-description-text {
    font-size: 0.875rem;
    line-height: 1.65;
    color: var(--text-2);
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-bottom: 6px;
}

.item-description-text.expanded {
    display: block;
    overflow: visible;
}

.item-description-toggle {
    background: none;
    border: none;
    padding: 0;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--accent);
    cursor: pointer;
    letter-spacing: 0.02em;
}

/* ── Shelf Status Section ────────────────────────────── */
.shelf-status-section {
    border-top: 1px solid var(--border);
    padding-top: 20px;
    margin-top: 20px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.shelf-current {
    display: flex;
    align-items: center;
    gap: 10px;
}

.shelf-label {
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-3);
}

.status-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.status-select {
    appearance: none;
    -webkit-appearance: none;
    padding: 6px 32px 6px 14px;
    border: 1.5px solid var(--border);
    border-radius: 999px;
    background: var(--surface);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    color: var(--text);
    font-size: 0.875rem;
    font-family: inherit;
    font-weight: 500;
    cursor: pointer;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.status-select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-dim);
}

.location-row { /* inherits border-bottom from .info-row */ }

.finished-date-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 10px;
}
.finished-date-row label {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-2);
}
.finished-date-input {
    padding: 7px 10px;
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    font-size: 0.875rem;
    font-family: inherit;
    color: var(--text);
    background: var(--bg);
    transition: border-color var(--transition);
}
.finished-date-input:focus {
    outline: none;
    border-color: var(--accent);
}


.location-inline-input {
    flex: 1;
    border: none;
    background: transparent;
    font-size: 0.825rem;
    font-family: inherit;
    color: var(--text);
    padding: 0;
    outline: none;
}

.location-inline-input::placeholder { color: var(--text-3); }

/* Two offset red pills multiplied together — the same construction as
   .app-logo and .nav-btn.active, which is how the rest of the app draws an
   emphasised chip. This was still a ghost outline button from the old style
   guide, the last thing on the item page that looked borrowed.
   The label needs its own stacking context: ::before is positioned, so at
   z-index 0 it paints ABOVE the button's non-positioned inline text and would
   sit on top of the words. Hence the span, exactly as .app-logo > span.
   Kept as ID rules because .btn-danger-ghost and .btn-sm both land later in
   the file — specificity, not source order, is what makes these win. */
#remove-from-library-btn {
    position: relative;
    isolation: isolate;
    margin-top: 12px;
    /* the offset pill overhangs 4px right / 3px down; reserve it so the
       multiply layer cannot touch whatever follows */
    margin-bottom: 3px;
    align-self: flex-start;
    padding: 7px 16px;
    background: #E08A7E;
    border: none;
    border-radius: var(--radius-pill);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
#remove-from-library-btn::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: #CE7F73;
    mix-blend-mode: multiply;
    transform: translate(4px, 3px);
    z-index: 0;
}
#remove-from-library-btn > span { position: relative; z-index: 1; }
#remove-from-library-btn:hover:not(:disabled) { background: #D67C6F; }

.lib-card-location {
    font-size: 0.72rem;
    color: var(--text-3);
    margin-top: 4px;
}

/* ── Library Controls ─────────────────────────────────── */
.lib-search-row {
    margin-bottom: 12px;
}
.lib-search-row .search-input {
    width: 100%;
    box-sizing: border-box;
}

.lib-filter-row {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

.lib-filter-select {
    padding: 6px 24px 6px 10px;
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--bg);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236B6865' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 7px center;
    -webkit-appearance: none;
    appearance: none;
    color: var(--text-2);
    font-size: 0.8rem;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    transition: border-color var(--transition), color var(--transition);
}

.lib-filter-select:focus {
    outline: none;
    border-color: var(--navy);
    color: var(--text);
}

.lib-filter-select.is-active {
    border-color: var(--navy);
    color: var(--text);
    background-color: var(--surface);
}

.lib-controls {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 20px;
}

.lib-tabs,
.lib-type-filter {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
}

.lib-tab,
.type-btn {
    padding: 6px 14px;
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    background: transparent;
    color: var(--text-2);
    font-size: 0.8rem;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}

.lib-tab:hover,
.type-btn:hover {
    background: var(--surface-alt);
    border-color: var(--border-strong);
    color: var(--text);
}

.lib-tab.active,
.type-btn.active {
    background: var(--navy);
    border-color: var(--navy);
    color: #fff;
}

/* ── Library Cards ────────────────────────────────────── */
.library-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.lib-card {
    display: flex;
    gap: 14px;
    align-items: flex-start;
    padding: 14px;
    background: var(--surface-alt);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    transition: box-shadow var(--transition);
}

.lib-card:hover {
    box-shadow: var(--shadow);
}

.lib-cover {
    flex-shrink: 0;
    width: 46px;
    height: 66px;
    border-radius: 4px;
    overflow: hidden;
    background: var(--border);
    border: 1px solid var(--border-strong);
}

.lib-cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.lib-card-info {
    flex: 1;
    min-width: 0;
}

.lib-card-title {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-bottom: 2px;
}

.lib-card-sub {
    font-size: 0.78rem;
    color: var(--text-2);
    margin-bottom: 8px;
}

.lib-card-right {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
}

/* ── Series Header ────────────────────────────────────── */
/* ── Series card — list mode (default) ─────────────────────────────────── */
.series-card {
    cursor: pointer;
    border-radius: var(--radius);
    background: var(--surface-alt);
    border: 1px solid var(--border);
    transition: box-shadow var(--transition);
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 14px;
    padding: 14px;
    overflow: visible;
}
.series-card:hover { box-shadow: var(--shadow); }

.series-card-cover {
    flex-shrink: 0;
    width: 46px;
    height: 66px;
    border-radius: 4px;
    overflow: hidden;
    background: var(--border);
    position: relative;
    border: 1px solid var(--border-strong);
    padding-top: 0;
}
.series-card-cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    position: static;
}
.series-card-no-cover {
    width: 100%;
    height: 100%;
    background: var(--border);
    position: static;
}
.series-card-count {
    position: absolute;
    bottom: 2px;
    right: 2px;
    background: rgba(0,0,0,0.72);
    color: #fff;
    font-size: 0.55rem;
    font-weight: 700;
    padding: 1px 4px;
    border-radius: 8px;
}
.series-card-info {
    flex: 1;
    min-width: 0;
}
.series-card-title {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-bottom: 2px;
}
.series-card-pub {
    font-size: 0.78rem;
    color: var(--text-2);
}

/* ── Series card — grid mode ────────────────────────────────────────────── */
#library-list.grid-view .series-card {
    flex-direction: column;
    padding: 0;
    gap: 0;
    border-radius: 10px;
    overflow: hidden;
    border: none;
}
#library-list.grid-view .series-card-cover {
    width: 100%;
    height: auto;
    padding-top: 150%;
    position: relative;
    border-radius: 0;
    border: none;
}
#library-list.grid-view .series-card-cover img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
#library-list.grid-view .series-card-no-cover {
    position: absolute;
    inset: 0;
    width: auto;
    height: auto;
}
#library-list.grid-view .series-card-count {
    bottom: 6px;
    right: 6px;
    font-size: 0.65rem;
    padding: 2px 6px;
}
#library-list.grid-view .series-card-info {
    padding: 6px 6px 8px;
}
#library-list.grid-view .series-card-title {
    font-size: 0.72rem;
    white-space: normal;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: unset;
}
#library-list.grid-view .series-card-pub {
    font-size: 0.65rem;
}

.series-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 0 6px;
    border-bottom: 1.5px solid var(--border-strong);
    margin-bottom: 6px;
    margin-top: 12px;
}

.series-header:first-child {
    margin-top: 0;
}

.series-name {
    font-size: 0.8rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text-2);
}

.series-count {
    font-size: 0.72rem;
    font-weight: 600;
    padding: 2px 7px;
    background: var(--border);
    border-radius: 99px;
    color: var(--text-3);
}

/* ── Review Section ───────────────────────────────────── */
.review-section {
    border-top: 1px solid var(--border);
    padding-top: 20px;
    margin-top: 8px;
}

.review-section-header {
    margin-bottom: 14px;
}

.review-section-title {
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-3);
}

.star-rating-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
}

.star-rating {
    display: flex;
    gap: 2px;
}

.rating-input {
    width: 52px;
    padding: 4px 6px;
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    font-size: 0.9rem;
    text-align: center;
}

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

.star {
    font-size: 1.7rem;
    cursor: pointer;
    color: var(--border-strong);
    transition: color var(--transition), transform 80ms ease;
    line-height: 1;
    user-select: none;
    display: inline-block;
    position: relative;
}

.star.filled  { color: #E8A020; }
.star.hovered { color: #F0B840; }
.star:hover   { transform: scale(1.15); }

.star.half {
    background: linear-gradient(to right, #E8A020 50%, var(--border-strong) 50%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

.star.hovered-half {
    background: linear-gradient(to right, #F0B840 50%, var(--border-strong) 50%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

.star.quarter {
    background: linear-gradient(to right, #E8A020 25%, var(--border-strong) 25%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

.star.hovered-quarter {
    background: linear-gradient(to right, #F0B840 25%, var(--border-strong) 25%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

.star.three-quarter {
    background: linear-gradient(to right, #E8A020 75%, var(--border-strong) 75%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

.star.hovered-three-quarter {
    background: linear-gradient(to right, #F0B840 75%, var(--border-strong) 75%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

.review-textarea {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    font-size: 0.85rem;
    font-family: inherit;
    color: var(--text);
    background: var(--bg);
    resize: vertical;
    min-height: 80px;
    display: block;
    margin-bottom: 10px;
    transition: border-color var(--transition);
}

.review-textarea:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-dim);
}

.review-form-actions {
    display: flex;
    gap: 8px;
}

.review-display {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.review-stars-display {
    display: flex;
    gap: 2px;
}

.review-stars-display .star {
    font-size: 1.3rem;
    cursor: default;
    transform: none !important;
}

.review-body-text {
    font-size: 0.875rem;
    color: var(--text-2);
    line-height: 1.55;
    white-space: pre-wrap;
}

.review-meta-actions {
    display: flex;
    gap: 8px;
    align-items: center;
    /* Breathing room above (from the review text) and below (from the divider) */
    margin: 14px 0 12px;
}

/* ── Diary + spoilers ─────────────────────────────────────────────────────── */

.review-section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.review-display-head {
    display: flex;
    align-items: center;
    gap: 12px;
}
.review-date-display {
    font-size: 0.78rem;
    color: var(--text-3);
}

.review-form-controls {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    margin: 8px 0;
}
.review-date-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.78rem;
    color: var(--text-2);
}
.review-date-field {
    padding: 5px 8px;
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    font-family: inherit;
    font-size: 0.82rem;
    color: var(--text);
    background: var(--bg);
}
.spoiler-check {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.78rem;
    color: var(--text-2);
    cursor: pointer;
}

/* Blurred until tapped */
.spoiler-hidden {
    filter: blur(5px);
    cursor: pointer;
    user-select: none;
}

.diary-history {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 12px;
    border-top: 1px solid var(--border);
    padding-top: 10px;
}
.diary-entry {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 0.8rem;
    color: var(--text-2);
}
.diary-entry-date { min-width: 84px; }
.diary-entry-stars .star { font-size: 0.85rem; cursor: default; transform: none !important; }
.diary-entry-rewatch { color: var(--text-3); }
.diary-entry-del {
    margin-left: auto;
    background: transparent;
    border: none;
    color: var(--text-3);
    cursor: pointer;
    font-size: 0.85rem;
    padding: 2px 6px;
}
.diary-entry-del:hover { color: var(--danger, #c0392b); }

.btn-danger-ghost {
    background: transparent;
    color: var(--danger);
    border: 1.5px solid var(--danger-dim);
}

.btn-danger-ghost:hover:not(:disabled) {
    background: var(--danger-dim);
    border-color: var(--danger);
}

/* ── Re-read badge ──────────────────────────────────── */
.reread-badge {
    font-size: 0.68rem;
    font-weight: 700;
    color: var(--accent);
    background: var(--accent-dim);
    border-radius: 4px;
    padding: 1px 5px;
    letter-spacing: 0.02em;
}

/* ── Type Divider ─────────────────────────────────────── */
.type-divider {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-3);
    padding: 14px 0 8px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 3px;
}

/* ── Reading Goal ─────────────────────────────────────── */


/* ── Library view toggle ──────────────────────────────── */
.view-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 20px;
}

.icon-btn {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-2);
    padding: 6px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: color var(--transition), background var(--transition);
}
.icon-btn:hover {
    color: var(--text);
    background: var(--surface-alt);
}

/* ── Grid view ─────────────────────────────────────────── */
#library-list.grid-view {
    display: grid;
    /* Auto-fill rather than a fixed column count. This was pinned to three
       columns at every width above 600px, so "show all" on a wide desktop
       stretched each cover to 460-540px tall and fit barely a row on screen.
       Filling to a ~150px minimum keeps tiles near the 172px shelf-tile scale
       at any width, and still lands on two columns at phone widths. */
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 8px;
    padding: 0;
}
#library-list.grid-view .series-header,
#library-list.grid-view .type-divider {
    grid-column: 1 / -1;
}
#library-list.grid-view .lib-card {
    flex-direction: column;
    padding: 0;
    gap: 0;
    border-radius: 10px;
    overflow: hidden;
    position: relative;
    border: none;
    background: var(--surface-alt);
    align-items: stretch;
    min-height: 0;
}
#library-list.grid-view .lib-cover {
    width: 100%;
    padding-top: 150%;
    position: relative;
    flex-shrink: 0;
    border-radius: 0;
}
#library-list.grid-view .lib-cover img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
#library-list.grid-view .lib-cover-placeholder {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}
#library-list.grid-view .lib-card-info {
    padding: 6px 6px 4px;
    flex: 1;
}
#library-list.grid-view .lib-card-title {
    font-size: 0.72rem;
    line-height: 1.3;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
#library-list.grid-view .lib-card-sub {
    display: none;
}
#library-list.grid-view .lib-card-location {
    display: none;
}
#library-list.grid-view .lib-card-right {
    position: absolute;
    top: 4px;
    right: 4px;
    flex-direction: column;
    gap: 4px;
}
#library-list.grid-view .lib-card-right .status-badge {
    font-size: 0.62rem;
    padding: 2px 5px;
}
#library-list.grid-view .lib-card-right .cr-page {
    display: none;
}

/* ── Goodreads Import ───────────────────────────────── */
.import-description {
    font-size: 0.85rem;
    color: var(--text-2);
    margin: 0 0 12px;
}
.import-controls {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.import-file-label {
    cursor: pointer;
    display: inline-flex;
    align-items: center;
}
.import-file-name {
    font-size: 0.82rem;
    color: var(--text-3);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 160px;
}
.import-preview {
    margin-top: 12px;
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}
.import-preview-text {
    font-size: 0.88rem;
    color: var(--text-2);
    margin: 0;
}
.import-progress {
    margin-top: 12px;
}
.import-progress-bar-wrap {
    background: var(--surface-alt);
    border-radius: 4px;
    height: 6px;
    overflow: hidden;
    margin-bottom: 6px;
}
.import-progress-bar {
    height: 100%;
    background: var(--accent);
    border-radius: 4px;
    width: 0%;
    transition: width 0.2s ease;
}
.import-progress-text {
    font-size: 0.8rem;
    color: var(--text-3);
    margin: 0;
}

/* ── Community ──────────────────────────────────────── */
.community-tabs {
    display: flex;
    gap: 4px;
    margin-bottom: 16px;
    border-bottom: 1.5px solid var(--border);
    padding-bottom: 0;
}
.community-tab {
    padding: 6px 16px;
    border: none;
    background: none;
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--text-2);
    cursor: pointer;
    border-bottom: 2px solid transparent;
    margin-bottom: -1.5px;
    font-family: inherit;
    transition: color var(--transition), border-color var(--transition);
}
.community-tab.active {
    color: var(--accent);
    border-bottom-color: var(--accent);
}

.community-panel { }

.friend-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 0;
    border-bottom: 1px solid var(--border);
}
.friend-info {
    flex: 1;
    min-width: 0;
    cursor: pointer;
}
.friend-name {
    display: block;
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--text);
}
.friend-username {
    font-size: 0.78rem;
    color: var(--text-2);
}

.up-hero {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 8px;
}

.community-search-row {
    display: flex;
    gap: 8px;
    margin-bottom: 16px;
}
.community-search-row .search-input {
    flex: 1;
}
.community-user-results {
    margin-bottom: 16px;
}
.community-user-card {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 10px;
    background: var(--surface-alt);
    cursor: pointer;
    margin-bottom: 6px;
    transition: background var(--transition);
}
.community-user-card:hover { background: var(--border); }
.community-user-info { display: flex; align-items: baseline; gap: 8px; }
.community-username    { font-weight: 600; color: var(--text); font-size: 0.9rem; }
.community-display-name { font-size: 0.8rem; color: var(--text-3); }

.suggested-readers-heading {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text-3);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin: 20px 0 8px;
}

.suggested-avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--navy);
    color: #fff;
    font-size: 0.75rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    overflow: hidden;
}
.suggested-avatar img { width: 100%; height: 100%; object-fit: cover; }

.community-feed { display: flex; flex-direction: column; gap: 10px; }
.feed-card {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    padding: 12px;
    background: var(--surface-alt);
    border-radius: 10px;
    cursor: pointer;
    transition: background var(--transition);
}
.feed-card:hover { background: var(--border); }
.feed-cover {
    width: 48px;
    height: 68px;
    object-fit: cover;
    border-radius: 5px;
    flex-shrink: 0;
    background: var(--bg);
}
.feed-cover-placeholder { background: var(--border); }
.feed-card-body { flex: 1; min-width: 0; }
.feed-action    { font-size: 0.88rem; color: var(--text-2); margin: 0 0 4px; line-height: 1.4; }
.feed-action strong { color: var(--text); }
.feed-username  { color: var(--accent); cursor: pointer; font-weight: 600; }
.feed-username:hover { text-decoration: underline; }
.feed-when      { font-size: 0.75rem; color: var(--text-3); }
.feed-stars     { color: #E8A020; font-size: 0.9rem; margin-left: 4px; }
.feed-stars .star { font-size: inherit; cursor: default; transform: none !important; }
.feed-review-body {
    font-size: 0.83rem;
    color: var(--text-2);
    font-style: italic;
    margin: 4px 0;
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* User profile overlay */
.up-hero    { display: flex; align-items: center; gap: 16px; margin-bottom: 12px; }
.user-bio   { font-size: 0.88rem; color: var(--text-2); margin: 0 0 20px; }
.community-review-card {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
}
.community-review-card:last-child { border-bottom: none; }

/* Community profile form */
.community-profile-form { display: flex; flex-direction: column; gap: 12px; }
.form-group         { display: flex; flex-direction: column; gap: 4px; }
.form-group label   { font-size: 0.8rem; color: var(--text-2); font-weight: 500; }
.form-group input[type="text"] {
    padding: 8px 12px;
    background: var(--surface-alt);
    border: 1.5px solid var(--border);
    border-radius: 8px;
    color: var(--text);
    font-size: 0.9rem;
    font-family: inherit;
}
.form-group input[type="text"]:focus { outline: none; border-color: var(--accent); }
.form-group-inline  { flex-direction: row; align-items: center; justify-content: space-between; }
.toggle-checkbox    { width: 20px; height: 20px; cursor: pointer; accent-color: var(--accent); }


/* ── Mood tags ───────────────────────────────────────────────── */
.shelf-detail-label {
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-3);
}
.tags-input-row { display: flex; gap: 8px; }
.tags-input-row .text-input { flex: 1; }
.text-input {
    padding: 8px 12px;
    background: var(--surface-alt);
    border: 1.5px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    font-size: 0.9rem;
    font-family: inherit;
}
.text-input:focus { outline: none; border-color: var(--accent); }

/* ── Library sections ────────────────────────────────────────── */
.library-section {
    margin-bottom: 28px;
}

.section-heading {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 16px 10px;
    user-select: none;
}
.section-heading[data-status]:active .section-heading-title { color: var(--accent); }

.section-heading-title {
    font-size: 17px;
    font-weight: 600;
    color: var(--text);
}
.section-heading-count {
    font-size: 12px;
    color: var(--text-2);
    background: var(--surface-alt);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 1px 7px;
    margin-left: 2px;
}
.section-heading-arrow {
    margin-left: auto;
    color: var(--text-3);
    font-size: 20px;
    line-height: 1;
}

.section-scroll-row {
    display: flex;
    gap: 10px;
    padding: 0 16px 4px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.section-scroll-row::-webkit-scrollbar { display: none; }

/* The same tiles the shelves use, wrapped into a grid instead of a scroll rail.
   Same auto-fill formula as #library-list.grid-view, and for the reason
   recorded there: a fixed column count stretches covers absurdly tall on a
   wide screen, and fixed-width tiles leave a ragged right edge instead. Two
   columns at phone widths, more as the window grows.
   Row gap exceeds column gap because captions run to two lines. */
.shelf-all-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 18px 10px;
    padding: 4px 16px 32px;
}
/* Tiles are built at fixed pixel sizes for the horizontal rails — 172x258 for
   a plain tile, and a 204-wide box for a series fan. In a grid the column has
   to decide the width instead, or plain tiles float in a column wider than
   they are and series tiles overflow theirs, putting the count badge on top of
   the next tile along. Percentages below are the original pixel ratios:
   172/204 = 84.3%, 250/258 = 96.9%, the fan offsets 11 and 22 of 204. */
.shelf-all-grid .scroll-tile {
    width: auto;
    /* Grid items stretch to the row's height by default, which pulls a tile's
       cover box past the aspect ratio it was given — most visible on the back
       tile, which has no caption to absorb it. Start-aligned, every cover keeps
       its own proportions and the captions still line up on the row. */
    align-self: start;
}

/* 93%, not the full column. A plain cover used to take the whole width while
   a run's sat at 84.3% of it, so the two read as different sizes on one row.
   Both give a little now and meet near the middle. */
.shelf-all-grid .tile-cover {
    width: 93%; height: auto;
    aspect-ratio: 172 / 258;
}
.shelf-all-grid .tile-cover-img,
.shelf-all-grid .tile-cover-blank {
    width: 100%; height: 100%;
}

/* The back tile faked its cover aspect with padding-top: 150%, which stacks on
   top of the grid's own aspect-ratio and left it half a cover taller than its
   neighbours. The grid already sizes the box. */
.shelf-all-grid .back-tile-cover {
    padding-top: 0 !important;
}

/* Same aspect as a plain cover, not the fan's own 204/258. In a rail the two
   share a height and differ in width, so captions line up; in a grid they
   share a width, and keeping the wider ratio would leave every series tile
   shorter than its neighbours and the caption row ragged. The fan sits inside
   the same box instead, which reads as inset rather than misaligned. */
/* Same 93% as a plain cover, so both boxes are the same height and the
   captions below them line up. The fan is sized against this box, not the
   column, and is free to overhang it — the column has the room. */
.shelf-all-grid .series-tile .tile-cover-stacked {
    width: 93%; height: auto;
    aspect-ratio: 172 / 258;
}
/* Width AND height as percentages of the box gave the cover an aspect of
   0.58 against a plain tile's 0.667 — 13% narrower — and object-fit: cover
   ate the sides, which is why series art came out with its title chopped off.
   Only the width is a percentage now; the aspect ratio supplies the height, so
   a run's cover is framed exactly like a standalone one. */
.shelf-all-grid .series-tile .tile-stack,
.shelf-all-grid .series-tile .tile-cover-main {
    width: 94.6%;
    height: auto;
    aspect-ratio: 172 / 258;
    top: 3.1%;
}
.shelf-all-grid .series-tile .tile-stack-2 { left: 8.6%; }
.shelf-all-grid .series-tile .tile-stack-1 { left: 4.3%; }
.shelf-all-grid .series-tile .tile-cover-main .tile-cover-img,
.shelf-all-grid .series-tile .tile-cover-main .tile-cover-blank {
    width: 100%; height: 100%;
}

.shelf-all-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding: 0 16px;
    margin-bottom: 14px;
}

.scroll-tile {
    flex: 0 0 96px;
    width: 96px;
    cursor: pointer;
    scroll-snap-align: start;
    position: relative;
}
.scroll-tile-cover {
    width: 96px;
    height: 144px;
    object-fit: cover;
    border-radius: var(--radius);
    display: block;
    background: var(--surface-alt);
    box-shadow: var(--shadow-sm);
}
.scroll-tile-no-cover {
    width: 96px;
    height: 144px;
    background: var(--surface-alt);
    border-radius: var(--radius);
}
.scroll-tile-title {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 11px;
    color: var(--text-2);
    margin-top: 5px;
    line-height: 1.35;
}
.scroll-tile-reread {
    position: absolute;
    top: 4px;
    right: 4px;
    background: var(--accent);
    color: #fff;
    border-radius: 8px;
    padding: 1px 5px;
    font-size: 10px;
    font-weight: 700;
    z-index: 1;
}

/* ── Expanded section header ─────────────────────────────────── */
.section-expanded-header {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 4px 16px 16px;
}
.section-back-btn { cursor: pointer; }

.back-tile {
    border: 1.5px solid var(--border) !important;
    background: var(--surface-alt) !important;
}
.back-tile-cover {
    display: flex !important;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    background: var(--surface-alt) !important;
    color: var(--text-3);
    padding-top: 150% !important; /* match cover aspect ratio */
    position: relative;
}
.back-tile-cover svg,
.back-tile-cover .back-tile-label {
    position: absolute;
}
.back-tile-cover svg { top: calc(50% - 30px); }
.back-tile-label {
    top: calc(50% + 6px);
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-2);
}
.back-tile-count {
    position: absolute;
    top: calc(50% + 26px);
    font-size: 0.72rem;
    color: var(--text-3);
}

/* List mode: back tile looks like a normal row */
#library-list:not(.grid-view) .back-tile-cover {
    padding-top: 0 !important;
    height: 100%;
    justify-content: center;
}
#library-list:not(.grid-view):not(.shelf-all-grid) .back-tile-cover svg,
#library-list:not(.grid-view):not(.shelf-all-grid) .back-tile-cover .back-tile-label,
#library-list:not(.grid-view):not(.shelf-all-grid) .back-tile-cover .back-tile-count {
    position: static;
}
#library-list:not(.grid-view):not(.shelf-all-grid) .back-tile-cover svg { margin-bottom: 2px; }
#library-list:not(.grid-view):not(.shelf-all-grid) .back-tile-label { font-size: 0.7rem; }
#library-list:not(.grid-view):not(.shelf-all-grid) .back-tile-count { display: none; }
.section-expanded-title {
    font-size: 17px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 6px;
}

/* ── Remove from Library (bottom of overlay) ─────────────────── */
.community-reviews-section {
    margin-top: 24px;
    padding-top: 16px;
    border-top: 1px solid var(--border);
}

.community-reviews-section .cr-item {
    display: block;
    padding: 12px 0;
    background: transparent;
    border: none;
    border-radius: 0;
    border-bottom: 1px solid var(--border);
}
.community-reviews-section .cr-item:last-child { border-bottom: none; }

.cr-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 3px;
}

.cr-name {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-2);
}

.cr-stars { font-size: 0.8rem; }

/* Pushed to the trailing edge so the name and stars stay grouped. */
.cr-date {
    margin-left: auto;
    font-size: 0.72rem;
    color: var(--text-3);
    white-space: nowrap;
}

.profile-review-card-date {
    font-size: 0.72rem;
    color: var(--text-3);
    margin-top: 4px;
}

.cr-body {
    font-size: 0.875rem;
    color: var(--text-2);
    line-height: 1.5;
    margin: 0;
    white-space: pre-wrap;
}

.remove-section {
    margin-top: 24px;
    padding-top: 16px;
    border-top: 1px solid var(--border);
}
.remove-confirm-row {
    margin-top: 10px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.remove-confirm-text {
    font-size: 0.875rem;
    color: var(--text-2);
}
.remove-confirm-btns {
    display: flex;
    gap: 8px;
}
/* Collapse tags container when empty */

/* ── Profile Hero ──────────────────────────────────────── */
.profile-hero {
    display: flex;
    gap: 16px;
    align-items: flex-start;
    margin-bottom: 20px;
    padding-bottom: 20px;
    border-bottom: 1px solid var(--border);
}

.profile-avatar {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    background: var(--navy);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    overflow: hidden;
}

.profile-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.profile-avatar.profile-avatar-cover {
    width: 48px;
    height: 68px;
    border-radius: var(--radius);
    background: var(--border);
}

.profile-avatar-initials {
    font-family: var(--font-display);
    font-size: 1.35rem;
    color: #fff;
    letter-spacing: 0.04em;
    line-height: 1;
}

.avatar-settings-row {
    display: flex;
    align-items: center;
    gap: 16px;
}

.profile-hero-info {
    flex: 1;
    max-width: 260px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.profile-display-name {
    font-family: var(--font-display);
    font-size: 1.2rem;
    font-weight: 400;
    color: var(--text);
    line-height: 1.2;
    margin: 0;
}

.profile-username-tag {
    font-size: 0.8rem;
    color: var(--text-2);
    margin: 0;
}

.profile-bio-text {
    font-size: 0.82rem;
    color: var(--text-2);
    line-height: 1.4;
    margin-top: 5px;
    margin-bottom: 2px;
}

.profile-hero-social {
    display: flex;
    gap: 8px;
    margin-top: 8px;
}

.profile-hero-social .social-count-btn {
    flex: none;
    flex-direction: row;
    align-items: center;
    gap: 5px;
    padding: 5px 10px;
    border-radius: var(--radius-sm);
}

.profile-hero-social .social-count {
    font-size: 0.88rem;
}

.profile-hero-social .social-label {
    font-size: 0.72rem;
}


/* Clickable currently-reading tiles */
.cr-item-clickable {
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition);
}
.cr-item-clickable:hover {
    background: var(--surface-alt);
    border-color: var(--border-strong);
}

/* Clickable review cards */
.profile-review-card[data-item-id],
.all-review-card[data-item-id] {
    cursor: pointer;
}
.profile-review-card[data-item-id]:hover .profile-review-card-title {
    text-decoration: underline;
}
.all-review-card[data-item-id]:hover .all-review-title {
    text-decoration: underline;
}

/* ── To Read Stack ─────────────────────────────────────── */
.to-read-section {
    margin-bottom: 28px;
}

.to-read-stack-btn {
    background: none;
    border: none;
    cursor: pointer;
    padding: 4px 0 8px;
    display: flex;
    align-items: center;
    gap: 20px;
    width: 100%;
    text-align: left;
}

.to-read-covers {
    position: relative;
    width: 100px;
    height: 104px;
    flex-shrink: 0;
    overflow: hidden;
}

.to-read-cover-item {
    position: absolute;
    width: 64px;
    height: 90px;
    border-radius: 4px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.22);
    top: 50%;
    left: 50%;
    transform-origin: 50% 100%;
    overflow: hidden;
    background: var(--border);
}

.to-read-cover-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.to-read-cover-item:nth-child(1) { transform: translate(-50%, -50%) rotate(0deg);   z-index: 4; }
.to-read-cover-item:nth-child(2) { transform: translate(-50%, -50%) rotate(-8deg);  z-index: 3; }
.to-read-cover-item:nth-child(3) { transform: translate(-50%, -50%) rotate(7deg);   z-index: 2; }
.to-read-cover-item:nth-child(4) { transform: translate(-50%, -50%) rotate(-13deg); z-index: 1; }

.to-read-stack-meta {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.to-read-count-label {
    font-size: 1rem;
    font-weight: 600;
    color: var(--text);
}

.to-read-tap-hint {
    font-size: 0.75rem;
    color: var(--text-3);
}

/* ── Profile Reviews Section ───────────────────────────── */
.profile-reviews-section {
    margin-bottom: 28px;
}

.profile-reviews-trigger {
    width: 100%;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px;
    cursor: pointer;
    text-align: left;
    display: block;
    transition: border-color var(--transition), background var(--transition);
}

.profile-reviews-trigger:hover {
    border-color: var(--border-strong);
    background: var(--surface-alt);
}

.review-histogram {
    display: flex;
    gap: 6px;
    align-items: flex-end;
    height: 60px;
    margin-bottom: 14px;
}

.review-histogram-col {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    min-width: 0;
}

.review-histogram-bar {
    width: 100%;
    background: var(--navy);
    border-radius: 3px 3px 0 0;
    min-height: 2px;
}

.review-histogram-bar.bar-empty {
    background: var(--border);
}

.review-histogram-label {
    font-size: 0.65rem;
    color: var(--text-3);
    font-weight: 600;
}

.profile-recent-reviews {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.profile-review-card {
    display: flex;
    gap: 10px;
    align-items: flex-start;
}

.profile-review-card-cover {
    width: 32px;
    height: 46px;
    object-fit: cover;
    border-radius: 3px;
    flex-shrink: 0;
    background: var(--border);
    display: block;
}

.profile-review-card-info {
    flex: 1;
    min-width: 0;
}

.profile-review-card-title {
    font-size: 0.83rem;
    font-weight: 600;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-bottom: 1px;
}

.profile-review-card-stars {
    font-size: 0.78rem;
    color: var(--accent);
    margin-bottom: 2px;
}
.profile-review-card-stars .star {
    font-size: inherit;
    cursor: default;
    transform: none !important;
}

.profile-review-card-body {
    font-size: 0.75rem;
    color: var(--text-2);
    line-height: 1.4;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

/* ── All Reviews Overlay ───────────────────────────────── */
.all-reviews-list {
    display: flex;
    flex-direction: column;
    gap: 0;
    margin-top: 4px;
}

.all-review-card {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    padding: 14px 0;
    border-bottom: 1px solid var(--border);
}

.all-review-card:first-child { padding-top: 0; }
.all-review-card:last-child  { border-bottom: none; }

.all-review-cover {
    width: 44px;
    height: 64px;
    object-fit: cover;
    border-radius: 4px;
    flex-shrink: 0;
    background: var(--border);
    display: block;
}

.all-review-info {
    flex: 1;
    min-width: 0;
}

.all-review-title {
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--text);
    margin-bottom: 3px;
}

.all-review-stars {
    font-size: 0.85rem;
    color: var(--accent);
    margin-bottom: 3px;
}
.all-review-stars .star {
    font-size: inherit;
    cursor: default;
    transform: none !important;
}

.all-review-body {
    font-size: 0.82rem;
    color: var(--text-2);
    line-height: 1.5;
    white-space: pre-wrap;
}

.all-review-date {
    font-size: 0.72rem;
    color: var(--text-3);
    margin-top: 4px;
}

/* ── Stats overlay ─────────────────────────────────────────────────────────── */

.stats-trigger-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 10px;
}

.stats-filter-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 20px;
}
.stats-filter-tab {
    padding: 6px 16px;
    border-radius: 20px;
    border: 1.5px solid var(--border);
    background: transparent;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--text-2);
    cursor: pointer;
}
.stats-filter-tab.active {
    background: var(--navy);
    border-color: var(--navy);
    color: #fff;
}

.stats-ol-section { margin-bottom: 28px; }

.stats-ol-heading {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-3);
    margin: 0 0 12px;
}

.stat-bar-chart {
    display: flex;
    align-items: flex-end;
    gap: 4px;
}
.stat-bar-col {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    min-width: 0;
}
.stat-bar-count {
    font-size: 0.6rem;
    font-weight: 600;
    color: var(--text-2);
    line-height: 1;
}
.stat-bar {
    width: 100%;
    background: var(--accent);
    border-radius: 3px 3px 0 0;
}
.stat-bar-empty { background: var(--border); }
.stat-bar-label {
    font-size: 0.58rem;
    color: var(--text-3);
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    width: 100%;
}

.genre-bar-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}
.genre-bar-label {
    font-size: 0.76rem;
    color: var(--text-2);
    width: 160px;
    flex-shrink: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.genre-bar-track {
    flex: 1;
    height: 6px;
    background: var(--border);
    border-radius: 3px;
    overflow: hidden;
}
.genre-bar-fill {
    height: 100%;
    background: var(--accent);
    border-radius: 3px;
    transition: width 0.4s ease;
}
.genre-bar-count {
    font-size: 0.7rem;
    color: var(--text-3);
    width: 24px;
    text-align: right;
    flex-shrink: 0;
}

/* ── Data provider attribution (Settings → About) ─────────────────────────── */

/* These used to be centred footers with a top border under the search results.
   In a settings section the surrounding rows are all left-aligned with their
   own label, so the border and the centring both had to go — the section
   heading is already the separator. */
.attribution-list {
    list-style: none;
    margin: 10px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.attribution-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    font-size: 0.7rem;
    line-height: 1.5;
    color: var(--text-3);
}

/* TMDB requires their logo be less prominent than the marks identifying the
   app itself, so it stays small. margin-top nudges it onto the first text
   line now that the row aligns to the top rather than centring. */
.attribution-logo {
    height: 12px;
    flex-shrink: 0;
    margin-top: 4px;
}

/* Five search tabs need to wrap on narrow screens */
.search-type-toggle {
    flex-wrap: wrap;
}

/* The search pills used to shrink below 480px (6px/12px, 11.5px) while the
   library's type filter kept 7px/16px at 12px, so the same six chips were
   visibly different sizes between the two views. Both now use the library's
   sizing; .search-type-toggle already wraps, which is what narrow screens
   actually needed. */

/* ── Cast section (movies & TV) ────────────────────────────────────────────── */

.item-watch-section {
    margin-top: 20px;
}
.item-watch-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.watch-group {
    display: flex;
    align-items: center;
    gap: 12px;
}
.watch-group-label {
    flex: 0 0 52px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-3);
}
.watch-logos {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.watch-logo {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    overflow: hidden;
    background: var(--surface-alt);
    box-shadow: var(--shadow-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.6rem;
    text-align: center;
    color: var(--text-2);
    padding: 2px;
}
.watch-logo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.watch-jw-link {
    font-size: 0.78rem;
    color: var(--accent);
    text-decoration: none;
    font-weight: 600;
}

.item-cast-section {
    margin-top: 20px;
}

.item-cast-list {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    padding-bottom: 6px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.item-cast-list::-webkit-scrollbar { display: none; }

.cast-card {
    flex: 0 0 84px;
    width: 84px;
    text-align: center;
}
.cast-photo {
    width: 84px;
    height: 84px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--surface-alt);
    margin: 0 auto 6px;
}
.cast-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.cast-photo-empty {
    width: 100%;
    height: 100%;
    background: linear-gradient(135deg, var(--surface-alt), var(--border));
}
.cast-name {
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.2;
    color: var(--text-1);
}
.cast-character {
    font-size: 0.7rem;
    line-height: 1.2;
    color: var(--text-3);
    margin-top: 2px;
}

/* ── Adaptations (film ↔ source book) ─────────────────────────────────────── */

.item-adaptation-section {
    margin-top: 20px;
}

.item-adaptation-list {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

/* Unverified TMDB credit — no work to link to, so it stays plain text. */
.adaptation-credit {
    margin: 0;
    font-size: 0.85rem;
    line-height: 1.4;
    color: var(--text-2);
}

.adaptation-tile {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 14px 8px 8px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--surface-alt);
    text-align: left;
    cursor: pointer;
    font: inherit;
    color: inherit;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.adaptation-tile:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-sm);
}
.adaptation-tile:active {
    transform: translateY(0);
}

.adaptation-cover {
    flex: 0 0 44px;
    width: 44px;
    height: 66px;
    border-radius: 6px;
    overflow: hidden;
    background: var(--surface-alt);
    display: block;
}
.adaptation-cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.adaptation-cover-empty {
    display: block;
    width: 100%;
    height: 100%;
    background: linear-gradient(135deg, var(--surface-alt), var(--border));
}

.adaptation-meta {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}
.adaptation-title {
    font-size: 0.85rem;
    font-weight: 600;
    line-height: 1.25;
    color: var(--text-1);
}
.adaptation-sub {
    font-size: 0.72rem;
    line-height: 1.2;
    color: var(--text-3);
}
.adaptation-badge {
    align-self: flex-start;
    margin-top: 2px;
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--type-book);
    mix-blend-mode: multiply;
    font-size: 0.62rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-1);
}

/* ── More in this series ──────────────────────────────────────────────────────
   A horizontal strip rather than the adaptation section's wrapping flex: a run
   can be a hundred issues, and wrapping that would bury everything under it.
   `.series-entry` and not `.series-tile` — that name is already taken by the
   shelf grid, where it means a whole series rather than one entry inside one,
   and #library-list's click handler reads it as "open the series detail". */
.item-series-section { margin-top: 20px; }

.item-series-count {
    margin-left: 8px;
    font-family: var(--font-mono);
    font-size: 0.72rem;
    font-weight: 400;
    color: var(--text-3);
    text-transform: none;
    letter-spacing: 0;
}

.item-series-list {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    overflow-y: hidden;
    /* Makes this the offsetParent for the entries, which _renderSeries relies on
       to centre the current one. Static, offsetLeft would resolve against
       #overlay-item and carry the whole desktop layout to the strip's left.
       Deliberately no scroll-snap: it applies to programmatic scrolls too, so
       proximity snapping would drag that centring back to a tile edge. */
    position: relative;
    /* Room for the lift on hover, which would otherwise be clipped by the
       scroll container. */
    padding: 4px 2px 10px;
}
.item-series-list::-webkit-scrollbar { height: 0; }

.series-entry {
    flex: 0 0 auto;
    width: 84px;
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 0;
    border: 0;
    background: none;
    text-align: left;
    font: inherit;
    color: inherit;
}
/* Every entry is tappable — one you don't own opens the lookup for it. Scoped to
   button because the strip renders divs on someone else's item, where it is
   deliberately inert. */
button.series-entry {
    cursor: pointer;
    transition: transform 0.12s ease;
}
button.series-entry:hover { transform: translateY(-2px); }
button.series-entry:active { transform: translateY(0); }

.series-entry-cover {
    position: relative;
    display: block;
    width: 84px;
    height: 126px;
    border-radius: 6px;
    overflow: hidden;
    background: var(--surface-alt);
    box-shadow: var(--shadow-sm);
}
.series-entry-cover img,
.series-entry-cover-empty {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.series-entry-cover-empty {
    background: linear-gradient(135deg, var(--surface-alt), var(--border));
}

/* What you don't own reads as an outline of the run — present, clearly not
   yours, and not competing with the covers that are. Opacity rather than a
   badge on every tile: in a long run the unowned ones are the majority, so
   badging them would be labelling the background.
   Held back from the 0.4 it started at, and lifted the whole way on hover:
   these open a lookup now, and something you can tap should not look switched
   off. */
.series-entry:not(.is-owned) .series-entry-cover {
    opacity: 0.5;
    transition: opacity 0.12s ease;
}
button.series-entry:not(.is-owned):hover .series-entry-cover { opacity: 1; }
.series-entry:not(.is-owned) .series-entry-num,
.series-entry:not(.is-owned) .series-entry-sub { color: var(--text-3); }

.series-entry.is-current .series-entry-cover {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.series-entry-here {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    padding: 2px 0;
    background: var(--accent);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 0.58rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    text-align: center;
}

.series-entry-num {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text);
}
.series-entry-sub {
    font-size: 0.66rem;
    line-height: 1.2;
    color: var(--text-3);
}

/* A franchise caption is a title, not "#12": it needs width, a proportional
   face, and a clamp. Two lines are RESERVED rather than merely allowed — the
   strip sizes to its tallest tile, so a one-line title next to a two-line one
   would otherwise leave the shorter tile's year floating mid-air. Same reason
   .tile-caption fixes its height on the library shelves. */
.item-series-list.is-titled .series-entry { width: 104px; }
.item-series-list.is-titled .series-entry-cover { width: 104px; height: 156px; }
.item-series-list.is-titled .series-entry-num {
    font-family: inherit;
    font-size: 0.7rem;
    line-height: 1.25;
    min-height: 2.5em;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
}

/* ── Likes + comments ─────────────────────────────────────────────────────── */

.social-bar {
    display: flex;
    gap: 14px;
    margin-top: 8px;
}
.social-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: none;
    border: none;
    padding: 2px 2px;
    cursor: pointer;
    color: var(--text-3);
    font-size: 0.8rem;
    font-family: inherit;
}
.social-ico { width: 16px; height: 16px; display: block; }
.social-like.liked { color: #c0392b; }
.social-like.liked .social-ico { fill: #c0392b; stroke: #c0392b; }
.social-btn:active { transform: scale(0.92); }

.comments-list {
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin: 12px 0 16px;
}
.comment-item {
    display: flex;
    gap: 10px;
}
.comment-avatar {
    flex: 0 0 32px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--navy);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8rem;
    font-weight: 600;
}
.comment-avatar img { width: 100%; height: 100%; object-fit: cover; }
.comment-body-wrap { flex: 1; min-width: 0; }
.comment-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 2px;
}
.comment-name { font-weight: 600; font-size: 0.82rem; color: var(--text-1); }
.comment-time { font-size: 0.72rem; color: var(--text-3); }
.comment-del {
    margin-left: auto;
    background: none;
    border: none;
    color: var(--text-3);
    cursor: pointer;
    font-size: 0.8rem;
}
.comment-text { font-size: 0.85rem; color: var(--text-2); line-height: 1.45; word-wrap: break-word; white-space: pre-wrap; }

.comment-input-row {
    display: flex;
    gap: 8px;
    position: sticky;
    bottom: 0;
    background: var(--bg);
    padding: 8px 0;
}

/* ── Custom lists ─────────────────────────────────────────────────────────── */

.profile-lists-section { margin-top: 8px; }
.lists-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
}
.profile-lists { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }

.list-card {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    cursor: pointer;
}
/* touch-action is the load-bearing part: without it a drag beginning on the
   grip is claimed by the page as a scroll and the reorder never starts. */
.drag-grip {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    padding: 4px 2px;
    background: none;
    border: none;
    border-radius: var(--radius-sm);
    color: var(--text-3);
    cursor: grab;
    touch-action: none;
    transition: color var(--transition);
}
.drag-grip:hover  { color: var(--text-2); }
.drag-grip:active { cursor: grabbing; }
/* Pulled back into the card's padding, which the borderless item rows lack. */
.list-card .drag-grip { margin-left: -4px; }
.drag-reordering {
    opacity: 0.75;
    border-color: var(--border-strong);
    box-shadow: var(--shadow-lg);
}
/* Carries #overlay-list because the row's own :hover rule is written with that
   id and would otherwise outrank this — and the row being dragged is, by
   definition, the one under the cursor. */
#overlay-list .list-item-row.drag-reordering,
#overlay-list .list-item-row.drag-reordering:hover {
    opacity: 0.9;
    background: var(--surface-alt);
    border-color: var(--border-strong);
    box-shadow: var(--shadow-sm);
    transform: none;
}

.list-card-info { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.list-card-name { font-weight: 600; font-size: 0.9rem; color: var(--text-1); }
.list-card-meta { font-size: 0.75rem; color: var(--text-3); }
.list-card-arrow { color: var(--text-3); font-size: 1.2rem; }

.list-detail-head { display: flex; align-items: center; gap: 10px; }
.list-detail-title { font-size: 1.4rem; }
.list-public-badge {
    font-size: 0.65rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--info);
    background: var(--info-dim);
    padding: 2px 8px;
    border-radius: 99px;
}
.list-detail-desc { color: var(--text-2); font-size: 0.9rem; margin: 6px 0; }
.list-owner-actions { display: flex; gap: 8px; margin: 10px 0 14px; }

.list-detail-items { display: flex; flex-direction: column; gap: 8px; }
.list-item-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 0;
    cursor: pointer;
    /* The note and the meta group carry flex-basis floors, so a row too narrow
       to seat them all sends them to lines of their own rather than crushing
       the title into one word per line. */
    flex-wrap: wrap;
}
.list-rank { font-weight: 700; color: var(--text-3); min-width: 20px; text-align: center; }
.list-item-cover {
    width: 40px; height: 60px;
    object-fit: cover;
    border-radius: 6px;
    background: var(--surface-alt);
    flex-shrink: 0;
}
.list-item-info { flex: 1 1 130px; min-width: 0; }
/* Always its own line, under the stars. Sharing the row meant the field ended
   where the stars began, so an unrated row got a longer box than a rated one
   and no two notes lined up. */
.list-note-wrap { flex: 1 1 100%; min-width: 0; }
/* Stars and the reorder/remove buttons travel together: on a narrow row they
   drop to a line of their own as one group, stars left, buttons right. */
.list-item-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
}
.list-item-title { font-weight: 600; font-size: 0.88rem; color: var(--text-1); }
.list-item-sub { font-size: 0.75rem; color: var(--text-3); }
/* ── Earned badges ────────────────────────────────────────────────────────── */
/* Modelled on .list-public-badge: small, mono, uppercase, tinted by media type
   so four badges on one profile stay distinguishable at a glance. */
.badge-row {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 5px;
    vertical-align: middle;
}
.badge-row:not(:empty) { margin-top: 8px; }
/* In a friend row the badge sits mid-sentence, so it takes its spacing from the
   text around it rather than opening a gap above. */
.badge-row-compact { margin-top: 0; margin-left: 6px; gap: 4px; }
/* In the feed it gets a line of its own, directly under the action. Inline, a
   badge sat between the name and the verb and pushed the event itself off the
   end of the row — the event is the reason the card exists. `html()` returns
   nothing at all when there are no badges, so no empty row is left behind. */
.feed-card-body > .badge-row-compact {
    display: flex;
    margin-left: 0;
    margin-top: 5px;
}

.earned-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 8px;
    border-radius: var(--radius-pill);
    font-family: var(--font-mono);
    font-size: 0.6rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    white-space: nowrap;
    color: var(--navy);
    background: var(--type-book);
}
.badge-row-compact .earned-badge { font-size: 0.55rem; padding: 1px 6px; }
.earned-badge[data-tone="book"]   { background: var(--type-book); }
.earned-badge[data-tone="comic"]  { background: var(--type-comic); }
.earned-badge[data-tone="screen"] { background: var(--type-screen); }
.earned-badge[data-tone="game"]   { background: var(--type-game); }
.earned-badge[data-tone="audiobook"]   { background: var(--type-audiobook); }
/* The three that are not about a medium borrow the semantic tints instead, so
   they read as a different kind of badge from the four media superlatives. */
/* Harshest and Enjoyer are opposites, and the pair a reader will hold up
   against each other — so they have to be told apart at a glance. The obvious
   picks, --danger-dim and --accent-dim, are both the same pale terracotta wash,
   and so are --danger and --accent, so neither background nor ink separated
   them. Cool against warm from the media palette does. Those two pastels are
   also worn by Biggest Critic and Most Verbose, which is a real repeat but a
   harmless one: those are different badges, rarely held together, and never
   read as a matched pair the way these two are. */
.earned-badge[data-tone="harsh"]   { background: var(--type-comic); }
.earned-badge[data-tone="warm"]    { background: var(--type-screen); }
.earned-badge[data-tone="balance"] { background: var(--info-dim); color: var(--info); }
/* The count rides inside the chip, dimmed — it is the evidence, not the label. */
.earned-badge-n {
    font-weight: 600;
    opacity: 0.62;
    font-size: 0.95em;
}

/* ── Hot this month (empty-search suggestions) ────────────────────────────── */
.hot-section { margin: 4px 0 18px; }
.hot-tile { cursor: pointer; }
/* The reader count sits on the cover, like the re-read badge it is modelled on,
   so the caption is left for the title alone. */
.hot-tile-count {
    position: absolute;
    /* Above .tile-cover-img, which sets z-index: 1 — without this the badge
       renders behind the artwork. Same layer the re-read badge uses. */
    z-index: 2;
    right: 6px;
    bottom: 6px;
    min-width: 20px;
    padding: 1px 5px;
    border-radius: var(--radius-pill);
    /* navy, not --tc: the type pastels are light, and white on them is
       unreadable against a blank cover. Matches .scroll-tile-reread, which
       has the same "legible over any artwork" problem. */
    background: var(--navy);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 0.62rem;
    font-weight: 700;
    text-align: center;
    line-height: 1.5;
    box-shadow: var(--shadow-sm);
}

/* ── Recently viewed (empty-search history) ───────────────────────────────── */
.recent-section { margin: 4px 0 18px; }
.recent-tile { cursor: pointer; }

/* Opposite corner from .hot-tile-count, and on the same layer: above
   .tile-cover-img's z-index: 1, or it renders behind the artwork.
   Always visible rather than revealed on hover — the target here is a thumb. */
.recent-forget {
    position: absolute;
    z-index: 2;
    top: 6px;
    right: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    border: none;
    border-radius: 50%;
    /* navy, not --tc, for the same reason as .hot-tile-count: the type pastels
       are light, and white on them is unreadable against a blank cover. */
    background: var(--navy);
    color: #fff;
    font-size: 15px;
    line-height: 1;
    opacity: 0.78;
    cursor: pointer;
    box-shadow: var(--shadow-sm);
}
.recent-forget:hover  { opacity: 1; }
.recent-forget:active { transform: scale(0.92); }

/* ── Read view vs edit view of a list's rows ──────────────────────────────── */
/* Reading, a row is a row: cover, title, stars, and the reason if one was
   written. The handles that change it only appear under Edit. */
#list-detail-items:not(.list-editing) .drag-grip,
#list-detail-items:not(.list-editing) .list-item-controls,
#list-detail-items:not(.list-editing) .list-note { display: none; }
/* An owner with nothing written has an empty wrapper; it would still take a
   flex line and leave a gap under every such row. */
#list-detail-items:not(.list-editing) .list-note-wrap:not(.has-note) { display: none; }
/* Same for the meta group when the row carries no rating: with the buttons
   hidden the wrapper is empty, and at ≤640px its flex-basis:100% still claimed
   a whole line plus the row gap. */
#list-detail-items:not(.list-editing) .list-item-meta:not(:has(.list-item-stars)) { display: none; }
/* Editing, the field replaces the prose rather than sitting under it. */
#list-detail-items.list-editing .list-note-text { display: none; }

.list-edit-fields {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 12px;
}
.list-edit-fields .search-input,
.list-edit-fields .review-textarea {
    width: 100%;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: var(--surface);
}
.list-edit-fields .search-input {
    font-family: var(--font-display);
    font-size: 1.1rem;
    font-weight: 700;
}

/* The curator's reason for the pick, and their rating of it. */
.list-note {
    display: block;
    width: 100%;
    margin-top: 5px;
    padding: 6px 9px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
    font-family: inherit;
    font-size: 0.75rem;
    color: var(--text-2);
    cursor: text;
}
.list-note::placeholder { color: var(--text-3); }
.list-note:focus {
    outline: none;
    border-color: var(--border-strong);
    color: var(--text);
}
.list-note-text {
    margin: 5px 0 0;
    font-size: 0.75rem;
    line-height: 1.45;
    color: var(--text-2);
}
/* The five stars are one glyph, never a run of characters that may break.
   inline-flex (which defaults to flex-wrap: nowrap) guarantees that on its own;
   white-space and flex-shrink stop the container being squeezed into forcing
   the issue in the first place. */
.list-item-stars {
    display: inline-flex;
    flex-wrap: nowrap;
    flex-shrink: 0;
    white-space: nowrap;
}
/* Narrow rows: the meta group takes a full line of its own too, above the note. */
@media (max-width: 640px) {
    .list-item-row  { align-items: flex-start; }
    /* Buttons pushed right by their own margin rather than space-between: on an
       unrated row the stars are absent, and space-between would slide the
       buttons to the left edge so their position varied row to row. */
    .list-item-meta {
        flex-basis: 100%;
        margin-left: 0;
    }
    .list-item-meta .list-item-controls { margin-left: auto; }
}
/* .star is sized for the rating widget, where it is a 1.7rem tap target. Here
   it is a read-out, so it loses the size and the hover feedback with it. */
.list-item-stars .star {
    font-size: 0.9rem;
    cursor: default;
}
.list-item-stars .star:hover { transform: none; }

.list-item-controls { display: flex; align-items: center; gap: 4px; }
.list-move, .list-remove {
    background: none;
    border: 1px solid var(--border);
    border-radius: 6px;
    width: 28px; height: 28px;
    cursor: pointer;
    color: var(--text-2);
    font-size: 0.85rem;
}
.list-move:disabled { opacity: 0.35; cursor: default; }
.list-remove { color: var(--danger, #c0392b); border-color: transparent; }

.list-pick-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 12px 4px;
    background: none;
    border: none;
    border-bottom: 1px solid var(--border);
    font-size: 0.9rem;
    color: var(--text-1);
    font-family: inherit;
    cursor: pointer;
}
.list-pick-check { font-size: 1.05rem; color: var(--accent); font-weight: 700; }

/* "Add to list" action row in the item details */
.add-to-list-row {
    border-bottom: none !important;
    padding-top: 6px;
}

/* Scan sits under the search box on its own line. It stays visible while the
   scanner is open — it is the active state, and the type chips above it are
   all inactive at that point, so hiding it would leave nothing showing which
   mode you are in. */
/* Scan is centred under the Search button, not under the row. The two rows
   share one track width so the centres can't drift: the scan row mirrors the
   search row's columns and drops the pill into the second one. */
#view-search { --search-action-w: 104px; }
#view-search .search-input-row #search-btn { width: var(--search-action-w); }

.search-scan-row {
    display: grid;
    grid-template-columns: 1fr var(--search-action-w);
    gap: 10px;
    margin: -8px 0 18px;
}
.search-scan-row .search-type-scan {
    grid-column: 2;
    justify-self: center;
    justify-content: center;
}
/* The rule that hides this is scoped to `.search-type-toggle .search-type-btn`,
   and Scan no longer lives in that row — so chip-fx stayed a flex child. Zero
   width, but the 7px gap still applied, pushing the label 3.5px off centre. */
.search-scan-row .chip-fx { display: none; }

/* ── Friends: following activity ──────────────────────────────────────────── */

#friends-following-list { display: flex; flex-direction: column; gap: 4px; margin-bottom: 20px; }
.friend-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 8px;
    border-radius: var(--radius);
    cursor: pointer;
}
.friend-row:hover { background: var(--surface-alt); }
.friend-info { flex: 1; min-width: 0; }
.friend-reading, .friend-activity {
    font-size: 0.78rem;
    color: var(--text-2);
    line-height: 1.4;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.friend-activity { color: var(--text-3); }
.friend-quiet { font-style: italic; }
.friend-reading strong, .friend-activity strong { color: var(--text-1); font-weight: 600; }
.friend-activity .star { font-size: 0.72rem; cursor: default; }

/* ===== U3 Search ===== */

/* -- Screen header (new — view-search previously had no title) --
   NB: no max-width here. The base .view rule centers content with
   percentage padding relative to the app-shell; capping the box width
   leaves that padding intact and crushes the content on wide screens. */

.u3-search-header {
    margin-bottom: 24px;
}

.u3-search-title {
    margin: 0 0 8px;
    font-family: var(--font-display);
    font-size: clamp(2.4rem, 6vw, 4rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1;
    color: var(--text);
}

.u3-search-tagline {
    font-family: var(--font-mono);
    font-size: 12.5px;
    color: var(--text-2);
}

/* -- Type tabs: pill chips carrying each media type's pastel -- */
.search-type-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    row-gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 22px;
}

.search-type-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 16px;
    border: 1.5px solid var(--border-strong);
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--text-2);
    font-family: var(--font-mono);
    font-size: 12px;
    /* 400 and 0.02em to match .lib-type-filter .type-btn; the active state
       still goes to 600 further down, same as the library's. At 500 with no
       letter-spacing the identical labels rendered ~1.2px narrower here. */
    font-weight: 400;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}

.search-type-btn::before {
    content: '';
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex-shrink: 0;
    background: var(--border-strong);
    transition: opacity var(--transition);
}

.search-type-btn[data-search-type="book"]::before  { background: var(--type-book); }
.search-type-btn[data-search-type="comic"]::before { background: var(--type-comic); }
.search-type-btn[data-search-type="movie"]::before,
.search-type-btn[data-search-type="tv"]::before     { background: var(--type-screen); }
.search-type-btn[data-search-type="game"]::before   { background: var(--type-game); }
.search-type-btn[data-search-type="audiobook"]::before   { background: var(--type-audiobook); }
.search-type-scan::before { display: none; }

.search-type-btn:hover {
    border-color: var(--navy);
    color: var(--navy);
}

.search-type-btn.active {
    border-color: transparent;
    background: var(--navy);
    color: #fff;
    font-weight: 600;
    box-shadow: var(--shadow-sm);
}

.search-type-btn.active::before { opacity: 0; }

/* Media-type pastel wash replaces the navy default for non-scan tabs */
.search-type-btn[data-search-type="book"].active {
    background: var(--type-book);
    color: var(--text);
}
.search-type-btn[data-search-type="comic"].active {
    background: var(--type-comic);
    color: var(--text);
}
.search-type-btn[data-search-type="movie"].active,
.search-type-btn[data-search-type="tv"].active {
    background: var(--type-screen);
    color: var(--text);
}
.search-type-btn[data-search-type="game"].active {
    background: var(--type-game);
    color: var(--text);
}
.search-type-btn[data-search-type="audiobook"].active {
    background: var(--type-audiobook);
    color: var(--text);
}
.search-type-btn[data-search-type="scan"].active {
    background: var(--navy);
    color: #fff;
}

/* .search-type-scan's margin-left:auto removed — it lived in the type-chip
   row and pushed Scan to the far end. It now has .search-scan-row to itself. */

/* -- Prominent search field + action -- */
#view-search .search-input-row {
    display: flex;
    gap: 10px;
    margin-bottom: 22px;
}

#view-search .search-input {
    flex: 1;
    padding: 14px 22px;
    border: 1px solid #D4DEE2;
    border-radius: var(--radius-pill);
    background: var(--surface);
    font-family: var(--font-mono);
    font-size: 14px;
    color: var(--text);
}

#view-search .search-input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-dim);
}

#view-search .search-input::placeholder {
    color: var(--text-3);
}

#search-btn {
    border-radius: var(--radius-pill);
    padding: 0 24px;
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    flex-shrink: 0;
}

#search-results .empty-state {
    font-family: var(--font-mono);
    font-size: 12px;
    padding: 50px 0;
}

/* -- Result cards: cover + pastel type dot + in-library badge -- */
.search-results {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.search-result-card {
    position: relative;
    padding: 14px 110px 14px 14px;
    align-items: center;
    border-radius: var(--radius);
    transition: box-shadow var(--transition), transform var(--transition), border-color var(--transition);
}

.search-result-card:hover {
    box-shadow: var(--shadow);
    border-color: var(--border-strong);
    transform: translateY(-1px);
}

.search-result-cover {
    position: relative;
    width: 46px;
    height: 66px;
}

/* Pastel dot on each cover, colored to match the active search tab's media type */
.search-result-cover::after {
    content: '';
    position: absolute;
    top: -6px;
    right: -6px;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(22, 35, 42, 0.15);
    z-index: 1;
    background: var(--border-strong);
}

#view-search:has(.search-type-btn[data-search-type="book"].active) .search-result-cover::after {
    background: var(--type-book);
}
#view-search:has(.search-type-btn[data-search-type="comic"].active) .search-result-cover::after {
    background: var(--type-comic);
}
#view-search:has(.search-type-btn[data-search-type="movie"].active) .search-result-cover::after,
#view-search:has(.search-type-btn[data-search-type="tv"].active) .search-result-cover::after {
    background: var(--type-screen);
}
#view-search:has(.search-type-btn[data-search-type="game"].active) .search-result-cover::after {
    background: var(--type-game);
}

.search-result-title {
    font-size: 0.95rem;
    font-weight: 600;
}

/* In-library indicator: quiet mono label with a check, not a loud pill */
.search-result-title .in-library-badge {
    position: absolute;
    right: 14px;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    background: none;
    padding: 0;
    margin: 0;
    border-radius: 0;
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-3);
}

.search-result-title .in-library-badge::after {
    content: ' \2713';
}

/* "+ ADD" affordance for rows that are not already in the library.
   Decorative only — the whole card already carries the click handler that adds/opens the item. */
.search-result-card:not(:has(.in-library-badge))::after {
    content: '+ ADD';
    position: absolute;
    right: 14px;
    top: 50%;
    transform: translateY(-50%);
    font-family: var(--font-mono);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.06em;
    padding: 7px 16px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--navy);
    color: var(--navy);
    transition: background var(--transition), color var(--transition);
    pointer-events: none;
}

.search-result-card:hover:not(:has(.in-library-badge))::after {
    background: var(--navy);
    color: #fff;
}

@media (max-width: 520px) {
    .search-result-card {
        padding-right: 14px;
    }
    .search-result-title .in-library-badge,
    .search-result-card:not(:has(.in-library-badge))::after {
        position: static;
        transform: none;
        display: inline-flex;
        margin-top: 6px;
    }
}

/* -- Scan tab: placeholder viewfinder treatment (shows through until the camera stream starts) -- */
#scanner-container {
    position: relative;
    background: repeating-linear-gradient(-45deg, #EDF2F4 0, #EDF2F4 14px, #F7FAFB 14px, #F7FAFB 28px);
}

#scanner-container::before {
    content: '';
    position: absolute;
    left: 50%;
    top: 24px;
    bottom: 24px;
    width: 1px;
    background: rgba(22, 35, 42, 0.12);
    pointer-events: none;
}

#scanner-container::after {
    content: 'point at a barcode';
    position: absolute;
    left: 50%;
    bottom: 14px;
    transform: translateX(-50%);
    z-index: 4;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--text-2);
    background: var(--bg);
    padding: 6px 14px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--border);
    pointer-events: none;
}

/* -- Manual barcode entry: pill input to match the search field language -- */
#manual-barcode-input {
    border-radius: var(--radius-pill);
    padding: 12px 20px;
    font-family: var(--font-mono);
}

#manual-lookup-btn {
    border-radius: var(--radius-pill);
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
}


/* ===== U6 overlay-stats ===== */

/* -- heading / eyebrow --------------------------------------------------- */
/* The heading is the page title, styled exactly like Library's — see the
   shared .view-title rule down in the U1 block. */
.u6-stats-heading { margin-bottom: 22px; }
.u6-stats-body .view-title { margin: 0; }

/* -- filter tabs (shared class, restyled) -------------------------------- */
.stats-filter-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 26px;
}
.stats-filter-tab {
    padding: 7px 16px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--border);
    background: transparent;
    font-family: var(--font-mono);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-2);
    cursor: pointer;
    transition: border-color var(--transition), color var(--transition), background var(--transition);
}
.stats-filter-tab:hover {
    border-color: var(--border-strong);
    color: var(--text);
}
.stats-filter-tab.active {
    background: var(--navy);
    border-color: var(--navy);
    color: #fff;
}

/* -- section headings (shared class, restyled) --------------------------- */
.stats-ol-section { margin-bottom: 30px; }
.stats-ol-section:not(:first-child) {
    border-top: 1px solid var(--border);
    padding-top: 16px;
}
.stats-ol-heading {
    display: flex;
    align-items: baseline;
    font-family: var(--font-mono);
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text);
    margin: 0 0 14px;
}
.stats-ol-heading:empty { display: none; }

/* -- overview / pages / reviews tiles (shared class, restyled) ----------- */
.stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
    gap: 10px;
    margin-bottom: 0;
}
.stat-card {
    /* Lets .stat-value size itself against this card (cqi) rather than the
       viewport — the tiles get narrow in the two-column stats layout. */
    container-type: inline-size;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 16px 16px 14px;
    text-align: left;
    display: flex;
    flex-direction: column;
    gap: 8px;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.stat-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
.stat-card.stat-accent { background: var(--navy); border-color: var(--navy); }
.stat-value {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    /* Sized against the CARD, not the viewport: in the two-column stats layout
       the tiles are narrow while the window is wide, so a vw-based rule keeps
       the text big and "2h 45m" spills past the padding. cqi tracks the card. */
    font-size: clamp(1.15rem, 18cqi, 1.7rem);
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--text);
    line-height: 1;
    min-width: 0;
    white-space: nowrap;
}
.stat-accent .stat-value { color: #fff; }
.stat-label {
    font-family: var(--font-mono);
    font-size: 0.62rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-2);
}
.stat-accent .stat-label { color: rgba(255,255,255,0.6); }

/* -- by-year / by-month bar chart (shared class, restyled) --------------- */
.stat-bar-chart {
    display: flex;
    align-items: flex-end;
    gap: 6px;
    max-width: 760px;
}
.stat-bar-col {
    flex: 1;
    max-width: 76px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    min-width: 0;
    padding: 8px 4px 10px;
    border-radius: var(--radius);
    transition: background var(--transition);
}
.stat-bar-col:hover { background: var(--surface-alt); }
.stat-bar-count {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.66rem;
    font-weight: 600;
    color: var(--text);
    line-height: 1;
}
.stat-bar {
    width: 100%;
    background: var(--accent);
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
    mix-blend-mode: multiply;
    transition: opacity var(--transition);
}
.stat-bar-empty { background: var(--border); mix-blend-mode: normal; }
.stat-bar-label {
    font-family: var(--font-mono);
    font-size: 0.62rem;
    letter-spacing: 0.03em;
    color: var(--text-2);
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    width: 100%;
}

/* -- ratings histogram (shared class, restyled) --------------------------- */
.review-histogram {
    display: flex;
    gap: 6px;
    align-items: flex-end;
    height: 76px;
    margin-bottom: 3px;
    padding: 4px 0 0;
}
.review-histogram-col {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    min-width: 0;
    padding: 4px 2px 6px;
    border-radius: var(--radius-sm);
    transition: background var(--transition);
}
.review-histogram-col:hover { background: var(--surface-alt); }
.review-histogram-bar {
    width: 100%;
    background: var(--success);
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
    min-height: 2px;
    mix-blend-mode: multiply;
}
.review-histogram-bar.bar-empty { background: var(--border); mix-blend-mode: normal; }
.review-histogram-label {
    font-family: var(--font-mono);
    font-size: 0.6rem;
    font-weight: 600;
    color: var(--text-3);
}

/* -- genres / by-format / top-creators rows (shared class, restyled) ----- */
.u6-bar-list { display: flex; flex-direction: column; gap: 2px; }
.genre-bar-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 0;
    padding: 7px 4px;
    border-radius: var(--radius-sm);
    transition: background var(--transition);
}
.genre-bar-row:hover { background: var(--surface-alt); }
.genre-bar-label {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    letter-spacing: 0.01em;
    color: var(--text-2);
    width: 150px;
    flex-shrink: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Squared off with a small radius, and segments separated by a hairline gap,
   so these read as the same object as the vertical stacked bars above rather
   than as a different chart language. Mirrors .stat-bar / .stat-bar-seg. */
.genre-bar-track {
    flex: 1;
    height: 10px;
    background: var(--surface-alt);
    border-radius: 3px;
    overflow: hidden;
}
/* The fill is a flex row of media-type segments (see _barTrack in app.js) —
   it carries the width, the segments carry the color. overflow stays visible
   so the gap between segments isn't clipped at the ends. */
.genre-bar-fill {
    height: 100%;
    display: flex;
    gap: 2px;
    background: transparent;
    border-radius: 0;
    overflow: visible;
    mix-blend-mode: multiply;
    transition: width 0.4s ease;
}
.genre-bar-seg { display: block; height: 100%; min-width: 3px; border-radius: 3px; }
.genre-bar-count {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.68rem;
    font-weight: 700;
    color: var(--text);
    width: 30px;
    text-align: right;
    flex-shrink: 0;
}

/* One label treatment across Format, Genres and Creators — they were three
   different looks (a pink uppercase chip, plain grey mono, and a bold ranked
   name) for the same kind of row. Ranked number + plain unbolded name. */
.u6-bar-list .genre-bar-label {
    color: var(--text);
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    font-size: 0.72rem;
    background: none;
    padding: 0;
    border-radius: 0;
}

/* ===== U2 Item detail ===== */
/* Overlay body for the item detail — restyle around app.js-owned ids.
   All colors via design tokens. New classes are .u2-* namespaced; shared
   classes the JS reads (.info-row, .status-select, .review-*, .cast-*, etc.)
   are restyled under this block, keeping their exact names.

   NOTE: app.js does not emit a media-type flag on #overlay-item, so the
   cover halo / progress ring are rendered as a neutral (rust/pastel) accent
   rather than per-type (book/comic/screen/game). Per-type tinting is listed
   under deferred_needs_js. */

/* ── Layout: wider hero on desktop ─────────────────────── */
.u2-detail-item .overlay-body {
    max-width: 1100px;
    margin: 0 auto;
}

/* Cover on the left, everything else in a single right column */
.u2-item-layout {
    display: flex;
    align-items: flex-start;
    gap: 56px;
}

.u2-main-col {
    flex: 1 1 auto;
    min-width: 0;
    max-width: 640px;
}

/* ── Cover with soft halo ──────────────────────────────── */
.u2-cover-wrap {
    position: sticky;
    top: 12px;
    width: 300px;
    flex-shrink: 0;
    align-self: flex-start;
    margin-top: 8px;
    isolation: isolate;
}

.u2-cover-halo {
    position: absolute;
    inset: -22px;
    z-index: -1;
    pointer-events: none;
}

/* Floating bubbles behind the cover — all the item's media color, animated */
.u2-halo-blob {
    position: absolute;
    border-radius: 50%;
    mix-blend-mode: multiply;
    background: var(--tc, var(--type-book));
}
.u2-halo-1 {
    width: 150px; height: 150px;
    left: -4%; top: -6%;
    opacity: 0.55;
    animation: ps-float-1 15s ease-in-out infinite;
}
.u2-halo-2 {
    width: 118px; height: 118px;
    right: -6%; top: 24%;
    opacity: 0.42;
    animation: ps-float-2 18s ease-in-out infinite;
}
.u2-halo-3 {
    width: 134px; height: 134px;
    left: 12%; bottom: -9%;
    opacity: 0.48;
    animation: ps-float-3 16s ease-in-out infinite;
}

@keyframes ps-float-1 { 0%{transform:translate(0,0)} 30%{transform:translate(20px,-14px)} 65%{transform:translate(-11px,16px)} 100%{transform:translate(0,0)} }
@keyframes ps-float-2 { 0%{transform:translate(0,0)} 35%{transform:translate(-17px,14px)} 70%{transform:translate(14px,-12px)} 100%{transform:translate(0,0)} }
@keyframes ps-float-3 { 0%{transform:translate(0,0)} 30%{transform:translate(15px,17px)} 60%{transform:translate(-15px,-9px)} 100%{transform:translate(0,0)} }
@media (prefers-reduced-motion: reduce) { .u2-halo-blob { animation: none !important; } }

.u2-cover-img {
    position: relative;
    width: 100%;
    height: auto;
    display: block;
    border-radius: 8px;
    border: 1px solid var(--border);
    box-shadow: 0 18px 40px rgba(22, 35, 42, 0.22);
    transform: rotate(-1.2deg);
    transition: transform var(--transition);
}
.u2-cover-wrap:hover .u2-cover-img {
    transform: rotate(0deg) translateY(-2px);
}
/* No cover art loaded: keep the tile shape, tint with surface */
.u2-cover-img:not([src]),
.u2-cover-img[src=""] {
    min-height: 450px;
    background: var(--surface-alt);
}

/* ── Title + inline number ─────────────────────────────── */
.u2-detail-item .item-detail-title {
    font-size: 2.85rem;
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.05;
}
.u2-detail-item .item-detail-issue {
    font-family: var(--font-mono);
    font-weight: 400;
    font-size: 1.25rem;
    color: var(--text-2);
}
.u2-detail-item .item-detail-sub {
    font-family: var(--font-mono);
    font-size: 0.82rem;
    color: var(--text-2);
    margin-bottom: 22px;
}

/* ── Mono meta grid ────────────────────────────────────── */
.u2-meta-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 40px;
    max-width: 560px;
    margin-bottom: 22px;
}
.u2-meta-grid .info-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 9px 0;
    border-bottom: 1px solid var(--border);
    font-family: var(--font-mono);
    font-size: 0.75rem;
}
.u2-meta-grid .info-row strong {
    min-width: 0;
    font-family: var(--font-mono);
    font-size: 0.72rem;
    font-weight: 400;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-3);
}
.u2-meta-grid .info-row span {
    font-family: var(--font-mono);
    font-size: 0.75rem;
    color: var(--text);
    text-align: right;
}
/* Rows that should span both columns */
.u2-meta-grid .u2-row-full {
    grid-column: 1 / -1;
}
/* The add-to-list row carries a button, not a label/value pair */
.u2-meta-grid .u2-row-plain {
    border-bottom: none;
    justify-content: flex-start;
    padding-top: 12px;
}
/* Two equal columns, not two buttons each sized to its own label. Flex won't do
   it here — the row has no free space to distribute, so flex-grow leaves each
   at min-content and "+ Add to list" stays a third wider than "↗ Recommend".
   Has to be scoped to .u2-meta-grid: the .info-row rule above sets display and
   gap at the same specificity and comes later in the file. */
.u2-meta-grid .add-to-list-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}
.u2-meta-grid .location-row .location-inline-input {
    font-family: var(--font-mono);
    font-size: 0.75rem;
    text-align: right;
}
.u2-meta-grid #item-classification {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0;
}
.u2-meta-grid .classification-pill {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--text);
}

/* ── Description ────────────────────────────────────────── */
.u2-detail-item .item-description-section {
    max-width: 620px;
    border-top: none;
    padding-top: 4px;
    margin-bottom: 3px;
}
.u2-detail-item .item-description-text {
    font-size: 0.95rem;
    line-height: 1.7;
    color: var(--navy-light);
}
.u2-detail-item .desc-ai-label {
    font-family: var(--font-mono);
    background: var(--surface-alt);
    color: var(--text-3);
}

/* ── Shared mono block label (Shelf / Your Diary / Add to shelf) ── */
.u2-block-label {
    display: block;
    font-family: var(--font-mono);
    font-size: 0.68rem;
    font-weight: 400;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-3);
    margin-bottom: 10px;
}

/* ── Shelf / status controls ───────────────────────────── */

/* The shelf block sits between the author line and the meta grid in the
   markup, because that is where a phone wants it. Desktop wants it after the
   description, and `order` is what moves it — which needs the hero to be a
   flex container. One DOM position, two layouts. */
.u2-detail-item .item-detail-head {
    display: flex;
    flex-direction: column;
}

.u2-shelf-block {
    max-width: 620px;
    margin-top: 26px;
}

/* Desktop restores the original position: last child of the hero, which is
   immediately after the description — exactly where it rendered when it was
   the hero's next sibling. Every other child keeps the default order of 0. */
@media (min-width: 721px) {
    .u2-shelf-block { order: 1; }
}
.u2-detail-item .shelf-status-section {
    border-top: 1px solid var(--border);
    padding-top: 20px;
    margin-top: 0;
}

/* Pill status trigger */
.u2-detail-item .status-select {
    border-radius: var(--radius-pill);
    border: 1px solid var(--border-strong);
    font-family: var(--font-mono);
    font-size: 0.8rem;
    padding: 8px 34px 8px 16px;
}
.u2-detail-item .status-select:hover {
    border-color: var(--navy);
    color: var(--navy);
}

.u2-detail-item .finished-date-input {
    font-family: var(--font-mono);
    font-size: 0.8rem;
    border-radius: var(--radius-pill);
    padding: 7px 14px;
}
.u2-detail-item .finished-date-row label {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-3);
}

.u2-detail-item .action-buttons {
    padding-top: 18px;
}

/* ── Where to watch / Cast section labels ──────────────── */
.u2-detail-item .item-watch-section,
.u2-detail-item .item-cast-section,
.u2-detail-item .item-adaptation-section,
.u2-detail-item .item-recommended-section,
.u2-detail-item .community-reviews-section {
    max-width: 620px;
}
.u2-detail-item .item-watch-section .section-label,
.u2-detail-item .item-cast-section .section-label,
.u2-detail-item .item-adaptation-section .section-label,
.u2-detail-item .item-recommended-section .section-label,
.u2-detail-item .community-reviews-section .section-label {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    font-weight: 400;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-3);
}
.u2-detail-item .watch-group-label {
    font-family: var(--font-mono);
    font-weight: 400;
    letter-spacing: 0.06em;
    color: var(--text-3);
}
.u2-detail-item .watch-logo {
    border-radius: 12px;
    box-shadow: var(--shadow-sm);
}
.u2-detail-item .watch-jw-link {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--accent);
}
.u2-detail-item .cast-name {
    font-size: 0.75rem;
    color: var(--text);
}
.u2-detail-item .cast-character {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    color: var(--text-3);
}

/* ── Diary card ────────────────────────────────────────── */
.u2-diary-card {
    position: relative;
    max-width: 620px;
    margin-top: 26px;
    padding: 20px 22px;
    border-top: none;
    border-radius: var(--radius-lg);
    background: var(--accent-dim);
    overflow: hidden;
}
.u2-diary-card .review-section-header {
    margin-bottom: 12px;
}
.u2-diary-card .review-section-title {
    margin-bottom: 0;
}
.u2-diary-card .review-textarea {
    background: rgba(255, 255, 255, 0.7);
    border: 1px solid var(--border);
    border-radius: 8px;
    font-size: 0.9rem;
    line-height: 1.6;
}
.u2-diary-card .review-textarea:focus {
    background: #fff;
    border-color: var(--accent);
}
.u2-diary-card .review-date-field {
    font-family: var(--font-mono);
    font-size: 0.76rem;
    background: rgba(255, 255, 255, 0.7);
}
.u2-diary-card .review-date-label,
.u2-diary-card .spoiler-check {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--text-2);
}
.u2-diary-card .review-date-display {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--text-2);
}
.u2-diary-card .diary-history {
    border-top: 1px solid var(--border);
}
.u2-diary-card .diary-entry,
.u2-diary-card .diary-entry-date {
    font-family: var(--font-mono);
    font-size: 0.74rem;
}
/* The diary Save pill used to be restyled here on its own. That treatment is
   now the base .btn-success rule, so this override said nothing the cascade
   didn't already say. */

/* ── Community reviews ─────────────────────────────────── */
.u2-detail-item .cr-name {
    font-family: var(--font-mono);
    font-size: 0.76rem;
    letter-spacing: 0.02em;
}
.u2-detail-item .cr-date,
#overlay-user-profile .profile-review-card-date {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    letter-spacing: 0.04em;
    color: var(--text-3);
}

/* ── Responsive: stack cover above the column on narrow screens ── */
@media (max-width: 720px) {
    .u2-item-layout {
        flex-direction: column;
        align-items: stretch;
        gap: 26px;
    }
    .u2-cover-wrap {
        position: relative;
        width: 200px;
        margin: 0 auto;
    }
    /* main column + every sibling section stack full-width (they live outside
       .u2-main-col, so without this they keep their desktop caps and a long
       paragraph can size to its content width and overflow the viewport) */
    .u2-main-col,
    .u2-detail-item .item-watch-section,
    .u2-detail-item .item-cast-section,
    .u2-detail-item .item-adaptation-section,
    .u2-detail-item .item-recommended-section,
    .u2-detail-item .community-reviews-section,
    .u2-detail-item .review-section,
    .u2-detail-item .book-rating-summary,
    .u2-detail-item .remove-from-library-section {
        max-width: none;
        width: 100%;
        min-width: 0;
    }
    .u2-detail-item .item-description-text {
        overflow-wrap: anywhere;
    }
    .u2-detail-item .item-detail-title {
        font-size: 1.9rem;
    }
    .u2-meta-grid {
        grid-template-columns: 1fr;
        gap: 0;
    }
    .u2-meta-grid .u2-row-full {
        grid-column: auto;
    }

    /* Now directly under the author line rather than under the description.
       The 26px top margin was clearing a paragraph; here it stacks on the sub
       line's own 22px and opens a gap wide enough to read as a break in the
       page. The bottom margin is what the meta grid used to supply itself. */
    .u2-shelf-block {
        margin-top: 4px;
        margin-bottom: 26px;
    }

    /* "SHELF" earned its keep when the block sat below a description and
       needed naming. Directly under the author line the chips are self-evident,
       and a second all-caps label this high competes with the title. The rule
       above them still marks the break. */
    .u2-shelf-block .u2-block-label {
        display: none;
    }

    /* Its 18px was clearing the description above it; here it stacks on the
       author line's 22 and the block's own 4, putting 44px above Add to
       Library against 26 below and visibly hanging the button off the author.
       Zeroed, both sides are 26. It also renders empty in the owned state —
       the button inside is what gets hidden, not the container — so the
       padding was silently padding the bottom of the chips too. */
    .u2-detail-item .action-buttons {
        padding-top: 0;
    }

    /* The rule and its 20px were the block's header treatment, from when it
       announced itself below a description. Under the author line it is a
       second divider inside the first thing you look at, and it made the
       chips sit 46px down against 26 below them. Both gone, so the chips
       land in the same place the Add to Library button does — 26 either
       side. Desktop keeps the divider; there it separates two real sections. */
    .u2-detail-item .shelf-status-section {
        border-top: none;
        padding-top: 0;
    }
}

/* ===== U1 Library ===== */

/* -- Screen header: display title + mono tagline, toggle pinned right -- */
.u1-lib-header {
    align-items: flex-end;
    gap: 20px;
}
.u1-lib-heading { min-width: 0; }

#view-library .view-title,
.u6-stats-body .view-title {
    font-family: var(--font-display);
    font-size: clamp(2.4rem, 6vw, 4rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1;
    color: var(--text);
}

.u1-lib-tagline {
    margin: 12px 0 0;
    font-family: var(--font-mono);
    font-size: 14px;
    color: var(--text-2);
}

#view-library .icon-btn { flex-shrink: 0; }

/* -- Controls: pill filter chips carrying each media type's pastel -- */
.lib-controls {
    gap: 12px;
    margin-bottom: 16px;
}

.lib-type-filter {
    align-items: center;
    gap: 8px;
    row-gap: 10px;
}

.type-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 16px;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--text-2);
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}

.type-btn[data-type]:not([data-type="all"])::before {
    content: '';
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
    background: var(--border-strong);
    transition: opacity var(--transition);
}
.type-btn[data-type="book"]::before  { background: var(--type-book); }
.type-btn[data-type="comic"]::before { background: var(--type-comic); }
.type-btn[data-type="movie"]::before,
.type-btn[data-type="tv"]::before    { background: var(--type-screen); }
.type-btn[data-type="game"]::before  { background: var(--type-game); }
.type-btn[data-type="audiobook"]::before  { background: var(--type-audiobook); }

.type-btn:hover {
    background: transparent;
    border-color: var(--navy);
    color: var(--navy);
}

.type-btn.active {
    background: var(--navy);
    border-color: transparent;
    color: #fff;
    font-weight: 600;
    box-shadow: var(--shadow-sm);
}
.type-btn.active::before { opacity: 0; }

/* Active media-type chip washes in its own pastel instead of navy */
.type-btn[data-type="book"].active  { background: var(--type-book);   color: var(--text); }
.type-btn[data-type="comic"].active { background: var(--type-comic);  color: var(--text); }
.type-btn[data-type="movie"].active,
.type-btn[data-type="tv"].active     { background: var(--type-screen); color: var(--text); }
.type-btn[data-type="game"].active  { background: var(--type-game);   color: var(--text); }
.type-btn[data-type="audiobook"].active  { background: var(--type-audiobook);   color: var(--text); }

/* Location filter: mono pill to match the chips */
.lib-type-filter .lib-filter-select {
    border-radius: var(--radius-pill);
    border: 1px solid var(--border);
    padding: 7px 28px 7px 14px;
    background-color: transparent;
    background-position: right 12px center;
    font-family: var(--font-mono);
    font-size: 12px;
}
.lib-type-filter .lib-filter-select:focus,
.lib-type-filter .lib-filter-select.is-active {
    border-color: var(--navy);
    background-color: var(--surface);
}

/* -- Search field: pill, mono -- */
.lib-search-row {
    margin-bottom: 22px;
}
.lib-search-row .search-input {
    width: 100%;
    box-sizing: border-box;
    padding: 12px 20px;
    border: 1px solid #D4DEE2;
    border-radius: var(--radius-pill);
    background: var(--surface);
    font-family: var(--font-mono);
    font-size: 13px;
    color: var(--text);
}
.lib-search-row .search-input::placeholder { color: var(--text-3); }
.lib-search-row .search-input:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-dim);
}

#library-list .empty-state {
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.02em;
    padding: 60px 0;
}

/* -- Sectioned (default) view: mono shelf headers + cover shelves -- */
.library-section { margin-bottom: 30px; }

.section-heading {
    gap: 10px;
    padding: 0 0 12px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 14px;
}
.section-heading-title {
    font-family: var(--font-mono);
    font-size: 0.74rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--text);
}
.section-heading-count {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.66rem;
    font-weight: 600;
    color: var(--text-3);
    background: transparent;
    border: none;
    padding: 0;
    margin-left: 0;
}
.section-heading-arrow {
    font-family: var(--font-mono);
    font-size: 1.1rem;
    color: var(--text-3);
    transition: transform var(--transition), color var(--transition);
}
.section-heading[data-status]:hover .section-heading-arrow {
    color: var(--text);
    transform: translateX(2px);
}

.section-scroll-row {
    gap: 20px;
    padding: 4px 0 6px;
}

.scroll-tile { transition: transform var(--transition); }
.scroll-tile:hover { transform: translateY(-4px); }
.scroll-tile-cover,
.scroll-tile-no-cover {
    border-radius: var(--radius-sm);
    box-shadow: 0 6px 16px rgba(22, 35, 42, 0.14);
}
.scroll-tile-title {
    font-family: var(--font-mono);
    font-size: 10.5px;
    color: var(--text-2);
    letter-spacing: 0.01em;
}
.scroll-tile-reread {
    background: var(--navy);
    font-family: var(--font-mono);
    border-radius: var(--radius-pill);
}

/* -- Item cards (list + flat/filtered view) -- */
.lib-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    transition: box-shadow var(--transition), border-color var(--transition), transform var(--transition);
}
.lib-card:hover {
    box-shadow: var(--shadow);
    border-color: var(--border-strong);
    transform: translateY(-1px);
}

.lib-cover {
    border-radius: var(--radius-sm);
    background: var(--surface-alt);
    border: 1px solid var(--border);
}

.lib-card-title {
    font-size: 0.92rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}
.lib-card-sub {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--text-2);
    letter-spacing: 0.01em;
}
.lib-card-location {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    color: var(--text-3);
}

/* -- Series cards + headers -- */
.series-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    transition: box-shadow var(--transition), border-color var(--transition), transform var(--transition);
}
.series-card:hover {
    box-shadow: var(--shadow);
    border-color: var(--border-strong);
    transform: translateY(-1px);
}
.series-card-cover {
    border-radius: var(--radius-sm);
    background: var(--surface-alt);
    border: 1px solid var(--border);
}
.series-card-count {
    background: var(--navy);
    color: #fff;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    border-radius: var(--radius-pill);
    padding: 1px 6px;
}
.series-card-title {
    font-size: 0.92rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}
.series-card-pub {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--text-2);
}

.series-header {
    gap: 10px;
    padding: 12px 0 8px;
    border-bottom: 1px solid var(--border);
}
.series-name {
    font-family: var(--font-mono);
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    color: var(--text);
}
.series-count {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.66rem;
    font-weight: 600;
    color: var(--text-3);
    background: transparent;
    padding: 0;
}

/* -- Type dividers: mono eyebrow -- */
.type-divider {
    font-family: var(--font-mono);
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    color: var(--text-3);
    padding: 16px 0 8px;
}

/* -- Status badges: mono uppercase pills (kept per-status colors) -- */
.status-badge {
    font-family: var(--font-mono);
    font-size: 0.62rem;
    font-weight: 600;
    letter-spacing: 0.08em;
}
.status-badge.to_read { background: var(--info-dim);    color: var(--info); }
.status-badge.paused  { background: var(--surface-alt); color: var(--navy-light); border: 1px solid var(--border); }

.reread-badge {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
}

/* -- Media-type cover tint: while a single type filter is active, empty
      cover placeholders wash in that type's pastel (mixed "All" view stays
      neutral). Per-card tint in the mixed view needs a JS-emitted data-type
      — see deferred_needs_js. -- */
#view-library:has(.type-btn[data-type="book"].active) .lib-cover:not(:has(img)),
#view-library:has(.type-btn[data-type="book"].active) .scroll-tile-no-cover,
#view-library:has(.type-btn[data-type="book"].active) .series-card-no-cover {
    background: var(--type-book);
}
#view-library:has(.type-btn[data-type="comic"].active) .lib-cover:not(:has(img)),
#view-library:has(.type-btn[data-type="comic"].active) .scroll-tile-no-cover,
#view-library:has(.type-btn[data-type="comic"].active) .series-card-no-cover {
    background: var(--type-comic);
}
#view-library:has(.type-btn[data-type="movie"].active) .lib-cover:not(:has(img)),
#view-library:has(.type-btn[data-type="movie"].active) .scroll-tile-no-cover,
#view-library:has(.type-btn[data-type="movie"].active) .series-card-no-cover,
#view-library:has(.type-btn[data-type="tv"].active) .lib-cover:not(:has(img)),
#view-library:has(.type-btn[data-type="tv"].active) .scroll-tile-no-cover,
#view-library:has(.type-btn[data-type="tv"].active) .series-card-no-cover {
    background: var(--type-screen);
}
#view-library:has(.type-btn[data-type="game"].active) .lib-cover:not(:has(img)),
#view-library:has(.type-btn[data-type="game"].active) .scroll-tile-no-cover,
#view-library:has(.type-btn[data-type="game"].active) .series-card-no-cover {
    background: var(--type-game);
}

/* -- Grid view: refined cards, pastel wash on empty covers via context -- */
#library-list.grid-view {
    gap: 14px;
}
#library-list.grid-view .lib-card,
#library-list.grid-view .series-card {
    background: var(--surface);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-sm);
}
#library-list.grid-view .lib-card:hover,
#library-list.grid-view .series-card:hover {
    box-shadow: var(--shadow);
    transform: translateY(-3px);
}
#library-list.grid-view .lib-card-title,
#library-list.grid-view .series-card-title {
    font-weight: 600;
}
#library-list.grid-view .type-divider,
#library-list.grid-view .series-header {
    margin-top: 6px;
}

/* ===== U5 Profile (view-profile) ===== */
/* Restyles the user's own profile screen to the Phantom Shelf design language.
   NOTE: shared item-card (.cr-card*) and list-card (.list-card*) classes are also
   used by community.js in #overlay-user-profile, and the shared summary-tile classes
   (.stats-grid/.stat-card/.stat-value/.stat-label) are owned by U6. To avoid
   collisions, every override here is scoped under #view-profile, and new structural
   classes are namespaced u5-*. The summary-grid classes are intentionally NOT
   redefined. */

/* ── Header ─────────────────────────────────────────────── */
#view-profile .profile-view-header {
    margin-bottom: 18px;
}
#view-profile .view-title {
    font-weight: 700;
    letter-spacing: -0.01em;
}

/* ── Identity hero ──────────────────────────────────────── */
#view-profile .profile-hero.u5-hero {
    gap: 22px;
    align-items: center;
    margin-bottom: 26px;
    padding-bottom: 24px;
    border-bottom: none;
}

/* Decorative overlapping pastel halo behind the avatar (design mockup vibe).
   #profile-avatar's own class/innerHTML is reset by app.js each render, so the
   halo lives on a static wrapper as sibling ::before/::after layers. */
.u5-hero-avatar {
    position: relative;
    flex-shrink: 0;
    width: 76px;
    height: 76px;
}
.u5-hero-avatar::before,
.u5-hero-avatar::after {
    content: "";
    position: absolute;
    border-radius: 50%;
    mix-blend-mode: multiply;
    pointer-events: none;
    z-index: 0;
}
.u5-hero-avatar::before {
    left: -9px;
    top: 14px;
    width: 44px;
    height: 44px;
    background: var(--type-game);   /* mint */
}
.u5-hero-avatar::after {
    right: -10px;
    top: -6px;
    width: 40px;
    height: 40px;
    background: var(--type-screen); /* blue */
}
.u5-hero-avatar .profile-avatar {
    position: relative;
    z-index: 1;
    width: 76px;
    height: 76px;
}
.u5-hero-avatar .profile-avatar-initials {
    font-family: var(--font-mono);
    font-weight: 600;
    font-size: 1.4rem;
    letter-spacing: 0.02em;
}

#view-profile .profile-hero-info {
    max-width: none;
    gap: 4px;
}
#view-profile .profile-display-name {
    font-size: 1.7rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.1;
}
#view-profile .profile-username-tag {
    font-family: var(--font-mono);
    font-size: 0.78rem;
    color: var(--text-2);
    letter-spacing: 0.01em;
}
#view-profile .profile-bio-text {
    font-family: var(--font-mono);
    font-size: 0.76rem;
    color: var(--text-2);
    line-height: 1.5;
    margin-top: 4px;
}

/* Social counts as inline mono text (design: "12 FOLLOWING  18 FOLLOWERS") */
#view-profile .profile-hero-social {
    gap: 20px;
    margin-top: 12px;
}
#view-profile .profile-hero-social .social-count-btn {
    background: none;
    border: none;
    padding: 0;
    gap: 5px;
    border-radius: 0;
    align-items: baseline;
}
#view-profile .profile-hero-social .social-count-btn:hover {
    background: none;
}
#view-profile .profile-hero-social .social-count-btn:hover .social-label {
    color: var(--text);
}
#view-profile .profile-hero-social .social-count {
    font-family: var(--font-mono);
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text);
}
#view-profile .profile-hero-social .social-label {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    font-weight: 500;
    letter-spacing: 0.08em;
    color: var(--text-2);
    transition: color var(--transition);
}

/* ── "Library" summary label above the shared stat grid ─── */
#view-profile .stats-trigger-row {
    padding-top: 4px;
    margin-bottom: 12px;
}

/* ── Sectioned item strips (In Progress / Finished / Up Next) ─── */
/* Turn each strip header into an uppercase mono label sitting on a divider,
   matching the design's ruled section rows. */
#view-profile .u5-strip {
    margin-bottom: 30px;
}
#view-profile .cr-section-header {
    gap: 10px;
    padding: 13px 0;
    margin-bottom: 3px;
}
#view-profile .cr-header-title {
    font-family: var(--font-mono);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text);
}
#view-profile .cr-count-badge {
    width: 20px;
    height: 20px;
    font-family: var(--font-mono);
    font-size: 0.66rem;
}

/* Cover cards: soft shadow + lift on hover. (JS emits no media-type on these
   cards, so a per-type pastel halo would require a JS change — see manifest.) */
#view-profile .cr-grid {
    gap: 28px;
    padding-bottom: 8px;
}
#view-profile .cr-card {
    width: 172px;
    transition: transform var(--transition);
}
#view-profile .cr-card-cover {
    width: 172px;
    height: 258px;
    border-radius: 7px;
    box-shadow: 0 8px 20px rgba(22, 35, 42, 0.16);
    background: var(--surface-alt);
    margin-bottom: 0;
}
#view-profile .cr-card-title {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--text);
    margin-top: 11px;
    line-height: 1.3;
}
#view-profile .cr-card.cr-item-clickable:hover {
    transform: translateY(-4px);
}
#view-profile .cr-card.cr-item-clickable:hover .cr-card-cover {
    opacity: 1;
}

/* ── Reviews section ────────────────────────────────────── */
#view-profile .profile-reviews-section .section-label {
    padding: 13px 0;
    margin-bottom: 3px;
}
#view-profile .profile-reviews-trigger {
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}
#view-profile .review-histogram-bar {
    background: var(--type-comic);
    mix-blend-mode: multiply;
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}
#view-profile .review-histogram-label {
    font-family: var(--font-mono);
    font-weight: 500;
    color: var(--text-3);
}

/* ── Lists ──────────────────────────────────────────────── */
#view-profile .profile-lists-section .lists-header {
    padding: 13px 0;
    margin-bottom: 8px;
}
#view-profile .profile-lists-section .section-label {
    margin-bottom: 0;
}
#view-profile #new-list-btn {
    font-family: var(--font-mono);
    font-size: 0.7rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
#view-profile .profile-lists {
    gap: 12px;
}
#view-profile .list-card {
    gap: 14px;
    padding: 14px 16px;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    transition: transform var(--transition), border-color var(--transition);
}
#view-profile .list-card:hover {
    transform: translateY(-2px);
    border-color: var(--border-strong);
}
/* Same specificity story as the item rows: the card's own id-scoped rules
   outrank a bare class, and the card being dragged is the one under the
   cursor, so the hover lift has to be cancelled explicitly. */
#view-profile .list-card.drag-reordering,
#view-profile .list-card.drag-reordering:hover {
    opacity: 0.75;
    border-color: var(--border-strong);
    box-shadow: var(--shadow-lg);
    transform: none;
}
#view-profile .list-card-name {
    font-family: var(--font-display);
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--text);
}
#view-profile .list-card-meta {
    font-family: var(--font-mono);
    font-size: 0.7rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-2);
    margin-top: 3px;
}
#view-profile .list-card-arrow {
    color: var(--text-3);
    font-size: 1.3rem;
    margin-left: auto;
}
#view-profile .profile-lists .empty-state {
    font-family: var(--font-mono);
    font-size: 0.78rem;
    color: var(--text-3);
}

/* ── Wider screens: give the profile a roomier hero ─────── */
@media (min-width: 900px) {
    #view-profile .profile-display-name {
        font-size: 2rem;
    }
    #view-profile .u5-hero-avatar,
    #view-profile .u5-hero-avatar .profile-avatar {
        width: 84px;
        height: 84px;
    }
}

/* ===== U4 Community ===== */
/* Scope: #view-community (feed + friends shell) and #overlay-user-profile
   (another reader's profile). All overrides are scoped to those containers so
   they never leak into #view-profile (owned by U5) or other screens. */

/* ── Header ─────────────────────────────────────────────────────────────── */
#view-community .view-header { margin-bottom: 6px; }
#view-community .view-title {
    font-family: var(--font-display);
    font-size: 2.1rem;
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1;
}
.u4-community-sub {
    font-family: var(--font-mono);
    font-size: 0.78rem;
    color: var(--text-2);
    margin: 8px 0 24px;
}

/* ── Tabs (pill segmented, navy = active) ───────────────────────────────── */
#view-community .community-tabs {
    border-bottom: none;
    gap: 8px;
    margin-bottom: 26px;
    padding-bottom: 0;
}
#view-community .community-tab {
    padding: 7px 18px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-pill);
    background: var(--surface);
    font-family: var(--font-mono);
    font-size: 0.68rem;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-2);
    margin-bottom: 0;
    transition: color var(--transition), border-color var(--transition), background var(--transition);
}
#view-community .community-tab:hover {
    border-color: var(--navy);
    color: var(--navy);
}
#view-community .community-tab.active {
    background: var(--navy);
    border-color: var(--navy);
    color: #fff;
}

/* ── Feed ───────────────────────────────────────────────────────────────── */
#view-community .community-feed { gap: 0; }
#view-community .feed-card {
    gap: 16px;
    align-items: flex-start;
    padding: 18px 6px;
    background: none;
    border: none;
    border-bottom: 1px solid var(--border);
    border-radius: 0;
    transition: background var(--transition);
}
#view-community .feed-card:hover {
    background: var(--surface-alt);
    border-radius: var(--radius);
    border-bottom-color: transparent;
}
#view-community .feed-cover {
    width: 46px;
    height: 68px;
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-sm);
    background: var(--surface-alt);
}
#view-community .feed-cover-placeholder {
    background: var(--surface-alt);
    border: 1px solid var(--border);
}
#view-community .feed-card-body { padding-top: 2px; }
#view-community .feed-action {
    font-size: 0.94rem;
    color: var(--text-2);
    line-height: 1.45;
    margin: 0 0 6px;
}
#view-community .feed-action strong { color: var(--text); font-weight: 700; }
#view-community .feed-username {
    color: var(--text);
    font-weight: 700;
    cursor: pointer;
}
#view-community .feed-username:hover { color: var(--accent); text-decoration: none; }
#view-community .feed-stars {
    color: #E8A020;
    letter-spacing: 1px;
}
/* The rating gets its own line so a long title can never push the stars into
   a wrap, and nowrap keeps a half-star run from splitting across two lines. */
.feed-rating-line {
    margin: 2px 0 0;
    line-height: 1.2;
    white-space: nowrap;
}
.feed-rating-line .feed-stars { margin-left: 0; }
#view-community .feed-review-body {
    margin: 8px 0;
    padding: 10px 14px;
    border-left: 3px solid var(--border-strong);
    background: var(--surface);
    border-radius: 0 var(--radius) var(--radius) 0;
    font-style: normal;
    font-size: 0.88rem;
    line-height: 1.55;
    color: var(--text-2);
}
#view-community .feed-when {
    font-family: var(--font-mono);
    font-size: 0.64rem;
    letter-spacing: 0.06em;
    color: var(--text-3);
}
#view-community .social-bar { margin-top: 10px; }

/* ── Friends: search + section headings ─────────────────────────────────── */
#view-community .community-search-row { margin-bottom: 22px; }
#view-community .search-input { border-radius: var(--radius-pill); }
#view-community .suggested-readers-heading {
    font-family: var(--font-mono);
    font-size: 0.64rem;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-3);
    margin: 22px 0 10px;
}

/* ── Friends / suggested reader rows ────────────────────────────────────── */
#view-community .community-user-card,
#view-community .friend-row {
    background: none;
    padding: 13px 8px;
    border-radius: var(--radius);
    border-bottom: 1px solid var(--border);
    margin-bottom: 0;
    gap: 16px;
}
#view-community .community-user-card:hover,
#view-community .friend-row:hover {
    background: var(--surface-alt);
    border-bottom-color: transparent;
}
#view-community .suggested-avatar {
    width: 40px;
    height: 40px;
    background: linear-gradient(135deg, var(--type-screen), var(--type-book));
    color: var(--text);
    font-family: var(--font-mono);
    font-size: 0.8rem;
    font-weight: 600;
}
#view-community .community-username {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.98rem;
    color: var(--text);
}
#view-community .community-display-name {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--text-2);
    margin-top: 2px;
}
#view-community .friend-reading,
#view-community .friend-activity {
    font-family: var(--font-mono);
    font-size: 0.7rem;
    margin-top: 3px;
}

/* ══════════════════════════════════════════════════════════════════════════
   #overlay-user-profile — another reader's profile.
   U5 scoped its .cr-card*/.list-card*/.social-count*/.review-histogram*
   overrides under #view-profile, so inside this overlay we own those shared
   classes. Everything here is scoped to #overlay-user-profile.
   ═════════════════════════════════════════════════════════════════════════ */

/* Hero */
#overlay-user-profile .profile-avatar {
    background: linear-gradient(135deg, var(--type-screen), var(--type-book) 55%, var(--type-game));
}
#overlay-user-profile .profile-avatar-initials {
    color: var(--text);
    font-family: var(--font-mono);
    font-weight: 600;
    letter-spacing: 0.02em;
}
#overlay-user-profile .profile-display-name {
    font-family: var(--font-display);
    font-size: 1.9rem;
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.1;
}
#overlay-user-profile .profile-username-tag {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--text-2);
    margin-top: 4px;
}
#overlay-user-profile .profile-bio-text {
    font-size: 0.86rem;
    color: var(--text-2);
    line-height: 1.5;
}
#overlay-user-profile .profile-hero-social .social-count {
    font-family: var(--font-mono);
    color: var(--text);
}
#overlay-user-profile .profile-hero-social .social-label {
    font-family: var(--font-mono);
    letter-spacing: 0.08em;
}

/* Stat tiles — mono numerals + uppercase mono labels */
#overlay-user-profile .stat-value {
    font-family: var(--font-mono);
    font-weight: 500;
    color: var(--text);
}
#overlay-user-profile .stat-label {
    font-family: var(--font-mono);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-3);
}

/* Section headers + count badges */

/* Reading / recently-read / to-read cover cards */

/* Review histogram */
#overlay-user-profile .review-histogram-bar.bar-empty { background: var(--border); }
#overlay-user-profile .review-histogram-label {
    font-family: var(--font-mono);
    color: var(--text-3);
}

/* Recent review cards */
#overlay-user-profile .profile-review-card-title {
    font-family: var(--font-display);
    font-weight: 500;
    color: var(--text);
}
#overlay-user-profile .profile-review-card-cover {
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-sm);
}
#overlay-user-profile .profile-review-card-body {
    font-size: 0.82rem;
    color: var(--text-2);
    line-height: 1.5;
}

/* Public lists */
#overlay-user-profile .list-card-name {
    font-family: var(--font-display);
    font-weight: 500;
    color: var(--text);
}
#overlay-user-profile .list-card-meta {
    font-family: var(--font-mono);
    font-size: 0.7rem;
    color: var(--text-3);
}

/* ===== U7 Auth + misc overlays (settings, series, comments, list, all-reviews, sheets) ===== */
/* These screens are not in the mockup — this extends the established design system:
   card surfaces + soft slate shadows, pill buttons, uppercase IBM Plex Mono labels,
   mono numerals, and the media-type pastels. All overrides are scoped to U7 containers
   (their ids) or to sheet/auth classes U7 owns outright, so nothing collides with other
   units' appended rules. Every id/hook from the JS is preserved. */

/* ── Shared overlay chrome (scoped to U7 overlays) ─────────────────────────── */
#overlay-series .overlay-top-bar,
#overlay-comments .overlay-top-bar,
#overlay-list .overlay-top-bar,
#overlay-all-reviews .overlay-top-bar {
    padding: 14px 20px;
    background: color-mix(in srgb, var(--surface) 88%, transparent);
    backdrop-filter: saturate(1.2) blur(6px);
}

#overlay-series .back-btn,
#overlay-comments .back-btn,
#overlay-list .back-btn,
#overlay-all-reviews .back-btn,
#view-settings #settings-back-btn {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-2);
}
#overlay-series .back-btn svg,
#overlay-comments .back-btn svg,
#overlay-list .back-btn svg,
#overlay-all-reviews .back-btn svg,
#view-settings #settings-back-btn svg {
    width: 15px;
    height: 15px;
}

/* Consistent overlay title (display font, tight tracking) */
#overlay-series .series-detail-title,
#overlay-list .list-detail-title,
#overlay-all-reviews .item-detail-title {
    font-family: var(--font-display);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.05;
    color: var(--text);
}
#overlay-all-reviews .item-detail-title { font-size: 1.7rem; }

/* ── Settings / Account ────────────────────────────────────────────────────── */
#view-settings .settings-view-header {
    padding-bottom: 14px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 8px;
}
#view-settings .view-title {
    font-family: var(--font-display);
    font-weight: 800;
    letter-spacing: -0.02em;
}
#view-settings .settings-section {
    padding: 20px 0;
    border-bottom: 1px solid var(--border);
}
#view-settings .settings-section:last-child { border-bottom: none; }
#view-settings .section-label {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-3);
    margin-bottom: 14px;
}
#view-settings .avatar-settings-row {
    display: flex;
    align-items: center;
    gap: 16px;
}
#view-settings .profile-avatar {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    background: var(--surface-alt);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-sm);
    background-size: cover;
    background-position: center;
    flex-shrink: 0;
}
#view-settings .community-profile-form { display: flex; flex-direction: column; gap: 14px; }
#view-settings .form-group { display: flex; flex-direction: column; gap: 6px; }
#view-settings .form-group label {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-2);
}
#view-settings .form-group input[type="text"] {
    padding: 10px 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    font-family: inherit;
    font-size: 0.9rem;
    transition: border-color var(--transition), box-shadow var(--transition);
}
#view-settings .form-group input[type="text"]:focus {
    outline: none;
    border-color: var(--navy);
    box-shadow: 0 0 0 3px var(--info-dim);
}
#view-settings .form-group-inline {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}
#view-settings .form-group-inline label { margin: 0; }
#view-settings .help-text {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    color: var(--text-3);
    line-height: 1.5;
}
#view-settings .import-description {
    font-size: 0.85rem;
    color: var(--text-2);
    line-height: 1.55;
    margin-bottom: 14px;
}
#view-settings .import-description code {
    font-family: var(--font-mono);
    font-size: 0.78rem;
    background: var(--surface-alt);
    border-radius: var(--radius-sm);
    padding: 1px 5px;
}
#view-settings .import-controls {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}
#view-settings .import-file-name {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--text-3);
}
#view-settings .import-preview {
    margin-top: 14px;
    padding: 14px 16px;
    background: var(--surface-alt);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}
#view-settings .import-preview-text {
    font-family: var(--font-mono);
    font-size: 0.78rem;
    color: var(--text-2);
    margin: 0;
}
#view-settings .import-progress { margin-top: 14px; }
#view-settings .import-progress-bar-wrap {
    height: 8px;
    border-radius: var(--radius-pill);
    background: var(--surface-alt);
    overflow: hidden;
    border: 1px solid var(--border);
}
#view-settings .import-progress-bar {
    height: 100%;
    width: 0;
    border-radius: var(--radius-pill);
    background: var(--navy);
    transition: width var(--transition);
}
#view-settings .import-progress-text {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    color: var(--text-2);
    margin-top: 8px;
}

/* ── Series detail overlay ─────────────────────────────────────────────────── */
#overlay-series .series-detail-title { font-size: 1.9rem; margin-bottom: 6px; }
#overlay-series .series-detail-publisher {
    font-family: var(--font-mono);
    font-size: 0.78rem;
    letter-spacing: 0.04em;
    color: var(--text-2);
    margin-bottom: 6px;
}
#overlay-series .series-detail-completion {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-3);
    margin: 4px 0 22px;
}
#overlay-series .series-issue-list { gap: 10px; }
#overlay-series .series-issue-card {
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 12px 14px;
    box-shadow: var(--shadow-sm);
    transition: transform var(--transition), box-shadow var(--transition);
}
#overlay-series .series-issue-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow);
}
#overlay-series .series-issue-cover {
    width: 42px;
    height: 60px;
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-sm);
}
#overlay-series .series-issue-num {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.92rem;
}

/* Series review block — scoped so it doesn't touch the item-detail review block */
#overlay-series .review-section {
    border-top: 1px solid var(--border);
    margin-top: 26px;
    padding-top: 22px;
}
#overlay-series .review-section-title {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-3);
}
#overlay-series .review-form,
#overlay-series .review-display {
    position: relative;
    padding: 18px 18px;
    border-radius: var(--radius-lg);
    background: var(--type-comic);
    /* pastel wash — comics are the series screen's natural media type */
}
#overlay-series .review-form {
    background:
        linear-gradient(color-mix(in srgb, var(--surface) 74%, transparent),
                        color-mix(in srgb, var(--surface) 74%, transparent)),
        var(--type-comic);
}
#overlay-series .review-textarea {
    background: rgba(255, 255, 255, 0.7);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}
#overlay-series .review-textarea:focus {
    border-color: var(--navy);
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.55);
}
#overlay-series .review-body-text {
    font-size: 0.9rem;
    color: var(--text);
    line-height: 1.6;
}

/* ── Comments overlay ──────────────────────────────────────────────────────── */
#overlay-comments .section-label {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-3);
    margin-bottom: 16px;
}
#overlay-comments .comments-list { gap: 16px; margin: 4px 0 16px; }
#overlay-comments .comment-item {
    padding: 12px 14px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    gap: 12px;
}
#overlay-comments .comment-avatar {
    background: var(--navy);
    box-shadow: var(--shadow-sm);
}
#overlay-comments .comment-name {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.85rem;
    color: var(--text);
}
#overlay-comments .comment-time {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    letter-spacing: 0.04em;
    color: var(--text-3);
}
#overlay-comments .comment-input-row {
    gap: 8px;
    padding: 12px 0;
    background: var(--surface);
    border-top: 1px solid var(--border);
}
#overlay-comments .comment-input-row .search-input {
    border-radius: var(--radius-pill);
    background: var(--surface);
    border: 1px solid var(--border-strong);
}

/* ── List detail overlay ───────────────────────────────────────────────────── */
#overlay-list .list-detail-head {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 3px;
}
#overlay-list .list-detail-title { font-size: 1.9rem; }
#overlay-list .list-public-badge {
    font-family: var(--font-mono);
    font-size: 0.6rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--info);
    background: var(--info-dim);
    padding: 3px 9px;
    border-radius: var(--radius-pill);
}
#overlay-list .list-detail-desc {
    font-size: 0.9rem;
    color: var(--text-2);
    line-height: 1.55;
    margin: 8px 0 4px;
}
#overlay-list .list-owner-actions { display: flex; gap: 8px; margin: 14px 0 18px; }
#overlay-list .list-detail-items { gap: 4px; }
#overlay-list .list-item-row {
    padding: 10px 12px;
    border-radius: var(--radius-lg);
    border: 1px solid transparent;
    transition: background var(--transition), border-color var(--transition), transform var(--transition);
}
#overlay-list .list-item-row:hover {
    background: var(--surface);
    border-color: var(--border);
    box-shadow: var(--shadow-sm);
    transform: translateY(-1px);
}
#overlay-list .list-rank {
    font-family: var(--font-mono);
    font-weight: 600;
    color: var(--text-3);
}
#overlay-list .list-item-cover {
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-sm);
}
#overlay-list .list-item-title {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--text);
}
#overlay-list .list-item-sub {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    color: var(--text-3);
}

/* ── All-reviews overlay ───────────────────────────────────────────────────── */
#overlay-all-reviews .all-review-card {
    gap: 14px;
    padding: 16px 0;
}
#overlay-all-reviews .all-review-cover {
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-sm);
}
#overlay-all-reviews .all-review-title {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.92rem;
}
#overlay-all-reviews .all-review-date {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    letter-spacing: 0.04em;
    color: var(--text-3);
}

/* ── Dialogs (list-picker, new-list, to-read, up-to-read, social) ──────────── */
/* Radius is set with the geometry further up so the squircle @supports block
   stays next to its own fallback. */
.social-sheet {
    border: 1px solid var(--border);
    box-shadow: var(--shadow-lg);
}
.social-sheet-header {
    padding: 10px 18px 14px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.social-sheet-title {
    font-family: var(--font-display);
    font-size: 1rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--text);
}
/* The card clips; the body is the part that scrolls inside it. */
.social-sheet-body {
    padding: 14px 18px 22px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}
.social-sheet-body .search-input {
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: var(--surface);
}
.social-sheet-body .review-textarea { border-radius: var(--radius); }
.social-sheet-body .spoiler-check {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    letter-spacing: 0.02em;
    color: var(--text-2);
}
/* list-picker rows → pill-ish tappable cards */
#list-picker-list .list-pick-row {
    padding: 12px 14px;
    margin-bottom: 6px;
    border: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    transition: background var(--transition), border-color var(--transition);
}
#list-picker-list .list-pick-row:hover {
    background: var(--surface-alt);
    border-color: var(--border-strong);
}
#list-picker-list .list-pick-check {
    font-family: var(--font-mono);
    color: var(--accent);
}

/* ── Add media to a list (search inside the list dialog) ───────────────────── */
.list-add-media { margin: 0 0 16px; }
.list-add-controls {
    display: flex;
    align-items: center;
    gap: 8px;
}
.list-add-controls .search-input { flex: 1; min-width: 0; }
#list-add-global-btn { flex-shrink: 0; white-space: nowrap; }
.list-add-media .search-input,
#list-search-sheet .search-input {
    width: 100%;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: var(--surface);
}
#list-search-sheet .search-input { margin-bottom: 4px; }
.list-add-results:not(:empty) { margin-top: 8px; }
.list-add-row {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px 10px;
    margin-bottom: 6px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition);
}
.list-add-row:hover {
    background: var(--surface-alt);
    border-color: var(--border-strong);
}
.list-add-cover {
    width: 32px;
    height: 46px;
    flex-shrink: 0;
    object-fit: cover;
    border-radius: var(--radius-sm);
    background: var(--surface-alt);
}
.list-add-info { flex: 1; min-width: 0; }
.list-add-title {
    font-family: var(--font-display);
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.list-add-sub {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    color: var(--text-2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.list-add-row .list-pick-check {
    font-family: var(--font-mono);
    color: var(--accent);
    flex-shrink: 0;
}
.list-add-results .empty-state { padding: 12px 4px; margin: 0; }

/* ── Confirm-what-you-are-adding panel ────────────────────────────────────── */
.add-preview { padding-top: 4px; }
.add-preview-back { margin-bottom: 12px; }
.add-preview-head {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    margin-bottom: 10px;
}
.add-preview-cover {
    width: 72px;
    height: 106px;
    flex-shrink: 0;
    object-fit: cover;
    border-radius: var(--radius-sm);
    background: var(--surface-alt);
}
.add-preview-info { flex: 1; min-width: 0; }
.add-preview-title {
    font-family: var(--font-display);
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.25;
    color: var(--text);
}
.add-preview-meta {
    margin-top: 4px;
    font-family: var(--font-mono);
    font-size: 0.7rem;
    color: var(--text-2);
}
/* Clamped rather than scrolled: this is a "is this the right one?" glance, and
   a long blurb would push the note and the button below the fold. */
.add-preview-desc {
    margin: 0 0 12px;
    font-size: 0.8rem;
    line-height: 1.5;
    color: var(--text-2);
    display: -webkit-box;
    -webkit-line-clamp: 5;
    line-clamp: 5;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.add-preview-desc-empty { color: var(--text-3); font-style: italic; }
.add-preview-note { width: 100%; margin-bottom: 10px; }
.add-preview-confirm { width: 100%; }
.add-preview-confirm:disabled { opacity: 0.6; cursor: default; }
/* to-read / up-to-read / social sheet rows */
.social-sheet-body .friend-row {
    border-bottom: 1px solid var(--border);
}
.social-sheet-body .friend-row:hover { background: var(--surface-alt); }
.social-sheet-body .friend-name {
    font-family: var(--font-display);
    font-weight: 600;
    color: var(--text);
}
.social-sheet-body .friend-username {
    font-family: var(--font-mono);
    font-size: 0.7rem;
    color: var(--text-2);
}

/* ── Auth / Sign-in screen ─────────────────────────────────────────────────── */
.auth-modal { background: var(--bg); }
.auth-card {
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 40px 34px 34px;
    box-shadow: 0 0 0 1px rgba(22, 35, 42, 0.04), var(--shadow-lg);
}
.auth-logo {
    font-family: var(--font-display);
    font-size: 1.9rem;
    font-weight: 800;
    letter-spacing: -0.02em;
    color: var(--navy);
    text-align: center;
    margin-bottom: 6px;
}
.auth-tagline {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    letter-spacing: 0.04em;
    color: var(--text-2);
    text-align: center;
    margin-bottom: 26px;
}
.auth-tabs {
    display: flex;
    gap: 4px;
    padding: 4px;
    border: none;
    background: var(--surface-alt);
    border-radius: var(--radius-pill);
    margin-bottom: 24px;
}
.auth-tab {
    flex: 1;
    padding: 9px 0;
    border-radius: var(--radius-pill);
    font-family: var(--font-mono);
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-2);
    transition: background var(--transition), color var(--transition), box-shadow var(--transition);
}
.auth-tab.active {
    background: var(--navy);
    color: #fff;
    box-shadow: var(--shadow-sm);
}
#auth-form label,
#forgot-password-panel label,
#reset-password-panel label {
    font-family: var(--font-mono);
    font-size: 0.66rem;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-2);
}
#auth-form input,
#forgot-password-panel input,
#reset-password-panel input {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}
#auth-form input:focus,
#forgot-password-panel input:focus,
#reset-password-panel input:focus {
    border-color: var(--navy);
    box-shadow: 0 0 0 3px var(--info-dim);
}
/* Username field + its shuffle button. The width override has to carry the
   #auth-form prefix: the base rule is `#auth-form input { width: 100% }`, and a
   class-only selector loses to it, which pushes the button off the card. */
.auth-username-row {
    display: flex;
    gap: 8px;
    align-items: stretch;
}
#auth-form .auth-username-row input {
    flex: 1;
    min-width: 0;
    width: auto;
}
#auth-username-shuffle {
    flex: 0 0 auto;
    line-height: 1;
}
#auth-username-feedback {
    display: block;
    margin-top: 6px;
}

.auth-error {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    letter-spacing: 0.02em;
}
.auth-link {
    font-family: var(--font-mono);
    font-size: 0.7rem;
    letter-spacing: 0.04em;
    color: var(--accent);
    text-decoration: none;
    border-bottom: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
    padding-bottom: 1px;
}
.auth-link:hover { color: var(--accent-hover); opacity: 1; }

/* ============================================================
   DESIGN REBUILD — Library screen + sidebar (faithful to mockup)
   ============================================================ */

/* ---- Venn media-mix hero (all widths) ---- */
.u1-lib-header { align-items: flex-start; gap: 40px; row-gap: 24px; flex-wrap: wrap; }
.lib-venn { margin-left: auto; display: flex; align-items: center; gap: 22px; }
.lib-venn:empty { display: none; }
.venn-plot { position: relative; width: 250px; height: 130px; flex: 0 0 auto; }
.venn-c { position: absolute; border-radius: 50%; mix-blend-mode: multiply; }
/* left/top are the circle's centre; the transform does the centring so the
   number sits inside its own circle rather than in an overlap. */
.venn-n { position: absolute; transform: translate(-50%, -50%); font-family: var(--font-mono); font-size: 11px; font-weight: 600; color: var(--text); white-space: nowrap; }
.venn-legend { display: flex; flex-direction: column; gap: 6px; font-family: var(--font-mono); font-size: 10.5px; color: var(--text-2); }
.venn-leg { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.venn-leg .key-dot { width: 11px; height: 11px; border-radius: 50%; flex: 0 0 auto; }
@media (max-width: 720px) { .venn-plot { display: none; } .lib-venn { margin-left: 0; } .venn-legend { flex-direction: row; flex-wrap: wrap; } }

/* ---- Shelves: heading + horizontal cover-tile gallery ---- */
.library-section { margin-top: 14px; }
.section-heading { display: flex; align-items: center; gap: 12px; padding: 6px 0 14px; border-bottom: 1px solid var(--border); }
/* Only headings that actually expand a section are clickable — the delegated
   handler keys on [data-status] too. The profile reuses .section-heading as a
   plain label, and used to inherit a pointer, an :active flash and a hover
   nudge for a click that never happened. */
.section-heading[data-status] { cursor: pointer; }
.section-heading::before {
    content: ""; width: 12px; height: 12px; border-radius: 50%; flex: 0 0 auto;
    background: var(--type-book);
    box-shadow: 7px 0 0 var(--type-comic), 14px 0 0 var(--type-screen);
    margin-right: 14px; mix-blend-mode: multiply;
}
.section-heading-title { font-family: var(--font-mono); font-size: 12px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text); }
.section-heading-count { font-family: var(--font-mono); font-size: 11px; color: var(--text-3); }
.section-heading-arrow { margin-left: auto; color: var(--text-2); font-size: 1.1rem; }
.section-scroll-row { display: flex; gap: 22px; padding: 12px 2px 30px; overflow-x: auto; overflow-y: hidden; }
.section-scroll-row::-webkit-scrollbar { height: 0; }

.scroll-tile { width: 172px; flex: 0 0 auto; cursor: pointer; transition: transform 140ms ease; }
.scroll-tile:hover { transform: translateY(-4px); }
.tile-cover { position: relative; width: 172px; height: 258px; }
.tile-dot { position: absolute; left: -12px; bottom: -12px; width: 76px; height: 76px; border-radius: 50%; background: var(--tc); mix-blend-mode: multiply; z-index: 0; }
.tile-cover-img { position: relative; z-index: 1; width: 172px; height: 258px; object-fit: cover; border-radius: 7px; box-shadow: 0 8px 20px rgba(22,35,42,0.16); display: block; }
.tile-cover-blank { position: relative; z-index: 1; display: block; width: 172px; height: 258px; border-radius: 7px; background: var(--tc); box-shadow: 0 8px 20px rgba(22,35,42,0.16); }
.scroll-tile-reread { position: absolute; z-index: 2; right: 8px; top: 8px; background: var(--navy); color: #fff; font-family: var(--font-mono); font-size: 11px; font-weight: 600; padding: 3px 8px; border-radius: 999px; }
/* Always reserve two lines. Titles vary between one line ("Life") and two
   ("White House Robot Romance"), and the shelf row sizes to its tallest tile —
   so a one-line caption left an extra line of blank space beneath it and the
   gap to the next shelf read 20px bigger on most tiles than on the few that
   wrapped. Fixing the height makes every tile identical and the gap uniform.
   Clamped at two lines so a very long title can't reintroduce the ragging. */
.tile-caption {
    margin-top: 12px; font-size: 15px; font-weight: 600; line-height: 1.3;
    max-width: 172px; color: var(--text);
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    min-height: 2.6em; overflow: hidden;
}
.tile-num { font-family: var(--font-mono); font-weight: 400; color: var(--text-2); font-size: 11.5px; }

/* Tighter shelf spacing on phones (desktop keeps its roomier values above) */
@media (max-width: 720px) {
    .library-section { margin-top: 6px; margin-bottom: 10px; }
    .section-scroll-row { padding-top: 8px; padding-bottom: 14px; }
    .section-heading { padding: 4px 0 10px; margin-bottom: 8px; }
}

/* ---- Design sidebar (desktop only) ---- */
@media (min-width: 900px) {
    .sidebar {
        display: flex; flex-direction: column;
        position: fixed; top: 0; left: 0; bottom: 0; width: 224px;
        background: var(--bg); border-right: 1px solid var(--border);
        padding: 28px 0 24px; z-index: 50;
    }
    .app-shell { margin: 0 0 0 224px; }
    .app-header { display: none; }               /* design has no desktop top bar; user chip lives in sidebar */

    .sidebar-brand { padding: 0 26px 26px; text-align: center; }
    .sidebar-title { display: block; font-family: var(--font-display); font-weight: 800; font-size: 1.15rem; line-height: 1.05; letter-spacing: -0.01em; color: var(--text); white-space: nowrap; }

    /* hand-built pastel logo mark */
    .ps-logo { position: relative; display: block; width: 58px; height: 47px; margin: 0 auto 12px; }
    .ps-book { position: absolute; bottom: 3px; border-radius: 3px; mix-blend-mode: multiply; }
    .ps-book-l { left: 0; width: 11px; height: 36px; background: #F6D3BE; transform: rotate(-7deg); transform-origin: bottom left; }
    .ps-book-r { right: 0; width: 11px; height: 31px; background: #EFC9DA; transform: rotate(7deg); transform-origin: bottom right; }
    .ps-ghost { position: absolute; inset: 0; }
    .ps-ghost-mint { position: absolute; left: 17px; bottom: 6px; width: 26px; height: 28px; border-radius: 13px 13px 0 0; background: #BFE6D2; mix-blend-mode: multiply; }
    .ps-ghost-blue { position: absolute; left: 21px; bottom: 6px; width: 26px; height: 24px; border-radius: 13px 13px 0 0; background: #BFDCF2; mix-blend-mode: multiply; }
    .ps-eye { position: absolute; bottom: 18px; width: 2.5px; height: 6px; border-radius: 99px; background: var(--navy); }
    .ps-eye-l { left: 26px; }
    .ps-eye-r { left: 33px; }
    .ps-baseline { position: absolute; left: -3px; bottom: 0; width: 64px; height: 2.5px; border-radius: 99px; background: var(--navy); }

    .sidebar-nav { display: flex; flex-direction: column; gap: 2px; padding: 0 14px; }
    .sidebar .nav-btn {
        position: relative; flex: none; flex-direction: row; justify-content: flex-start; align-items: center; gap: 10px;
        padding: 10px 12px; border-radius: 10px; background: transparent; overflow: visible;
        color: var(--text-2); font-family: var(--font-mono); font-size: 13px; font-weight: 400;
    }
    .sidebar .nav-btn .nav-index { position: relative; z-index: 1; font-size: 11px; color: var(--text-3); }
    .sidebar .nav-btn .nav-label { position: relative; z-index: 1; font-family: var(--font-mono); font-size: 13px; font-weight: 400; text-transform: none; letter-spacing: 0; color: inherit; }
    .sidebar .nav-btn:hover:not(.active) { background: var(--surface-alt); color: var(--text); }
    /* layered pastel-blob active state (mint base + blue + peach offset) */
    .sidebar .nav-btn.active { background: var(--type-book); color: var(--text); font-weight: 600; }
    .sidebar .nav-btn.active .nav-label { font-weight: 600; color: var(--text); }
    .sidebar .nav-btn.active .nav-index { color: var(--text-2); font-weight: 600; }
    /* Same technique as .app-logo and the mobile bottom nav: identical boxes,
       small translate. The old asymmetric insets (left 7/14, right -4/-8) both
       offset AND stretched each layer, so the stack read as a smear rather than
       three copies of one pill. */
    .sidebar .nav-btn.active::before,
    .sidebar .nav-btn.active::after {
        content: ""; position: absolute; inset: 0; border-radius: 10px;
        mix-blend-mode: multiply; z-index: 0;
    }
    .sidebar .nav-btn.active::before { background: var(--type-comic);  transform: translate(4px, 3px); }
    .sidebar .nav-btn.active::after  { background: var(--type-screen); transform: translate(8px, 5px); }

}

/* ---- Type filter chips: overlapping-pastel active state (per media color) ---- */
.lib-type-filter .type-btn {
    position: relative; isolation: isolate; overflow: visible;
    display: inline-flex; align-items: center; gap: 7px;
    padding: 7px 16px; border-radius: 999px; border: 1px solid var(--border-strong);
    background: transparent; color: var(--text-2);
    font-family: var(--font-mono); font-size: 12px; font-weight: 400; cursor: pointer;
    transition: color 140ms ease, border-color 140ms ease;
}
.lib-type-filter .type-btn:not(.active)::before { content: none; }   /* drop the old single-dot pseudo */
.lib-type-filter .type-btn:hover:not(.active) { border-color: var(--text); color: var(--text); }
.lib-type-filter .type-btn .chip-label { position: relative; z-index: 1; }
.lib-type-filter .type-btn .chip-dot { position: relative; z-index: 1; width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.lib-type-filter .type-btn[data-type="book"]  .chip-dot { background: var(--type-book); }
.lib-type-filter .type-btn[data-type="comic"] .chip-dot { background: var(--type-comic); }
.lib-type-filter .type-btn[data-type="movie"] .chip-dot,
.lib-type-filter .type-btn[data-type="tv"]    .chip-dot { background: var(--type-screen); }
.lib-type-filter .type-btn[data-type="game"]  .chip-dot { background: var(--type-game); }
.lib-type-filter .type-btn[data-type="audiobook"]  .chip-dot { background: var(--type-audiobook); }

.lib-type-filter .type-btn.active { border-color: transparent; color: var(--text); font-weight: 600; background: transparent; }
.lib-type-filter .type-btn.active::before,
.lib-type-filter .type-btn.active::after {
    content: ""; position: absolute; border-radius: 999px; mix-blend-mode: multiply; z-index: -1;
    background: var(--cl, var(--type-book));
}
.lib-type-filter .type-btn.active::before { inset: -1px; }
.lib-type-filter .type-btn.active::after  { left: 5px; top: 2px; right: -5px; bottom: -3px; background: var(--cl2, var(--cl)); }
.lib-type-filter .type-btn[data-type="all"].active   { --cl: var(--type-book);   --cl2: var(--type-comic); }
.lib-type-filter .type-btn[data-type="book"].active  { --cl: var(--type-book);   --cl2: var(--type-book); }
.lib-type-filter .type-btn[data-type="comic"].active { --cl: var(--type-comic);  --cl2: var(--type-comic); }
.lib-type-filter .type-btn[data-type="movie"].active,
.lib-type-filter .type-btn[data-type="tv"].active    { --cl: var(--type-screen); --cl2: var(--type-screen); }
.lib-type-filter .type-btn[data-type="game"].active  { --cl: var(--type-game);   --cl2: var(--type-game); }
.lib-type-filter .type-btn[data-type="audiobook"].active  { --cl: var(--type-audiobook);   --cl2: var(--type-audiobook); }

/* ---- Item detail: per-media type tint (design language) ---- */
#overlay-item .u2-diary-card { background: color-mix(in srgb, var(--tc, var(--accent)) 34%, #FFFFFF); }
#overlay-item .u2-cover-img:not([src]),
#overlay-item .u2-cover-img[src=""] { background: color-mix(in srgb, var(--tc, var(--surface-alt)) 55%, #FFFFFF); }

/* ---- Overlapping-pastel active state for tab selectors (search / stats / community) ---- */
.search-type-toggle .search-type-btn,
.stats-filter-tabs .stats-filter-tab,
.community-tabs .community-tab {
    position: relative; isolation: isolate; overflow: visible; background: transparent;
}
.search-type-toggle .search-type-btn.active,
.stats-filter-tabs .stats-filter-tab.active,
.community-tabs .community-tab.active {
    background: transparent; color: var(--text); font-weight: 600; border-color: transparent;
}
.search-type-toggle .search-type-btn.active::before,
.search-type-toggle .search-type-btn.active::after,
.stats-filter-tabs .stats-filter-tab.active::before,
.stats-filter-tabs .stats-filter-tab.active::after,
.community-tabs .community-tab.active::before,
.community-tabs .community-tab.active::after {
    content: ""; position: absolute; border-radius: 999px; mix-blend-mode: multiply; z-index: -1;
    background: var(--cl, var(--type-book));
}
.search-type-toggle .search-type-btn.active::before,
.stats-filter-tabs .stats-filter-tab.active::before,
.community-tabs .community-tab.active::before { inset: -1px; }
.search-type-toggle .search-type-btn.active::after,
.stats-filter-tabs .stats-filter-tab.active::after,
.community-tabs .community-tab.active::after { left: 5px; top: 2px; right: -5px; bottom: -3px; background: var(--cl2, var(--cl)); }

/* per-type colors */
.search-type-btn[data-search-type="book"].active  { --cl: var(--type-book); }
.search-type-btn[data-search-type="comic"].active { --cl: var(--type-comic); }
.search-type-btn[data-search-type="movie"].active,
.search-type-btn[data-search-type="tv"].active     { --cl: var(--type-screen); }
.search-type-btn[data-search-type="game"].active   { --cl: var(--type-game); }
.search-type-btn[data-search-type="audiobook"].active   { --cl: var(--type-audiobook); }
.search-type-btn[data-search-type="scan"].active   { --cl: var(--type-book); --cl2: var(--type-comic); }
.stats-filter-tab[data-filter="books"].active   { --cl: var(--type-book); }
.stats-filter-tab[data-filter="audio"].active   { --cl: var(--type-audiobook); }
.stats-filter-tab[data-filter="comics"].active  { --cl: var(--type-comic); }
.stats-filter-tab[data-filter="screen"].active  { --cl: var(--type-screen); }
.stats-filter-tab[data-filter="games"].active   { --cl: var(--type-game); }
.stats-filter-tab[data-filter="all"].active,
.stats-filter-tab[data-filter="fiction"].active,
.stats-filter-tab[data-filter="nonfiction"].active { --cl: var(--type-book); --cl2: var(--type-comic); }
/* Community tabs are about PEOPLE, so they take the lavender/butter pair rather
   than the book/comic pastels — the same reasoning that moved the profile-overlap
   Venn off --type-comic and --type-screen. Mint and blue on Feed and Friends
   read as a media-type split, which is not what these tabs divide.
   Needs the #view-community prefix to beat the id-scoped rule further down. */
.community-tab.active,
#view-community .community-tabs .community-tab.active {
    --cl:  var(--overlap-mine);
    --cl2: var(--overlap-theirs);
}

/* Three uppercase mono labels are wider than two, and .community-tabs has no
   wrap and no overflow rule — on a narrow phone the row would clip. */
.community-tabs { flex-wrap: wrap; row-gap: 8px; }

/* Pending count inside the tab, same treatment as the profile-overlap segments. */
.community-tab-n {
    font-family: var(--font-mono);
    font-size: 11px;
    margin-left: 7px;
    opacity: 0.75;
}

/* ── Recommendations inbox ─────────────────────────────────────────────────── */
.community-recs-list { display: flex; flex-direction: column; gap: 10px; }

.rec-card {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    cursor: pointer;
}
/* Acted-on rows stay in the list, so pending ones need to lead visually.
   Social rows are deliberately exempt: they never ask for an action, so
   "already seen" must not borrow the styling that means "already dealt with".
   A like from last week is still worth reading at full strength — and since
   the watermark is stamped on every visit, dimming seen rows would fade the
   whole social half permanently after the first look. */
.rec-card:not(.social-card):not(.rec-card-pending) { opacity: 0.62; }
.rec-card-pending,
.social-card-new { border-color: var(--border-strong); }

.rec-card-cover {
    width: 44px; height: 64px; flex-shrink: 0;
    object-fit: cover; border-radius: 3px; background: var(--border);
}
.rec-card-info  { flex: 1; min-width: 0; }
.rec-card-title { font-weight: 600; font-size: 0.9rem; }
.rec-card-sub   { font-size: 0.78rem; color: var(--text-3); margin-top: 1px; }
.rec-card-from  {
    font-family: var(--font-mono);
    font-size: 0.68rem;
    letter-spacing: 0.04em;
    color: var(--text-3);
    margin-top: 4px;
}
.rec-card-note  {
    font-size: 0.82rem;
    color: var(--text-2);
    margin: 6px 0 0;
    white-space: pre-wrap;
}
.rec-card-actions { display: flex; flex-direction: column; gap: 6px; flex-shrink: 0; }
/* Add is ink; Dismiss is its outlined counterpart, so the pair reads as primary
   and secondary rather than two filled pills of different families. Scoped
   rather than applied to .btn-secondary globally, which is used app-wide. */
.rec-card-actions .btn-secondary {
    background: transparent;
    border-color: var(--border-strong);
    color: var(--text-2);
    font-family: var(--font-mono);
    font-size: 0.64rem;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 6px 13px;
}
.rec-card-actions .btn-secondary:hover:not(:disabled) {
    background: transparent;
    border-color: var(--text);
    color: var(--text);
}
.rec-card-state {
    font-family: var(--font-mono);
    font-size: 0.66rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-3);
    flex-shrink: 0;
    align-self: center;
}

/* ── "Recommended by" on the item page ─────────────────────────────────────── */
.item-recommended-list { display: flex; flex-direction: column; gap: 12px; }
.rec-by-item {
    padding: 10px 12px;
    border-radius: var(--radius);
    background: var(--surface-alt);
}
.rec-by-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.rec-by-name { font-weight: 600; font-size: 0.85rem; cursor: pointer; }
.rec-by-name:hover { color: var(--accent); }
.rec-by-stars { font-size: 0.78rem; }
.rec-by-date {
    margin-left: auto;
    font-family: var(--font-mono);
    font-size: 0.68rem;
    color: var(--text-3);
    white-space: nowrap;
}
.rec-by-note {
    font-size: 0.85rem;
    color: var(--text-2);
    margin: 6px 0 0;
    white-space: pre-wrap;
}
.rec-by-review {
    font-size: 0.82rem;
    color: var(--text-2);
    margin: 6px 0 0;
    padding-top: 6px;
    border-top: 1px solid var(--border);
    white-space: pre-wrap;
}
.rec-by-spoiler { color: var(--text-3); font-style: italic; }

/* Send is a .btn-primary, which the rebuild only restyled per-screen — so it
   would otherwise sit in the sheet as a sans-serif pill next to the mono Add on
   the cards it produces. Matches how U3 scoped the Search button. */
#recommend-send {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

/* The picker reuses .friend-row; disabled rows are already-sent. */
#recommend-picker-list .recommend-pick-row {
    width: 100%;
    border: none;
    background: none;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}
#recommend-picker-list .recommend-pick-row:disabled { opacity: 0.5; cursor: default; }
/* Why a row is closed off — their shelf status, or that you already sent it. */
.recommend-pick-why {
    font-family: var(--font-mono);
    font-size: 0.64rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-3);
    white-space: nowrap;
    margin-left: auto;
    padding-right: 10px;
}
/* Selected, not yet sent — distinct from the dimmed already-sent rows above. */
#recommend-picker-list .recommend-pick-row.picked { background: var(--surface-alt); }
#recommend-picker-list .recommend-pick-row.picked .friend-name { font-weight: 700; }
#recommend-picker-list .recommend-pick-row.picked .list-pick-check { color: var(--success); }

/* ---- Search result cards: typeColor corner dot (driven by active search tab) ---- */
#view-search:has(.search-type-btn[data-search-type="book"].active)  { --st: var(--type-book); }
#view-search:has(.search-type-btn[data-search-type="comic"].active) { --st: var(--type-comic); }
#view-search:has(.search-type-btn[data-search-type="movie"].active),
#view-search:has(.search-type-btn[data-search-type="tv"].active)    { --st: var(--type-screen); }
#view-search:has(.search-type-btn[data-search-type="game"].active)  { --st: var(--type-game); }
#view-search:has(.search-type-btn[data-search-type="audiobook"].active)  { --st: var(--type-audiobook); }
#view-search .search-result-cover { position: relative; overflow: visible; }
#view-search .search-result-cover::after {
    content: ""; position: absolute; right: -6px; top: -6px; width: 16px; height: 16px;
    border-radius: 50%; background: var(--st, var(--type-book));
    box-shadow: 0 1px 3px rgba(22,35,42,0.15); z-index: 1;
}
#view-search .search-result-cover:empty,
#view-search .search-result-cover:not(:has(img)) { background: color-mix(in srgb, var(--st, var(--type-book)) 55%, #fff); }

/* ---- Community feed: avatar + per-media type accent (design) ---- */
#view-community .feed-card { position: relative; align-items: flex-start; }
#view-community .feed-avatar {
    position: relative; flex: 0 0 auto; width: 36px; height: 36px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-family: var(--font-mono); font-size: 12px; font-weight: 600; color: var(--text);
    background: color-mix(in srgb, var(--tc, var(--type-book)) 60%, #fff);
}
#view-community .feed-cover { position: relative; }
#view-community .feed-cover::after {
    content: ""; position: absolute; right: -5px; top: -5px; width: 14px; height: 14px;
    border-radius: 50%; background: var(--tc, var(--type-book)); box-shadow: 0 1px 3px rgba(22,35,42,0.18);
}
#view-community .feed-review-body {
    border-left: 3px solid var(--tc, var(--type-book));
    padding-left: 11px; margin-left: 1px;
}

/* ---- Community FEED/FRIENDS tabs: overlapping-pastel active (override id-specific navy) ---- */
#view-community .community-tabs .community-tab.active { background: transparent; color: var(--text); border-color: transparent; --cl: var(--overlap-mine); --cl2: var(--overlap-theirs); }
#view-community .community-tabs .community-tab.active::before,
#view-community .community-tabs .community-tab.active::after {
    content: ""; position: absolute; border-radius: 999px; mix-blend-mode: multiply; z-index: -1; background: var(--cl);
}
#view-community .community-tabs .community-tab.active::before { inset: -1px; }
#view-community .community-tabs .community-tab.active::after { left: 5px; top: 2px; right: -5px; bottom: -3px; background: var(--cl2); }

/* ============================================================
   DESIGN REBUILD — Profile screen (match mockup)
   ============================================================ */
#view-profile .profile-hero { display: flex; align-items: center; gap: 28px; row-gap: 24px; flex-wrap: wrap; }
#view-profile .profile-venn { margin-left: auto; }
#view-profile .profile-username-tag { font-family: var(--font-mono); font-size: 0.78rem; color: var(--text-2); }

/* Avatar: pastel circles behind, the user's photo (or initials) on top */
#view-profile .u5-hero-avatar { overflow: visible; }
#view-profile .u5-hero-avatar::before,
#view-profile .u5-hero-avatar::after { content: none !important; }
#view-profile .profile-avatar {
    position: relative; isolation: isolate; width: 88px; height: 88px;
    border-radius: 50%; background: var(--type-comic); overflow: visible;
}
#view-profile .profile-avatar::before,
#view-profile .profile-avatar::after {
    content: ""; position: absolute; border-radius: 50%; mix-blend-mode: multiply; z-index: -1;
}
#view-profile .profile-avatar::before { width: 84px; height: 84px; left: -13px; top: 10px; background: var(--type-book); }
#view-profile .profile-avatar::after  { width: 72px; height: 72px; right: -11px; top: -8px; background: var(--type-screen); }
#view-profile .profile-avatar img {
    position: relative; z-index: 1; width: 88px; height: 88px; border-radius: 50%;
    object-fit: cover; display: block; box-shadow: 0 2px 10px rgba(22,35,42,0.18);
}
#view-profile .profile-avatar .profile-avatar-initials {
    position: relative; z-index: 1; width: 88px; height: 88px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-family: var(--font-mono); font-size: 1.5rem; font-weight: 600; color: var(--text); background: transparent;
}

/* Reading-stat tiles: big display number + mono label */
#view-profile .profile-stat-card { padding: 18px 20px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); text-align: left; }
#view-profile .profile-stat-card .stat-value { font-family: var(--font-display); font-size: 2rem; font-weight: 800; line-height: 1; color: var(--text); }
#view-profile .profile-stat-card .stat-label { display: block; margin-top: 8px; font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-2); }

/* FULL STATS pill — layered-pastel chip, matching the sidebar/nav active state */
#view-profile .full-stats-btn {
    position: relative; isolation: isolate; display: inline-flex; margin-top: 14px;
    padding: 8px 18px; border: none; border-radius: 8px; cursor: pointer;
    background: var(--type-book);
    font-family: var(--font-mono); font-size: 0.7rem; font-weight: 600; letter-spacing: 0.08em; color: var(--text);
    transition: transform var(--transition);
}
#view-profile .full-stats-btn::before,
#view-profile .full-stats-btn::after { content: ""; position: absolute; inset: 0; border-radius: 8px; mix-blend-mode: multiply; z-index: 0; }
#view-profile .full-stats-btn::before { background: var(--type-comic); transform: translate(4px, 3px); }
#view-profile .full-stats-btn::after  { background: var(--type-screen); transform: translate(8px, 5px); }
#view-profile .full-stats-btn > span { position: relative; z-index: 1; }
#view-profile .full-stats-btn:hover { transform: translateY(-2px); }

/* Stacked-spine list cards */
#view-profile .list-card { display: flex; align-items: center; gap: 16px; padding: 14px 18px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); }
#view-profile .list-spines { position: relative; width: 56px; height: 44px; flex: 0 0 auto; }
#view-profile .list-spine { position: absolute; width: 28px; height: 40px; border-radius: 3px; }
#view-profile .list-spine:nth-child(1) { left: 0;  top: 2px; }
#view-profile .list-spine:nth-child(2) { left: 14px; top: 0;  box-shadow: -2px 0 4px rgba(22,35,42,0.2); }
#view-profile .list-spine:nth-child(3) { left: 28px; top: 4px; box-shadow: -2px 0 4px rgba(22,35,42,0.2); }
#view-profile .list-card-info { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
#view-profile .list-card-name { font-family: var(--font-display); font-size: 0.95rem; font-weight: 600; color: var(--text); }
#view-profile .list-card-meta { font-family: var(--font-mono); font-size: 0.66rem; color: var(--text-2); }
#view-profile .list-card-dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }

/* ---- Profile stat tiles: fill width + keep big numbers inside the box ---- */
#view-profile #stats-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
#view-profile .profile-stat-card { min-width: 0; overflow: hidden; }
#view-profile .profile-stat-card .stat-value { font-size: clamp(1.4rem, 2.2vw, 2rem); white-space: nowrap; letter-spacing: -0.02em; }
#view-profile .profile-stat-card .stat-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* stats overview tiles: same guard against overflow */
#overlay-stats .stat-value { white-space: nowrap; letter-spacing: -0.01em; }

/* Full-stats pill sits under the Library tiles */
#view-profile .full-stats-row { margin: 14px 0 0; display: flex; }
#view-profile .full-stats-row .full-stats-btn { margin-top: 0; }

/* ---- Stats: format pills + year slider row ---- */
.stats-controls { display: flex; align-items: center; gap: 16px; row-gap: 12px; flex-wrap: wrap; margin-bottom: 22px; }
.stats-year-slider { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.stats-year-caption { font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.14em; color: var(--text-3); }
.stats-year-label { font-family: var(--font-mono); font-size: 0.78rem; font-weight: 600; color: var(--text); min-width: 58px; text-align: right; }
#stats-year-range { -webkit-appearance: none; appearance: none; width: 160px; height: 4px; border-radius: 999px; background: var(--border-strong); outline: none; cursor: pointer; }
#stats-year-range::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 16px; height: 16px; border-radius: 50%; background: var(--navy); border: 2px solid #fff; box-shadow: 0 1px 3px rgba(22,35,42,0.3); cursor: pointer; }
#stats-year-range::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: var(--navy); border: 2px solid #fff; box-shadow: 0 1px 3px rgba(22,35,42,0.3); cursor: pointer; }
#stats-year-range::-moz-range-track { height: 4px; border-radius: 999px; background: var(--border-strong); }
@media (max-width: 640px) { .stats-year-slider { margin-left: 0; width: 100%; } #stats-year-range { flex: 1; width: auto; } }

/* ---- Stats: media-type stacked bars + ranked creators ---- */
/* Ranked rows across all three bar lists, not just creators */
.u6-bar-list .creator-row { gap: 12px; }
.u6-bar-list .creator-rank {
    font-family: var(--font-mono); font-size: 0.66rem; color: var(--text-3);
    width: 20px; flex: 0 0 auto; text-align: right;
}

/* ---- Stats overview: dot matrix ----------------------------------------
   One dot per item (per `scale` items once the library is huge), inked in the
   media-type pastel with the app's signature multiply blend. `--dot` and
   `--dot-gap` are set inline by _openStatsOverlay from the in-scope total. */
#stats-ol-summary .empty-state { padding: 22px 0; text-align: left; }

.dot-matrix { --dot: 11px; --dot-gap: 7px; display: flex; flex-direction: column; gap: 26px; }

.dot-matrix-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.dot-matrix-total {
    font-family: var(--font-display); font-size: 3.1rem; font-weight: 800;
    line-height: 0.9; letter-spacing: -0.03em; color: var(--text);
}
.dot-matrix-cap {
    font-family: var(--font-mono); font-size: 0.66rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.16em; color: var(--text-2);
}
.dot-matrix-scale {
    margin-left: auto; font-family: var(--font-mono); font-size: 0.56rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.14em; color: var(--text-3); white-space: nowrap;
}

.dot-groups { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 30px 34px; }
.dot-group { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; min-width: 0; max-width: 100%; }
.dot-block {
    display: grid; grid-template-columns: repeat(auto-fill, var(--dot));
    gap: var(--dot-gap); max-width: 100%;
}
.dot-cell {
    display: block; width: var(--dot); height: var(--dot); border-radius: 50%;
    background: var(--tc); mix-blend-mode: multiply;
}
.dot-group-label {
    font-family: var(--font-mono); font-size: 0.62rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-2);
}
.dot-group-count {
    font-family: var(--font-display); font-size: 1.6rem; font-weight: 800;
    line-height: 1; letter-spacing: -0.02em; color: var(--text);
}

/* Status columns as a kanban board: a lane panel per reading stage, holding
   one card per media type present in that stage. Own class names on purpose:
   .stat-card & friends stay reserved for the pages/reviews/profile/community
   grids, which still use the shared tile styling. */
.ol-board-wrap { border-top: 1px solid var(--border); padding-top: 22px; }
.ol-board { display: flex; align-items: flex-start; gap: 12px; }
.ol-col {
    flex: 1 1 0; min-width: 158px;
    background: var(--lane); border-radius: 12px; padding: 12px 11px 13px;
}
.ol-col-head {
    display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
    margin-bottom: 10px; padding-bottom: 9px; border-bottom: 1px solid var(--lane-line);
}
.ol-col-label {
    font-family: var(--font-mono); font-size: 0.6rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-2);
}
.ol-col-total {
    font-family: var(--font-display); font-size: 19px; font-weight: 800;
    line-height: 1; color: var(--text); font-variant-numeric: tabular-nums;
}
.ol-col-cards { display: flex; flex-direction: column; gap: 7px; }
/* Cards sit on the grey lane, so they stay opaque — multiply here would mute
   the pastels into the panel. The dot matrix above still multiplies on white. */
.ol-card {
    display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
    background: var(--tc); border-radius: 9px; padding: 9px 11px;
}
.ol-card-type {
    font-family: var(--font-mono); font-size: 0.53rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.08em; color: #33454E;
    min-width: 0; overflow-wrap: anywhere;
}
.ol-card-count {
    font-family: var(--font-display); font-size: 15px; font-weight: 800;
    line-height: 1; color: var(--text); font-variant-numeric: tabular-nums;
}

@media (max-width: 720px) {
    /* Scroll the board sideways rather than crushing five columns; only this
       container scrolls, never the page. Deliberately NOT bled out to the
       viewport edges with negative margins + matching padding: scroll-snap
       ignores the start padding, so the container loads already scrolled past
       it and the first column ends up flush to the screen edge instead of
       aligned with the heading. Staying inside the section's own padding keeps
       that alignment for free. */
    .ol-board-wrap { overflow-x: auto; scroll-snap-type: x proximity; padding-bottom: 6px; }
    .ol-col { flex: 0 0 158px; scroll-snap-align: start; }
}

@media (max-width: 640px) {
    .dot-matrix { gap: 22px; }
    .dot-groups { gap: 24px 26px; }
    .dot-matrix-total { font-size: 2.5rem; }
    .dot-matrix-scale { margin-left: 0; flex-basis: 100%; }
}

/* Two-column stats on desktop. Below 1000px this never applies, so phones and
   tablets keep the single column exactly as before.

   Sections pair off automatically, which matters because most of them hide
   themselves when empty — grid auto-flow just re-pairs whatever is left rather
   than leaving a hole. Three span the full width: the heading/controls, the
   Overview (its kanban board is five 158px columns and would be forced into a
   scroll at half width), and Reviews, whose histogram wants the room. */
@media (min-width: 1000px) {
    .u6-stats-body {
        display: grid;
        grid-template-columns: 1fr 1fr;
        column-gap: 40px;
        align-items: start;
    }
    .u6-stats-body > .u6-stats-heading,
    .u6-stats-body > .stats-controls,
    .u6-stats-body > #stats-overview-section,
    .u6-stats-body > #stats-reviews-section,
    /* set by _balanceStatsColumns on a section left alone on its row */
    .u6-stats-body > .stats-ol-section.stats-span-2 {
        grid-column: 1 / -1;
    }
    /* Row rhythm comes from the section's own margin, so a section that ends
       up alone on a row doesn't leave a doubled gap under it. */
    .u6-stats-body > .stats-ol-section { margin-bottom: 26px; }
}

/* Names the title behind a superlative tile (Longest Book / Longest Film).
   Clamped to two lines so one long name can't stretch the row's tiles. */
.stat-sub {
    font-size: 0.72rem; line-height: 1.3; color: var(--text-2); margin-top: -2px;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}

/* Caveat line under a stats grid — e.g. how many books lacked a page count */
.stats-note {
    font-family: var(--font-mono); font-size: 0.6rem; letter-spacing: 0.04em;
    color: var(--text-3); margin: 10px 0 0;
}

/* ---- Stats: Media Mix donut ---- */
.stats-mediamix { display: flex; align-items: center; gap: 26px; padding: 8px 0 4px; flex-wrap: wrap; }
.mix-donut { position: relative; width: 170px; height: 170px; border-radius: 50%; flex: 0 0 auto; }
.mix-donut-hole { position: absolute; left: 50px; top: 50px; width: 70px; height: 70px; border-radius: 50%; background: var(--bg); display: flex; flex-direction: column; align-items: center; justify-content: center; }
.mix-donut-total { font-family: var(--font-display); font-size: 1.25rem; font-weight: 800; line-height: 1; color: var(--text); }
.mix-donut-cap { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.1em; color: var(--text-3); margin-top: 2px; }
.mix-legend { display: flex; flex-direction: column; gap: 8px; }
.mix-leg { display: flex; align-items: center; gap: 10px; padding: 5px 8px; border-radius: 8px; cursor: pointer; font-family: var(--font-mono); font-size: 0.72rem; color: var(--text-2); transition: background 140ms ease; }
.mix-leg:hover { background: var(--surface-alt); }
.mix-leg .key-dot { width: 12px; height: 12px; border-radius: 50%; flex: 0 0 auto; }
.mix-leg-label { width: 96px; }
.mix-leg-count { font-weight: 600; color: var(--text); }
.mix-leg-pct { color: var(--text-3); }

/* ---- Stats: stacked type-segment bars + click-to-drill ---- */
.stat-bar { display: flex; flex-direction: column-reverse; overflow: hidden; border-radius: 4px 4px 0 0; }
.stat-bar-seg { display: block; width: 100%; min-height: 2px; }
.stat-bar-clickable { cursor: pointer; }
.stat-bar-clickable:hover .stat-bar { filter: brightness(0.96); }
.stat-bar-clickable:hover .stat-bar-label { color: var(--text); }

.stat-drill:empty { display: none; }
.stat-drill { margin: 12px 0 4px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); padding: 14px 18px; max-width: 760px; }
.stat-drill-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 2px; }
.stat-drill-title { font-family: var(--font-mono); font-size: 0.7rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text); }
.stat-drill-clear { margin-left: auto; font-family: var(--font-mono); font-size: 0.64rem; color: var(--text-2); cursor: pointer; letter-spacing: 0.05em; }
.stat-drill-clear:hover { color: var(--text); }
.stat-drill-row { display: flex; align-items: center; gap: 12px; padding: 8px 0; border-top: 1px solid var(--border); cursor: pointer; }
.stat-drill-dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.stat-drill-name { font-size: 0.9rem; font-weight: 600; color: var(--text); }
.stat-drill-sub { font-family: var(--font-mono); font-size: 0.64rem; color: var(--text-3); margin-left: auto; }
.stat-drill-row:hover .stat-drill-name { color: var(--accent); }

/* Ratings histogram: bars stacked by media type + ½★…★★★★★ axis */
/* Stacked-by-media-type bars. Was scoped to the stats histogram; it's the
   house style for this chart, so it hangs off a class both users opt into. */
.hist-stacked .review-histogram-bar:not(.bar-empty) {
    display: flex;
    flex-direction: column-reverse;
    gap: 1px;
    background: transparent;
    mix-blend-mode: normal;
    overflow: hidden;
}
.hist-stacked .review-histogram-seg { display: block; width: 100%; min-height: 2px; border-radius: 2px; }
.review-histogram-axis { display: flex; justify-content: space-between; padding: 6px 4px 0; font-family: var(--font-mono); font-size: 0.6rem; color: var(--border-strong); max-width: 760px; }

/* Stacked bar segments read as distinct pieces (gap + rounding), like the mockup */
.stat-bar-chart .stat-bar { gap: 2px; overflow: visible; background: transparent; border-radius: 0; }
.stat-bar-chart .stat-bar-empty { background: var(--border); border-radius: 3px; }
.stat-bar-seg { border-radius: 3px; min-height: 3px; }

/* ---- Library: series stacked-cover tile (design) ---- */
.series-tile { width: 204px; }
.series-tile .tile-cover-stacked { position: relative; width: 204px; height: 258px; }
.series-tile .tile-stack { position: absolute; top: 8px; width: 172px; height: 250px; border-radius: 7px; background: var(--tc); box-shadow: 0 8px 20px rgba(22,35,42,0.18); }
.series-tile .tile-stack-2 { left: 22px; opacity: 0.4; transform: rotate(2deg); }
.series-tile .tile-stack-1 { left: 11px; opacity: 0.65; transform: rotate(1deg); }
.series-tile .tile-cover-main { position: absolute; left: 0; top: 8px; z-index: 1; width: 172px; height: 250px; }
.series-tile .tile-cover-main .tile-cover-img,
.series-tile .tile-cover-main .tile-cover-blank { width: 172px; height: 250px; }
.series-tile .tile-dot { z-index: 0; }
.series-tile .tile-series-badge { position: absolute; right: 2px; bottom: -6px; z-index: 3; padding: 3px 9px; border-radius: 999px; background: var(--navy); color: #fff; font-family: var(--font-mono); font-size: 10px; font-weight: 600; }

/* ============================================================
   Cosmetic fidelity batch
   ============================================================ */
/* Item breadcrumb: "← Library / • TYPE" */
.back-btn .bc-type { display: inline-flex; align-items: center; gap: 6px; margin-left: 4px; font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.06em; color: var(--text-3); }
.back-btn .bc-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; }

/* Sidebar logo — ghost feet */
@media (min-width: 900px) {
    .ps-ghost-mint::after, .ps-ghost-blue::after {
        content: ""; position: absolute; left: 3px; bottom: -2px; width: 5px; height: 5px;
        border-radius: 0 0 3px 3px; mix-blend-mode: multiply;
    }
    .ps-ghost-mint::after { background: #BFE6D2; box-shadow: 8px 0 0 #BFE6D2, 16px 0 0 #BFE6D2; }
    .ps-ghost-blue::after { background: #BFDCF2; box-shadow: 8px 0 0 #BFDCF2, 16px 0 0 #BFDCF2; }
}

/* Community feed avatar: overlapping pastel circles + initials on top */
#view-community .feed-avatar { background: transparent; position: relative; isolation: isolate; overflow: visible; }
#view-community .feed-avatar::before { content: ""; position: absolute; inset: 0; border-radius: 50%; background: var(--type-comic); mix-blend-mode: multiply; z-index: -1; }
#view-community .feed-avatar::after { content: ""; position: absolute; width: 26px; height: 26px; left: -5px; top: -4px; border-radius: 50%; background: var(--type-screen); mix-blend-mode: multiply; z-index: -1; }
/* Profile photo fills the circle; drop the decorative blobs behind a real photo */
#view-community .feed-avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; display: block; }
#view-community .feed-avatar:has(img) { background: transparent; }
#view-community .feed-avatar:has(img)::before,
#view-community .feed-avatar:has(img)::after { content: none; }

/* Profile "In Progress" cards: typeColor corner dot */
#view-profile .cr-card-cover-wrap { position: relative; display: block; }
/* Matched to .tile-dot on the Library shelves: same 76px circle, same offset,
   and behind the cover rather than on top of it. At z-index 2 it painted over
   the artwork — with multiply that reads as a stain on the corner of the cover
   rather than as something the cover is sitting on. */
#view-profile .cr-card-dot {
    position: absolute;
    left: -12px;
    bottom: -12px;
    z-index: 0;
    width: 76px;
    height: 76px;
    border-radius: 50%;
    background: var(--tc, var(--type-book));
    mix-blend-mode: multiply;
}
#view-profile .cr-card-cover { position: relative; z-index: 1; }

/* Toast: pill with the mint/blue blob (icon still conveys success/error) */
.toast { border-radius: var(--radius-pill) !important; border-left: none !important; position: relative; isolation: isolate; overflow: visible; }
.toast::before { content: ""; position: absolute; inset: 0; border-radius: var(--radius-pill); background: var(--type-book); mix-blend-mode: multiply; z-index: -1; }
.toast::after { content: ""; position: absolute; left: 6px; top: 3px; right: -3px; bottom: -3px; border-radius: var(--radius-pill); background: var(--type-comic); mix-blend-mode: multiply; opacity: 0.7; z-index: -1; }

/* Shelf "show all" toggle + mono empty state */
.section-heading-arrow { margin-left: auto; font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.08em; color: var(--text-2); text-transform: uppercase; }
.empty-state { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.04em; color: var(--text-3); text-align: center; padding: 40px 0; }

/* ---- Item detail: in-library status as pill chips (overlapping-blob active) ---- */
#overlay-item .shelf-status-chips { display: flex; gap: 8px; flex-wrap: wrap; }
#overlay-item .shelf-status-chip {
    position: relative; isolation: isolate; overflow: visible;
    padding: 8px 16px; border-radius: 999px; border: 1px solid var(--border-strong);
    background: transparent; color: var(--text-2); cursor: pointer;
    font-family: var(--font-mono); font-size: 0.72rem;
    transition: color 140ms ease, border-color 140ms ease;
}
#overlay-item .shelf-status-chip:hover:not(.active) { border-color: var(--text); color: var(--text); }
#overlay-item .shelf-status-chip.active { border-color: transparent; color: var(--text); font-weight: 600; }
#overlay-item .shelf-status-chip.active::before,
#overlay-item .shelf-status-chip.active::after {
    content: ""; position: absolute; border-radius: 999px; mix-blend-mode: multiply; z-index: -1;
    background: var(--tc, var(--type-book));
}
#overlay-item .shelf-status-chip.active::before { inset: -1px; }
#overlay-item .shelf-status-chip.active::after { left: 5px; top: 2px; right: -5px; bottom: -4px; }

/* ---- Profile: Ratings | Lists two-column row (design) ---- */
#view-profile .profile-two-col { display: flex; gap: 40px; flex-wrap: wrap; align-items: flex-start; }
#view-profile .profile-two-col > * { flex: 1 1 260px; min-width: 260px; margin-top: 0; }
#view-profile #review-histogram .review-histogram-bar:not(.bar-empty) { background: linear-gradient(to top, var(--type-book), var(--type-comic)); }

/* ---- Games: crop the landscape cover art to portrait, like the library tiles ---- */
#overlay-item[data-media-type="game"] .u2-cover-img {
    aspect-ratio: 2 / 3;
    height: auto;
    object-fit: cover;
    object-position: center;
}

/* ---- Roomier shelves now that tiles are larger ---- */
/* Shelf rhythm. Three earlier `.library-section` rules each set their own
   margins, which stacked with the scroll row's bottom padding and the flex
   gap into ~96px of dead space after a shelf against only 32px above it —
   sections read as drifting apart rather than evenly spaced. Collapse the
   separation into ONE value: no vertical margin on the section, and the
   space between shelves comes from the scroll row's bottom padding (which
   also has to clear the tile shadow) plus the section's bottom margin. */
.section-scroll-row { gap: 28px; padding: 18px 2px 16px; }
.library-section { margin-top: 0; margin-bottom: 8px; }
.section-heading { padding: 8px 0 14px; }
.section-heading-title { font-size: 13px; }

@media (max-width: 720px) {
    .section-scroll-row { padding: 10px 2px 12px; }
    .library-section { margin-top: 0; margin-bottom: 6px; }
}

/* ---- Fix: old `.type-btn.active::before{opacity:0}` (dot hider) was killing the
   first blob layer of the overlapping-pill active state. Restore both layers. ---- */
.lib-type-filter .type-btn.active::before,
.lib-type-filter .type-btn.active::after,
.search-type-toggle .search-type-btn.active::before,
.search-type-toggle .search-type-btn.active::after {
    opacity: 1;
}
/* Make the overlap read clearly: base layer + a more offset second layer */
.lib-type-filter .type-btn.active::after,
.search-type-toggle .search-type-btn.active::after {
    left: 8px; top: 3px; right: -8px; bottom: -5px;
    background: var(--cl2, var(--cl));
}

/* ============================================================
   Filter chips: faithful 3-blob active state (copied from the design)
   ============================================================ */
.lib-type-filter .type-btn { position: relative; overflow: visible; background: transparent; }
.lib-type-filter .type-btn.active { background: transparent; border-color: transparent; color: var(--text); font-weight: 600; }
/* remove the old flat fill + 2-pseudo blob attempt */
.lib-type-filter .type-btn.active::before,
.lib-type-filter .type-btn.active::after { content: none; }
/* three offset multiply blobs, exactly like the mockup */
.lib-type-filter .type-btn .chip-fx { display: none; }
.lib-type-filter .type-btn.active .chip-fx { display: block; position: absolute; inset: 0; pointer-events: none; }
.lib-type-filter .type-btn.active .chip-fx i { position: absolute; border-radius: 999px; mix-blend-mode: multiply; }
.lib-type-filter .type-btn.active .chip-fx i:nth-child(1) { inset: -1px; background: var(--l1, var(--type-book)); }
.lib-type-filter .type-btn.active .chip-fx i:nth-child(2) { left: 4px; top: 1px; right: -4px; bottom: -3px; background: var(--l2, var(--type-book)); }
.lib-type-filter .type-btn.active .chip-fx i:nth-child(3) { left: 9px; top: 3px; right: -7px; bottom: -5px; background: var(--l3, var(--type-book)); }
.lib-type-filter .type-btn .chip-label,
.lib-type-filter .type-btn .chip-dot { position: relative; }
.lib-type-filter .type-btn[data-type="all"].active   { --l1: var(--type-book);   --l2: var(--type-comic);  --l3: var(--type-screen); }
.lib-type-filter .type-btn[data-type="book"].active  { --l1: var(--type-book);   --l2: var(--type-book);   --l3: transparent; }
.lib-type-filter .type-btn[data-type="comic"].active { --l1: var(--type-comic);  --l2: var(--type-comic);  --l3: transparent; }
.lib-type-filter .type-btn[data-type="movie"].active,
.lib-type-filter .type-btn[data-type="tv"].active    { --l1: var(--type-screen); --l2: var(--type-screen); --l3: transparent; }
.lib-type-filter .type-btn[data-type="game"].active  { --l1: var(--type-game);   --l2: var(--type-game);   --l3: transparent; }
.lib-type-filter .type-btn[data-type="audiobook"].active  { --l1: var(--type-audiobook);   --l2: var(--type-audiobook);   --l3: transparent; }

/* ---- Search type pills: bring to full parity with the library filter pills.
   The search toggle never got the 3-blob chip-fx treatment — it still carried
   an old solid pastel fill + a 2-pseudo offset blob (the muddy look). Neutralise
   both and render the same clean 3-<i> overlapping-pastel blobs as the library. */
.search-type-toggle .search-type-btn {
    isolation: isolate;
    overflow: visible;
    gap: 7px;
}
/* kill the legacy single-dot pseudo, the solid active fill, and the 2-pseudo blobs */
.search-type-toggle .search-type-btn::before { content: none; }
.search-type-toggle .search-type-btn.active,
.search-type-toggle .search-type-btn[data-search-type].active {
    background: transparent;
    color: var(--text);
    font-weight: 600;
    border-color: transparent;
    box-shadow: none;
}
.search-type-toggle .search-type-btn.active::before,
.search-type-toggle .search-type-btn.active::after { content: none; }

.search-type-toggle .search-type-btn .chip-label { position: relative; z-index: 1; }
.search-type-toggle .search-type-btn .chip-dot {
    position: relative; z-index: 1; width: 8px; height: 8px;
    border-radius: 50%; flex: 0 0 auto;
}
.search-type-toggle .search-type-btn[data-search-type="book"]  .chip-dot { background: var(--type-book); }
.search-type-toggle .search-type-btn[data-search-type="comic"] .chip-dot { background: var(--type-comic); }
.search-type-toggle .search-type-btn[data-search-type="movie"] .chip-dot,
.search-type-toggle .search-type-btn[data-search-type="tv"]    .chip-dot { background: var(--type-screen); }
.search-type-toggle .search-type-btn[data-search-type="game"]  .chip-dot { background: var(--type-game); }
.search-type-toggle .search-type-btn[data-search-type="audiobook"]  .chip-dot { background: var(--type-audiobook); }

.search-type-toggle .search-type-btn .chip-fx { display: none; }
.search-type-toggle .search-type-btn.active .chip-fx {
    display: block; position: absolute; inset: 0; pointer-events: none;
}
.search-type-toggle .search-type-btn.active .chip-fx i {
    position: absolute; border-radius: 999px; mix-blend-mode: multiply;
}
.search-type-toggle .search-type-btn.active .chip-fx i:nth-child(1) { inset: -1px; background: var(--l1, var(--type-book)); }
.search-type-toggle .search-type-btn.active .chip-fx i:nth-child(2) { left: 4px; top: 1px; right: -4px; bottom: -3px; background: var(--l2, var(--type-book)); }
.search-type-toggle .search-type-btn.active .chip-fx i:nth-child(3) { left: 9px; top: 3px; right: -7px; bottom: -5px; background: var(--l3, var(--type-book)); }

/* All: the same three-pastel stack the library's All chip uses, so the two
   toggles read as the same control. */
.search-type-toggle .search-type-btn[data-search-type="all"].active   { --l1: var(--type-book);   --l2: var(--type-comic);  --l3: var(--type-screen); }
.search-type-toggle .search-type-btn[data-search-type="book"].active  { --l1: var(--type-book);   --l2: var(--type-book);   --l3: transparent; }
.search-type-toggle .search-type-btn[data-search-type="comic"].active { --l1: var(--type-comic);  --l2: var(--type-comic);  --l3: transparent; }
.search-type-toggle .search-type-btn[data-search-type="movie"].active,
.search-type-toggle .search-type-btn[data-search-type="tv"].active    { --l1: var(--type-screen); --l2: var(--type-screen); --l3: transparent; }
.search-type-toggle .search-type-btn[data-search-type="game"].active  { --l1: var(--type-game);   --l2: var(--type-game);   --l3: transparent; }
.search-type-toggle .search-type-btn[data-search-type="audiobook"].active  { --l1: var(--type-audiobook);   --l2: var(--type-audiobook);   --l3: transparent; }
.search-type-toggle .search-type-btn[data-search-type="scan"].active  { --l1: var(--type-book);   --l2: var(--type-comic);  --l3: var(--type-screen); }

/* ===== Other-user profile: overlap hero + library-style shelves ========== */

.up-overlap {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius-lg); padding: 20px; margin: 22px 0 6px;
}
/* Phone: the Venn sits beside its numbers, everything stacked. */
.up-ov-summary { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }

/* Desktop: summary on the left, shelf on the right. The card used to be one
   left-aligned column — a Venn, a number, then two covers — leaving most of a
   1600px row empty. */
@media (min-width: 900px) {
    .up-overlap {
        display: grid;
        grid-template-columns: minmax(260px, 420px) minmax(0, 1fr);
        gap: 36px;
        align-items: start;
    }
    .up-ov-summary { flex-direction: column; align-items: flex-start; gap: 18px; }
    .up-ov-summary .up-ov-figure { flex: none; width: 100%; }
    .up-segs { margin-top: 0; }
    /* The shelf keeps its own scroll box, so a long run still scrolls rather
       than stretching the card. */
    .up-ov-shelf { min-width: 0; }
}

/* Circles are positioned in px by _renderOverlap; multiply is what makes the
   intersection read as a third colour rather than a stacking order. */
.up-venn { position: relative; flex: 0 0 auto; }
/* Circles/labels are the Library's .venn-c/.venn-n. Only the stacking differs:
   here a number can sit in the intersection, so it has to clear both circles. */
.up-venn .venn-n { z-index: 2; font-size: 13.5px; }

.up-ov-figure { flex: 1; min-width: 190px; }
.up-ov-value {
    font-family: var(--font-display); font-size: 2.6rem; font-weight: 800;
    letter-spacing: -0.03em; line-height: 1; color: var(--text);
}
.up-ov-caption {
    font-family: var(--font-mono); font-size: 0.62rem; font-weight: 600;
    letter-spacing: 0.13em; text-transform: uppercase; color: var(--text-2); margin-top: 6px;
}
.up-ov-track {
    height: 7px; background: var(--border); border-radius: 4px;
    margin-top: 12px; max-width: 260px; overflow: hidden;
}
.up-ov-track i {
    display: block; height: 100%; border-radius: 4px;
    background: linear-gradient(90deg, var(--type-comic), var(--type-screen));
}
.up-ov-note {
    font-family: var(--font-mono); font-size: 0.66rem; color: var(--text-3); margin-top: 8px;
}

.up-segs {
    display: flex; gap: 6px; background: var(--lane); border-radius: var(--radius-pill);
    padding: 4px; margin: 18px 0 0; width: fit-content; max-width: 100%; flex-wrap: wrap;
}
.up-seg {
    border: none; background: transparent; border-radius: var(--radius-pill);
    padding: 7px 15px; font-family: var(--font-display); font-size: 12.5px; font-weight: 600;
    color: var(--text-2); cursor: pointer; white-space: nowrap;
    display: flex; align-items: center; gap: 7px; transition: var(--transition);
}
.up-seg.active { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); }
.up-seg-n { font-family: var(--font-mono); font-size: 11px; opacity: 0.6; }

/* The shelf lives inside a bordered card, so it doesn't need the Library's
   generous bottom padding — that space is the card's own. */
.up-ov-row { padding: 16px 2px 4px; gap: 20px; }
#up-ov-empty { padding: 20px 2px 6px; margin: 0; text-align: left; }

/* Section headings here are labels, not "show all" targets, so they lose the
   Library's pointer + hover affordance. The one real button keeps its own. */
/* .section-heading-arrow already carries the type; a <button> just needs the
   chrome reset. Shared so the Library's arrow can become a real button too. */
button.section-heading-arrow {
    background: none; border: none; padding: 0; cursor: pointer;
}
button.section-heading-arrow:hover { color: var(--accent); }

/* Half the row, and tall enough to read as a chart rather than a strip: at 76px
   the bars were shorter than their own labels. */
#up-review-histogram { margin: 16px 0 4px; height: 180px; }
/* Sits under the histogram, which otherwise left its column half empty. */
.up-hist-note {
    font-family: var(--font-mono); font-size: 0.66rem; color: var(--text-3);
    margin: 10px 0 0; line-height: 1.6;
}
.up-hist-note b { font-family: var(--font-display); font-size: 0.95rem; font-weight: 800; color: var(--text); }
/* Ten half-star columns need a tighter gap than five. */
#up-review-histogram.hist-half { gap: 4px; }

/* Stacked on a phone. On desktop the histogram and the reviews sat side by side
   in the left half of the overlay with the whole right half empty; making them
   an actual two-column grid uses that width and gives the review prose a
   readable measure instead of a hard max-width. */
.up-reviews-body { display: grid; gap: 18px; }
@media (min-width: 900px) {
    .up-reviews-body {
        /* Even halves — the histogram was a 420px sliver next to a 1200px
           block of cards. */
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        gap: 12px 44px;
        align-items: start;
    }
    #up-review-histogram { margin-top: 6px; }
    /* The list set the section's height, not the chart: three cards run 390-460px
       against the chart column's ~220px (180px of bars plus labels and the note),
       so the section stretched and left the chart column a screen of white — the
       taller the reviews, the worse it got. Capped to the chart so both columns
       end together; the rest scrolls, and "show all" still opens the full set.
       A card cut off at the fold is the affordance that there is more. */
    .up-reviews-list {
        max-height: 220px;
        overflow-y: auto;
        scrollbar-gutter: stable;
    }
}
/* Half-star columns carry no label. The span still has to occupy the same box
   as a labelled one, or its bar drops to a different baseline — so give the
   label an explicit line box rather than relying on an empty span's height. */
#up-review-histogram .review-histogram-label {
    line-height: 1.1; height: 1.1em; display: block;
}
/* Above 900px the grid column caps the measure; below it the list is the only
   thing on its row, so it needs its own cap — full-width prose across a wide
   overlay is unreadable, and it also meant a long review never wrapped far
   enough to need "more". */
.up-reviews-list { display: flex; flex-direction: column; gap: 10px; padding-top: 4px; }
@media (max-width: 899px) {
    .up-reviews-list { max-width: 720px; }
}
/* Past ~1250px the single column stops being a column and becomes one very long
   line of prose. Wrapping the cards into tracks fills the row with content
   instead of stretching each line, and keeps the measure readable. */
@media (min-width: 1250px) {
    .up-reviews-list {
        display: grid;
        /* 300, not 330: with a 420px histogram column, 330 left only one
           672px track at 1440 — back to the over-long line this fixes. */
        grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
        gap: 14px;
        /* stretch (the default) so cards in a row share a height — with `start`
           a one-line review sat noticeably short of its neighbours. */
    }
}
/* Side by side they have to read as cards, not as three columns of loose text:
   a real border, room to breathe, and a cover big enough to recognise. */
#overlay-user-profile .up-reviews-list .profile-review-card {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 16px;
    gap: 13px;
    transition: border-color var(--transition);
}
#overlay-user-profile .up-reviews-list .profile-review-card:hover {
    border-color: var(--border-strong);
}
#overlay-user-profile .up-reviews-list .profile-review-card-cover {
    width: 50px; height: 75px;
}
/* Wrap rather than ellipsis — in a narrow track most titles would be cut. */
#overlay-user-profile .up-reviews-list .profile-review-card-title {
    white-space: normal; font-size: 0.88rem; line-height: 1.3; margin-bottom: 3px;
}
/* The clamp itself is .profile-review-card-body's; this view just gets a third
   line and keeps paragraph breaks. .body-open releases it. */
#overlay-user-profile .profile-review-card-body {
    -webkit-line-clamp: 3; white-space: pre-wrap;
}
#overlay-user-profile .body-open .profile-review-card-body {
    display: block; overflow: visible;
}
.up-review-more {
    background: none; border: none; padding: 4px 0 0; cursor: pointer;
    font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--accent);
}

@media (max-width: 720px) {
    .up-overlap { padding: 16px; margin: 16px 0 4px; }
    .up-ov-summary { gap: 18px; }
    .up-ov-value { font-size: 2.1rem; }
    .up-ov-row { gap: 16px; padding: 14px 2px 2px; }
}

/* ── Cover picker ─────────────────────────────────────────────────────────── */

/* Long-press on an image otherwise raises the browser's own "save image"
   callout on iOS and a selection on Android, both of which pre-empt ours. */
#comic-cover-img {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}

.cover-picker-badge {
    position: absolute;
    right: 8px;
    bottom: 8px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 5px 8px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
    color: var(--text);
    background: color-mix(in srgb, var(--bg) 82%, transparent);
    backdrop-filter: blur(6px);
    border: 1px solid var(--border-strong);
    border-radius: 999px;
    cursor: pointer;
    /* .u2-cover-wrap isolates, and the halo blobs sit above the image. */
    z-index: 2;
}
.cover-picker-badge:hover { background: var(--bg); }

.cover-picker-hint {
    margin: 0 0 12px;
    font-size: 13px;
    color: var(--text-dim);
}

.cover-picker-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
    gap: 12px;
}

.cover-option {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 4px;
    background: none;
    border: 2px solid transparent;
    border-radius: 8px;
    cursor: pointer;
    text-align: center;
}
.cover-option img {
    width: 100%;
    aspect-ratio: 2 / 3;
    object-fit: cover;
    border-radius: 6px;
    border: 1px solid var(--border-strong);
    display: block;
}
.cover-option.selected { border-color: var(--accent); }
.cover-option.selected img { border-color: var(--accent); }

.cover-option-pub {
    font-size: 11px;
    color: var(--text-dim);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Key for the library-overlap Venn. Sits under the figure rather than beside
   the plot, whose children are absolutely positioned into a measured box. */
.up-ov-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 8px;
    font-family: var(--font-mono);
    font-size: 10.5px;
    color: var(--text-2);
}
.up-ov-key { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.up-ov-key i {
    width: 11px;
    height: 11px;
    border-radius: 50%;
    flex: 0 0 auto;
}

/* ── Search: All (mixed-type results) ──────────────────────────────────────── */

.search-group + .search-group { margin-top: 22px; }

.search-group-title {
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-2);
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    gap: 8px;
}
/* The section's own tint, as a dot before the label — the same cue the library
   filter chips use, so a group is identifiable without reading it. */
.search-group-title::before {
    content: '';
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--border-strong);
    flex: 0 0 auto;
}
.search-group[data-type="book"]  .search-group-title::before { background: var(--type-book); }
.search-group[data-type="comic"] .search-group-title::before { background: var(--type-comic); }
.search-group[data-type="movie"] .search-group-title::before,
.search-group[data-type="tv"]    .search-group-title::before { background: var(--type-screen); }
.search-group[data-type="game"]  .search-group-title::before { background: var(--type-game); }
.search-group[data-type="audiobook"]  .search-group-title::before { background: var(--type-audiobook); }

/* The cover dot is tinted from the ACTIVE TAB elsewhere, via a --st custom
   property set on #view-search. That can't work once results are mixed, and it
   falls back to --type-book, so under All every dot came out mint.
   Setting --st further down the tree is the fix rather than overriding
   `background`: the rule that paints the dot is #view-search-scoped and would
   win any specificity fight, but a custom property resolves from the nearest
   ancestor that sets it, so the group (or a card carrying its own data-type,
   as the All typeahead does) simply wins. */
.search-group[data-type="book"],
.search-result-card[data-type="book"]  { --st: var(--type-book); }
.search-group[data-type="comic"],
.search-result-card[data-type="comic"] { --st: var(--type-comic); }
.search-group[data-type="movie"],
.search-group[data-type="tv"],
.search-result-card[data-type="movie"],
.search-result-card[data-type="tv"]    { --st: var(--type-screen); }
.search-group[data-type="game"],
.search-result-card[data-type="game"]  { --st: var(--type-game); }
.search-group[data-type="audiobook"],
.search-result-card[data-type="audiobook"]  { --st: var(--type-audiobook); }

/* Library search with no matches: the plain message plus a way out.
   #library-list is a grid in grid-view, so an empty state left to itself
   becomes one ~150px column — the message wraps to a sliver and the button
   overflows its own pill. Both empty states span the full row instead. */
#library-list.grid-view > .empty-state,
#library-list.grid-view > .lib-empty-search { grid-column: 1 / -1; }

.lib-empty-search {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 8px 16px 24px;
    text-align: center;
}
/* #library-list .empty-state sets 60px of vertical padding, and an ID beats a
   class — so this has to carry the id too, or the message floats far from the
   button it belongs with. */
#library-list .lib-empty-search .empty-state { padding: 0 0 4px; }
.lib-search-everywhere {
    max-width: 100%;
    /* A long query must wrap inside the pill rather than spill out of it. */
    white-space: normal;
    height: auto;
    line-height: 1.35;
}

/* Capped sections in the All view. The attribute selector outranks
   .search-result-card's own display, so hidden cards actually stay hidden. */
.search-group .search-result-card[hidden] { display: none; }

.search-group-more {
    display: block;
    width: 100%;
    margin-top: 10px;
}

/* ── iOS: stop the page zooming when a field is focused ────────────────────── */
/* Safari on iOS zooms the page whenever a focused control's text is smaller
   than 16px, which is why tapping the search box shifts the whole layout.
   The usual shortcut — maximum-scale=1 or user-scalable=no on the viewport —
   also disables pinch-zoom for everyone, so the fix belongs here.
   
   Targeted by input capability rather than width: an iPad in landscape reports
   1024px+ and still zooms, while a narrow desktop window never does.
   
   !important is load-bearing here, not laziness. Nearly every control in this
   sheet is sized by an id selector, so nothing short of another id — eighteen
   of them, and a fresh regression each time a field is added — would win.
   This is a device constraint overriding a design size, which is exactly the
   case the escape hatch exists for. Checkboxes, radios and ranges are excluded
   since they render no text. */
@media (hover: none) and (pointer: coarse) {
    input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]),
    textarea,
    select {
        font-size: 16px !important;
    }
}


/* ── Media-type chips: staggered rows on narrow screens ─────────────────────
   Seven chips (Audio joined Books, Comics, Movies, TV, Games and All), which is
   what this section is now derived for. It was written for six, and adding the
   seventh broke every constant in it at once — worth stating plainly, because
   the same thing will happen to the next person who adds an eighth.

   Two shapes only, which is the point of the rewrite:

     655px and up   one row; none of this applies
     below that     a 4 + 3 stagger, second row centred under the first

   The old version had three bands and a forced break after Movies. With a
   seventh chip the leading group no longer ended where that break assumed, so
   400-599 wrapped to THREE rows (All/Books/Audio/Comics, then a lonely Movies,
   then TV+Games) — and 600-654, which used to be the "they all fit" case, now
   showed six chips and an orphaned Games.

   655, not 600, because that is where seven chips actually stop wrapping: the
   row measures 635px against 20px of padding each side. Measured, not guessed.

   The old inset was a fixed 127px on TV, chosen so TV+Games centred under the
   Comics chip above. That is a nicer alignment than centring, and it is why it
   was written that way — but it hard-codes a sum of label widths, so it silently
   became wrong the moment a chip was inserted before it, landing mid-row rather
   than at a row start. It cited vtrap2.js as its guard; no such file was ever
   committed, which is exactly why the breakage went unnoticed. Auto margins give
   up that alignment in exchange for a rule with nothing to re-derive — and the
   offset row is Movies/TV/Games at every width now, so one rule covers it.

   tests/chip-rows.test.mjs is the guard this time, and it exists: it lays the
   real markup out in a real browser at fourteen widths and asserts the shape,
   including that Library and Search still match. `npm test` after touching a
   chip label, this block, or either chip row. */
/* The UA's `[hidden] { display: none }` loses to the author `display: inline-flex`
   / `display: block` rules below on ORIGIN, not specificity — an author rule beats
   a UA rule however weak its selector, so no amount of trimming those selectors
   would let it through. _syncTypeChips's hiding has to be spelled out here to
   take effect at all. */
.lib-type-filter .type-btn[hidden],
.lib-type-filter .chip-row-break[hidden] { display: none; }

.chip-row-break { display: none; }

@media (max-width: 654px) {
    .chip-row-break {
        display: block;
        flex-basis: 100%;
        height: 0;
        margin: 0;
    }
    /* The spacer is zero-height but it is still a flex item, so it takes a line
       of its own and the container's row-gap lands TWICE — once above it and
       once below.

       Halving the gap is the fix rather than a negative margin on the spacer:
       Chromium clamps a flex line's cross size at zero, so margin-top: -10px on
       a zero-height item measurably does nothing. The spacer guarantees exactly
       three lines, hence exactly two gaps, so 5 + 5 lands on the 10px the rest
       of the layout uses. */
    .lib-type-filter,
    .search-type-toggle {
        row-gap: 5px;
    }
}

/* The stagger is a phone effect and only reads as one while the offset is small.
   The autos centre the second row in the CONTAINER, but the first row is
   left-packed at a fixed 347px, so the gap between the two centres grows with
   the viewport: 21px at 430, 133px by 654, where it stops looking staggered and
   starts looking unrelated. Past phone widths the two rows simply left-align,
   which is a plain block and wants no explanation. */
/* Marker classes rather than data-type, because the endpoints of the offset row
   MOVE. These used to name Movies and Games directly, which was fine while all
   seven chips were always present — but the library now hides types you own
   nothing of, and a hidden Games took its margin-right with it, leaving the row
   shoved against the right edge. _syncTypeChips keeps the classes on the first
   and last VISIBLE chip of the second row; they ship in the markup so the very
   first paint is right, and the search row (never hidden) just keeps them. */
@media (max-width: 469px) {
    .lib-type-filter    .chip-offset-start,
    .search-type-toggle .chip-offset-start { margin-left: auto; }
    .lib-type-filter    .chip-offset-end,
    .search-type-toggle .chip-offset-end   { margin-right: auto; }
}

/* Below 390 the four leading chips need 347px against 320 of usable width, so
   row one wraps and the 4 + 3 shape collapses into three ragged rows. Trimming
   10px of horizontal padding from each chip buys back the 40px and holds the
   shape down to 360, the narrowest phone still worth targeting. */
@media (max-width: 389px) {
    .lib-type-filter    .type-btn,
    .search-type-toggle .search-type-btn {
        padding-left: 11px;
        padding-right: 11px;
    }
}
