{#if cropFile && browser}
{#await import('$lib/components/AvatarCropModal.svelte') then { default: AvatarCropModal }}
Welcome to Pro!
Your subscription is being activated. Refresh the page in a moment if the Pro badge doesn't appear yet.
{avatarError}
{:else}{m.profile_click_to_change()}
{/if}{m.profile_free_limits()}
{m.profile_upgrade_heading()}
{m.profile_upgrade_desc()} See plans →
{#if checkoutError}{checkoutError}
{/if}{m.profile_pro_active()}
{m.profile_pro_perks()}
{m.profile_theme_label()}
{m.profile_font_family()}
{m.profile_text_size()}
Playback
{m.profile_auto_advance()}
Load the next chapter automatically when audio ends
Announce chapter
Read the chapter title aloud before advancing
Audio mode
{audioStore.audioMode === 'stream' ? 'Stream — starts within seconds' : 'Generate — waits for full audio'} {#if audioStore.voice.startsWith('cfai:')} (not available for CF AI){/if}
{m.profile_session_unrecognised()}
{m.profile_no_sessions()}
{:else}{session.ip}
{/if}{m.profile_session_signed_in({ date: formatDate(session.created_at) })} {#if session.last_seen && session.last_seen !== session.created_at} {m.profile_session_last_seen({ date: formatDate(session.last_seen) })} {/if}
{#if pushState === 'subscribed'} You'll receive a push notification when new chapters are added to books in your library. {:else if pushState === 'denied'} Notifications are blocked by your browser. Change the permission in your browser settings. {:else} Get notified when new chapters arrive for books in your library. {/if}
{#if pushError}{pushError}
{/if}Delete account
This permanently deletes your account, reading history, settings, and all associated data. This action cannot be undone.
{deleteError}
{/if}{stat.value}
{stat.label}
{data.stats.streak}
day streak
{data.stats.avgRatingGiven > 0 ? data.stats.avgRatingGiven.toFixed(1) : '—'}
avg rating given
{data.stats.booksDropped} dropped book{data.stats.booksDropped !== 1 ? 's' : ''} — revisit your library
{/if}No reading history yet.
{item.title}
Chapter {item.chapter}
{#if item.updated} {(() => { const ms = Date.now() - new Date(item.updated).getTime(); const mins = Math.floor(ms / 60000); if (mins < 60) return mins <= 1 ? 'just now' : `${mins}m ago`; const hrs = Math.floor(mins / 60); if (hrs < 24) return `${hrs}h ago`; const days = Math.floor(hrs / 24); if (days < 30) return `${days}d ago`; return new Date(item.updated).toLocaleDateString(undefined, { month: 'short', day: 'numeric' }); })()} {/if}
{/each} {/if}