/** * Privacy policy, terms of service and cookie policy — in both app languages. * * Written to describe what this app *actually* does (local-first storage, the * key never leaving the browser, opt-in server copies), not a template. The * pages that render this live in app/privacy, app/terms and app/cookies; the * cookie banner links to the same text. Keep them in step with the code. */ export type LegalSection = { heading: string; paragraphs: string[]; list?: string[]; }; export type LegalDocument = { title: string; updated: string; intro: string; sections: LegalSection[]; footer: string; }; const UPDATED = "October 2026"; const PRIVACY_EN: LegalDocument = { title: "Privacy policy", updated: UPDATED, intro: "Freezmo is a self-hosted study app with no accounts. This page describes exactly what happens to your data — nothing here is boilerplate.", sections: [ { heading: "Everything lives in your browser", paragraphs: [ "Your decks, folders, homework, chats, study history and settings are stored in this browser (localStorage and IndexedDB). Nothing is uploaded unless you switch on one of the opt-ins below.", "Clearing the site data deletes it. Settings → Export all data gives you a complete copy at any time.", ], }, { heading: "Your Ollama API key", paragraphs: [ "The key is kept in this browser only. It is sent to this Freezmo server for the single model call you asked for, forwarded to Ollama, and forgotten: never written to disk, never logged, never part of a backup, sync payload or share link.", ], }, { heading: "What the server stores — only if you opt in", paragraphs: ["There is no other server-side data. Each of these is off until you turn it on:"], list: [ "Sync — an encrypted blob the server cannot read (the key stays in your browser). Revocable from Settings → Delete synced data.", "Reminders — the push endpoint your browser gave us, its keys and a timestamp. No personal data, no history.", "Reported questions — the question text, the deck and activity ids and a timestamp. These are how bad AI cards get fixed; they are the one thing an operator can read.", ], }, { heading: "What the server does not store", paragraphs: [ "No accounts, no email addresses, no analytics, no cookies, no tracking. The rate limiter keeps a client IP address in memory for a few minutes to stop floods and never writes it to disk.", ], }, { heading: "Third parties", paragraphs: [ "Model calls go to the Ollama endpoint this instance is configured for, using your key — Ollama's own privacy terms apply to them. Reminders travel through your browser's push service (Google, Mozilla or Apple). There is nothing else: no ads, no analytics, no embeds.", ], }, { heading: "Your choices", paragraphs: [ "Delete the local copy by clearing the site data (or Settings). Revoke the synced copy from Settings. Turn reminders off from Settings. If you want a reported question removed from the operator's file, ask the person running this instance — it is their file.", ], }, ], footer: "Plain-language description of how this app handles data — not legal advice.", }; const PRIVACY_CS: LegalDocument = { title: "Zásady ochrany soukromí", updated: "říjen 2026", intro: "Freezmo je samoobslužná studijní aplikace bez účtů. Tahle stránka popisuje, co se přesně děje s tvými daty — nic z toho není šablona.", sections: [ { heading: "Všechno zůstává v tvém prohlížeči", paragraphs: [ "Sady, složky, úkoly, chaty, historie učení i nastavení jsou uložené v tomto prohlížeči (localStorage a IndexedDB). Nic se neodesílá, dokud nezapneš některou z níže uvedených voleb.", "Smazáním dat stránky je smažeš. Nastavení → Exportovat všechna data ti kdykoli dá úplnou kopii.", ], }, { heading: "Tvůj API klíč Ollama", paragraphs: [ "Klíč je uložený jen v tomto prohlížeči. Posílá se tomuto serveru Freezmo pro jeden požadovaný modelový dotaz, server ho předá Ollamě a zapomene ho: nikdy se neukládá na disk, neloguje se a není součástí zálohy, synchronizace ani sdíleného odkazu.", ], }, { heading: "Co server ukládá — jen když to zapneš", paragraphs: ["Jiná data na serveru nejsou. Každá z těchhle věcí je vypnutá, dokud ji nezapneš:"], list: [ "Synchronizace — zašifrovaný blob, který server nedokáže přečíst (klíč zůstává v prohlížeči). Zrušitelný v Nastavení → Smazat synchronizovaná data.", "Připomínky — push endpoint, který ti dal prohlížeč, jeho klíče a časové razítko. Žádná osobní data, žádná historie.", "Nahlášené otázky — text otázky, ID sady a aktivity a časové razítko. Díky nim se opravují špatné AI kartičky; je to jediná věc, kterou provozovatel může číst.", ], }, { heading: "Co server neukládá", paragraphs: [ "Žádné účty, e-maily, analytiku, cookies ani sledování. Omezovač rychlosti drží IP adresu klienta pár minut v paměti, aby zastavil záplavy požadavků, a nikdy ji nezapisuje na disk.", ], }, { heading: "Třetí strany", paragraphs: [ "Modelové dotazy jdou na Ollama endpoint, který je tato instance nastavená používat, a to s tvým klíčem — platí na ně vlastní podmínky Ollamy. Připomínky putují přes push službu tvého prohlížeče (Google, Mozilla nebo Apple). Nic jiného tu není: žádné reklamy, analytika ani vložený obsah.", ], }, { heading: "Tvoje volby", paragraphs: [ "Lokální kopii smažeš smazáním dat stránky (nebo v Nastavení). Synchronizovanou kopii zrušíš v Nastavení. Připomínky vypneš v Nastavení. Pokud chceš, aby provozovatel odstranil nahlášenou otázku ze svého souboru, řekni mu to — ten soubor je jeho.", ], }, ], footer: "Popis v lidské řeči, jak aplikace nakládá s daty — není právní rada.", }; const TERMS_EN: LegalDocument = { title: "Terms of service", updated: UPDATED, intro: "Freezmo is free software (GPL-3.0-only) that someone is hosting for you — usually a friend or yourself. These are the house rules for using that instance.", sections: [ { heading: "The software comes as-is", paragraphs: [ "Freezmo is provided under the GNU General Public License v3 only, without warranty of any kind to the extent the law allows. AI output can be wrong: read it before you hand it in — that is what the note under every card is for.", ], }, { heading: "Your key, your usage", paragraphs: [ "You bring your own Ollama API key. Limits, costs and account standing are between you and Ollama. Never paste a key you do not own, and keep your own key to yourself.", ], }, { heading: "Fair use of the instance", paragraphs: [ "Don't flood it, don't try to break it and don't use it to attack anything else. The operator can rate-limit, block or shut the instance down at any time, and the app already refuses obvious abuse.", ], }, { heading: "Your content", paragraphs: [ "Your notes, decks, homework and chats are yours. They stay in your browser, so the operator cannot read them — the only exception is a question you report on purpose (see the privacy policy).", ], }, { heading: "Availability and changes", paragraphs: [ "This instance is a courtesy, with no uptime promise. The app and these terms may change; the current version always lives in the app, linked from Settings.", ], }, { heading: "Liability", paragraphs: [ "To the extent permitted by law, the operator and the authors are not liable for anything this app does or fails to do — including lost study time, lost data or a wrong answer in your homework.", ], }, ], footer: "Plain-language terms for a self-hosted app — not legal advice.", }; const TERMS_CS: LegalDocument = { title: "Podmínky použití", updated: "říjen 2026", intro: "Freezmo je svobodný software (GPL-3.0-only), který ti někdo hostuje — většinou kamarád nebo ty sám. Tohle jsou pravidla pro používání téhle instance.", sections: [ { heading: "Software je tak, jak je", paragraphs: [ "Freezmo se poskytuje pod licencí GNU General Public License v3 only, bez jakékoli záruky v rozsahu, který zákon dovoluje. AI výstup může být špatně: než ho odevzdáš, přečti si ho — od toho je poznámka pod každou kartičkou.", ], }, { heading: "Tvůj klíč, tvoje spotřeba", paragraphs: [ "Používáš vlastní API klíč Ollama. Limity, náklady a stav účtu jsou mezi tebou a Ollamou. Nikdy nevkládej klíč, který ti nepatří, a ten svůj nikomu nedávej.", ], }, { heading: "Férové používání instance", paragraphs: [ "Nezahlcuj ji, nezkoušej ji rozbít a nepoužívej ji k útoku na něco jiného. Provozovatel může kdykoli omezit rychlost, zablokovat přístup nebo instanci vypnout; aplikace už sama odmítá zjevné zneužití.", ], }, { heading: "Tvůj obsah", paragraphs: [ "Poznámky, sady, úkoly a chaty jsou tvoje. Zůstávají v tvém prohlížeči, takže je provozovatel nemůže číst — jediná výjimka je otázka, kterou sám nahlásíš (viz zásady soukromí).", ], }, { heading: "Dostupnost a změny", paragraphs: [ "Instance je zdvořilost, bez slibu dostupnosti. Aplikace i tyhle podmínky se mohou měnit; aktuální verze je vždy v aplikaci, odkaz v Nastavení.", ], }, { heading: "Odpovědnost", paragraphs: [ "V rozsahu, který zákon dovoluje, provozovatel ani autoři neodpovídají za nic, co aplikace udělá nebo neudělá — včetně ztraceného času na učení, ztracených dat nebo špatné odpovědi v úkolu.", ], }, ], footer: "Podmínky v lidské řeči pro samoobslužnou aplikaci — nejsou právní rada.", }; const COOKIES_EN: LegalDocument = { title: "Cookie policy", updated: UPDATED, intro: "Short version: Freezmo sets no cookies at all. This page exists because the law asks for one, and because it is worth being explicit.", sections: [ { heading: "No cookies", paragraphs: [ "The server sends no Set-Cookie header and the app never touches document.cookie. There are no third-party embeds, no pixels and no tag managers.", ], }, { heading: "Local storage instead", paragraphs: [ "The app keeps your data in localStorage and IndexedDB — the same idea as a cookie, except it is never sent to the server automatically. It is strictly necessary for the app to work (it *is* the app's storage), which is why it does not need consent; the banner only tells you it happens.", ], list: [ "Settings: language, theme, daily goal, haptics, chat notes preference.", "Content: decks, folders, homework, chats, study history and schedule.", "Bookkeeping: the sync id, the last-synced time, which questions you reported, whether you dismissed this banner.", ], }, { heading: "No tracking, no analytics, no ads", paragraphs: ["Nothing measures you, and nothing is sold. The only counters the app keeps are the rate limits on the server, held in memory."], }, { heading: "Clearing it", paragraphs: [ "Clear the site data in your browser to wipe the local copy, or use Settings → Export all data first if you want a backup. The opt-in server copies (sync, reminders, reports) are described in the privacy policy.", ], }, ], footer: "Plain-language description of what this app stores in your browser — not legal advice.", }; const COOKIES_CS: LegalDocument = { title: "Zásady používání cookies", updated: "říjen 2026", intro: "Krátce: Freezmo nepoužívá žádné cookies. Tahle stránka existuje proto, že to zákon vyžaduje — a protože je dobré to říct napřímo.", sections: [ { heading: "Žádné cookies", paragraphs: [ "Server neposílá hlavičku Set-Cookie a aplikace se nikdy nedotkne document.cookie. Nejsou tu žádné vložené prvky třetích stran, pixely ani správci značek.", ], }, { heading: "Místo toho lokální úložiště", paragraphs: [ "Aplikace drží tvá data v localStorage a IndexedDB — stejná myšlenka jako cookie, jen se nikdy neposílají serveru automaticky. Je to nezbytné pro fungování aplikace (je to *její* úložiště), a proto to nepotřebuje souhlas; banner ti to jen oznamuje.", ], list: [ "Nastavení: jazyk, téma, denní cíl, haptika, preference poznámek pro chat.", "Obsah: sady, složky, úkoly, chaty, historie a plán učení.", "Evidence: sync ID, čas poslední synchronizace, které otázky jsi nahlásil, jestli jsi zavřel tenhle banner.", ], }, { heading: "Žádné sledování, analytika ani reklamy", paragraphs: ["Nic tě neměří a nic se neprodává. Jediné počítadla jsou limity rychlosti na serveru, držené v paměti."], }, { heading: "Jak to smazat", paragraphs: [ "Smaž data stránky v prohlížeči, nebo si nejdřív udělej kopii přes Nastavení → Exportovat všechna data. Volitelné kopie na serveru (synchronizace, připomínky, hlášení) popisují zásady soukromí.", ], }, ], footer: "Popis v lidské řeči, co aplikace ukládá v prohlížeči — není právní rada.", }; export type LegalSlug = "privacy" | "terms" | "cookies"; export const LEGAL: Record = { privacy: { en: PRIVACY_EN, cs: PRIVACY_CS }, terms: { en: TERMS_EN, cs: TERMS_CS }, cookies: { en: COOKIES_EN, cs: COOKIES_CS }, };