/* ========================================================= diora — dark radio player theme ========================================================= */ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } :root { --bg: #000; --bg-card: transparent; --bg-alt: transparent; --bg-row: transparent; --bg-row-alt: transparent; --border: #2a2a2a; --accent: #e63946; --accent-hover: #ff4d58; --green: #2ecc71; --yellow: #f1c40f; --font: 'Courier New', Courier, monospace; --radius: 3px; --nav-h: 48px; --bar-h: 72px; /* contrast scheme — default: white on dark */ --fg: #fff; --fg-muted: #fff; --outline: #000; --text: var(--fg); --text-muted: var(--fg); } /* inverted: black on white */ body.bright-bg { --bg: #fff; --bg-card: #f5f5f5; --bg-alt: #f0f0f0; --bg-row: #fafafa; --bg-row-alt: #f5f5f5; --fg: #000; --fg-muted: #000; --outline: #fff; --border: #bbb; } html, body { background: var(--bg); color: var(--fg); font-family: var(--font); font-size: 14px; font-weight: 600; line-height: 1.5; min-height: 100vh; text-shadow: -1px -1px 0 var(--outline), 1px -1px 0 var(--outline), -1px 1px 0 var(--outline), 1px 1px 0 var(--outline); } /* Elements with their own coloured backgrounds — no outline, no override */ .btn-play, .btn-amazon, .btn-lastfm, .btn-danger, .btn-primary, .navbar-brand { text-shadow: none; } /* Accent colour stays red regardless of scheme */ .navbar-brand { color: var(--accent); } .tab-btn.active { color: var(--accent); } a { color: var(--accent); text-decoration: none; } a:hover { color: var(--accent-hover); text-decoration: underline; } /* ========================================================= NAVBAR ========================================================= */ .navbar { position: sticky; top: 0; z-index: 100; display: flex; align-items: center; justify-content: space-between; height: var(--nav-h); padding: 0 1.5rem; background: transparent; border-bottom: 1px solid var(--border); } .navbar-brand { font-size: 1.4rem; font-weight: bold; letter-spacing: 0.05em; color: var(--accent); text-decoration: none; } .navbar-brand:hover { color: var(--accent-hover); text-decoration: none; } .navbar-links { display: flex; align-items: center; gap: 1rem; } .navbar-user { color: var(--text-muted); font-size: 0.85rem; } /* ========================================================= MAIN CONTENT ========================================================= */ .main-content { max-width: 1100px; margin: 0 auto; padding: 1rem 1.5rem calc(var(--bar-h) + 2rem); } /* ========================================================= MESSAGES ========================================================= */ .messages { margin-bottom: 1rem; } .message { padding: 0.6rem 1rem; border-radius: var(--radius); margin-bottom: 0.4rem; background: var(--bg-alt); border-left: 3px solid var(--text-muted); } .message-error { border-color: var(--accent); } .message-success { border-color: var(--green); } .message-warning { border-color: var(--yellow); } /* ========================================================= NOW PLAYING BAR (fixed at bottom) ========================================================= */ .now-playing-bar { position: fixed; bottom: 0; left: 0; right: 0; height: var(--bar-h); background: transparent; border-top: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; padding: 0 1.5rem; z-index: 200; gap: 1rem; } .now-playing-info { display: flex; flex-direction: column; flex: 1; min-width: 0; overflow: hidden; } .now-playing-station { font-size: 0.75rem; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .now-playing-track { font-size: 0.95rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text); } .now-playing-controls { display: flex; align-items: center; gap: 0.75rem; flex-shrink: 0; } .volume-label { display: flex; align-items: center; gap: 0.4rem; color: var(--text-muted); font-size: 0.75rem; } .volume-slider { width: 80px; accent-color: var(--accent); cursor: pointer; } /* ========================================================= AFFILIATE SECTION ========================================================= */ .affiliate-section { display: flex; align-items: center; gap: 1.25rem; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 1rem; margin-bottom: 1.5rem; } .affiliate-artwork { width: 80px; height: 80px; object-fit: cover; border-radius: var(--radius); flex-shrink: 0; background: var(--bg-alt); } .affiliate-info { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; } .affiliate-track { font-size: 1rem; font-weight: bold; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .affiliate-artist { font-size: 0.85rem; color: var(--text-muted); } .affiliate-album { font-size: 0.8rem; color: var(--text-muted); font-style: italic; } .btn-amazon { display: inline-block; margin-top: 0.5rem; background: #ff9900; color: #000; padding: 0.3rem 0.8rem; border-radius: var(--radius); font-weight: bold; font-size: 0.8rem; } .btn-amazon:hover { background: #ffad33; color: #000; text-decoration: none; } /* ========================================================= TABS ========================================================= */ .tabs { display: flex; border-bottom: 1px solid var(--border); margin-bottom: 1.25rem; gap: 0; } .tab-btn { background: none; border: none; border-bottom: 2px solid transparent; color: var(--text-muted); cursor: pointer; font-family: var(--font); font-size: 0.9rem; padding: 0.5rem 1.25rem; transition: color 0.15s, border-color 0.15s; } .tab-btn:hover { color: var(--text); } .tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); } .tab-panel { min-height: 200px; } .sub-tabs { border-bottom-color: transparent; margin-bottom: 1rem; } .sub-tabs .tab-btn { font-size: 0.8rem; padding: 0.3rem 1rem; color: var(--text-muted); } .sub-tabs .tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); } /* ========================================================= SEARCH ========================================================= */ .search-bar { display: flex; gap: 0.5rem; margin-bottom: 1rem; } .search-input { flex: 1; background: transparent; border: 1px solid var(--border); border-radius: var(--radius); color: var(--text); font-family: var(--font); font-size: 0.9rem; padding: 0.4rem 0.7rem; outline: none; } .search-input:focus { border-color: var(--accent); } .status-msg { color: var(--text-muted); font-size: 0.85rem; min-height: 1.4em; margin-bottom: 0.5rem; } /* ========================================================= TABLES ========================================================= */ .data-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; } .data-table th { background: var(--bg-alt); border-bottom: 1px solid var(--border); color: var(--text-muted); font-weight: normal; padding: 0.45rem 0.7rem; text-align: left; } .data-table td { padding: 0.4rem 0.7rem; border-bottom: 1px solid var(--border); vertical-align: middle; max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .data-table tbody tr:nth-child(odd) { background: transparent; } .data-table tbody tr:nth-child(even) { background: transparent; } .data-table tbody tr:hover { background: rgba(255, 255, 255, 0.05); } .empty-msg { color: var(--text-muted); text-align: center; padding: 1.5rem !important; } .history-time { color: var(--text-muted); font-size: 0.75rem; white-space: nowrap; } /* ========================================================= BUTTONS ========================================================= */ .btn { background: transparent; border: 1px solid var(--border); border-radius: var(--radius); color: var(--text); cursor: pointer; font-family: var(--font); font-size: 0.85rem; padding: 0.35rem 0.75rem; transition: background 0.1s, border-color 0.1s; white-space: nowrap; } .btn:hover { background: rgba(255, 255, 255, 0.07); border-color: #444; } .btn-play { background: var(--accent); border-color: var(--accent); color: #fff; font-size: 0.9rem; padding: 0.4rem 1rem; } .btn-play:hover { background: var(--accent-hover); border-color: var(--accent-hover); } .btn-play.playing { background: #333; border-color: #555; color: var(--text); } .btn-save { color: var(--yellow); border-color: #444; } .btn-save:hover { background: #2a2a00; border-color: var(--yellow); } .btn-sm { font-size: 0.78rem; padding: 0.25rem 0.5rem; } .btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; } .btn-primary:hover { background: var(--accent-hover); } .btn-danger { background: #300; border-color: #700; color: #faa; } .btn-danger:hover { background: #500; border-color: #a00; color: #fff; } .btn-lastfm { background: #d51007; border-color: #d51007; color: #fff; display: inline-block; padding: 0.4rem 1rem; border-radius: var(--radius); font-family: var(--font); font-size: 0.9rem; cursor: pointer; border: 1px solid transparent; } .btn-lastfm:hover { background: #ff1a0e; color: #fff; text-decoration: none; } .btn-full { width: 100%; padding: 0.55rem; font-size: 0.95rem; } .btn-link { background: none; border: none; color: var(--accent); cursor: pointer; font-family: var(--font); font-size: 1rem; padding: 0; } .btn-link:hover { color: var(--accent-hover); text-decoration: underline; } .btn-icon { background: none; border: none; color: var(--text-muted); cursor: pointer; font-size: 1rem; padding: 0; line-height: 1; } .btn-icon.active { color: var(--yellow); } .btn-icon:hover { color: var(--yellow); } .inline-form { display: inline; } /* ========================================================= AUTH FORMS ========================================================= */ .auth-container { max-width: 400px; margin: 3rem auto; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 2rem; } .auth-title { font-size: 1.4rem; margin-bottom: 1.5rem; color: var(--text); } .auth-form { display: flex; flex-direction: column; gap: 1rem; } .form-group { display: flex; flex-direction: column; gap: 0.25rem; } .form-label { font-size: 0.85rem; color: var(--text-muted); } .auth-form input[type="text"], .auth-form input[type="password"], .auth-form input[type="email"] { background: var(--bg-alt); border: 1px solid var(--border); border-radius: var(--radius); color: var(--text); font-family: var(--font); font-size: 0.9rem; padding: 0.45rem 0.7rem; outline: none; width: 100%; } .auth-form input:focus { border-color: var(--accent); } .field-errors { list-style: none; color: var(--accent); font-size: 0.8rem; } .form-errors { color: var(--accent); font-size: 0.85rem; background: #1a0000; border: 1px solid #500; border-radius: var(--radius); padding: 0.5rem 0.75rem; } .field-help { color: var(--text-muted); font-size: 0.75rem; } .auth-switch { margin-top: 1.25rem; font-size: 0.85rem; color: var(--text-muted); text-align: center; } /* ========================================================= SETTINGS ========================================================= */ .settings-container { max-width: 600px; margin: 2rem auto; } .settings-title { font-size: 1.4rem; margin-bottom: 1.5rem; } .settings-section { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 1.25rem; margin-bottom: 1.25rem; } .settings-section h2 { font-size: 1rem; color: var(--text-muted); margin-bottom: 1rem; text-transform: uppercase; letter-spacing: 0.08em; } .lastfm-description { color: var(--text-muted); font-size: 0.85rem; margin-bottom: 0.75rem; } .connected-status { margin-bottom: 0.75rem; font-size: 0.9rem; } .checkbox-label { display: flex; align-items: center; gap: 0.5rem; cursor: pointer; font-size: 0.9rem; } .auth-prompt { color: var(--text-muted); padding: 1.5rem 0; } /* ========================================================= RESPONSIVE ========================================================= */ /* ========================================================= RECOMMENDATIONS ========================================================= */ .recommendations-section { padding: 12px 16px 4px; border-bottom: 1px solid #222; } .recommendations-context { font-size: 0.75rem; color: var(--fg); margin: 0 0 8px; text-transform: uppercase; letter-spacing: 0.05em; } .recommendations-list { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 8px; } .recommendations-list li { display: flex; align-items: center; gap: 6px; } .muted { color: var(--fg); font-size: 0.8rem; } @media (max-width: 600px) { .main-content { padding: 0.75rem 0.75rem calc(var(--bar-h) + 1.5rem); } .now-playing-bar { flex-direction: column; height: auto; padding: 0.5rem 0.75rem; gap: 0.4rem; } .now-playing-info { width: 100%; } .now-playing-controls { width: 100%; justify-content: space-between; } .volume-slider { width: 60px; } .affiliate-section { flex-direction: column; align-items: flex-start; } .data-table th:nth-child(3), .data-table td:nth-child(3), .data-table th:nth-child(4), .data-table td:nth-child(4) { display: none; } .auth-container { margin: 1rem; padding: 1.25rem; } } .import-bar { padding: 8px 16px; display: flex; align-items: center; gap: 10px; border-bottom: 1px solid #1a1a1a; } /* ========================================================= TIMER WIDGET ========================================================= */ .timer-widget { display: flex; align-items: center; gap: 6px; font-variant-numeric: tabular-nums; margin-left: 8px; } .timer-phase { font-size: 0.7rem; color: var(--fg); text-transform: uppercase; letter-spacing: 0.05em; width: 36px; text-align: right; } .timer-display { font-size: 1rem; font-weight: 600; letter-spacing: 0.05em; min-width: 48px; } /* ========================================================= DO NOT DISTURB / FOCUS MODE ========================================================= */ body.dnd-mode .navbar, body.dnd-mode .tabs, body.dnd-mode .tab-panel, body.dnd-mode .affiliate-section { display: none !important; } body.dnd-mode .now-playing-bar { position: fixed; inset: 0; height: 100vh; flex-direction: column; justify-content: center; align-items: center; gap: 24px; background: transparent; z-index: 9999; } body.dnd-mode.dnd-dark { background: #000 !important; background-image: none !important; } body.dnd-mode.dnd-dark .now-playing-bar { background: #000; } .dnd-only { display: none; } body.dnd-mode .dnd-only { display: inline; } body.dnd-mode .now-playing-info { text-align: center; flex-direction: column; gap: 12px; } body.dnd-mode .now-playing-station { font-size: 1.6rem; } body.dnd-mode .now-playing-track { font-size: 1rem; color: var(--fg); } body.dnd-mode .timer-display { font-size: 3.5rem; } /* ========================================================= MOOD CHIPS ========================================================= */ .mood-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 16px; border-bottom: 1px solid #1a1a1a; } .mood-chip { background: transparent; border: 1px solid #333; color: #ccc; border-radius: 999px; padding: 3px 12px; font-size: 0.78rem; cursor: pointer; transition: background 0.15s, border-color 0.15s; } .mood-chip:hover { background: rgba(255, 255, 255, 0.05); border-color: #555; } .focus-today { font-size: 0.72rem; color: var(--fg); margin-left: 8px; white-space: nowrap; } .curated-lists-container { padding: 12px 16px 0; } .curated-section { margin-bottom: 16px; } .curated-label { font-size: 0.75rem; color: var(--fg); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 6px; } .curated-stations { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 4px; } .curated-stations li { display: flex; align-items: center; gap: 8px; } .curated-name { font-size: 0.85rem; color: var(--fg); } .btn-delete-history { background: none; border: none; color: var(--muted, #888); cursor: pointer; font-size: 0.75rem; padding: 0 4px; opacity: 0.5; } .btn-delete-history:hover { opacity: 1; color: #e55; } #donation-hint { position: fixed; bottom: 24px; right: 24px; background: var(--surface, #1e1e2e); border: 1px solid var(--border, #333); border-radius: 8px; padding: 12px 16px; display: flex; align-items: center; gap: 12px; font-size: 0.85rem; box-shadow: 0 4px 16px rgba(0,0,0,0.4); z-index: 999; animation: hint-in 0.3s ease; max-width: 320px; } #donation-hint.hiding { animation: hint-out 0.4s ease forwards; } #donation-hint button { background: none; border: none; cursor: pointer; color: var(--muted, #888); font-size: 0.8rem; padding: 0; flex-shrink: 0; } #donation-hint button:hover { color: var(--fg, #fff); } @keyframes hint-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } } @keyframes hint-out { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(12px); } } .featured-section { padding: 8px 0 12px; border-bottom: 1px solid var(--border, #333); margin-bottom: 12px; } .featured-label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted, #888); margin: 0 0 8px; } .featured-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 6px; } .featured-list li { display: flex; align-items: center; gap: 8px; } .volume-num { width: 44px; background: var(--surface, #1e1e2e); border: 1px solid var(--border, #333); border-radius: 4px; color: var(--fg, #fff); font-size: 0.8rem; padding: 2px 4px; text-align: center; } .volume-num::-webkit-inner-spin-button, .volume-num::-webkit-outer-spin-button { display: none; } .volume-num { -moz-appearance: textfield; } /* ===== PODCAST COMPONENTS ===== */ .podcast-seek-bar { display: flex; align-items: center; gap: 6px; padding: 0 12px; flex: 1; min-width: 0; } .skip-btn { font-size: 0.72rem; opacity: 0.8; white-space: nowrap; padding: 2px 4px; } .skip-btn:hover { opacity: 1; } .speed-btns { display: flex; gap: 2px; margin-left: 4px; flex-shrink: 0; } .speed-btn { background: none; border: 1px solid var(--border, #444); color: var(--fg, #fff); border-radius: 3px; font-size: 0.68rem; padding: 1px 4px; cursor: pointer; opacity: 0.6; white-space: nowrap; } .speed-btn:hover { opacity: 1; } .speed-btn.active { opacity: 1; border-color: var(--accent, #e63946); color: var(--accent, #e63946); } .seek-slider { flex: 1; accent-color: var(--accent, #e63946); cursor: pointer; height: 4px; } .seek-time { font-size: 0.75rem; color: var(--text-muted, #888); white-space: nowrap; font-variant-numeric: tabular-nums; } .podcast-toolbar { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 0 12px; border-bottom: 1px solid var(--border, #333); margin-bottom: 10px; align-items: center; } .podcast-pane { } .podcast-feed-list { display: flex; flex-direction: column; gap: 6px; } .podcast-feed-item { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--border, #222); } .podcast-feed-info { flex: 1; min-width: 0; } .podcast-feed-title { font-weight: bold; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .podcast-feed-actions { display: flex; gap: 4px; flex-shrink: 0; } .podcast-thumb { width: 48px; height: 48px; object-fit: cover; border-radius: 4px; flex-shrink: 0; } .podcast-thumb-lg { width: 80px; height: 80px; object-fit: cover; border-radius: 6px; flex-shrink: 0; } .podcast-thumb-placeholder { width: 48px; height: 48px; background: var(--surface, #1e1e2e); border-radius: 4px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; } .podcast-unplayed-badge { background: var(--accent, #e63946); color: #fff; border-radius: 99px; padding: 1px 7px; font-size: 0.7rem; margin-left: 6px; } .episode-list { display: flex; flex-direction: column; gap: 4px; } .episode-item { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--border, #222); } .episode-item.episode-played { opacity: 0.5; } .episode-info { flex: 1; min-width: 0; } .episode-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 0.9rem; } .episode-actions { display: flex; gap: 4px; flex-shrink: 0; } .podcast-search-list { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; } .podcast-search-item { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--border, #222); } .podcast-search-info { flex: 1; min-width: 0; } .podcast-queue-ol { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 4px; } .podcast-feed-header { margin-bottom: 12px; } .podcast-feed-header-inner { display: flex; align-items: center; gap: 14px; } /* Clickable episode title (episode list) */ .ep-clickable { cursor: pointer; } .ep-clickable:hover { color: var(--accent, #e63946); text-decoration: underline; } /* Clickable episode title / feed name in the now-playing bar */ .podcast-track-link, .podcast-station-link { cursor: pointer; } .podcast-track-link:hover, .podcast-station-link:hover { color: var(--accent, #e63946); text-decoration: underline; } /* ===== SIDEBAR ===== */ .sidebar-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.45); z-index: 299; } .sidebar { position: fixed; top: 0; right: 0; width: 400px; max-width: 100vw; /* stop above the now-playing bar */ bottom: 72px; background: var(--surface, #111); border-left: 1px solid var(--border, #333); z-index: 300; display: flex; flex-direction: column; transform: translateX(100%); transition: transform 0.22s ease; overflow: hidden; } .sidebar.open { transform: translateX(0); } .sidebar-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; padding: 14px 16px 10px; border-bottom: 1px solid var(--border, #333); flex-shrink: 0; } .sidebar-title { font-weight: bold; font-size: 0.95rem; line-height: 1.3; } .sidebar-close { flex-shrink: 0; margin-top: -2px; } .sidebar-body { flex: 1; overflow-y: auto; padding: 16px; font-size: 0.88rem; line-height: 1.6; } /* Style links and basic HTML inside shownotes */ .sidebar-body a { color: var(--accent, #e63946); } .sidebar-body p { margin: 0 0 10px; } .sidebar-body ul, .sidebar-body ol { margin: 0 0 10px; padding-left: 20px; } .sidebar-body h1, .sidebar-body h2, .sidebar-body h3 { font-size: 0.9rem; margin: 12px 0 4px; } @media (max-width: 600px) { .sidebar { width: 100vw; } .podcast-seek-bar { padding: 0 6px; } .podcast-thumb { width: 40px; height: 40px; } .podcast-thumb-lg { width: 60px; height: 60px; } .podcast-feed-actions { flex-direction: column; } .episode-actions { flex-direction: column; } } /* ========================================================= Ebook reader + book list + focus station ========================================================= */ /* --- Drop zone --- */ .book-drop-zone { border: 2px dashed var(--border); border-radius: var(--radius); padding: 24px 16px; text-align: center; margin: 12px 0; cursor: pointer; transition: border-color 0.15s, background 0.15s; display: flex; flex-direction: column; gap: 6px; align-items: center; } .book-drop-zone:hover, .book-drop-zone.drag-over { border-color: var(--accent); background: rgba(255,255,255,0.04); } .book-drop-zone label { color: var(--accent); cursor: pointer; } .enc-key-prompt { padding: 24px 0 16px; } .book-key-bar { display: flex; align-items: center; gap: 8px; margin-top: 1rem; padding-top: 0.75rem; border-top: 1px solid var(--border); } /* --- Book list --- */ .book-list { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; } .book-item { display: flex; justify-content: space-between; align-items: center; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius); gap: 12px; } .book-item-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; } .book-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .book-author, .book-progress { font-size: 12px; } .book-item-actions { display: flex; gap: 6px; flex-shrink: 0; } /* --- PDF pages --- */ .pdf-page-wrapper { margin: 0 auto 1rem; display: flex; justify-content: center; } .pdf-page { display: block; max-width: 100%; box-shadow: 0 2px 8px rgba(0,0,0,0.25); } /* --- Reader overlay --- */ .reader-overlay { position: fixed; top: var(--nav-h); left: 0; right: 0; bottom: var(--bar-h); background: var(--bg); z-index: 200; display: flex; flex-direction: column; } .reader-header { display: flex; justify-content: space-between; align-items: center; padding: 8px 16px; border-bottom: 1px solid var(--border); flex-shrink: 0; gap: 12px; } .reader-title { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; } .reader-header-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; } .reader-progress-wrap { display: flex; align-items: center; gap: 4px; } .reader-content { flex: 1; overflow-y: scroll; padding: 24px 16px; line-height: 1.8; font-family: Georgia, 'Times New Roman', serif; font-size: 16px; font-weight: 400; } .reader-content > * { max-width: 65ch; margin-left: auto; margin-right: auto; } .reader-content p { margin-bottom: 1em; } .reader-content h1, .reader-content h2, .reader-content h3 { margin: 1.4em 0 0.6em; font-family: var(--font); } /* --- Focus station sidebar --- */ .focus-preset-list { list-style: none; display: flex; flex-direction: column; gap: 6px; margin: 10px 0; } .focus-preset-list li.focus-preset-active button { border-color: var(--accent); color: var(--accent); } .focus-custom-input { display: flex; flex-direction: column; gap: 6px; margin-top: 12px; } /* --- Table of contents sidebar --- */ .toc-list { list-style: none; display: flex; flex-direction: column; gap: 2px; } .toc-entry { display: block; width: 100%; text-align: left; padding: 4px 0; font-size: 13px; white-space: normal; word-break: break-word; } .toc-entry:hover { color: var(--accent); } /* Focus station pending (playing interrupted) */ #focus-station-btn.focus-pending { color: var(--accent); animation: focus-pulse 1.4s ease-in-out infinite; } @keyframes focus-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } } /* ========================================================= Reader feature additions ========================================================= */ /* Reader themes */ .reader-theme-sepia .reader-content { background:#f5e6c8; color:#3b2a1a; } .reader-theme-bright .reader-content { background:#fff; color:#111; } .reader-content > * { max-width:var(--reader-max-width,65ch); margin-left:auto; margin-right:auto; } /* Inline panels */ .reader-settings-panel, .reader-search-bar { display:flex; align-items:center; gap:12px; padding:8px 16px; border-bottom:1px solid var(--border); flex-shrink:0; flex-wrap:wrap; background:var(--bg); } .reader-settings-panel input[type="range"] { width:80px; } /* PDF inner container — shares origin with canvas so text layer aligns exactly */ .pdf-page-inner { position:relative; display:inline-block; line-height:0; } /* PDF text layer — sits flush over the canvas inside pdf-page-inner */ .pdf-text-layer { position:absolute; top:0; left:0; width:100%; height:100%; overflow:hidden; pointer-events:none; } .pdf-text-layer span { position:absolute; color:transparent !important; background:transparent; white-space:pre; cursor:text; pointer-events:auto; user-select:text; -webkit-user-select:text; line-height:1; } .pdf-text-layer span::selection { background:rgba(0,120,255,0.3); } .pdf-text-layer span.reader-search-match { background:rgba(241,196,15,.5); } .pdf-text-layer span.reader-search-match.active { background:rgba(230,57,70,.6); } /* PDF invert */ #reader-overlay.pdf-inverted .pdf-page { filter:invert(1); } /* PDF paginated */ .reader-content.pdf-paginated { overflow:hidden !important; display:flex; align-items:center; justify-content:center; } .pdf-paginated .pdf-page-wrapper { margin:0; } /* Highlight popover */ .highlight-popover { position:fixed; z-index:500; display:flex; gap:6px; background:var(--bg-card,#1a1a1a); border:1px solid var(--border); border-radius:var(--radius); padding:6px 8px; box-shadow:0 4px 16px rgba(0,0,0,.5); } .hl-color-btn { width:24px; height:24px; border-radius:50%; border:2px solid transparent; cursor:pointer; font-weight:700; font-size:12px; color:#000; line-height:1; } .hl-color-btn:hover { border-color:#fff; } .hl-note-btn { background:none; border:1px solid var(--border); color:var(--fg); padding:2px 6px; border-radius:var(--radius); cursor:pointer; } /* Highlight marks */ .epub-highlight { border-radius:2px; cursor:pointer; } .epub-highlight[data-color="yellow"] { background:rgba(241,196,15,.4); } .epub-highlight[data-color="green"] { background:rgba(46,204,113,.35); } .epub-highlight[data-color="blue"] { background:rgba(52,152,219,.35); } .epub-highlight[data-color="red"] { background:rgba(230,57,70,.35); } /* Search matches */ mark.reader-search-match { background:rgba(241,196,15,.6); color:inherit; border-radius:2px; } mark.reader-search-match.active { background:rgba(230,57,70,.7); } #rs-search-count { font-size:12px; min-width:50px; } /* Bookmarks sidebar */ .bookmark-entry { display:flex; width:100%; padding:6px 0; font-size:13px; justify-content:space-between; border-bottom:1px solid var(--border); } /* Toast */ .reader-toast { position:fixed; bottom:calc(var(--bar-h) + 16px); left:50%; transform:translateX(-50%); background:var(--fg); color:var(--bg); padding:6px 14px; border-radius:var(--radius); font-size:13px; z-index:600; animation:toast-fade 2s ease forwards; pointer-events:none; } @keyframes toast-fade { 0%,70%{opacity:1} 100%{opacity:0} } .build-time { position: fixed; bottom: 4px; right: 6px; font-size: 0.65rem; color: #444; pointer-events: none; z-index: 1; }