diff --git a/src/app/(app)/epub/[id]/page.tsx b/src/app/(app)/epub/[id]/page.tsx index f786c49..cf89c37 100644 --- a/src/app/(app)/epub/[id]/page.tsx +++ b/src/app/(app)/epub/[id]/page.tsx @@ -170,7 +170,7 @@ export default function EPUBPage() { if (error) { return (
-

{error}

+

{error}

-

{error}

+

{error}

-

{error}

+

{error}

{showDetailedParseLoader ? ( -
+
-
+
PDF Layout Parse

{statusText}

-
+

{hasMeasuredProgress ? `Page ${pagesParsed} / ${totalPages}` : 'Awaiting first page'} @@ -354,7 +354,7 @@ export default function PDFViewerPage() {

) : ( -
+
@@ -366,9 +366,9 @@ export default function PDFViewerPage() {
- - - + + +
)} diff --git a/src/app/(app)/signin/page.tsx b/src/app/(app)/signin/page.tsx index b89332b..bd0e93a 100644 --- a/src/app/(app)/signin/page.tsx +++ b/src/app/(app)/signin/page.tsx @@ -132,16 +132,16 @@ function SignInContent() { {/* Alerts */} {sessionExpired && ( -
-

+

+

Your session has expired. Please sign in again.

)} {error && ( -
-

{error}

+
+

{error}

)} diff --git a/src/app/(app)/signup/page.tsx b/src/app/(app)/signup/page.tsx index fec63de..20b87b9 100644 --- a/src/app/(app)/signup/page.tsx +++ b/src/app/(app)/signup/page.tsx @@ -125,7 +125,7 @@ export default function SignUpPage() { const { checks, strength } = validatePassword(password); const strengthLabels = ['Very Weak', 'Weak', 'Fair', 'Good', 'Strong']; - const strengthColors = ['bg-red-500', 'bg-orange-500', 'bg-yellow-500', 'bg-blue-500', 'bg-green-500']; + const strengthColors = ['bg-danger', 'bg-danger', 'bg-accent', 'bg-accent', 'bg-accent']; return (
@@ -134,8 +134,8 @@ export default function SignUpPage() {

Create your account to get started

{error && ( -
-

{error}

+
+

{error}

)} @@ -190,12 +190,12 @@ export default function SignUpPage() { /> ))}
-

= 3 ? 'text-green-600' : 'text-red-600'}`}> +

= 3 ? 'text-accent' : 'text-danger'}`}> {strengthLabels[strength - 1] || 'Very Weak'}

{Object.entries(checks).map(([key, passed]) => ( -
+
{passed ? '✓' : '○'} {key === 'length' && 'At least 8 characters'} @@ -223,7 +223,7 @@ export default function SignUpPage() { focus:outline-none focus:ring-2 focus:ring-accent" /> {passwordConfirmation && password && ( -

+

{password === passwordConfirmation ? '✓ Passwords match' : '✗ Passwords do not match'}

)} diff --git a/src/components/AudiobookExportModal.tsx b/src/components/AudiobookExportModal.tsx index e84f4dd..27d4c67 100644 --- a/src/components/AudiobookExportModal.tsx +++ b/src/components/AudiobookExportModal.tsx @@ -490,7 +490,7 @@ export function AudiobookExportModal({
{isLegacyAudiobookMissingSettings && ( -
+
Saved generation settings not found
This audiobook was likely created before v1 metadata was introduced, so OpenReader can't know @@ -694,9 +694,9 @@ export function AudiobookExportModal({
- + @@ -696,7 +696,7 @@ export function AdminProvidersPanel() { diff --git a/src/components/auth/ClaimDataModal.tsx b/src/components/auth/ClaimDataModal.tsx index 397a1ff..f354da8 100644 --- a/src/components/auth/ClaimDataModal.tsx +++ b/src/components/auth/ClaimDataModal.tsx @@ -112,9 +112,9 @@ export default function ClaimDataModal({ Claim it now to attach it to your account.

-
+
Claimable data
-
    +
    • {claimableCounts.documents} document(s)
    • {claimableCounts.audiobooks} audiobook(s)
    • {claimableCounts.preferences} preference set(s)
    • @@ -122,7 +122,7 @@ export default function ClaimDataModal({
-

+

⚠️ First user to claim this data will own it and revoke access for anyone else.

diff --git a/src/components/auth/RateLimitBanner.tsx b/src/components/auth/RateLimitBanner.tsx index 67377e4..5a8274f 100644 --- a/src/components/auth/RateLimitBanner.tsx +++ b/src/components/auth/RateLimitBanner.tsx @@ -19,13 +19,13 @@ export function RateLimitBanner({ className = '' }: RateLimitBannerProps) { const isAnonymous = status.userType === 'anonymous'; return ( -
+
- + Daily TTS limit reached. - + {`Used ${formatCharCount(status.currentCount)} / ${formatCharCount(status.limit)} characters.`} {' Resets in '}{timeUntilReset}. @@ -64,7 +64,7 @@ export function RateLimitIndicator({ className = '' }: RateLimitBannerProps) { if (isAtLimit) { return ( - + Limit reached ); diff --git a/src/components/doclist/DocumentList.tsx b/src/components/doclist/DocumentList.tsx index 7db6d67..3d62772 100644 --- a/src/components/doclist/DocumentList.tsx +++ b/src/components/doclist/DocumentList.tsx @@ -139,7 +139,7 @@ function SidebarUploadLoader({ const dashOffset = circumference - (progress / 100) * circumference; return ( -
+
{label} diff --git a/src/components/doclist/DocumentPreview.tsx b/src/components/doclist/DocumentPreview.tsx index 0518c3a..b2ce3a2 100644 --- a/src/components/doclist/DocumentPreview.tsx +++ b/src/components/doclist/DocumentPreview.tsx @@ -285,16 +285,16 @@ export function DocumentPreview({ doc }: DocumentPreviewProps) { ) : textPreview ? ( <> -
+
-
+
{isTxtFile ? ( -
+                
                   {textPreview}
                 
) : ( -
+
{children}, img: () => null, blockquote: (props) => ( -
+
), code: (props) => ( ), diff --git a/src/components/doclist/views/DocumentTile.tsx b/src/components/doclist/views/DocumentTile.tsx index d113529..179c48c 100644 --- a/src/components/doclist/views/DocumentTile.tsx +++ b/src/components/doclist/views/DocumentTile.tsx @@ -166,9 +166,9 @@ export function DocumentTile({ > {doc.type === 'pdf' ? ( - + ) : doc.type === 'epub' ? ( - + ) : ( )} diff --git a/src/components/doclist/views/GalleryView.tsx b/src/components/doclist/views/GalleryView.tsx index b680b9d..2857221 100644 --- a/src/components/doclist/views/GalleryView.tsx +++ b/src/components/doclist/views/GalleryView.tsx @@ -38,8 +38,8 @@ function formatParseStatus(status: DocumentListDocument['parseStatus']): string } function KindIcon({ doc, className }: { doc: DocumentListDocument; className?: string }) { - if (doc.type === 'pdf') return ; - if (doc.type === 'epub') return ; + if (doc.type === 'pdf') return ; + if (doc.type === 'epub') return ; return ; } diff --git a/src/components/doclist/views/ListView.tsx b/src/components/doclist/views/ListView.tsx index 7baaabf..4bb69b6 100644 --- a/src/components/doclist/views/ListView.tsx +++ b/src/components/doclist/views/ListView.tsx @@ -29,8 +29,8 @@ function formatDate(ms: number): string { } function KindIcon({ doc }: { doc: DocumentListDocument }) { - if (doc.type === 'pdf') return ; - if (doc.type === 'epub') return ; + if (doc.type === 'pdf') return ; + if (doc.type === 'epub') return ; return ; } diff --git a/src/components/doclist/window/FinderSidebar.tsx b/src/components/doclist/window/FinderSidebar.tsx index 8e69493..e5f77db 100644 --- a/src/components/doclist/window/FinderSidebar.tsx +++ b/src/components/doclist/window/FinderSidebar.tsx @@ -315,7 +315,7 @@ export function FinderSidebar({ onRowAction?.(); }} disabled={disabled} - className={`${disabled ? 'text-muted/60 cursor-not-allowed' : active ? 'bg-offbase text-accent' : 'text-foreground'} group flex w-full items-center gap-2 rounded-md px-2 py-2 text-xs`} + className={`${disabled ? 'text-faint cursor-not-allowed' : active ? 'bg-offbase text-accent' : 'text-foreground'} group flex w-full items-center gap-2 rounded-md px-2 py-2 text-xs`} > diff --git a/src/components/documents/DexieMigrationModal.tsx b/src/components/documents/DexieMigrationModal.tsx index 96ade51..3a13356 100644 --- a/src/components/documents/DexieMigrationModal.tsx +++ b/src/components/documents/DexieMigrationModal.tsx @@ -181,7 +181,7 @@ export function DexieMigrationModal({
)} - {!isUploading && status ?

{status}

: null} + {!isUploading && status ?

{status}

: null}
diff --git a/src/components/documents/DocumentSelectionModal.tsx b/src/components/documents/DocumentSelectionModal.tsx index 1ee240b..17c2f31 100644 --- a/src/components/documents/DocumentSelectionModal.tsx +++ b/src/components/documents/DocumentSelectionModal.tsx @@ -167,7 +167,7 @@ export function DocumentSelectionModal({ {isLoading ? ( ) : errorMessage ? ( -
{errorMessage}
+
{errorMessage}
) : files.length === 0 ? (
No documents found.
) : ( @@ -179,7 +179,7 @@ export function DocumentSelectionModal({ key={file.id} onClick={(e) => handleRowClick(e, file.id)} className={`flex items-center gap-3 px-3 py-2 rounded-md cursor-pointer text-sm select-none - ${isSelected ? 'bg-accent/10' : 'hover:bg-offbase'} + ${isSelected ? 'bg-accent-wash' : 'hover:bg-offbase'} `} >
e.stopPropagation()}> diff --git a/src/components/documents/DocumentSettings.tsx b/src/components/documents/DocumentSettings.tsx index 4dd1f9b..fc10cab 100644 --- a/src/components/documents/DocumentSettings.tsx +++ b/src/components/documents/DocumentSettings.tsx @@ -214,14 +214,14 @@ export function DocumentSettings({ isOpen, setIsOpen, epub, html, pdf }: { action={
- + PP-DocLayout-V3 {pdf.parseStatus ?? 'pending'} + ); +} + +export function Menu({ + children, + className = '', +}: { + children: ReactNode; + className?: string; +}) { + return ( +
+ {children} +
+ ); +} + export function Section({ title, subtitle, @@ -69,11 +157,11 @@ export function Section({ }) { if (variant === 'flat') { return ( -
+

{title}

- {subtitle ?

{subtitle}

: null} + {subtitle ?

{subtitle}

: null}
{action ?
{action}
: null}
@@ -83,12 +171,12 @@ export function Section({ } return ( -
-
+
+

{title}

- {subtitle ?

{subtitle}

: null} + {subtitle ?

{subtitle}

: null}
{action ?
{action}
: null}
@@ -108,7 +196,7 @@ export function Card({ className?: string; }) { return ( -
+
{children}
); @@ -159,13 +247,13 @@ export function Switch({ aria-describedby={ariaDescribedBy} disabled={disabled} onClick={() => onChange(!checked)} - className={`relative inline-flex shrink-0 cursor-pointer items-center rounded-full border border-offbase transition-colors duration-fast ease-standard focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed ${s.track} ${ - checked ? 'bg-accent' : 'bg-offbase' + className={`relative inline-flex shrink-0 cursor-pointer items-center rounded-full border border-line transition-colors duration-fast ease-standard focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed ${s.track} ${ + checked ? 'bg-accent' : 'bg-line-strong' }`} >
{right ?
{right}
: null} - {label ? : null} + {label ? : null} {children} - {hint ?

{hint}

: null} + {hint ?

{hint}

: null}
); } @@ -289,10 +377,10 @@ export function Badge({ }) { const toneClass = tone === 'accent' - ? 'text-accent' + ? 'text-accent bg-accent-wash' : tone === 'foreground' - ? 'text-foreground bg-offbase' - : 'text-muted bg-offbase'; + ? 'text-foreground bg-surface-sunken' + : 'text-soft bg-surface-sunken'; return ( {children} diff --git a/src/components/icons/Icons.tsx b/src/components/icons/Icons.tsx index 74c6e8f..7304ecf 100644 --- a/src/components/icons/Icons.tsx +++ b/src/components/icons/Icons.tsx @@ -246,7 +246,7 @@ export function GithubIcon(props: React.SVGProps) { export function PDFIcon(props: React.SVGProps) { return ( ) { export function EPUBIcon(props: React.SVGProps) { return ( ) : hasManifestError ? ( - error + error ) : ( )} @@ -698,7 +698,7 @@ export function SegmentsSidebar({ isOpen, setIsOpen, documentId, epubBookRef }:
{hasManifestError && ( -
{manifestErrorMessage}
+
{manifestErrorMessage}
)} {isManifestLoading && ( @@ -741,10 +741,10 @@ export function SegmentsSidebar({ isOpen, setIsOpen, documentId, epubBookRef }:
  • {showGroupHeader && ( -
    +
    {groupLabel} @@ -758,7 +758,7 @@ export function SegmentsSidebar({ isOpen, setIsOpen, documentId, epubBookRef }: type="button" onClick={() => { if (canJump) handleJump(segmentIndex, row.locator); }} disabled={!canJump} - className={`text-xs font-medium shrink-0 pt-0.5 ${canJump ? 'text-muted hover:text-accent' : 'text-muted/50 cursor-not-allowed'}`} + className={`text-xs font-medium shrink-0 pt-0.5 ${canJump ? 'text-muted hover:text-accent' : 'text-faint cursor-not-allowed'}`} title={canJump ? (playable ? 'Play this segment' : 'Jump to this segment') : 'Text not loaded yet'} aria-label={`Segment ${segmentIndex + 1}`} > @@ -772,7 +772,7 @@ export function SegmentsSidebar({ isOpen, setIsOpen, documentId, epubBookRef }: disabled={!canJump} className={`block w-full text-left ${canJump ? '' : 'cursor-not-allowed'}`} > -

    +

    {sentenceText || ( [text not loaded — press play to fetch] @@ -796,7 +796,7 @@ export function SegmentsSidebar({ isOpen, setIsOpen, documentId, epubBookRef }: )} {!canJump && ( - + not loaded )} @@ -820,7 +820,7 @@ export function SegmentsSidebar({ isOpen, setIsOpen, documentId, epubBookRef }: className={[ 'max-w-full whitespace-normal break-words text-left leading-none text-[10px] px-1 py-0.5 rounded border transition-colors', isActive - ? 'border-accent text-accent bg-offbase/60' + ? 'border-accent text-accent bg-surface-sunken' : known ? 'border-offbase text-muted hover:border-accent hover:text-accent' : 'border-offbase text-muted opacity-60 cursor-not-allowed', diff --git a/src/components/views/PDFViewer.tsx b/src/components/views/PDFViewer.tsx index 6ac12de..593cc34 100644 --- a/src/components/views/PDFViewer.tsx +++ b/src/components/views/PDFViewer.tsx @@ -480,7 +480,7 @@ export function PDFViewer({ zoomLevel, onDocumentReady, pdfState }: PDFViewerPro return (