diff --git a/src/index.css b/src/index.css index 64767f60..a4463aa3 100644 --- a/src/index.css +++ b/src/index.css @@ -1,299 +1,19 @@ -:root { - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; +@import './styles/base/variables.css'; +@import './styles/base/global.css'; +@import './styles/layout/app.css'; +@import './styles/layout/sidebar.css'; +@import './styles/layout/highlights.css'; +@import './styles/components/icon-button.css'; +@import './styles/components/profile.css'; +@import './styles/components/cards.css'; +@import './styles/components/modals.css'; +@import './styles/components/toast.css'; +@import './styles/components/forms.css'; +@import './styles/components/reader.css'; +@import './styles/components/settings.css'; +@import './styles/utils/animations.css'; +@import './styles/utils/utilities.css'; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - - --reading-font: 'Source Serif 4', serif; - --reading-font-size: 18px; - /* Layout variables */ - --sidebar-width: 320px; - --sidebar-collapsed-width: 64px; - --highlights-width: 360px; - --highlights-collapsed-width: 56px; - --main-max-width: 900px; - --main-horizontal-padding: 1rem; - - /* Mobile breakpoints */ - --mobile-breakpoint: 768px; - --tablet-breakpoint: 1024px; - - /* Mobile touch target minimum */ - --min-touch-target: 44px; - - /* Safe area insets for notched devices */ - --safe-area-top: env(safe-area-inset-top, 0px); - --safe-area-bottom: env(safe-area-inset-bottom, 0px); - --safe-area-left: env(safe-area-inset-left, 0px); - --safe-area-right: env(safe-area-inset-right, 0px); -} - -body { - margin: 0; - min-width: 320px; - min-height: 100vh; - overscroll-behavior: none; - -webkit-overflow-scrolling: touch; -} - -/* Use dynamic viewport height if supported */ -@supports (height: 100dvh) { - body { - min-height: 100dvh; - } -} - -body.mobile-sidebar-open { - overflow: hidden; - position: fixed; - width: 100%; -} - -#root { - max-width: none; - margin: 0; - padding: 1rem; -} - -@media (max-width: 768px) { - #root { - padding: 0; - } -} - -.app { - text-align: center; - position: relative; -} - -.app header { - margin-bottom: 2rem; -} - -.app header h1 { - font-size: 2.5rem; - margin: 0; - color: #646cff; -} - -.app header p { - margin: 0.5rem 0 0 0; - color: #888; -} - -/* Bookmarks Styles */ -.bookmarks-container { - background: #1a1a1a; - border: 1px solid #333; - border-radius: 12px; - display: flex; - flex-direction: column; - height: 100%; - overflow: hidden; - text-align: left; - padding: 0; -} - -.bookmarks-container .view-mode-controls { - margin-top: auto; - padding: 1rem; - border-top: 1px solid #333; - background: transparent; - border-radius: 0; -} - -.bookmarks-container .bookmarks-list { - padding: 0.5rem; - overflow-y: auto; - overflow-x: hidden; - flex: 1; - width: 100%; - max-width: 100%; - box-sizing: border-box; -} - -.sidebar-header-bar { - display: flex; - align-items: center; - justify-content: space-between; - gap: 0.75rem; - padding: 0.75rem 1rem; - background: #1a1a1a; - border: 1px solid #333; - border-radius: 12px 12px 0 0; - margin-bottom: 0; -} - -.sidebar-header-right { - display: flex; - align-items: center; - gap: 0.5rem; - margin-left: auto; -} - -.mobile-hamburger-btn { - display: none; - position: fixed; - top: calc(1rem + env(safe-area-inset-top)); - left: calc(1rem + env(safe-area-inset-left)); - z-index: 900; - background: #2a2a2a; - border: 1px solid #444; - border-radius: 8px; - color: #ddd; - width: var(--min-touch-target); - height: var(--min-touch-target); - align-items: center; - justify-content: center; - cursor: pointer; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); - transition: transform 0.2s ease, opacity 0.3s ease, visibility 0.3s ease; -} - -.mobile-hamburger-btn.hidden { - opacity: 0; - visibility: hidden; - pointer-events: none; -} - -.mobile-hamburger-btn.visible { - opacity: 1; - visibility: visible; -} - -.mobile-hamburger-btn:active { - transform: scale(0.95); -} - -.mobile-close-btn { - display: none; -} - -@media (max-width: 768px) { - .mobile-hamburger-btn { - display: flex; - } - - .sidebar-header-bar .toggle-sidebar-btn { - display: none; - } - - .mobile-close-btn { - display: flex; - } -} - -.view-mode-controls { - display: flex; - align-items: center; - justify-content: center; - gap: 0.5rem; -} - -.profile-avatar { - width: 33px; - height: 33px; - border-radius: 6px; - overflow: hidden; - display: flex; - align-items: center; - justify-content: center; - background: #2a2a2a; - border: 1px solid #444; - flex-shrink: 0; - color: #ddd; - box-sizing: border-box; -} - -.profile-avatar img { - width: 100%; - height: 100%; - object-fit: cover; -} - -.profile-avatar svg { - font-size: 1.25rem; -} - -.sidebar-header-bar .toggle-sidebar-btn { - background: transparent; - color: #ddd; - border: 1px solid #444; - padding: 0; - border-radius: 6px; - cursor: pointer; - transition: all 0.2s ease; - display: flex; - align-items: center; - justify-content: center; - width: 33px; - height: 33px; - flex-shrink: 0; - box-sizing: border-box; -} - -.sidebar-header-bar .toggle-sidebar-btn:hover { - background: #2a2a2a; - color: #fff; -} - -.sidebar-header-bar .toggle-sidebar-btn:active { - transform: translateY(1px); -} - -.bookmarks-container.collapsed { - display: flex; - align-items: flex-start; - justify-content: flex-start; - padding: 0; - background: transparent; - border: none; -} - -.bookmarks-container.collapsed .toggle-sidebar-btn { - background: #2a2a2a; - color: #ddd; - border: none; - padding: 0; - border-radius: 0; - cursor: pointer; - transition: all 0.2s ease; - display: flex; - align-items: center; - justify-content: center; - width: 48px; - height: 36px; - flex-shrink: 0; -} - -.bookmarks-container.collapsed .toggle-sidebar-btn:hover { - background: #333; - color: #fff; -} - -.bookmarks-container.collapsed .toggle-sidebar-btn:active { - transform: translateY(1px); -} - -.bookmarks-container.collapsed .toggle-sidebar-btn.with-icon { - width: auto; - padding: 0 0.5rem; - gap: 0.5rem; -} - -.bookmarks-container.collapsed .toggle-sidebar-btn .glow-blue { - color: #646cff; - filter: drop-shadow(0 0 4px rgba(100, 108, 255, 0.6)); -} .user-info { margin: 0.5rem 0 0 0; @@ -360,55 +80,6 @@ body.mobile-sidebar-open { background: #218838; } -/* Generic IconButton styling */ -.icon-button { - display: inline-flex; - align-items: center; - justify-content: center; - border: 1px solid #444; - border-radius: 6px; - background: #2a2a2a; - color: #ddd; - cursor: pointer; - min-width: 33px; - min-height: 33px; - padding: 0; - box-sizing: border-box; -} - -.icon-button:hover { background: #333; } -.icon-button:active { transform: translateY(1px); } - -.icon-button.primary { background: #646cff; color: white; border-color: #646cff; } -.icon-button.primary:hover { filter: brightness(1.05); } - -.icon-button.success { background: #28a745; color: white; border-color: #28a745; } -.icon-button.success:hover { filter: brightness(1.05); } - -.icon-button.ghost { background: #2a2a2a; } - -/* Mobile touch target improvements */ -@media (max-width: 768px) { - .icon-button { - min-width: var(--min-touch-target); - min-height: var(--min-touch-target); - } -} - -/* Disable hover effects on touch devices */ -@media (pointer: coarse) { - .icon-button:hover { - background: #2a2a2a; - } - - .icon-button.ghost:hover { - background: #2a2a2a; - } - - .icon-button:active { - background: #333; - } -} .bookmark-events { margin: 1rem 0; diff --git a/src/styles/base/global.css b/src/styles/base/global.css index e69de29b..9b9fdd04 100644 --- a/src/styles/base/global.css +++ b/src/styles/base/global.css @@ -0,0 +1,68 @@ +/* Global element styles and app container */ +body { + margin: 0; + min-width: 320px; + min-height: 100vh; + overscroll-behavior: none; + -webkit-overflow-scrolling: touch; +} + +/* Use dynamic viewport height if supported */ +@supports (height: 100dvh) { + body { + min-height: 100dvh; + } +} + +body.mobile-sidebar-open { + overflow: hidden; + position: fixed; + width: 100%; +} + +#root { + max-width: none; + margin: 0; + padding: 1rem; +} + +@media (max-width: 768px) { + #root { + padding: 0; + } +} + +.app { + text-align: center; + position: relative; +} + +.app header { + margin-bottom: 2rem; +} + +.app header h1 { + font-size: 2.5rem; + margin: 0; + color: #646cff; +} + +.app header p { + margin: 0.5rem 0 0 0; + color: #888; +} + +.loading { + text-align: center; + padding: 2rem; + color: #ccc; +} + +.loading { + flex: 1; + display: flex; + align-items: center; + justify-content: center; +} + + diff --git a/src/styles/base/variables.css b/src/styles/base/variables.css index e69de29b..d24b8e0e 100644 --- a/src/styles/base/variables.css +++ b/src/styles/base/variables.css @@ -0,0 +1,48 @@ +/* CSS variables and color-scheme */ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; + + --reading-font: 'Source Serif 4', serif; + --reading-font-size: 18px; + /* Layout variables */ + --sidebar-width: 320px; + --sidebar-collapsed-width: 64px; + --highlights-width: 360px; + --highlights-collapsed-width: 56px; + --main-max-width: 900px; + --main-horizontal-padding: 1rem; + + /* Mobile breakpoints */ + --mobile-breakpoint: 768px; + --tablet-breakpoint: 1024px; + + /* Mobile touch target minimum */ + --min-touch-target: 44px; + + /* Safe area insets for notched devices */ + --safe-area-top: env(safe-area-inset-top, 0px); + --safe-area-bottom: env(safe-area-inset-bottom, 0px); + --safe-area-left: env(safe-area-inset-left, 0px); + --safe-area-right: env(safe-area-inset-right, 0px); +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } +} + + diff --git a/src/styles/components/cards.css b/src/styles/components/cards.css index e69de29b..826d2879 100644 --- a/src/styles/components/cards.css +++ b/src/styles/components/cards.css @@ -0,0 +1,97 @@ +/* Bookmark item and blog post cards */ +.bookmark-item { background: #1a1a1a; padding: 1.5rem; border-radius: 12px; transition: all 0.2s ease; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } +.bookmark-item:hover { transform: translateY(-2px); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); } +.bookmark-item h3 { margin: 0 0 0.5rem 0; color: #fff; font-size: 1.2rem; } +.bookmark-url { color: #646cff; text-decoration: none; display: block; margin-bottom: 0.5rem; word-break: break-all; background: none; border: none; padding: 0; font: inherit; cursor: pointer; text-align: left; width: 100%; } +.bookmark-url:hover { text-decoration: underline; } +.bookmark-content { color: #ccc; margin: 0.5rem 0; line-height: 1.4; word-wrap: break-word; overflow-wrap: break-word; word-break: break-word; } +.bookmark-meta { color: #888; font-size: 0.9rem; margin-top: 0.5rem; } + +.individual-bookmarks { margin: 1rem 0; } +.individual-bookmarks h4 { margin: 0 0 1rem 0; font-size: 1rem; color: #fff; } + +.bookmarks-grid { display: flex; flex-direction: column; gap: 1rem; width: 100%; max-width: 100%; } +.bookmarks-grid.bookmarks-compact { gap: 0.5rem; } +.bookmarks-grid.bookmarks-large { gap: 1.5rem; } +@media (max-width: 768px) { + .bookmarks-grid { gap: 0.75rem; } + .bookmarks-grid.bookmarks-compact { gap: 0.25rem; } + .bookmarks-grid.bookmarks-large { gap: 1rem; } +} + +.individual-bookmark { background: transparent; padding: 1rem; border-radius: 8px; transition: all 0.2s ease; border: 1px solid transparent; word-wrap: break-word; overflow-wrap: break-word; word-break: break-word; overflow: hidden; } +.individual-bookmark:hover { border-color: transparent; background: #2a2a2a; } + +/* Compact view */ +.individual-bookmark.compact { padding: 0.5rem 0.5rem; background: transparent; border: none; border-bottom: 1px solid #2a2a2a; border-radius: 0; box-shadow: none; width: 100%; max-width: 100%; overflow: hidden; } +.individual-bookmark.compact:hover { background: #252525; border-bottom-color: #333; transform: none; box-shadow: none; } +.compact-row { display: flex; align-items: center; gap: 0.5rem; height: 28px; width: 100%; min-width: 0; overflow: hidden; } +.compact-row.clickable { cursor: pointer; } +.compact-row.clickable:active { opacity: 0.8; } +.bookmark-type-compact { display: flex; align-items: center; gap: 0.25rem; color: #646cff; font-size: 0.85rem; flex-shrink: 0; } +.compact-text { flex: 1; min-width: 0; color: #ccc; font-size: 0.85rem; line-height: 1.2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.bookmark-date-compact { font-size: 0.7rem; color: #666; flex-shrink: 0; white-space: nowrap; } +.compact-read-btn { background: transparent; color: #888; border: none; padding: 0; border-radius: 4px; cursor: pointer; font-size: 0.75rem; display: flex; align-items: center; justify-content: center; width: 24px; height: 22px; flex-shrink: 0; transition: color 0.2s ease; } +.compact-read-btn:hover { color: #ccc; } +.compact-read-btn:active { transform: translateY(1px); } + +.bookmark-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.75rem; flex-wrap: wrap; gap: 0.5rem; } +.bookmark-type { color: #646cff; font-size: 0.9rem; display: flex; align-items: center; gap: 0.35rem; } +.bookmark-id { font-family: monospace; font-size: 0.8rem; color: #888; background: #1a1a1a; padding: 0.25rem 0.5rem; border-radius: 4px; } +.bookmark-date { font-size: 0.8rem; color: #666; } +.bookmark-date-link { font-size: 0.8rem; color: #666; text-decoration: none; transition: color 0.2s ease; } +.bookmark-date-link:hover { color: #8ab4f8; text-decoration: underline; } +.individual-bookmark .bookmark-content { margin: 0.75rem 0; color: #ccc; line-height: 1.6; font-size: 0.9rem; word-wrap: break-word; overflow-wrap: break-word; word-break: break-word; } +.expand-toggle { margin: 0.25rem 0; background: transparent; border: none; color: #888; cursor: pointer; width: 100%; height: 22px; display: flex; align-items: center; justify-content: center; } +.expand-toggle:hover { color: #bbb; } +.bookmark-footer { display: flex; justify-content: space-between; align-items: center; margin-top: 0.75rem; gap: 0.75rem; } +.bookmark-meta-minimal { font-size: 0.8rem; color: #888; } +.author-link-minimal { color: #888; text-decoration: none; transition: color 0.2s ease; } +.author-link-minimal:hover { color: #aaa; } +.read-now-button-minimal { background: #28a745; color: white; border: none; padding: 0.5rem 1rem; border-radius: 6px; cursor: pointer; font-weight: 600; font-size: 0.85rem; transition: all 0.2s ease; white-space: nowrap; } +.read-now-button-minimal:hover { background: #218838; } +.expand-toggle-urls { margin-top: 0.5rem; background: transparent; border: none; color: #646cff; cursor: pointer; font-size: 0.8rem; padding: 0.25rem 0; text-decoration: underline; } +.expand-toggle-urls:hover { color: #8088ff; } + +/* Large preview view */ +.individual-bookmark.large { padding: 0; display: flex; flex-direction: column; overflow: hidden; } +.large-preview-image { width: 100%; height: 180px; background: #1a1a1a; background-size: cover; background-position: center; background-repeat: no-repeat; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s ease; border-bottom: 1px solid #333; position: relative; } +.large-preview-image:hover { opacity: 0.9; } +.large-preview-image::after { content: ''; position: absolute; inset: 0; background: linear-gradient(to bottom, transparent 60%, rgba(0,0,0,0.3) 100%); pointer-events: none; } +.preview-placeholder { font-size: 3rem; color: #444; } +.large-content { padding: 1.25rem; } +.large-text { color: #ccc; font-size: 0.95rem; line-height: 1.6; margin-bottom: 1rem; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; } +.large-footer { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; font-size: 0.8rem; color: #888; padding-top: 0.75rem; border-top: 1px solid #333; } +.large-author { flex: 1; } +.large-read-button { background: #28a745; color: white; border: none; padding: 0.5rem 1rem; border-radius: 6px; cursor: pointer; font-weight: 600; font-size: 0.85rem; transition: all 0.2s ease; display: flex; align-items: center; gap: 0.5rem; } +.large-read-button:hover { background: #218838; } + +/* Blog cards (Explore) */ +.explore-container { padding: 2rem; max-width: 1400px; margin: 0 auto; min-height: 100vh; } +.explore-header { text-align: center; margin-bottom: 3rem; } +.explore-header h1 { font-size: 2.5rem; margin: 0 0 1rem 0; color: #646cff; display: flex; align-items: center; justify-content: center; gap: 1rem; } +.explore-subtitle { font-size: 1.125rem; color: rgba(255, 255, 255, 0.7); margin: 0; } +.explore-loading, .explore-error { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1rem; color: rgba(255, 255, 255, 0.7); } +.explore-loading { min-height: 0; padding: 0.25rem 0; } +.explore-error { color: #ff6b6b; } +.explore-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 2rem; margin-top: 2rem; } +.blog-post-card { background: #1a1a1a; border: 1px solid #333; border-radius: 12px; overflow: hidden; transition: all 0.3s ease; cursor: pointer; display: flex; flex-direction: column; height: 100%; } +.blog-post-card:hover { border-color: #646cff; transform: translateY(-4px); box-shadow: 0 8px 24px rgba(100, 108, 255, 0.15); } +.blog-post-card-image { width: 100%; height: 200px; overflow: hidden; background: #0f0f0f; } +.blog-post-card-image img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.3s ease; } +.blog-post-card:hover .blog-post-card-image img { transform: scale(1.05); } +.blog-post-card-content { padding: 1.5rem; display: flex; flex-direction: column; gap: 1rem; flex: 1; } +.blog-post-card-title { font-size: 1.25rem; font-weight: 600; margin: 0; color: rgba(255, 255, 255, 0.95); line-height: 1.4; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } +.blog-post-card-summary { font-size: 0.875rem; color: rgba(255, 255, 255, 0.6); margin: 0; line-height: 1.6; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; flex: 1; } +.blog-post-card-meta { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding-top: 0.75rem; border-top: 1px solid #333; font-size: 0.75rem; color: rgba(255, 255, 255, 0.5); flex-wrap: wrap; } +.blog-post-card-author, .blog-post-card-date { display: flex; align-items: center; gap: 0.5rem; } +.blog-post-card-author svg, .blog-post-card-date svg { opacity: 0.7; } +@media (max-width: 768px) { + .explore-container { padding: 1rem; } + .explore-header h1 { font-size: 2rem; } + .explore-grid { grid-template-columns: 1fr; gap: 1.5rem; } + .blog-post-card-summary { -webkit-line-clamp: 2; font-size: 0.8rem; } + .blog-post-card-content { padding: 1rem; } +} + + diff --git a/src/styles/components/forms.css b/src/styles/components/forms.css index e69de29b..c023cb5f 100644 --- a/src/styles/components/forms.css +++ b/src/styles/components/forms.css @@ -0,0 +1,30 @@ +/* Forms and controls for settings */ +.setting-group { margin-bottom: 1.5rem; text-align: left; } +.setting-group.setting-inline { display: flex; align-items: center; gap: 1rem; } +.setting-label { text-align: left; flex: 1; } +.setting-control { display: flex; justify-content: flex-end; align-items: center; } +.setting-group.setting-inline label { margin-bottom: 0; } +.setting-group label { display: block; margin-bottom: 0.5rem; color: #ccc; font-weight: 500; text-align: left; } +.setting-buttons { display: flex; align-items: center; gap: 0.5rem; } +.color-picker { display: flex; align-items: center; gap: 0.5rem; } +.color-swatch { width: 33px; height: 33px; border: 1px solid #444; border-radius: 6px; cursor: pointer; transition: all 0.2s; position: relative; } +.color-swatch:hover { border-color: #888; } +.color-swatch.active { border-color: #646cff; box-shadow: 0 0 0 2px #646cff; } +.color-swatch.active::after { content: '✓'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #000; font-size: 0.875rem; font-weight: bold; text-shadow: 0 0 2px #fff; } +.font-size-btn { min-width: 33px; height: 33px; padding: 0; background: transparent; border: 1px solid #444; border-radius: 6px; color: #ccc; cursor: pointer; transition: all 0.2s; font-weight: bold; display: flex; align-items: center; justify-content: center; } +.font-size-btn:hover { background: #333; border-color: #666; } +.font-size-btn.active { background: #646cff; border-color: #646cff; color: white; } +.setting-preview { margin: 1.5rem 0; padding: 1rem; background: #1a1a1a; border: 1px solid #333; border-radius: 8px; } +.preview-label { font-size: 0.875rem; color: #999; margin-bottom: 0.75rem; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; } +.preview-content { color: #ddd; line-height: 1.7; } +.preview-content h3 { margin: 0 0 1rem 0; font-size: 1.5em; color: #fff; } +.preview-content p { margin: 0.75rem 0; } +.setting-select { width: 100%; padding: 0.5rem; background: #2a2a2a; border: 1px solid #444; border-radius: 4px; color: #fff; font-size: 1rem; } +.setting-inline .setting-select { width: auto; min-width: 200px; flex: 1; } +.setting-select:focus { outline: none; border-color: #646cff; } +.font-select option { padding: 0.5rem; font-size: 1rem; } +.checkbox-label { display: flex !important; align-items: center; gap: 0.75rem; cursor: pointer; user-select: none; text-align: left; justify-content: flex-start; margin-bottom: 0 !important; font-weight: normal !important; } +.setting-checkbox { width: 18px; height: 18px; cursor: pointer; flex-shrink: 0; margin: 0; accent-color: #646cff; } +.checkbox-label span { color: #ddd; text-align: left; font-weight: 500; } + + diff --git a/src/styles/components/icon-button.css b/src/styles/components/icon-button.css index e69de29b..79ee25cd 100644 --- a/src/styles/components/icon-button.css +++ b/src/styles/components/icon-button.css @@ -0,0 +1,43 @@ +/* Generic IconButton styling */ +.icon-button { + display: inline-flex; + align-items: center; + justify-content: center; + border: 1px solid #444; + border-radius: 6px; + background: #2a2a2a; + color: #ddd; + cursor: pointer; + min-width: 33px; + min-height: 33px; + padding: 0; + box-sizing: border-box; +} + +.icon-button:hover { background: #333; } +.icon-button:active { transform: translateY(1px); } + +.icon-button.primary { background: #646cff; color: white; border-color: #646cff; } +.icon-button.primary:hover { filter: brightness(1.05); } + +.icon-button.success { background: #28a745; color: white; border-color: #28a745; } +.icon-button.success:hover { filter: brightness(1.05); } + +.icon-button.ghost { background: #2a2a2a; } + +/* Mobile touch target improvements */ +@media (max-width: 768px) { + .icon-button { + min-width: var(--min-touch-target); + min-height: var(--min-touch-target); + } +} + +/* Disable hover effects on touch devices */ +@media (pointer: coarse) { + .icon-button:hover { background: #2a2a2a; } + .icon-button.ghost:hover { background: #2a2a2a; } + .icon-button:active { background: #333; } +} + + diff --git a/src/styles/components/modals.css b/src/styles/components/modals.css index e69de29b..08845f23 100644 --- a/src/styles/components/modals.css +++ b/src/styles/components/modals.css @@ -0,0 +1,28 @@ +/* Add Bookmark Modal */ +.modal-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.75); display: flex; align-items: center; justify-content: center; z-index: 10000; padding: 1rem; } +.modal-content { background: #1a1a1a; border: 1px solid #333; border-radius: 12px; max-width: 500px; width: 100%; max-height: 90vh; overflow-y: auto; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5); box-sizing: border-box; } +@media (max-width: 768px) { + .modal-overlay { padding: 0; align-items: flex-end; } + .modal-content { max-width: 100%; max-height: 95vh; max-height: 95dvh; border-radius: 16px 16px 0 0; margin: 0; padding-bottom: var(--safe-area-bottom); } +} +.modal-header { display: flex; align-items: center; justify-content: space-between; padding: 1.5rem; border-bottom: 1px solid #333; } +.modal-header h2 { margin: 0; font-size: 1.5rem; color: #fff; } +.modal-form { padding: 1.5rem; } +.form-group { margin-bottom: 1.25rem; } +.form-group label { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.5rem; color: #ccc; font-size: 0.9rem; font-weight: 500; } +.fetching-indicator { font-size: 0.8rem; color: #999; font-weight: normal; display: inline-flex; align-items: center; gap: 0.5rem; } +.form-group input, .form-group textarea { width: 100%; padding: 0.75rem; background: #2a2a2a; border: 1px solid #444; border-radius: 6px; color: #fff; font-size: 1rem; font-family: inherit; transition: border-color 0.2s; box-sizing: border-box; } +.form-group input:focus, .form-group textarea:focus { outline: none; border-color: #646cff; } +.form-group input:disabled, .form-group textarea:disabled { opacity: 0.6; cursor: not-allowed; } +.form-group textarea { resize: vertical; min-height: 80px; } +.form-helper-text { margin-top: 0.25rem; font-size: 0.8rem; color: #999; line-height: 1.4; } +.modal-error { padding: 0.75rem; background: rgba(220, 53, 69, 0.1); border: 1px solid #dc3545; border-radius: 6px; color: #dc3545; font-size: 0.9rem; margin-bottom: 1rem; } +.modal-actions { display: flex; gap: 0.75rem; justify-content: flex-end; margin-top: 1.5rem; } +.btn-secondary { padding: 0.75rem 1.5rem; background: #2a2a2a; border: 1px solid #444; border-radius: 6px; color: #ccc; font-size: 1rem; cursor: pointer; transition: all 0.2s; } +.btn-secondary:hover:not(:disabled) { background: #333; border-color: #646cff; color: white; } +.btn-secondary:disabled { opacity: 0.6; cursor: not-allowed; } +.btn-primary { padding: 0.75rem 1.5rem; background: #646cff; border: none; border-radius: 6px; color: white; font-size: 1rem; cursor: pointer; transition: background-color 0.2s; } +.btn-primary:hover:not(:disabled) { background: #535bf2; } +.btn-primary:disabled { opacity: 0.6; cursor: not-allowed; } + + diff --git a/src/styles/components/profile.css b/src/styles/components/profile.css index e69de29b..1d38ccf8 100644 --- a/src/styles/components/profile.css +++ b/src/styles/components/profile.css @@ -0,0 +1,20 @@ +/* Profile UI fragments */ +.author-card-container { display: flex; justify-content: center; padding: 2rem 1rem; } +.author-card { display: flex; gap: 1rem; padding: 1.5rem; background: #1a1a1a; border: 1px solid #333; border-radius: 12px; max-width: 600px; width: 100%; } +.author-card-avatar { flex-shrink: 0; width: 60px; height: 60px; border-radius: 50%; overflow: hidden; background: #2a2a2a; display: flex; align-items: center; justify-content: center; color: #666; } +.author-card-avatar img { width: 100%; height: 100%; object-fit: cover; } +.author-card-avatar svg { font-size: 2.5rem; } +.author-card-content { flex: 1; min-width: 0; } +.author-card-name { font-size: 1rem; font-weight: 600; color: #ddd; margin-bottom: 0.5rem; } +.author-card-bio { font-size: 0.9rem; color: #999; line-height: 1.5; margin: 0; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; } + +@media (max-width: 768px) { + .author-card-container { padding: 1.5rem 1rem; } + .author-card { padding: 1rem; } + .author-card-avatar { width: 48px; height: 48px; } + .author-card-avatar svg { font-size: 2rem; } + .author-card-name { font-size: 0.95rem; } + .author-card-bio { font-size: 0.85rem; -webkit-line-clamp: 2; } +} + + diff --git a/src/styles/components/reader.css b/src/styles/components/reader.css index e69de29b..6e3dff73 100644 --- a/src/styles/components/reader.css +++ b/src/styles/components/reader.css @@ -0,0 +1,69 @@ +/* Reader view */ +.reader { background: #1a1a1a; border: 1px solid #333; border-radius: 8px; padding: 0.75rem; text-align: left; overflow: hidden; contain: layout style; } +.reader.empty { color: #888; } +.loading-spinner { display: flex; align-items: center; gap: 0.5rem; color: #888; } +.loading-spinner svg { font-size: 1.2rem; } +.reader-header { margin-bottom: 2rem; position: relative; } +.reader-title { margin: 0 0 0.75rem 0; font-family: var(--reading-font); } +.reader-summary { color: #aaa; font-size: 1.1rem; line-height: 1.5; margin: 0 0 1rem 0; font-family: var(--reading-font); } +.reader-meta { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; } +.publish-date { display: flex; align-items: center; gap: 0.4rem; font-size: 0.813rem; color: rgba(136, 136, 136, 0.7); opacity: 0.85; } +.publish-date svg { font-size: 0.75rem; opacity: 0.6; } +.publish-date-topright { position: absolute; top: 1rem; right: 1rem; font-size: 0.813rem; color: #fff; padding: 0.4rem 0.75rem; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); z-index: 10; } +.reading-time { display: flex; align-items: center; gap: 0.5rem; padding: 0.375rem 0.75rem; background: rgba(136, 136, 136, 0.1); border: 1px solid rgba(136, 136, 136, 0.3); border-radius: 6px; font-size: 0.875rem; color: #888; } +.reading-time svg { font-size: 0.875rem; } +.highlight-indicator { display: flex; align-items: center; gap: 0.5rem; padding: 0.375rem 0.75rem; background: rgba(100, 108, 255, 0.1); border: 1px solid rgba(100, 108, 255, 0.3); border-radius: 6px; font-size: 0.875rem; color: #646cff; } +.highlight-indicator svg { font-size: 0.875rem; } +.reader-html { color: #ddd; line-height: 1.6; word-wrap: break-word; overflow-wrap: break-word; word-break: break-word; font-family: var(--reading-font); font-size: var(--reading-font-size); } +.reader-markdown { color: #ddd; line-height: 1.7; font-family: var(--reading-font); font-size: var(--reading-font-size); } +/* Ensure content is left-aligned even if source markup uses center */ +.reader .reader-html *, .reader .reader-markdown * { text-align: left !important; font-family: inherit !important; } +.reader center, .reader [align="center"] { text-align: left !important; } +/* Tame images from external content */ +.reader .reader-html img, .reader .reader-markdown img { max-width: 100%; max-height: 70vh; height: auto; width: auto; display: block; margin: 0.75rem 0; border-radius: 6px; } +.reader-markdown h1, .reader-markdown h2, .reader-markdown h3, .reader-markdown h4 { margin-top: 1.2rem; } +.reader-markdown p { margin: 0.5rem 0; } +.reader-html p, .reader-html div, .reader-html span, .reader-html li, .reader-html td, .reader-html th { font-size: 1em !important; } +.reader-markdown a { color: #8ab4f8; text-decoration: none; } +.reader-markdown a:hover { text-decoration: underline; } +.reader-markdown pre, .reader-markdown code { background: #111; border: 1px solid #333; border-radius: 6px; } +.reader-markdown pre { padding: 0.75rem; overflow: auto; } +.reader-markdown code { padding: 0.1rem 0.3rem; } +/* Mark as Read button */ +.mark-as-read-container { display: flex; justify-content: center; align-items: center; padding: 2rem 1rem; margin-top: 2rem; border-top: 1px solid #333; } +.mark-as-read-btn { display: flex; align-items: center; gap: 0.5rem; padding: 0.75rem 1.5rem; background: #2a2a2a; color: #ddd; border: 1px solid #444; border-radius: 8px; font-size: 1rem; font-weight: 500; cursor: pointer; transition: all 0.2s ease; min-width: 160px; justify-content: center; } +.mark-as-read-btn:hover:not(:disabled) { background: #333; border-color: #555; transform: translateY(-1px); } +.mark-as-read-btn:active:not(:disabled) { transform: translateY(0); } +.mark-as-read-btn:disabled { opacity: 0.6; cursor: not-allowed; } +.mark-as-read-btn svg { font-size: 1.1rem; } +@media (max-width: 768px) { + .mark-as-read-container { padding: 1.5rem 1rem; } + .mark-as-read-btn { width: 100%; max-width: 300px; } +} + +/* Hero image in reader/card views */ +.article-hero-image { width: 100%; height: 200px; background-size: cover; background-position: center; background-repeat: no-repeat; cursor: pointer; transition: all 0.2s ease; border-radius: 8px 8px 0 0; position: relative; } +.article-hero-image:hover { opacity: 0.9; } +.article-hero-image::after { content: ''; position: absolute; inset: 0; background: linear-gradient(to bottom, transparent 60%, rgba(0,0,0,0.4) 100%); pointer-events: none; border-radius: 8px 8px 0 0; } +.reader-hero-image { width: calc(100% + 1.5rem); margin: -0.75rem -0.75rem 2rem -0.75rem; border-radius: 0; overflow: hidden; position: relative; min-height: 300px; } +.reader-hero-image img { width: 100%; height: auto; max-height: 500px; object-fit: cover; display: block; } +.reader-header-overlay { position: absolute; bottom: 0; left: 0; right: 0; padding: 2rem 2rem 1.5rem; background: linear-gradient(to top, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.6) 60%, rgba(0, 0, 0, 0) 100%); } +.reader-header-overlay .reader-title { color: #fff; text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5); margin-bottom: 0.75rem; } +.reader-header-overlay .reader-summary { color: rgba(255, 255, 255, 0.9); font-size: 1.1rem; line-height: 1.5; margin: 0 0 1rem 0; text-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); font-family: var(--reading-font); } +.reader-header-overlay .reader-meta { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; } +.reader-header-overlay .publish-date { color: rgba(255, 255, 255, 0.65); text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); opacity: 1; } +.reader-header-overlay .publish-date svg { opacity: 0.7; } +.reader-header-overlay .reading-time, .reader-header-overlay .highlight-indicator { background: rgba(255, 255, 255, 0.15); backdrop-filter: blur(8px); border: 1px solid rgba(255, 255, 255, 0.25); color: #fff; } +.reader-header-overlay .highlight-indicator { background: rgba(100, 108, 255, 0.25); border: 1px solid rgba(100, 108, 255, 0.4); } +.reader-summary-below-image { display: none; } +@media (max-width: 768px) { + .reader-header-overlay .reader-summary.hide-on-mobile { display: none; } + .reader-summary-below-image { display: block; padding: 0 0 1.5rem 0; margin-top: -1rem; } + .reader-summary-below-image .reader-summary { color: #aaa; font-size: 1rem; line-height: 1.6; margin: 0; } + .reader-hero-image { min-height: 280px; max-height: 400px; height: 50vh; } + .reader-hero-image img { height: 100%; width: 100%; object-fit: cover; object-position: center; } + .reader-header-overlay { padding: 1.5rem 1rem 1rem; } + .reader-header-overlay .reader-title { font-size: 1.5rem; line-height: 1.3; } +} + + diff --git a/src/styles/components/settings.css b/src/styles/components/settings.css index e69de29b..95cb0cca 100644 --- a/src/styles/components/settings.css +++ b/src/styles/components/settings.css @@ -0,0 +1,15 @@ +/* Settings view containers */ +.settings-view { display: flex; flex-direction: column; height: 100%; overflow: hidden; padding: 0.75rem 1rem; text-align: left; } +.settings-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.5rem; padding: 0; } +.settings-header h2 { margin: 0; font-size: 1.5rem; font-weight: 600; text-align: left; } +.settings-header-actions { display: flex; gap: 0.5rem; align-items: center; } +.settings-content { overflow-y: auto; flex: 1; margin-bottom: 1rem; text-align: left; padding: 0 0.25rem 2rem 0.25rem; } +.settings-section { margin-bottom: 2.5rem; } +.settings-section:last-child { margin-bottom: 0; } +.section-title { font-size: 1rem; font-weight: 600; color: #fff; margin: 0 0 1rem 0; padding-bottom: 0.5rem; border-bottom: 1px solid #333; text-transform: uppercase; letter-spacing: 0.05em; } +.settings-footer { display: flex; justify-content: flex-start; padding: 1rem 0 0.5rem 0; flex-shrink: 0; } +.settings-footer .btn-primary { background: #646cff; color: white; border: none; padding: 0.75rem 1.5rem; border-radius: 4px; font-size: 1rem; cursor: pointer; transition: background-color 0.2s; display: flex; align-items: center; gap: 0.5rem; } +.settings-footer .btn-primary:hover:not(:disabled) { background: #535bf2; } +.settings-footer .btn-primary:disabled { opacity: 0.6; cursor: not-allowed; } + + diff --git a/src/styles/components/toast.css b/src/styles/components/toast.css index e69de29b..e7487882 100644 --- a/src/styles/components/toast.css +++ b/src/styles/components/toast.css @@ -0,0 +1,13 @@ +/* Toast Notification */ +.toast { position: fixed; top: 2rem; right: 2rem; background: #1a1a1a; color: #fff; padding: 1rem 1.5rem; border-radius: 8px; border: 1px solid #333; display: flex; align-items: center; gap: 0.75rem; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); animation: toast-slide-in 0.3s ease-out; z-index: 9999; font-size: 0.95rem; } +@media (max-width: 768px) { + .toast { top: auto; bottom: calc(1rem + var(--safe-area-bottom)); right: 1rem; left: 1rem; max-width: calc(100% - 2rem); } + @keyframes toast-slide-in { from { transform: translateY(100px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } +} +.toast-success { border-color: #28a745; } +.toast-success svg { color: #28a745; } +.toast-error { border-color: #dc3545; } +.toast-error svg { color: #dc3545; } +@keyframes toast-slide-in { from { transform: translateX(400px); opacity: 0; } to { transform: translateX(0); opacity: 1; } } + + diff --git a/src/styles/layout/app.css b/src/styles/layout/app.css index e69de29b..62dbce0b 100644 --- a/src/styles/layout/app.css +++ b/src/styles/layout/app.css @@ -0,0 +1,145 @@ +/* App-level layout and panes */ +.bookmarks-list { + display: flex; + flex-direction: column; + gap: 1.5rem; + max-width: 600px; + margin: 0 auto; +} + +/* Two-pane layout (legacy support) */ +.two-pane { + display: grid; + grid-template-columns: 360px 1fr; + column-gap: 0; + height: calc(100vh - 4rem); + transition: grid-template-columns 0.3s ease; +} + +.two-pane.sidebar-collapsed { grid-template-columns: 60px 1fr; } + +/* Three-pane layout */ +.three-pane { + display: grid; + grid-template-columns: var(--sidebar-width) 1fr var(--highlights-width); + column-gap: 0; + height: calc(100vh - 2rem); + transition: grid-template-columns 0.3s ease; + position: relative; +} + +@supports (height: 100dvh) { + .three-pane { height: calc(100dvh - 2rem); } +} + +.three-pane.sidebar-collapsed { grid-template-columns: var(--sidebar-collapsed-width) 1fr var(--highlights-width); } +.three-pane.highlights-collapsed { grid-template-columns: var(--sidebar-width) 1fr var(--highlights-collapsed-width); } +.three-pane.sidebar-collapsed.highlights-collapsed { grid-template-columns: var(--sidebar-collapsed-width) 1fr var(--highlights-collapsed-width); } + +/* Mobile three-pane layout */ +@media (max-width: 768px) { + .three-pane { + grid-template-columns: 1fr; + grid-template-rows: 1fr; + height: 100vh; + height: 100dvh; + } + .three-pane.sidebar-collapsed, + .three-pane.highlights-collapsed, + .three-pane.sidebar-collapsed.highlights-collapsed { grid-template-columns: 1fr; } +} + +.pane.sidebar { overflow-y: auto; height: 100%; } +.pane.main { + overflow-y: auto; + height: 100%; + max-width: var(--main-max-width); + margin: 0 auto; + padding: 0 var(--main-horizontal-padding); + overflow-x: hidden; + contain: layout style; +} + +/* Remove padding when sidebar is collapsed for zero gap */ +.three-pane.sidebar-collapsed .pane.main { padding-left: 0; } +.three-pane.sidebar-collapsed.highlights-collapsed .pane.main { padding-left: 0; } +.pane.highlights { overflow-y: auto; height: 100%; } + +/* Ensure panes are stacked in the correct order on desktop */ +@media (min-width: 769px) { + /* Desktop stacking to keep highlights above main without overlap */ + .three-pane .pane.sidebar { z-index: 1; } + .three-pane .pane.main { z-index: 1; } + .three-pane .pane.highlights { z-index: 2; } +} + +/* Mobile pane styles */ +@media (max-width: 768px) { + /* Both sidepanes slide in as overlays */ + .pane.sidebar, + .pane.highlights { + position: fixed; + top: 0; + width: 85%; + max-width: 320px; + height: 100vh; + height: 100dvh; + background: #1a1a1a; + z-index: 1001; /* Above backdrop */ + transition: transform 0.3s ease; + box-shadow: none; + display: flex; + flex-direction: column; + } + /* Ensure content fills the mobile sidepanes */ + .pane.sidebar > *, + .pane.highlights > * { width: 100%; height: 100%; } + /* Remove borders from containers in mobile overlays */ + .pane.sidebar .bookmarks-container, + .pane.highlights .highlights-container { border: none; border-radius: 0; flex: 1; min-height: 0; } + /* Bookmarks sidebar from left */ + .pane.sidebar { left: 0; transform: translateX(-100%); } + .pane.sidebar.mobile-open { transform: translateX(0); box-shadow: 4px 0 12px rgba(0, 0, 0, 0.5); } + /* Highlights sidebar from right */ + .pane.highlights { right: 0; transform: translateX(100%); } + .pane.highlights.mobile-open { transform: translateX(0); box-shadow: -4px 0 12px rgba(0, 0, 0, 0.5); } + .pane.main { grid-column: 1; grid-row: 1; padding: 0.5rem; max-width: 100%; transition: opacity 0.2s ease; } + /* Hide main content when sidepanes are open on mobile */ + .three-pane .pane.main.mobile-hidden { opacity: 0; pointer-events: none; } + .mobile-sidebar-backdrop { + display: none; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.45); + z-index: 999; /* Below sidepanes */ + opacity: 0; + transition: opacity 0.3s ease; + } + .mobile-sidebar-backdrop.visible { display: block; opacity: 1; } + .mobile-highlights-btn { + display: none; + position: fixed; + top: calc(1rem + env(safe-area-inset-top)); + right: calc(1rem + env(safe-area-inset-right)); + z-index: 900; + background: #2a2a2a; + border: 1px solid #444; + border-radius: 8px; + color: #ddd; + width: var(--min-touch-target); + height: var(--min-touch-target); + align-items: center; + justify-content: center; + cursor: pointer; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); + transition: transform 0.2s ease, opacity 0.3s ease, visibility 0.3s ease; + } + .mobile-highlights-btn.hidden { opacity: 0; visibility: hidden; pointer-events: none; } + .mobile-highlights-btn.visible { opacity: 1; visibility: visible; } + @media (max-width: 768px) { .mobile-highlights-btn { display: flex; } } +} + + diff --git a/src/styles/layout/highlights.css b/src/styles/layout/highlights.css index e69de29b..f0742d30 100644 --- a/src/styles/layout/highlights.css +++ b/src/styles/layout/highlights.css @@ -0,0 +1,150 @@ +/* Highlights panel layout and interactions */ +.highlights-container { + background: #1a1a1a; + border: 1px solid #333; + border-radius: 12px; + display: flex; + flex-direction: column; + height: 100%; + overflow: hidden; +} + +.highlights-container.collapsed { + display: flex; + align-items: flex-start; + justify-content: flex-start; + padding: 0; + background: transparent; + border: none; +} + +.highlights-container.collapsed .toggle-highlights-btn { + background: #2a2a2a; + color: #ddd; + border: none; + padding: 0; + border-radius: 0; + cursor: pointer; + transition: all 0.2s ease; + display: flex; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; +} + +.highlights-container.collapsed .toggle-highlights-btn:hover { background: #333; color: #fff; } +.highlights-container.collapsed .toggle-highlights-btn:active { transform: translateY(1px); } +.highlights-container.collapsed .toggle-highlights-btn.with-icon { width: auto; padding: 0 0.5rem; gap: 0.5rem; } + +.highlights-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.75rem 1rem; + border-bottom: 1px solid #333; + background: #1a1a1a; + border-radius: 12px 12px 0 0; +} + +.highlights-actions { display: flex; align-items: center; justify-content: space-between; width: 100%; } +.highlights-actions-left { display: flex; align-items: center; gap: 0.5rem; } + +.highlights-title { display: flex; align-items: center; gap: 0.5rem; } +.highlights-title h3 { margin: 0; font-size: 1rem; font-weight: 600; } +.highlights-title .count { color: #888; font-size: 0.875rem; } + +.highlight-mode-toggle { display: flex; gap: 0.25rem; padding: 0.25rem; background: rgba(255, 255, 255, 0.05); border-radius: 4px; } +.highlight-mode-toggle .mode-btn { background: none; border: none; color: #888; cursor: pointer; padding: 0.375rem 0.5rem; border-radius: 3px; transition: all 0.2s; font-size: 0.9rem; } +.highlight-mode-toggle .mode-btn:hover { background: rgba(255, 255, 255, 0.1); color: #fff; } +.highlight-mode-toggle .mode-btn.active { background: #646cff; color: #fff; } + +/* Three-level highlight toggles */ +.highlight-level-toggles { display: flex; gap: 0.25rem; padding: 0.25rem; background: rgba(255, 255, 255, 0.05); border-radius: 4px; } +.highlight-level-toggles .level-toggle-btn { background: none; border: none; color: #888; cursor: pointer; padding: 0.375rem 0.5rem; border-radius: 3px; transition: all 0.2s; font-size: 0.9rem; } +.highlight-level-toggles .level-toggle-btn:hover { background: rgba(255, 255, 255, 0.1); } +.highlight-level-toggles .level-toggle-btn.active { background: rgba(255, 255, 255, 0.1); opacity: 1; } +.highlight-level-toggles .level-toggle-btn:not(.active) { opacity: 0.4; } +.highlight-level-toggles .level-toggle-btn:disabled { opacity: 0.3; cursor: not-allowed; } +.highlight-level-toggles .level-toggle-btn:disabled:hover { background: none; } + +.refresh-highlights-btn, +.toggle-highlight-display-btn, +.toggle-highlights-btn { + background: transparent; + color: #ddd; + border: 1px solid #444; + padding: 0; + border-radius: 6px; + cursor: pointer; + width: 36px; + height: 36px; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; +} + +.refresh-highlights-btn:hover, +.toggle-highlight-display-btn:hover, +.toggle-highlights-btn:hover { background: #2a2a2a; color: #fff; } +.refresh-highlights-btn:active, +.toggle-highlight-display-btn:active, +.toggle-highlights-btn:active { transform: translateY(1px); } +.refresh-highlights-btn:disabled { opacity: 0.5; cursor: not-allowed; } +.refresh-highlights-btn:disabled:hover { background: transparent; color: #ddd; } + +.highlights-loading, +.highlights-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 2rem 1rem; color: #888; text-align: center; gap: 0.5rem; } +.highlights-empty svg { color: #555; margin-bottom: 0.5rem; } +.empty-hint { font-size: 0.875rem; color: #666; margin-top: 0.5rem; } + +.highlights-list { overflow-y: auto; padding: 1rem; display: flex; flex-direction: column; gap: 1rem; } +.highlight-item { background: #1e1e1e; border: 1px solid #333; border-radius: 8px; padding: 1rem; display: flex; gap: 0.75rem; transition: border-color 0.2s ease; } +.highlight-item:hover { border-color: #646cff; } +.highlight-item.selected { border-color: #646cff; background: #252525; box-shadow: 0 0 0 2px rgba(100, 108, 255, 0.3); } + +/* Level colors in sidebar items */ +.highlight-item.level-mine { border-color: color-mix(in srgb, var(--highlight-color-mine, #ffff00) 60%, #333); box-shadow: 0 0 0 1px color-mix(in srgb, var(--highlight-color-mine, #ffff00) 25%, transparent); } +.highlight-item.level-friends { border-color: color-mix(in srgb, var(--highlight-color-friends, #f97316) 60%, #333); box-shadow: 0 0 0 1px color-mix(in srgb, var(--highlight-color-friends, #f97316) 25%, transparent); } +.highlight-item.level-nostrverse { border-color: color-mix(in srgb, var(--highlight-color-nostrverse, #9333ea) 60%, #333); box-shadow: 0 0 0 1px color-mix(in srgb, var(--highlight-color-nostrverse, #9333ea) 25%, transparent); } + +.highlight-quote-icon { color: #646cff; font-size: 1.2rem; flex-shrink: 0; margin-top: 0.25rem; position: relative; } +.highlight-relay-indicator { position: absolute; bottom: -4px; left: -6px; font-size: 0.7rem; color: #888; opacity: 0.7; transition: all 0.2s ease; cursor: pointer; padding: 4px; min-width: 20px; min-height: 20px; display: flex; align-items: center; justify-content: center; } +.highlight-relay-indicator:hover { opacity: 1; color: #aaa; transform: scale(1.1); } +.highlight-relay-indicator:active { transform: scale(0.95); } +.highlight-delete-btn { position: absolute; bottom: -4px; right: -6px; font-size: 0.7rem; color: #888; opacity: 0.7; transition: all 0.2s ease; cursor: pointer; padding: 4px; min-width: 20px; min-height: 20px; display: flex; align-items: center; justify-content: center; } +.highlight-delete-btn:hover { opacity: 1; color: #ff4444; transform: scale(1.1); } +.highlight-delete-btn:active { transform: scale(0.95); } + +/* Mobile: Larger touch targets and better spacing */ +@media (max-width: 768px) { + .highlight-quote-icon { min-width: 100px; } + .highlight-relay-indicator { bottom: -8px; left: -8px; padding: 8px; min-width: var(--min-touch-target); min-height: var(--min-touch-target); font-size: 0.85rem; } + .highlight-delete-btn { bottom: -8px; right: -8px; padding: 8px; min-width: var(--min-touch-target); min-height: var(--min-touch-target); font-size: 0.85rem; } +} + +/* Level-colored quote icon */ +.highlight-item.level-mine .highlight-quote-icon { color: var(--highlight-color-mine, #ffff00); } +.highlight-item.level-friends .highlight-quote-icon { color: var(--highlight-color-friends, #f97316); } +.highlight-item.level-nostrverse .highlight-quote-icon { color: var(--highlight-color-nostrverse, #9333ea); } + +.highlight-content { flex: 1; display: flex; flex-direction: column; gap: 0.75rem; } +.highlight-text { margin: 0; padding: 0; font-style: italic; color: #ddd; line-height: 1.6; border-left: none; font-size: 0.95rem; } +.highlight-comment { margin-top: 0.5rem; padding: 0.75rem; background: rgba(100, 108, 255, 0.1); border-left: 3px solid #646cff; border-radius: 4px; font-size: 0.875rem; color: #ddd; line-height: 1.5; } + +.highlight-meta { display: flex; align-items: center; gap: 0.5rem; font-size: 0.8rem; color: #888; flex-wrap: nowrap; min-height: 20px; } +.highlight-author { color: #aaa; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 150px; line-height: 1; } +.highlight-meta-separator { color: #666; flex-shrink: 0; line-height: 1; } +.highlight-time { color: #888; white-space: nowrap; flex-shrink: 0; line-height: 1; } +.highlight-menu-wrapper { position: relative; margin-left: auto; flex-shrink: 0; } +.highlight-menu-btn { background: none; border: none; color: #888; cursor: pointer; padding: 0.25rem 0.5rem; font-size: 0.875rem; display: flex; align-items: center; transition: color 0.2s ease; border-radius: 4px; } +.highlight-menu-btn:hover { color: #646cff; background: rgba(100, 108, 255, 0.1); } +.highlight-menu { position: absolute; right: 0; top: calc(100% + 4px); background: #2a2a2a; border: 1px solid #444; border-radius: 6px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); z-index: 1000; min-width: 160px; overflow: hidden; } +.highlight-menu-item { width: 100%; background: none; border: none; color: #ddd; padding: 0.625rem 0.875rem; font-size: 0.875rem; display: flex; align-items: center; gap: 0.625rem; cursor: pointer; transition: all 0.15s ease; text-align: left; white-space: nowrap; } +.highlight-menu-item:hover { background: rgba(100, 108, 255, 0.15); color: #fff; } +.highlight-menu-item:disabled { opacity: 0.5; cursor: not-allowed; } +.highlight-menu-item-danger:hover { background: rgba(255, 68, 68, 0.15); color: #ff4444; } +.highlight-menu-item svg { font-size: 0.875rem; flex-shrink: 0; } + + diff --git a/src/styles/layout/sidebar.css b/src/styles/layout/sidebar.css index e69de29b..7d1e977d 100644 --- a/src/styles/layout/sidebar.css +++ b/src/styles/layout/sidebar.css @@ -0,0 +1,183 @@ +/* Bookmarks and sidebar layout */ +.bookmarks-container { + background: #1a1a1a; + border: 1px solid #333; + border-radius: 12px; + display: flex; + flex-direction: column; + height: 100%; + overflow: hidden; + text-align: left; + padding: 0; +} + +.bookmarks-container .view-mode-controls { + margin-top: auto; + padding: 1rem; + border-top: 1px solid #333; + background: transparent; + border-radius: 0; +} + +.bookmarks-container .bookmarks-list { + padding: 0.5rem; + overflow-y: auto; + overflow-x: hidden; + flex: 1; + width: 100%; + max-width: 100%; + box-sizing: border-box; +} + +.sidebar-header-bar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.75rem; + padding: 0.75rem 1rem; + background: #1a1a1a; + border: 1px solid #333; + border-radius: 12px 12px 0 0; + margin-bottom: 0; +} + +.sidebar-header-right { + display: flex; + align-items: center; + gap: 0.5rem; + margin-left: auto; +} + +.mobile-hamburger-btn { + display: none; + position: fixed; + top: calc(1rem + env(safe-area-inset-top)); + left: calc(1rem + env(safe-area-inset-left)); + z-index: 900; + background: #2a2a2a; + border: 1px solid #444; + border-radius: 8px; + color: #ddd; + width: var(--min-touch-target); + height: var(--min-touch-target); + align-items: center; + justify-content: center; + cursor: pointer; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); + transition: transform 0.2s ease, opacity 0.3s ease, visibility 0.3s ease; +} + +.mobile-hamburger-btn.hidden { + opacity: 0; + visibility: hidden; + pointer-events: none; +} + +.mobile-hamburger-btn.visible { + opacity: 1; + visibility: visible; +} + +.mobile-hamburger-btn:active { + transform: scale(0.95); +} + +.mobile-close-btn { + display: none; +} + +@media (max-width: 768px) { + .mobile-hamburger-btn { display: flex; } + .sidebar-header-bar .toggle-sidebar-btn { display: none; } + .mobile-close-btn { display: flex; } +} + +.view-mode-controls { + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; +} + +.profile-avatar { + width: 33px; + height: 33px; + border-radius: 6px; + overflow: hidden; + display: flex; + align-items: center; + justify-content: center; + background: #2a2a2a; + border: 1px solid #444; + flex-shrink: 0; + color: #ddd; + box-sizing: border-box; +} + +.profile-avatar img { width: 100%; height: 100%; object-fit: cover; } +.profile-avatar svg { font-size: 1.25rem; } + +.sidebar-header-bar .toggle-sidebar-btn { + background: transparent; + color: #ddd; + border: 1px solid #444; + padding: 0; + border-radius: 6px; + cursor: pointer; + transition: all 0.2s ease; + display: flex; + align-items: center; + justify-content: center; + width: 33px; + height: 33px; + flex-shrink: 0; + box-sizing: border-box; +} + +.sidebar-header-bar .toggle-sidebar-btn:hover { background: #2a2a2a; color: #fff; } +.sidebar-header-bar .toggle-sidebar-btn:active { transform: translateY(1px); } + +.bookmarks-container.collapsed { + display: flex; + align-items: flex-start; + justify-content: flex-start; + padding: 0; + background: transparent; + border: none; +} + +.bookmarks-container.collapsed .toggle-sidebar-btn { + background: #2a2a2a; + color: #ddd; + border: none; + padding: 0; + border-radius: 0; + cursor: pointer; + transition: all 0.2s ease; + display: flex; + align-items: center; + justify-content: center; + width: 48px; + height: 36px; + flex-shrink: 0; +} + +.bookmarks-container.collapsed .toggle-sidebar-btn:hover { background: #333; color: #fff; } +.bookmarks-container.collapsed .toggle-sidebar-btn:active { transform: translateY(1px); } +.bookmarks-container.collapsed .toggle-sidebar-btn.with-icon { width: auto; padding: 0 0.5rem; gap: 0.5rem; } +.bookmarks-container.collapsed .toggle-sidebar-btn .glow-blue { color: #646cff; filter: drop-shadow(0 0 4px rgba(100, 108, 255, 0.6)); } + +.user-info { margin: 0.5rem 0 0 0; color: #888; font-size: 0.9rem; font-family: monospace; } +.bookmark-count { color: #666; font-size: 0.9rem; margin: 0.5rem 0; } +.event-link { color: #8ab4f8; text-decoration: none; font-weight: 500; } +.event-link:hover { text-decoration: underline; } + +.bookmark-urls { margin: 0.75rem 0; } +.bookmark-url { display: block; margin: 0.25rem 0; color: #007bff; text-decoration: none; word-break: break-all; background: none; border: none; padding: 0; font: inherit; cursor: pointer; text-align: left; width: 100%; } +.bookmark-url:hover { text-decoration: underline; } + +.url-row { display: flex; align-items: center; gap: 0.5rem; } +.read-inline-btn { background: #28a745; color: white; border: none; padding: 0.25rem 0.5rem; border-radius: 4px; cursor: pointer; } +.read-inline-btn:hover { background: #218838; } + + diff --git a/src/styles/utils/animations.css b/src/styles/utils/animations.css index e69de29b..5149c5c3 100644 --- a/src/styles/utils/animations.css +++ b/src/styles/utils/animations.css @@ -0,0 +1,24 @@ +/* Reusable keyframes */ +@keyframes pulse-glow { + 0%, 100% { opacity: 0.8; transform: scale(1); } + 50% { opacity: 1; transform: scale(1.1); } +} + +@keyframes toast-slide-in { + from { transform: translateX(400px); opacity: 0; } + to { transform: translateX(0); opacity: 1; } +} + +@keyframes pulse { + 0%, 100% { opacity: 0.4; transform: scale(1); } + 50% { opacity: 1; transform: scale(1.1); } +} + +@keyframes highlight-pulse-animation { + 0%, 100% { box-shadow: 0 0 8px rgba(var(--highlight-rgb, 255, 255, 0), 0.2); transform: scale(1); } + 25% { box-shadow: 0 0 20px rgba(var(--highlight-rgb, 255, 255, 0), 0.6); transform: scale(1.02); } + 50% { box-shadow: 0 0 8px rgba(var(--highlight-rgb, 255, 255, 0), 0.2); transform: scale(1); } + 75% { box-shadow: 0 0 20px rgba(var(--highlight-rgb, 255, 255, 0), 0.6); transform: scale(1.02); } +} + + diff --git a/src/styles/utils/utilities.css b/src/styles/utils/utilities.css index e69de29b..76bcc706 100644 --- a/src/styles/utils/utilities.css +++ b/src/styles/utils/utilities.css @@ -0,0 +1,42 @@ +/* Inline content highlights - utilities */ +.content-highlight, .content-highlight-marker { background: rgba(var(--highlight-rgb, 255, 255, 0), 0.35); padding: 0.125rem 0.25rem; cursor: pointer; transition: all 0.2s ease; position: relative; border-radius: 2px; box-shadow: 0 0 8px rgba(var(--highlight-rgb, 255, 255, 0), 0.2); contain: layout style; } +.content-highlight:hover, .content-highlight-marker:hover { background: rgba(var(--highlight-rgb, 255, 255, 0), 0.5); box-shadow: 0 0 12px rgba(var(--highlight-rgb, 255, 255, 0), 0.3); } +.content-highlight-underline { background: transparent; padding: 0; cursor: pointer; transition: all 0.2s ease; position: relative; text-decoration: underline; text-decoration-color: rgba(var(--highlight-rgb, 255, 255, 0), 0.8); text-decoration-thickness: 2px; text-underline-offset: 2px; contain: layout style; } +.content-highlight-underline:hover { text-decoration-color: rgba(var(--highlight-rgb, 255, 255, 0), 1); text-decoration-thickness: 3px; } +.content-highlight.highlight-pulse, .content-highlight-marker.highlight-pulse, .content-highlight-underline.highlight-pulse { animation: highlight-pulse-animation 1.5s ease-in-out; } +.reader-html .content-highlight, .reader-markdown .content-highlight, .reader-html .content-highlight-marker, .reader-markdown .content-highlight-marker, .reader-html .content-highlight-underline, .reader-markdown .content-highlight-underline { color: inherit; } +.reader-html .content-highlight, .reader-markdown .content-highlight, .reader-html .content-highlight-marker, .reader-markdown .content-highlight-marker { text-decoration: none; } +/* Three-level highlight colors */ +.content-highlight-marker.level-mine, .content-highlight.level-mine { background: color-mix(in srgb, var(--highlight-color-mine, #ffff00) 35%, transparent); box-shadow: 0 0 8px color-mix(in srgb, var(--highlight-color-mine, #ffff00) 20%, transparent); } +.content-highlight-marker.level-mine:hover, .content-highlight.level-mine:hover { background: color-mix(in srgb, var(--highlight-color-mine, #ffff00) 50%, transparent); box-shadow: 0 0 12px color-mix(in srgb, var(--highlight-color-mine, #ffff00) 30%, transparent); } +.content-highlight-marker.level-friends, .content-highlight.level-friends { background: color-mix(in srgb, var(--highlight-color-friends, #f97316) 35%, transparent); box-shadow: 0 0 8px color-mix(in srgb, var(--highlight-color-friends, #f97316) 20%, transparent); } +.content-highlight-marker.level-friends:hover, .content-highlight.level-friends:hover { background: color-mix(in srgb, var(--highlight-color-friends, #f97316) 50%, transparent); box-shadow: 0 0 12px color-mix(in srgb, var(--highlight-color-friends, #f97316) 30%, transparent); } +.content-highlight-marker.level-nostrverse, .content-highlight.level-nostrverse { background: color-mix(in srgb, var(--highlight-color-nostrverse, #9333ea) 35%, transparent); box-shadow: 0 0 8px color-mix(in srgb, var(--highlight-color-nostrverse, #9333ea) 20%, transparent); } +.content-highlight-marker.level-nostrverse:hover, .content-highlight.level-nostrverse:hover { background: color-mix(in srgb, var(--highlight-color-nostrverse, #9333ea) 50%, transparent); box-shadow: 0 0 12px color-mix(in srgb, var(--highlight-color-nostrverse, #9333ea) 30%, transparent); } +/* Underline styles for three levels */ +.content-highlight-underline.level-mine { text-decoration-color: color-mix(in srgb, var(--highlight-color-mine, #ffff00) 80%, transparent); } +.content-highlight-underline.level-mine:hover { text-decoration-color: var(--highlight-color-mine, #ffff00); } +.content-highlight-underline.level-friends { text-decoration-color: color-mix(in srgb, var(--highlight-color-friends, #f97316) 80%, transparent); } +.content-highlight-underline.level-friends:hover { text-decoration-color: var(--highlight-color-friends, #f97316); } +.content-highlight-underline.level-nostrverse { text-decoration-color: color-mix(in srgb, var(--highlight-color-nostrverse, #9333ea) 80%, transparent); } +.content-highlight-underline.level-nostrverse:hover { text-decoration-color: var(--highlight-color-nostrverse, #9333ea); } +/* Ensure highlights work in both light and dark mode */ +@media (prefers-color-scheme: light) { + .content-highlight, .content-highlight-marker { background: rgba(var(--highlight-rgb, 255, 255, 0), 0.4); box-shadow: 0 0 6px rgba(var(--highlight-rgb, 255, 255, 0), 0.15); } + .content-highlight:hover, .content-highlight-marker:hover { background: rgba(var(--highlight-rgb, 255, 255, 0), 0.55); box-shadow: 0 0 10px rgba(var(--highlight-rgb, 255, 255, 0), 0.25); } + .content-highlight-underline { text-decoration-color: rgba(var(--highlight-rgb, 255, 255, 0), 0.9); } + .content-highlight-underline:hover { text-decoration-color: rgba(var(--highlight-rgb, 255, 255, 0), 1); } + /* Three-level overrides for light mode */ + .content-highlight-marker.level-mine, .content-highlight.level-mine { background: color-mix(in srgb, var(--highlight-color-mine, #ffff00) 40%, transparent); box-shadow: 0 0 6px color-mix(in srgb, var(--highlight-color-mine, #ffff00) 15%, transparent); } + .content-highlight-marker.level-mine:hover, .content-highlight.level-mine:hover { background: color-mix(in srgb, var(--highlight-color-mine, #ffff00) 55%, transparent); box-shadow: 0 0 10px color-mix(in srgb, var(--highlight-color-mine, #ffff00) 25%, transparent); } + .content-highlight-marker.level-friends, .content-highlight.level-friends { background: color-mix(in srgb, var(--highlight-color-friends, #f97316) 40%, transparent); box-shadow: 0 0 6px color-mix(in srgb, var(--highlight-color-friends, #f97316) 15%, transparent); } + .content-highlight-marker.level-friends:hover, .content-highlight.level-friends:hover { background: color-mix(in srgb, var(--highlight-color-friends, #f97316) 55%, transparent); box-shadow: 0 0 10px color-mix(in srgb, var(--highlight-color-friends, #f97316) 25%, transparent); } + .content-highlight-marker.level-nostrverse, .content-highlight.level-nostrverse { background: color-mix(in srgb, var(--highlight-color-nostrverse, #9333ea) 40%, transparent); box-shadow: 0 0 6px color-mix(in srgb, var(--highlight-color-nostrverse, #9333ea) 15%, transparent); } + .content-highlight-marker.level-nostrverse:hover, .content-highlight.level-nostrverse:hover { background: color-mix(in srgb, var(--highlight-color-nostrverse, #9333ea) 55%, transparent); box-shadow: 0 0 10px color-mix(in srgb, var(--highlight-color-nostrverse, #9333ea) 25%, transparent); } + .content-highlight-underline.level-mine { text-decoration-color: color-mix(in srgb, var(--highlight-color-mine, #ffff00) 90%, transparent); } + .content-highlight-underline.level-friends { text-decoration-color: color-mix(in srgb, var(--highlight-color-friends, #f97316) 90%, transparent); } + .content-highlight-underline.level-nostrverse { text-decoration-color: color-mix(in srgb, var(--highlight-color-nostrverse, #9333ea) 90%, transparent); } + .highlight-indicator { background: rgba(100, 108, 255, 0.15); border-color: rgba(100, 108, 255, 0.4); } +} + +