/* global window */
// =============================================================
// Help Content. Single source of truth for every article on /help.
//
// Each article is an object: { slug, category, icon, title, summary,
// tags, blocks }. Titles and copy are bilingual ({ en, it }). Blocks
// are typed (para, list, steps, kbd, image, video, callout, code,
// table) and rendered by HelpArticle.jsx.
//
// Adding a new article: append an entry below + generate its
// help/<slug>/index.html stub (tools/build-help.sh).
// =============================================================

const HELP_CATEGORIES = [
  {
    id: "getting-started",
    title: { en: "Getting Started", it: "Per iniziare" },
    icon: "🚀",
    accent: "#34D399",
    desc: {
      en: "Install, grant permissions, dictate your first sentence.",
      it: "Installa, concedi i permessi, detta la tua prima frase.",
    },
  },
  {
    id: "the-pill",
    title: { en: "The Pill", it: "La Pill" },
    icon: "💊",
    accent: "#38BDF8",
    desc: {
      en: "The small overlay that turns into a live waveform when you talk.",
      it: "Il piccolo overlay che diventa una forma d'onda quando parli.",
    },
  },
  {
    id: "hotkey",
    title: { en: "Hotkey", it: "Scorciatoia" },
    icon: "⌨️",
    accent: "#818CF8",
    desc: {
      en: "How to start and stop recording. Defaults, custom combos, gestures.",
      it: "Come avviare e fermare la registrazione. Default, combo custom, gesture.",
    },
  },
  {
    id: "ai-styles",
    title: { en: "AI Styles & Tones", it: "Stili AI e Toni" },
    icon: "✨",
    accent: "#F472B6",
    desc: {
      en: "Polish, summarise, translate, or rewrite the transcription on the fly.",
      it: "Correggi, riassumi, traduci o riscrivi la trascrizione al volo.",
    },
  },
  {
    id: "providers",
    title: { en: "Providers & Models", it: "Provider e Modelli" },
    icon: "🤖",
    accent: "#FACC15",
    desc: {
      en: "Local Whisper or cloud STT, your own API key, optional local LLM.",
      it: "Whisper locale o STT cloud, la tua API key, LLM locale opzionale.",
    },
  },
  {
    id: "history-privacy",
    title: { en: "History & Privacy", it: "Cronologia e Privacy" },
    icon: "🛡️",
    accent: "#A78BFA",
    desc: {
      en: "Search past transcriptions. Understand and control what is sent.",
      it: "Cerca tra le trascrizioni passate. Capisci e controlla cosa viene inviato.",
    },
  },
  {
    id: "settings-reference",
    title: { en: "Settings Reference", it: "Riferimento Impostazioni" },
    icon: "🛠️",
    accent: "#22D3EE",
    desc: {
      en: "Every Settings tab explained: General, Models, Shortcut, Output, Overlay, History, Privacy, Audio, Stats, About.",
      it: "Ogni tab delle Impostazioni spiegato: Generale, Modelli, Scorciatoia, Output, Overlay, Cronologia, Privacy, Audio, Statistiche, Info.",
    },
  },
  {
    id: "use-cases",
    title: { en: "Use Cases", it: "Casi d'uso" },
    icon: "🎯",
    accent: "#F97316",
    desc: {
      en: "AI prompts, meeting recaps, email drafting, code comments, multilingual content, accessibility.",
      it: "Prompt AI, recap di riunioni, email, commenti di codice, contenuti multilingua, accessibilità.",
    },
  },
  {
    id: "integrations",
    title: { en: "Integrations", it: "Integrazioni" },
    icon: "🔌",
    accent: "#14B8A6",
    desc: {
      en: "Plug Dimmy into Claude Desktop, Claude CLI, Notion. MCP setup and recipes.",
      it: "Collega Dimmy a Claude Desktop, Claude CLI, Notion. Setup MCP e ricette.",
    },
  },
  {
    id: "troubleshooting",
    title: { en: "Troubleshooting", it: "Risoluzione problemi" },
    icon: "🔧",
    accent: "#FB923C",
    desc: {
      en: "Microphone, hotkey, install warnings, transcription quality.",
      it: "Microfono, scorciatoia, avvisi di installazione, qualità trascrizione.",
    },
  },
];

// Block helpers for legibility
const h = (text) => ({ type: "heading", text });
const p = (text) => ({ type: "para", text });
const list = (items, { ordered = false } = {}) => ({ type: "list", ordered, items });
const steps = (items) => ({ type: "steps", items });
const kbd = (keys, caption) => ({ type: "kbd", keys, caption });
// image(caption, ratio, src?, alt?)
// Without src: renders a dashed placeholder box (design default).
// With src: renders the real screenshot (path is relative to site root,
// e.g. "/assets/help/install/win-download.png"). Falls back to the
// placeholder automatically if the image fails to load.
const image = (caption, ratio, src, alt) => ({ type: "image", caption, ratio, src, alt });
const video = (caption) => ({ type: "video", caption });
// carousel(slides, caption?) — a stepper gallery. Each slide is
// { src, label, ratio? } where src follows the same rules as image()'s
// src (string | {light,dark} | {win,mac}).
const carousel = (slides, caption) => ({ type: "carousel", slides, caption });
const callout = (kind, text) => ({ type: "callout", kind, text });
const code = (snippet, lang) => ({ type: "code", snippet, lang });
const table = (headers, rows) => ({ type: "table", headers, rows });

// =============================================================
// Articles. Order inside each category controls display order in
// the hub. The first article in each category gets a "Start here"
// hint.
// =============================================================
const HELP_ARTICLES = [
  // ---------- Getting Started ----------
  {
    slug: "install",
    category: "getting-started",
    icon: "📥",
    title: {
      en: "Install Dimmy on Mac, Windows, or Linux",
      it: "Installa Dimmy su Mac, Windows o Linux",
    },
    summary: {
      en: "Download the installer for your operating system, run it, launch Dimmy. Takes around a minute.",
      it: "Scarica l'installer per il tuo sistema operativo, eseguilo, avvia Dimmy. Circa un minuto.",
    },
    tags: ["install", "download", "setup", "windows", "macos", "linux", "dmg", "exe", "appimage"],
    blocks: {
      en: [
        p("Dimmy ships as a native installer on Windows (per-user, no admin prompt) and macOS (standard drag-and-drop). On Linux it builds from source today; a tested, signed AppImage is on the waitlist."),
        image("Download buttons on dimmy.app showing macOS and Windows, with Linux on the waitlist", "16/9", { light: "/assets/help/install/download-buttons-light.png", dark: "/assets/help/install/download-buttons-dark.png" }),
        h("Windows"),
        steps([
          "Open dimmy.app, click Download for Windows. You get Dimmy-Setup.exe (around 12 MB).",
          "Double-click the installer. SmartScreen may warn the first time: click More info, then Run anyway.",
          "Dimmy installs in your user folder (AppData). No admin password is needed.",
          "The app opens automatically when install finishes.",
        ]),
        h("macOS"),
        steps([
          "Open dimmy.app, click Download for macOS. You get Dimmy-macos-arm64.dmg (around 25 MB).",
          "Open the DMG and drag Dimmy.app into Applications.",
          "Double-click Dimmy in Applications. Gatekeeper may complain the first time: see Troubleshooting → macOS Gatekeeper.",
          "Grant microphone and accessibility permissions when asked.",
        ]),
        callout("info", "Requires macOS 12 Monterey or newer on Apple Silicon (M1/M2/M3/M4)."),
        h("Linux"),
        callout("info", "The prebuilt Linux AppImage is still in testing, so it isn't offered as a one-click download yet. Dimmy ships from source on Linux for now. Want a tested, signed AppImage instead? Join the Linux waitlist on dimmy.app and we'll send one note the day it lands."),
        steps([
          "Clone github.com/KonradDallaOrg/dimmy and follow the build steps in the README (GTK4 frontend, shared Rust core).",
          "Once you have a Dimmy-linux-x86_64.AppImage, open a terminal in the folder where it is.",
          "Run chmod +x Dimmy-linux-x86_64.AppImage to make it executable.",
          "Run ./Dimmy-linux-x86_64.AppImage to launch.",
        ]),
        code("chmod +x Dimmy-linux-x86_64.AppImage\n./Dimmy-linux-x86_64.AppImage", "bash"),
        h("What happens next"),
        p("On first launch, Dimmy walks you through onboarding: grant microphone permission, pick a model (a local one to download, or a Groq key for cloud), set your shortcut, try it. After that the pill appears and you are ready to dictate. See [[first-dictation|Your first dictation]] for the walkthrough."),
      ],
      it: [
        p("Dimmy si installa con un installer nativo su Windows (per-utente, niente password admin) e macOS (drag-and-drop standard). Su Linux per ora si compila dai sorgenti; un AppImage testato e firmato è in waitlist."),
        image("I pulsanti di download su dimmy.app con macOS e Windows, Linux in waitlist", "16/9", { light: "/assets/help/install/download-buttons-light.png", dark: "/assets/help/install/download-buttons-dark.png" }),
        h("Windows"),
        steps([
          "Apri dimmy.app e clicca Download per Windows. Ottieni Dimmy-Setup.exe (circa 12 MB).",
          "Doppio click sull'installer. SmartScreen potrebbe avvisarti la prima volta: clicca Ulteriori informazioni e poi Esegui comunque.",
          "Dimmy si installa nella tua cartella utente (AppData). Non serve la password admin.",
          "L'app si apre da sola al termine dell'installazione.",
        ]),
        h("macOS"),
        steps([
          "Apri dimmy.app e clicca Download per macOS. Ottieni Dimmy-macos-arm64.dmg (circa 25 MB).",
          "Apri il DMG e trascina Dimmy.app nella cartella Applicazioni.",
          "Doppio click su Dimmy. Gatekeeper potrebbe lamentarsi la prima volta: vedi Risoluzione problemi → Gatekeeper.",
          "Concedi i permessi per microfono e accessibilità quando richiesto.",
        ]),
        callout("info", "Richiede macOS 12 Monterey o successivo, su Apple Silicon (M1/M2/M3/M4)."),
        h("Linux"),
        callout("info", "L'AppImage Linux pre-compilato è ancora in test, quindi non è offerto come download diretto. Per ora Dimmy su Linux si compila dai sorgenti. Vuoi un AppImage testato e firmato? Iscriviti alla waitlist Linux su dimmy.app e ti scriviamo una sola volta, il giorno in cui esce."),
        steps([
          "Clona github.com/KonradDallaOrg/dimmy e segui i passi di build nel README (frontend GTK4, core Rust condiviso).",
          "Quando hai un Dimmy-linux-x86_64.AppImage, apri un terminale nella cartella dove si trova.",
          "Esegui chmod +x Dimmy-linux-x86_64.AppImage per renderlo eseguibile.",
          "Esegui ./Dimmy-linux-x86_64.AppImage per avviarlo.",
        ]),
        code("chmod +x Dimmy-linux-x86_64.AppImage\n./Dimmy-linux-x86_64.AppImage", "bash"),
        h("Cosa succede dopo"),
        p("Al primo avvio Dimmy ti accompagna nell'onboarding: concedi il permesso al microfono, scegli un modello (uno locale da scaricare, oppure una key Groq per il cloud), imposta la scorciatoia, prova. Dopo, la pill compare a schermo e puoi iniziare a dettare. Vedi [[first-dictation|La tua prima dettatura]] per il walkthrough."),
      ],
    },
  },

  {
    slug: "first-dictation",
    category: "getting-started",
    icon: "🎙️",
    title: {
      en: "Your first dictation in 60 seconds",
      it: "La tua prima dettatura in 60 secondi",
    },
    summary: {
      en: "Open any app with a text field, press the hotkey, say a sentence, release. The text lands where the cursor was.",
      it: "Apri qualsiasi app con un campo di testo, premi la scorciatoia, dì una frase, rilascia. Il testo compare dove c'era il cursore.",
    },
    tags: ["first", "start", "quickstart", "tutorial", "begin", "dictation", "record", "onboarding", "setup", "parakeet", "groq"],
    blocks: {
      en: [
        callout("tip", "Make sure your cursor is blinking somewhere. Dimmy pastes wherever the OS thinks you are typing."),
        video("60-second walkthrough of opening a note, holding the hotkey, speaking, releasing"),
        h("Onboarding, step by step"),
        p("On first launch Dimmy runs a short wizard: welcome, pick a model, set your shortcut, try it. Here is what each step asks for."),
        carousel({
          win: [
            { src: "/assets/help/first-dictation/win-welcome.png", label: "Welcome" },
            { src: "/assets/help/first-dictation/win-model.png", label: "Pick a model" },
            { src: "/assets/help/first-dictation/win-shortcut.png", label: "Set your shortcut" },
            { src: "/assets/help/first-dictation/win-tryit.png", label: "Try it" },
          ],
          mac: [
            { src: { light: "/assets/help/first-dictation/mac-welcome-light.png", dark: "/assets/help/first-dictation/mac-welcome-dark.png" }, label: "Welcome" },
            { src: { light: "/assets/help/first-dictation/mac-permissions-light.png", dark: "/assets/help/first-dictation/mac-permissions-dark.png" }, label: "Permissions" },
            { src: { light: "/assets/help/first-dictation/mac-model-light.png", dark: "/assets/help/first-dictation/mac-model-dark.png" }, label: "Pick a model" },
            { src: { light: "/assets/help/first-dictation/mac-shortcut-light.png", dark: "/assets/help/first-dictation/mac-shortcut-dark.png" }, label: "Set your shortcut" },
            { src: { light: "/assets/help/first-dictation/mac-tryit-light.png", dark: "/assets/help/first-dictation/mac-tryit-dark.png" }, label: "Try it" },
          ],
        }),
        h("Pick a model"),
        p("Choose where transcription runs. Both platforms now show two cards: Local and Cloud (Groq)."),
        list([
          "Local: private, offline, runs on your machine. Pick a model from the dropdown (Parakeet, around 466 MB, or a Whisper size), then download it. You see a live progress bar with a percent while it downloads. If it fails you get a Download failed message with the reason and a Try again button. The Parakeet bundle resumes a partial download instead of starting over on both platforms; Whisper sizes also resume on Windows, but on macOS a Whisper retry re-downloads from scratch.",
          "Cloud (Groq): fastest and most accurate. Paste a Groq key in the gsk_... field. Dimmy validates it on the spot: Validating…, then Ready to use, or the error if the key is rejected. No key yet? Use the Get API key link, which opens console.groq.com/keys.",
        ]),
        callout("info", "Cloud (Groq) in onboarding is now on macOS too, matching Windows. Either platform can finish setup with a local model, a Groq key, or both."),
        h("Set your shortcut"),
        p("Pick the keys you dictate with. The step starts from the shortcut Dimmy is already using, so if you re-run setup it shows your real combo, not a default."),
        list([
          "Windows: a free capture box. Click it, then press and hold the combo you want. Dimmy records exactly those keys, Windows key included. Choose Push-to-Talk or Toggle below. The combo you set is applied to the live hotkey before the Try it step, so the keys you just chose are the keys that fire.",
          "Mac: the default is the fn key. The step offers presets fn, Control+Option, and Control+Shift, plus a Custom recorder. You can change it later in Settings under Shortcut.",
        ]),
        h("Try it"),
        p("Dimmy shows the pill and arms your shortcut so you can test recording right inside the wizard before you finish."),
        h("The 3 steps"),
        steps([
          "Click into any text field. A note, a browser tab, a chat box, a code editor.",
          "Press your hotkey. On Mac that's the fn key by default, on Windows and Linux it's Win + Alt. Speak naturally.",
          "Release the hotkey. The pill goes through transcribe → enhance → done, and the text appears where your cursor was.",
        ]),
        h("Watch the pill"),
        p("The pill in the corner of your screen tells you what is happening. Idle when waiting, rainbow border with a live waveform while recording, dots while transcribing, a coloured border during AI enhancement, a green check when text was pasted."),
        image("Pill states: idle, recording, transcribing, done", "16/9", { win: "/assets/help/first-dictation/pill-states.png" }),
        h("If nothing pastes"),
        list([
          "Make sure a text field was focused before you pressed the hotkey.",
          "On macOS, grant accessibility permission (System Settings → Privacy → Accessibility → Dimmy).",
          "If the cursor moved away while you were speaking, the text still lands in the clipboard. Cmd/Ctrl + V to paste it manually.",
        ]),
        h("Redo the setup"),
        p("Want to run the wizard again? Open Settings, go to the About page, find Run setup again and click Open setup. The wizard reopens and is idempotent: a model you already downloaded and a key you already saved are detected and kept, so nothing is re-downloaded and you are not asked for a key twice. Same on Windows and Mac."),
        callout("info", "Try the [[hotkey-modes|toggle mode]] if hold-to-record feels awkward: press once to start, press again to stop."),
      ],
      it: [
        callout("tip", "Assicurati che ci sia un cursore lampeggiante da qualche parte. Dimmy incolla dove il sistema crede che tu stia scrivendo."),
        video("Walkthrough di 60 secondi: apri una nota, tieni premuta la scorciatoia, parla, rilascia"),
        h("Onboarding, passo per passo"),
        p("Al primo avvio Dimmy mostra un breve wizard: benvenuto, scegli un modello, imposta la scorciatoia, prova. Ecco cosa chiede ogni passo."),
        carousel({
          win: [
            { src: "/assets/help/first-dictation/win-welcome.png", label: "Benvenuto" },
            { src: "/assets/help/first-dictation/win-model.png", label: "Scegli un modello" },
            { src: "/assets/help/first-dictation/win-shortcut.png", label: "Imposta la scorciatoia" },
            { src: "/assets/help/first-dictation/win-tryit.png", label: "Prova" },
          ],
          mac: [
            { src: { light: "/assets/help/first-dictation/mac-welcome-light.png", dark: "/assets/help/first-dictation/mac-welcome-dark.png" }, label: "Benvenuto" },
            { src: { light: "/assets/help/first-dictation/mac-permissions-light.png", dark: "/assets/help/first-dictation/mac-permissions-dark.png" }, label: "Permessi" },
            { src: { light: "/assets/help/first-dictation/mac-model-light.png", dark: "/assets/help/first-dictation/mac-model-dark.png" }, label: "Scegli un modello" },
            { src: { light: "/assets/help/first-dictation/mac-shortcut-light.png", dark: "/assets/help/first-dictation/mac-shortcut-dark.png" }, label: "Imposta la scorciatoia" },
            { src: { light: "/assets/help/first-dictation/mac-tryit-light.png", dark: "/assets/help/first-dictation/mac-tryit-dark.png" }, label: "Prova" },
          ],
        }),
        h("Scegli un modello"),
        p("Decidi dove gira la trascrizione. Ora entrambe le piattaforme mostrano due card: Local e Cloud (Groq)."),
        list([
          "Local: privato, offline, gira sul tuo computer. Scegli un modello dal menu (Parakeet, circa 466 MB, o una taglia di Whisper), poi scaricalo. Durante il download vedi una barra di avanzamento con la percentuale. Se fallisce compare Download failed con il motivo e un pulsante Try again. Il bundle Parakeet riprende un download parziale invece di ricominciare da capo su entrambe le piattaforme; le taglie di Whisper riprendono anche su Windows, ma su macOS un retry di Whisper si riscarica da zero.",
          "Cloud (Groq): il più veloce e accurato. Incolla una key Groq nel campo gsk_... Dimmy la valida al volo: Validating…, poi Ready to use, oppure l'errore se la key viene rifiutata. Non hai ancora una key? Usa il link Get API key, che apre console.groq.com/keys.",
        ]),
        callout("info", "Cloud (Groq) nell'onboarding ora c'è anche su macOS, in parità con Windows. Su entrambe le piattaforme puoi finire il setup con un modello locale, una key Groq, o entrambi."),
        h("Imposta la scorciatoia"),
        p("Scegli i tasti con cui detti. Il passo parte dalla scorciatoia che Dimmy sta già usando, così se rifai il setup ti mostra la tua combo reale, non un default."),
        list([
          "Windows: un box a cattura libera. Cliccalo, poi premi e tieni premuta la combo che vuoi. Dimmy registra esattamente quei tasti, tasto Windows incluso. Sotto scegli Push-to-Talk o Toggle. La combo che imposti viene applicata alla hotkey live prima del passo Try it, così i tasti che hai appena scelto sono quelli che la attivano.",
          "Mac: di default è il tasto fn. Il passo offre i preset fn, Control+Option e Control+Shift, più un registratore Custom. Puoi cambiarla dopo nelle Impostazioni, alla voce Scorciatoia.",
        ]),
        h("Prova"),
        p("Dimmy mostra la pill e arma la tua scorciatoia, così puoi provare la registrazione dentro il wizard prima di finire."),
        h("I 3 passi"),
        steps([
          "Clicca su un campo di testo qualsiasi. Una nota, una scheda del browser, una chat, un editor di codice.",
          "Premi la scorciatoia. Su Mac di default è il tasto fn, su Windows e Linux è Win + Alt. Parla normalmente.",
          "Rilascia la scorciatoia. La pill passa per transcribe → enhance → done, e il testo compare dove era il cursore.",
        ]),
        h("Guarda la pill"),
        p("La pill nell'angolo dello schermo ti dice cosa sta succedendo. Idle in attesa, bordo arcobaleno con forma d'onda mentre registri, puntini durante la trascrizione, bordo colorato durante l'enhancement AI, check verde quando il testo è stato incollato."),
        image("Stati della pill: idle, registrazione, trascrizione, fatto", "16/9", { win: "/assets/help/first-dictation/pill-states.png" }),
        h("Se non incolla niente"),
        list([
          "Assicurati di aver messo a fuoco un campo di testo prima di premere la scorciatoia.",
          "Su macOS, concedi il permesso accessibilità (Impostazioni di sistema → Privacy → Accessibilità → Dimmy).",
          "Se il cursore si è spostato mentre parlavi, il testo finisce comunque negli appunti. Cmd/Ctrl + V per incollarlo a mano.",
        ]),
        h("Rifare il setup"),
        p("Vuoi rilanciare il wizard? Apri le Impostazioni, vai alla pagina Info, trova Run setup again e clicca Open setup. Il wizard si riapre ed è idempotente: un modello già scaricato e una key già salvata vengono rilevati e tenuti, quindi non si riscarica niente e non ti viene richiesta la key una seconda volta. Uguale su Windows e Mac."),
        callout("info", "Prova la [[hotkey-modes|modalità toggle]] se il hold ti scomoda: premi una volta per iniziare, di nuovo per fermare."),
      ],
    },
  },

  {
    slug: "permissions",
    category: "getting-started",
    icon: "🔐",
    title: {
      en: "Permissions Dimmy needs",
      it: "Permessi che servono a Dimmy",
    },
    summary: {
      en: "Microphone everywhere. Accessibility on macOS to type into other apps. Nothing else, ever.",
      it: "Microfono ovunque. Accessibilità su macOS per scrivere in altre app. Nient'altro, mai.",
    },
    tags: ["permissions", "microphone", "accessibility", "mac", "privacy", "grant"],
    blocks: {
      en: [
        p("Dimmy asks for the minimum permissions needed to record your voice and paste the result. Everything is granted by the OS itself, not by Dimmy. You can revoke any time from system settings."),
        h("Microphone (all platforms)"),
        p("Required. Without microphone access Dimmy cannot record audio. The OS will prompt the first time you press the hotkey."),
        image("macOS microphone prompt", "16/9"),
        h("Accessibility (macOS only)"),
        p("Required on macOS so Dimmy can paste the transcription into the focused app. Without it the text still lands in the clipboard but is not auto-pasted."),
        steps([
          "Open System Settings → Privacy & Security → Accessibility.",
          "Find Dimmy in the list and turn the switch on.",
          "If Dimmy is not in the list, click the + and add it from /Applications/Dimmy.app.",
        ]),
        h("What Dimmy never asks for"),
        list([
          "Network access prompts. Dimmy talks to the public internet only when you turn on a cloud provider.",
          "Disk access beyond its own app data folder.",
          "Camera, contacts, location, photos, calendar, reminders. Never touched.",
        ]),
        callout("info", "Want to see exactly what is sent and when? Read [[telemetry|Telemetry]] and the full [[/privacy|Privacy policy]]."),
      ],
      it: [
        p("Dimmy chiede solo i permessi minimi indispensabili per registrare la tua voce e incollare il risultato. Tutto viene concesso dal sistema operativo, non da Dimmy. Puoi revocare tutto in qualsiasi momento dalle impostazioni di sistema."),
        h("Microfono (tutte le piattaforme)"),
        p("Obbligatorio. Senza accesso al microfono Dimmy non può registrare audio. Il sistema operativo te lo chiede la prima volta che premi la scorciatoia."),
        image("Prompt microfono di macOS", "16/9"),
        h("Accessibilità (solo macOS)"),
        p("Obbligatorio su macOS perché Dimmy possa incollare la trascrizione nell'app attiva. Senza, il testo finisce comunque negli appunti ma non viene incollato in automatico."),
        steps([
          "Apri Impostazioni di sistema → Privacy e sicurezza → Accessibilità.",
          "Trova Dimmy nella lista e attiva l'interruttore.",
          "Se Dimmy non è in lista, clicca il + e aggiungilo da /Applicazioni/Dimmy.app.",
        ]),
        h("Cosa Dimmy non chiede mai"),
        list([
          "Prompt di accesso alla rete. Dimmy comunica con Internet solo quando attivi un provider cloud.",
          "Accesso al disco oltre la sua cartella di dati.",
          "Fotocamera, contatti, posizione, foto, calendario, promemoria. Mai toccati.",
        ]),
        callout("info", "Vuoi vedere esattamente cosa viene inviato e quando? Leggi [[telemetry|Telemetria]] e la [[/privacy|Privacy policy]] completa."),
      ],
    },
  },

  // ---------- The Pill ----------
  {
    slug: "pill-overview",
    category: "the-pill",
    icon: "💊",
    title: {
      en: "What the pill is",
      it: "Cos'è la pill",
    },
    summary: {
      en: "The small always-on-top overlay. It shows whether Dimmy is idle, recording, transcribing, or done.",
      it: "Il piccolo overlay sempre in primo piano. Mostra se Dimmy è in attesa, sta registrando, trascrivendo o ha finito.",
    },
    tags: ["pill", "overlay", "ui", "hud", "indicator", "always on top"],
    blocks: {
      en: [
        p("The pill is the visual heart of Dimmy. It is a small overlay that floats above every window on your screen, like a tiny status light. It is the only persistent UI: there is no main window, no dock icon parade, no popup."),
        image("The Dimmy pill in its idle state, anchored top-right of the screen", "16/9", { win: "/assets/help/pill/idle.png" }),
        h("Why it exists"),
        list([
          "You can see at a glance what Dimmy is doing without alt-tabbing.",
          "It doubles as a click target: left-click toggles recording, right-click opens settings.",
          "It changes shape and colour to reflect every step of the pipeline. No silence, no guessing.",
        ]),
        h("Where it lives"),
        p("By default the pill sits in the top-right corner. You can drag it anywhere on screen, or pin it to one of the four corners. See [[pill-position|Move, resize, hide the pill]]."),
        callout("tip", "On Windows and Linux you can scroll on the pill itself to cycle AI styles. Ctrl + scroll cycles tones. See [[scroll-shortcuts|Scroll shortcuts]]."),
      ],
      it: [
        p("La pill è il cuore visivo di Dimmy. È un piccolo overlay che galleggia sopra ogni finestra dello schermo, come una piccola spia di stato. È l'unica UI persistente: niente finestra principale, niente parata di icone nel dock, niente popup."),
        image("La pill di Dimmy in stato idle, ancorata in alto a destra dello schermo", "16/9", { win: "/assets/help/pill/idle.png" }),
        h("Perché esiste"),
        list([
          "Vedi a colpo d'occhio cosa sta facendo Dimmy, senza alt-tab.",
          "Funziona anche da bersaglio click: click sinistro avvia/ferma la registrazione, click destro apre le impostazioni.",
          "Cambia forma e colore a ogni step della pipeline. Niente silenzi, niente da indovinare.",
        ]),
        h("Dove sta"),
        p("Di default la pill sta nell'angolo in alto a destra. Puoi trascinarla ovunque sullo schermo, o agganciarla a uno dei quattro angoli. Vedi [[pill-position|Sposta, ridimensiona, nascondi la pill]]."),
        callout("tip", "Su Windows e Linux puoi scrollare direttamente sulla pill per cambiare stile AI. Ctrl + scroll cambia il tono. Vedi [[scroll-shortcuts|Scroll shortcuts]]."),
      ],
    },
  },

  {
    slug: "pill-states",
    category: "the-pill",
    icon: "🎨",
    title: {
      en: "All pill states explained",
      it: "Tutti gli stati della pill",
    },
    summary: {
      en: "Idle, recording, transcribing, LLM, done, error. Each one has a unique shape, colour, and animation.",
      it: "Idle, registrazione, trascrizione, LLM, fatto, errore. Ognuno ha forma, colore e animazione propri.",
    },
    tags: ["pill", "states", "colors", "indicator", "waveform", "animation", "ui"],
    blocks: {
      en: [
        p("Every state of the dictation pipeline maps to a distinct pill state. Once you've used Dimmy for a day you read the pill without thinking."),
        image("The six pill states side-by-side: idle, recording, transcribing, LLM, done, error", "21/9", { win: "/assets/help/pill/states-strip.png" }),
        table(
          ["State", "Visual", "Meaning"],
          [
            ["Idle", "Small capsule, dim border", "Waiting for the hotkey."],
            ["Recording", "Expanded pill, rainbow border, live waveform", "Capturing audio. Bars move with your voice."],
            ["Transcribing", "Dots or spinner, solid border", "Running STT, local or cloud."],
            ["LLM processing", "Style-coloured border, style icon", "Post-processing with the active style."],
            ["Done", "Green checkmark, brief", "Text was pasted into the focused app."],
            ["Error", "Red border, tooltip", "Something failed. Hover for the reason."],
          ],
        ),
        h("Live waveform"),
        p("While recording, the pill expands and shows a real-time volume meter built from the same audio that goes to the transcriber. If you see no bars moving, your microphone is silent or muted at the OS level."),
        video("Recording the same phrase three times with different volume levels, watching the waveform respond"),
        h("Style icon"),
        p("During LLM processing, the icon inside the pill switches to the active style (a pencil for Correct, a sparkle for Elaborate, and so on). Tells you at a glance which style will be applied."),
      ],
      it: [
        p("Ogni stato della pipeline di dettatura ha uno stato della pill distinto. Dopo un giorno di uso, leggi la pill senza pensarci."),
        image("I sei stati della pill affiancati: idle, registrazione, trascrizione, LLM, fatto, errore", "21/9", { win: "/assets/help/pill/states-strip.png" }),
        table(
          ["Stato", "Aspetto", "Significato"],
          [
            ["Idle", "Piccola capsula, bordo smorzato", "In attesa della scorciatoia."],
            ["Registrazione", "Pill espansa, bordo arcobaleno, waveform live", "Sto registrando. Le barre seguono la tua voce."],
            ["Trascrizione", "Puntini o spinner, bordo solido", "Sto trascrivendo, in locale o cloud."],
            ["LLM", "Bordo colorato dello stile, icona stile", "Sto post-processando con lo stile attivo."],
            ["Fatto", "Check verde, breve", "Il testo è stato incollato nell'app attiva."],
            ["Errore", "Bordo rosso, tooltip", "Qualcosa è andato storto. Passa sopra per il motivo."],
          ],
        ),
        h("Waveform live"),
        p("Durante la registrazione la pill si espande e mostra un VU meter in tempo reale, costruito sullo stesso audio che va al transcriber. Se non vedi barre muoversi, il microfono è silenzioso o mutato dal sistema."),
        video("Stessa frase registrata tre volte a volumi diversi, guardando la waveform reagire"),
        h("Icona dello stile"),
        p("Durante la fase LLM, l'icona dentro la pill diventa quella dello stile attivo (matita per Correct, sparkle per Elaborate, e così via). Sai a colpo d'occhio quale stile verrà applicato."),
      ],
    },
  },

  {
    slug: "pill-position",
    category: "the-pill",
    icon: "📍",
    title: {
      en: "Move, resize, hide the pill",
      it: "Sposta, ridimensiona, nascondi la pill",
    },
    summary: {
      en: "Drag the pill anywhere. Pin to a corner. Change opacity when idle. Hide it entirely until the hotkey is pressed.",
      it: "Trascina la pill ovunque. Agganciala a un angolo. Cambia l'opacità quando è idle. Nascondila finché non premi la scorciatoia.",
    },
    tags: ["pill", "position", "move", "hide", "opacity", "overlay", "settings"],
    blocks: {
      en: [
        h("Drag it"),
        p("Click and hold anywhere on the pill, drag to a new spot, release. The position is remembered across launches. You don't need to open Settings to move it."),
        image("Dragging the pill from top-right to bottom-left", "16/9"),
        h("Pin to a corner"),
        p("Right-click the pill (or open Settings → Overlay) and pick a corner. The pill snaps and stays there even when the screen resolution changes."),
        h("Idle opacity"),
        p("Settings → Overlay → Idle opacity. Dial it down to 30 % so the pill nearly disappears between recordings. It pops back to full opacity the moment you press the hotkey."),
        image("Slider showing idle opacity from 100% to 30%", "16/9", { win: { light: "/assets/help/pill/opacity-slider-light.png", dark: "/assets/help/pill/opacity-slider-dark.png" } }),
        h("Hide entirely"),
        p("Settings → Overlay → Hide when idle. The pill disappears until you press the hotkey, then fades in for recording. Good for screen recordings and presentations."),
        callout("warn", "If you fully hide the pill, double-check your hotkey before disabling it. There is no other way to start a recording."),
      ],
      it: [
        h("Trascinala"),
        p("Click e tieni premuto su un punto qualsiasi della pill, trascina dove vuoi, rilascia. La posizione viene ricordata tra i lanci. Non serve aprire le impostazioni per spostarla."),
        image("Trascinamento della pill da alto-destra a basso-sinistra", "16/9"),
        h("Aggancia a un angolo"),
        p("Click destro sulla pill (o apri Impostazioni → Overlay) e scegli un angolo. La pill si aggancia e ci resta anche se cambia la risoluzione dello schermo."),
        h("Opacità in idle"),
        p("Impostazioni → Overlay → Opacità in idle. Abbassala al 30 % per farla quasi sparire tra una registrazione e l'altra. Torna piena appena premi la scorciatoia."),
        image("Slider che mostra l'opacità in idle da 100% a 30%", "16/9", { win: { light: "/assets/help/pill/opacity-slider-light.png", dark: "/assets/help/pill/opacity-slider-dark.png" } }),
        h("Nascondila del tutto"),
        p("Impostazioni → Overlay → Nascondi in idle. La pill sparisce finché non premi la scorciatoia, poi appare in dissolvenza per la registrazione. Utile per screen recording e presentazioni."),
        callout("warn", "Se nascondi del tutto la pill, ricontrolla la scorciatoia prima di farlo. Non c'è altro modo per avviare una registrazione."),
      ],
    },
  },

  {
    slug: "tray-menu",
    category: "the-pill",
    icon: "🍎",
    title: {
      en: "Tray and menu-bar icon",
      it: "Icona nel tray e nella menu-bar",
    },
    summary: {
      en: "Besides the pill, Dimmy puts a tiny icon in your system tray (Windows, Linux) or menu bar (macOS). Quick access to Settings, History, Quit.",
      it: "Oltre alla pill, Dimmy mette una piccola icona nel system tray (Windows, Linux) o nella menu bar (macOS). Accesso rapido a Impostazioni, Cronologia, Esci.",
    },
    tags: ["tray", "menu bar", "system tray", "macos", "windows", "icon", "settings"],
    blocks: {
      en: [
        image("The tray icon expanded into a menu with Settings, History, Quit", "16/9"),
        h("What's in the menu"),
        list([
          "Open Settings.",
          "Open History.",
          "Pause Dimmy. Temporarily disables the hotkey.",
          "Quit Dimmy.",
        ]),
        h("Where it lives"),
        list([
          "macOS: menu bar (top-right of screen).",
          "Windows: system tray (bottom-right, may be hidden behind the ^ arrow).",
          "Linux: system tray (depends on your DE, e.g. GNOME requires an extension like AppIndicator).",
        ]),
        callout("tip", "If you don't see the tray icon on Linux, you probably need the AppIndicator extension. On GNOME: install gnome-shell-extension-appindicator."),
      ],
      it: [
        image("L'icona nel tray espansa in un menu con Impostazioni, Cronologia, Esci", "16/9"),
        h("Cosa contiene il menu"),
        list([
          "Apri Impostazioni.",
          "Apri Cronologia.",
          "Pausa Dimmy. Disattiva temporaneamente la scorciatoia.",
          "Esci da Dimmy.",
        ]),
        h("Dove si trova"),
        list([
          "macOS: menu bar (in alto a destra dello schermo).",
          "Windows: system tray (in basso a destra, può essere nascosto sotto la freccia ^).",
          "Linux: system tray (dipende dal DE, su GNOME serve l'estensione AppIndicator).",
        ]),
        callout("tip", "Se su Linux non vedi l'icona nel tray, probabilmente ti serve l'estensione AppIndicator. Su GNOME: installa gnome-shell-extension-appindicator."),
      ],
    },
  },

  // ---------- Hotkey ----------
  {
    slug: "hotkey-default",
    category: "hotkey",
    icon: "⌨️",
    title: {
      en: "Default hotkey per platform",
      it: "Scorciatoia di default per piattaforma",
    },
    summary: {
      en: "Cmd + Option on macOS, Win + Alt on Windows and Linux. Two-key combos chosen to never clash with system shortcuts.",
      it: "Cmd + Option su macOS, Win + Alt su Windows e Linux. Combo a due tasti scelte per non andare in conflitto col sistema.",
    },
    tags: ["hotkey", "shortcut", "default", "keys", "modifier", "cmd", "alt", "win"],
    blocks: {
      en: [
        h("The defaults"),
        kbd(["Cmd", "Option"], "macOS"),
        kbd(["Win", "Alt"], "Windows and Linux"),
        p("Both combos use two modifier keys with no letter or number. That avoids every common system shortcut and most app shortcuts. Holding both starts recording, releasing both stops it."),
        h("Why two modifiers"),
        p("Single-modifier hotkeys (just Cmd, just Alt) would fire every time you do anything else. Combos with letters (Cmd + Shift + V) clash with paste and similar apps. Two pure modifier keys give a reliable, never-confused trigger."),
        callout("info", "Want to change it? See [[hotkey-change|Change your hotkey]]."),
      ],
      it: [
        h("I default"),
        kbd(["Cmd", "Option"], "macOS"),
        kbd(["Win", "Alt"], "Windows e Linux"),
        p("Entrambe le combo usano due tasti modificatori senza lettere o numeri. Così non vanno in conflitto con nessuna scorciatoia di sistema e quasi nessuna scorciatoia delle app. Tenendoli premuti parte la registrazione, rilasciandoli si ferma."),
        h("Perché due modificatori"),
        p("Le scorciatoie a un singolo modificatore (solo Cmd, solo Alt) si attiverebbero ogni volta che fai altro. Le combo con lettere (Cmd + Shift + V) vanno in conflitto con copia-incolla e simili. Due modificatori puri danno un trigger affidabile e impossibile da confondere."),
        callout("info", "Vuoi cambiarla? Vedi [[hotkey-change|Cambia la tua scorciatoia]]."),
      ],
    },
  },

  {
    slug: "hotkey-change",
    category: "hotkey",
    icon: "🔧",
    title: {
      en: "Change your hotkey",
      it: "Cambia la tua scorciatoia",
    },
    summary: {
      en: "Settings → Shortcut. Press the new combo. Dimmy validates it against system shortcuts and saves.",
      it: "Impostazioni → Scorciatoia. Premi la nuova combo. Dimmy la convalida e la salva.",
    },
    tags: ["hotkey", "change", "customize", "modify", "configure", "settings"],
    blocks: {
      en: [
        steps([
          "Right-click the pill (or open the tray menu) → Settings.",
          "Go to the Shortcut tab.",
          "Click the current combo. The box turns red and says Press a key combination.",
          "Press the new combo. Dimmy listens for modifier-only or modifier + key combos.",
          "Click Save. The change takes effect immediately.",
        ]),
        image("Settings → Shortcut tab showing the capture input ready to record", "16/9", { win: { light: "/assets/help/hotkey-change/shortcut-tab-light.png", dark: "/assets/help/hotkey-change/shortcut-tab-dark.png" }, mac: { light: "/assets/help/app-settings/shortcut-light.png", dark: "/assets/help/app-settings/shortcut-dark.png" } }),
        h("Combos that work"),
        list([
          "Two modifier keys (Cmd + Option, Ctrl + Alt, Win + Shift, ...). Recommended.",
          "Three modifier keys (Cmd + Option + Shift). For when two clash with an app.",
          "Modifier + letter or number (Cmd + Shift + V). Works but may clash with apps.",
        ]),
        h("Combos that don't work"),
        list([
          "Just a letter or number on its own. Would fire on every keystroke.",
          "Combos already taken by the OS (Cmd + Tab, Win + L, ...). Dimmy refuses with a tooltip.",
        ]),
        callout("tip", "If you map Dimmy to the same key on every platform you switch between, set Cmd + Option on Mac, Ctrl + Alt on Windows/Linux. Same physical positions."),
      ],
      it: [
        steps([
          "Click destro sulla pill (o apri il menu del tray) → Impostazioni.",
          "Vai al tab Scorciatoia.",
          "Clicca sulla combo attuale. Il riquadro diventa rosso e dice Premi una combinazione.",
          "Premi la nuova combo. Dimmy ascolta combo a soli modificatori o modificatore + tasto.",
          "Clicca Salva. La modifica è immediata.",
        ]),
        image("Impostazioni → tab Scorciatoia con l'input di cattura pronto", "16/9", { win: { light: "/assets/help/hotkey-change/shortcut-tab-light.png", dark: "/assets/help/hotkey-change/shortcut-tab-dark.png" }, mac: { light: "/assets/help/app-settings/shortcut-light.png", dark: "/assets/help/app-settings/shortcut-dark.png" } }),
        h("Combo che funzionano"),
        list([
          "Due tasti modificatori (Cmd + Option, Ctrl + Alt, Win + Shift, ...). Consigliato.",
          "Tre tasti modificatori (Cmd + Option + Shift). Quando le combo a due vanno in conflitto.",
          "Modificatore + lettera o numero (Cmd + Shift + V). Funziona ma può andare in conflitto con le app.",
        ]),
        h("Combo che non funzionano"),
        list([
          "Solo una lettera o un numero. Si attiverebbero a ogni tasto.",
          "Combo già usate dal sistema operativo (Cmd + Tab, Win + L, ...). Dimmy le rifiuta con un tooltip.",
        ]),
        callout("tip", "Se passi tra piattaforme diverse e vuoi la stessa posizione fisica, imposta Cmd + Option su Mac e Ctrl + Alt su Windows/Linux."),
      ],
    },
  },

  {
    slug: "hotkey-modes",
    category: "hotkey",
    icon: "🔁",
    title: {
      en: "Toggle vs hold-to-record",
      it: "Toggle vs tieni-premuto",
    },
    summary: {
      en: "Hold-to-record: hold the hotkey while talking. Toggle: press once to start, again to stop. Both work, pick what feels right.",
      it: "Tieni-premuto: tieni la scorciatoia mentre parli. Toggle: premi una volta per iniziare, di nuovo per fermare. Entrambe funzionano, scegli tu.",
    },
    tags: ["hotkey", "mode", "toggle", "hold", "ptt", "push to talk", "settings"],
    blocks: {
      en: [
        h("Hold-to-record (default)"),
        p("Press the hotkey, speak, release. Same model as a walkie-talkie. Best for short bursts, dictating into chat boxes, quick voice prompts."),
        image("Hold-to-record: press → speak → release timeline", "16/9"),
        h("Toggle"),
        p("Press the hotkey once to start, press again to stop. Best for long-form dictation where you want hands free, like writing an email body or recording a meeting recap."),
        image("Toggle: press → speak as long as you want → press again", "16/9"),
        h("Switching modes"),
        steps([
          "Open Settings → Shortcut.",
          "Pick Mode: Hold or Mode: Toggle.",
          "Save. The change applies to the next recording.",
        ]),
        callout("tip", "You can keep both modes available if you set two different hotkeys, one for Hold and one for Toggle, in advanced settings. (Roadmap.)"),
      ],
      it: [
        h("Tieni-premuto (default)"),
        p("Premi la scorciatoia, parla, rilascia. Stesso modello di un walkie-talkie. Ideale per burst brevi, dettatura in chat, prompt vocali rapidi."),
        image("Tieni-premuto: premi → parla → rilascia su timeline", "16/9"),
        h("Toggle"),
        p("Premi la scorciatoia una volta per iniziare, di nuovo per fermare. Ideale per dettature lunghe a mani libere: il corpo di una email, il recap di una riunione."),
        image("Toggle: premi → parla quanto vuoi → premi di nuovo", "16/9"),
        h("Cambia modalità"),
        steps([
          "Apri Impostazioni → Scorciatoia.",
          "Scegli Modalità: Tieni-premuto o Modalità: Toggle.",
          "Salva. La modifica si applica alla prossima registrazione.",
        ]),
        callout("tip", "Puoi tenere entrambe le modalità se imposti due scorciatoie diverse, una per Hold e una per Toggle, nelle impostazioni avanzate. (Roadmap.)"),
      ],
    },
  },

  {
    slug: "hotkey-dictionary-command",
    category: "hotkey",
    icon: "🎛️",
    title: {
      en: "Dictionary and Command Mode shortcuts",
      it: "Scorciatoie Dizionario e Command Mode",
    },
    summary: {
      en: "Two optional shortcuts beside the dictation hotkey: add selected text to your dictionary (Ctrl + Shift + D) and run a one-shot AI command.",
      it: "Due scorciatoie opzionali oltre a quella di dettatura: aggiungi il testo selezionato al dizionario (Ctrl + Shift + D) e lancia un comando AI one-shot.",
    },
    tags: ["hotkey", "shortcut", "dictionary", "command", "command mode", "vocabulary", "settings"],
    blocks: {
      en: [
        p("The dictation hotkey starts and stops recording ([[hotkey-default|the defaults]]). Settings → Shortcut also holds two optional shortcuts for specific actions."),
        h("Add-to-dictionary shortcut"),
        kbd(["Ctrl", "Shift", "D"], "Windows default"),
        p("Select a word in any app (a name, a brand, a technical term) and press the combo. Dimmy adds it to your custom dictionary, so future transcriptions get it right. Entries can be up to 100 characters; you review and remove them in Settings."),
        p("On macOS the same action also lives in the Services menu: select text → right-click → Services → Add to Dimmy Dictionary."),
        h("Command Mode shortcut"),
        p("Unset by default. Once set, press it instead of the dictation hotkey to run a single AI command: transform the selected text, or generate and insert when nothing is selected. After the paste it auto-clears and the next recording is normal dictation again. It follows the same Hold or Toggle mode as your dictation shortcut. Full guide: [[command-mode|Command Mode]]."),
        h("Conflicts"),
        p("Dimmy refuses combos that overlap each other. Ctrl + Space clashes with Ctrl + Shift + Space because one is contained in the other. If a new combo conflicts with your dictation or dictionary shortcut you get a toast and the change is not saved."),
        callout("tip", "You can skip the Command Mode shortcut entirely and use the sticky toggle in the pill menu instead: turn it on, fire several commands in a row, turn it off."),
      ],
      it: [
        p("La scorciatoia di dettatura avvia e ferma la registrazione ([[hotkey-default|i default]]). In Impostazioni → Scorciatoia trovi anche due scorciatoie opzionali per azioni specifiche."),
        h("Scorciatoia aggiungi-al-dizionario"),
        kbd(["Ctrl", "Shift", "D"], "Default su Windows"),
        p("Seleziona una parola in qualsiasi app (un nome, un brand, un termine tecnico) e premi la combo. Dimmy la aggiunge al tuo dizionario personale, così le trascrizioni future la scrivono giusta. Voci fino a 100 caratteri; le rivedi e rimuovi dalle Impostazioni."),
        p("Su macOS la stessa azione è anche nel menu Servizi: seleziona il testo → click destro → Servizi → Add to Dimmy Dictionary."),
        h("Scorciatoia Command Mode"),
        p("Non impostata di default. Una volta impostata, premila al posto della scorciatoia di dettatura per lanciare un singolo comando AI: trasforma il testo selezionato, oppure genera e inserisce quando non c'è selezione. Dopo l'incolla si disattiva da sola e la registrazione successiva torna a essere dettatura normale. Segue la stessa modalità Tieni-premuto o Toggle della scorciatoia di dettatura. Guida completa: [[command-mode|Command Mode]]."),
        h("Conflitti"),
        p("Dimmy rifiuta le combo che si sovrappongono tra loro. Ctrl + Space va in conflitto con Ctrl + Shift + Space perché una è contenuta nell'altra. Se una nuova combo entra in conflitto con la scorciatoia di dettatura o del dizionario compare un toast e la modifica non viene salvata."),
        callout("tip", "Puoi anche non impostare la scorciatoia Command Mode e usare il toggle persistente nel menu della pill: lo accendi, lanci più comandi di fila, lo spegni."),
      ],
    },
  },

  {
    slug: "scroll-shortcuts",
    category: "hotkey",
    icon: "🖱️",
    title: {
      en: "Switch style or tone with the scroll wheel",
      it: "Cambia stile o tono con la rotella di scroll",
    },
    summary: {
      en: "Scroll on the pill to cycle AI styles. Ctrl + scroll to cycle tones. No need to open Settings.",
      it: "Scrolla sulla pill per cambiare stile AI. Ctrl + scroll per cambiare tono. Senza aprire le impostazioni.",
    },
    tags: ["scroll", "gesture", "shortcut", "style", "tone", "pill"],
    blocks: {
      en: [
        p("The pill is also a mini control surface. Hover the cursor over it and scroll the mouse wheel to cycle through the 13 AI styles. Hold Ctrl while scrolling to cycle the 5 tones instead."),
        video("Hovering the pill and scrolling to cycle through Correct, Summarize, Professional, Gen-Z styles"),
        h("Visual feedback"),
        p("Each scroll click shows a tiny label next to the pill with the new style or tone name. The label fades after a second so it never gets in the way."),
        image("Scroll feedback label next to the pill: Style: Professional", "16/9"),
        h("Trackpad gestures"),
        p("On macOS you can also two-finger scroll on the pill. Same effect. The pill ignores horizontal swipes and pinches."),
        callout("info", "If you find scroll-on-pill annoying, turn it off in Settings → Overlay → Scroll gestures."),
      ],
      it: [
        p("La pill è anche una mini-superficie di controllo. Posiziona il cursore sopra di lei e scrolla la rotella del mouse per cambiare uno dei 13 stili AI. Tieni Ctrl mentre scrolli per cambiare invece il tono tra i 5 disponibili."),
        video("Hover sulla pill mentre scrolla, ciclo tra gli stili Correct, Summarize, Professional, Gen-Z"),
        h("Feedback visivo"),
        p("Ogni click di scroll mostra un'etichetta accanto alla pill con il nome del nuovo stile o tono. L'etichetta sparisce dopo un secondo, così non disturba."),
        image("Etichetta di feedback dello scroll accanto alla pill: Style: Professional", "16/9"),
        h("Gesture da trackpad"),
        p("Su macOS puoi anche fare scroll a due dita sopra la pill. Stesso effetto. La pill ignora swipe orizzontali e pinch."),
        callout("info", "Se lo scroll sulla pill ti dà fastidio, lo puoi spegnere in Impostazioni → Overlay → Gesture di scroll."),
      ],
    },
  },

  // ---------- AI Styles & Tones ----------
  {
    slug: "styles",
    category: "ai-styles",
    icon: "✨",
    title: {
      en: "The 13 AI styles",
      it: "I 13 stili AI",
    },
    summary: {
      en: "After transcription, an optional LLM pass rewrites your text. From Correct to Imbruttito, with 11 styles in between.",
      it: "Dopo la trascrizione, un LLM opzionale riscrive il testo. Da Correct a Imbruttito, con 11 stili nel mezzo.",
    },
    tags: ["styles", "llm", "ai", "rewrite", "correct", "summarize", "elaborate", "professional", "imbruttito"],
    blocks: {
      en: [
        p("By default the LLM pass is Off and Dimmy pastes the raw transcription. Pick a style to have it rewritten before paste. Switch styles on the fly with [[scroll-shortcuts|scroll-on-pill]] or from Settings → Output."),
        image("Settings → Output showing the 13 styles in a grid", "16/9", { win: { light: "/assets/help/styles/output-grid-light.png", dark: "/assets/help/styles/output-grid-dark.png" }, mac: { light: "/assets/help/app-settings/output-light.png", dark: "/assets/help/app-settings/output-dark.png" } }),
        table(
          ["Style", "Effect"],
          [
            ["Off", "No LLM. Raw transcription."],
            ["Correct", "Fix grammar, punctuation, obvious typos. The safe default."],
            ["Summarize", "Condense to key points. Great for long monologues."],
            ["Elaborate", "Expand with detail. Turns bullet points into prose."],
            ["Comprehensible", "Rewrite for clarity. For when you stumbled while speaking."],
            ["Professional", "Business or email tone. No fluff."],
            ["Prompt", "Reshape as an LLM prompt. Optimised for ChatGPT, Claude, Cursor."],
            ["Gen-Z", "Slang rewrite. fr fr no cap."],
            ["Boomer", "Old-school formal rewrite."],
            ["Emoji", "Insert tasteful emoji at the right spots."],
            ["Acronyms", "Replace phrases with abbreviations. ASAP, FYI, TLDR."],
            ["Imbruttito", "Milanese grumpy rewrite. Italian humour."],
            ["Custom", "Your own system prompt. See [[custom-prompts|Write your own prompt]]."],
          ],
        ),
        h("Tones modulate styles"),
        p("On top of the style, pick a tone: neutral, friendly, formal, casual, enthusiastic. The tone shifts the register without changing the style. See [[tones|The 5 tones]]."),
        callout("tip", "Use Correct for everyday Slack/Discord messages. Use Prompt before sending to ChatGPT or Claude. Use Professional for emails. Use Summarize after a long voice note."),
      ],
      it: [
        p("Di default il passaggio LLM è Off e Dimmy incolla la trascrizione grezza. Scegli uno stile per farlo riscrivere prima dell'incolla. Cambia stile al volo con [[scroll-shortcuts|scroll sulla pill]] o da Impostazioni → Output."),
        image("Impostazioni → Output con i 13 stili in griglia", "16/9", { win: { light: "/assets/help/styles/output-grid-light.png", dark: "/assets/help/styles/output-grid-dark.png" }, mac: { light: "/assets/help/app-settings/output-light.png", dark: "/assets/help/app-settings/output-dark.png" } }),
        table(
          ["Stile", "Effetto"],
          [
            ["Off", "Niente LLM. Trascrizione grezza."],
            ["Correct", "Sistema grammatica, punteggiatura, refusi ovvi. Il default sicuro."],
            ["Summarize", "Riassume per punti chiave. Ottimo per monologhi lunghi."],
            ["Elaborate", "Espande con dettagli. Da elenchi puntati a prosa."],
            ["Comprehensible", "Riscrive per chiarezza. Quando hai inciampato parlando."],
            ["Professional", "Tono business o da email. Niente fronzoli."],
            ["Prompt", "Riformatta come prompt LLM. Ottimizzato per ChatGPT, Claude, Cursor."],
            ["Gen-Z", "Riscrittura in slang. fr fr no cap."],
            ["Boomer", "Riscrittura vecchia scuola, formale."],
            ["Emoji", "Inserisce emoji con gusto nei punti giusti."],
            ["Acronyms", "Sostituisce frasi con abbreviazioni. ASAP, FYI, TLDR."],
            ["Imbruttito", "Riscrittura imbruttita milanese. Umorismo italiano."],
            ["Custom", "Il tuo prompt di sistema. Vedi [[custom-prompts|Scrivi il tuo prompt]]."],
          ],
        ),
        h("I toni modulano gli stili"),
        p("Sopra allo stile, scegli un tono: neutral, friendly, formal, casual, enthusiastic. Il tono sposta il registro senza cambiare lo stile. Vedi [[tones|I 5 toni]]."),
        callout("tip", "Usa Correct per messaggi quotidiani su Slack/Discord. Usa Prompt prima di mandare a ChatGPT o Claude. Usa Professional per le email. Usa Summarize dopo un vocale lungo."),
      ],
    },
  },

  {
    slug: "command-mode",
    category: "ai-styles",
    icon: "🪄",
    title: {
      en: "Command Mode: speak instructions, not text",
      it: "Command Mode: parla per comandare, non per dettare",
    },
    summary: {
      en: "Select text and say what to do with it. Or, with nothing selected, ask Dimmy to write something at the cursor. The AI does the rest.",
      it: "Seleziona del testo e di' cosa farne. Oppure, senza selezione, chiedi a Dimmy di scrivere qualcosa al cursore. Il resto lo fa l'AI.",
    },
    tags: ["command", "command mode", "edit", "transform", "rewrite", "selection", "generate", "ai", "llm", "amber"],
    blocks: {
      en: [
        p("Normal dictation types what you say. Command Mode flips that: what you say becomes an instruction, and the AI edits or writes text for you, directly in whatever app you are in. The result replaces the selection or appears at the cursor, like a normal paste."),
        video("Selecting a paragraph, saying 'make it more formal', and watching it get replaced in place"),
        h("With text selected"),
        p("Select text in any app, start a recording in Command Mode, and speak. Dimmy reads the selection, applies your instruction, and replaces the selection with the result."),
        list([
          "“Make it more formal.”",
          "“Translate to English.”",
          "“Fix the grammar.”",
          "“Turn this into bullet points.”",
          "“Shorten it to one sentence.”",
        ]),
        p("If you dictate plain content instead of an instruction, Dimmy understands and simply replaces the selection with what you said. Handy for rewriting a sentence by voice."),
        h("With nothing selected"),
        p("With no selection, your words become a writing request and the result is inserted at the cursor."),
        list([
          "“Write a polite decline to this meeting invite.”",
          "“Draft a short tweet about our launch.”",
          "“Give me three subject lines for this email.”",
        ]),
        p("Literal content still works: say “the quick brown fox” and that is exactly what gets inserted, cleaned up with capitalization and punctuation."),
        h("Two ways to turn it on"),
        p("Sticky toggle. Right-click the pill → Command (edit selection). The same toggle is in the tray menu on Windows and in the menu-bar and Dock menus on macOS. The mode stays on, and every recording is a command, until you toggle it off. The pill's dot turns amber while it is active."),
        image("Pill menu with Command (edit selection) checked, pill dot amber", "16/9"),
        p("One-shot shortcut. Set a dedicated combo in Settings → Shortcut → Command mode shortcut (unset by default). Press it instead of the dictation hotkey to run a single command, then Dimmy goes straight back to normal dictation. It follows the same Hold or Toggle mode as your dictation hotkey. See [[hotkey-dictionary-command|Dictionary and Command Mode shortcuts]]."),
        h("What it needs"),
        p("Command Mode uses the same AI model as the [[styles|AI styles]]: a cloud provider with your [[api-keys|API key]], a [[local-llm|local LLM]], or your Claude subscription. If no model is configured, Dimmy shows a toast pointing to Settings → Providers & keys."),
        callout("tip", "Two rules the AI always follows: it keeps your language unless you explicitly ask to translate, and it outputs only the resulting text. No “Sure, here is…”, no quotes, no commentary."),
      ],
      it: [
        p("La dettatura normale scrive quello che dici. Command Mode lo ribalta: quello che dici diventa un'istruzione, e l'AI modifica o scrive il testo per te, direttamente nell'app in cui ti trovi. Il risultato sostituisce la selezione o appare al cursore, come un normale incolla."),
        video("Selezione di un paragrafo, 'rendilo più formale' a voce, e la sostituzione sul posto"),
        h("Con del testo selezionato"),
        p("Seleziona del testo in qualsiasi app, avvia una registrazione in Command Mode e parla. Dimmy legge la selezione, applica la tua istruzione e sostituisce la selezione con il risultato."),
        list([
          "“Rendilo più formale.”",
          "“Traduci in inglese.”",
          "“Sistema la grammatica.”",
          "“Trasformalo in elenco puntato.”",
          "“Accorcialo a una frase.”",
        ]),
        p("Se invece di un'istruzione detti del contenuto, Dimmy lo capisce e sostituisce la selezione con quello che hai detto. Comodo per riscrivere una frase a voce."),
        h("Senza nulla selezionato"),
        p("Senza selezione, le tue parole diventano una richiesta di scrittura e il risultato viene inserito al cursore."),
        list([
          "“Scrivi un rifiuto cortese a questo invito di riunione.”",
          "“Buttami giù un tweet breve sul nostro lancio.”",
          "“Dammi tre oggetti per questa email.”",
        ]),
        p("Il contenuto letterale funziona comunque: di' “la volpe veloce marrone” ed è esattamente quello che viene inserito, ripulito con maiuscole e punteggiatura."),
        h("Due modi per attivarlo"),
        p("Toggle persistente. Click destro sulla pill → Command (edit selection). Lo stesso toggle è nel menu del tray su Windows e nei menu della barra e del Dock su macOS. La modalità resta attiva, e ogni registrazione è un comando, finché non la spegni. Il puntino della pill diventa ambra mentre è attiva."),
        image("Menu della pill con Command (edit selection) spuntato, puntino della pill ambra", "16/9"),
        p("Scorciatoia one-shot. Imposta una combo dedicata in Impostazioni → Scorciatoia → Command mode shortcut (non impostata di default). Premila al posto della scorciatoia di dettatura per lanciare un singolo comando, poi Dimmy torna subito alla dettatura normale. Segue la stessa modalità Tieni-premuto o Toggle della scorciatoia di dettatura. Vedi [[hotkey-dictionary-command|Scorciatoie Dizionario e Command Mode]]."),
        h("Cosa serve"),
        p("Command Mode usa lo stesso modello AI degli [[styles|stili AI]]: un provider cloud con la tua [[api-keys|API key]], un [[local-llm|LLM locale]] o il tuo abbonamento Claude. Se nessun modello è configurato, Dimmy mostra un toast che punta a Impostazioni → Provider e chiavi."),
        callout("tip", "Due regole che l'AI segue sempre: mantiene la tua lingua a meno che tu non chieda esplicitamente di tradurre, e produce solo il testo risultante. Niente “Certo, ecco qui…”, niente virgolette, niente commenti."),
      ],
    },
  },

  {
    slug: "tones",
    category: "ai-styles",
    icon: "🎚️",
    title: {
      en: "The 5 tones",
      it: "I 5 toni",
    },
    summary: {
      en: "Neutral, friendly, formal, casual, enthusiastic. The tone slider sits on top of the style and changes register only.",
      it: "Neutral, friendly, formal, casual, enthusiastic. Lo slider del tono sta sopra allo stile e cambia solo il registro.",
    },
    tags: ["tone", "register", "style", "llm", "settings"],
    blocks: {
      en: [
        p("Tones are modifiers, not styles. Pick a style first (Correct, Professional, ...) then choose a tone. Same content, different register."),
        table(
          ["Tone", "Feel", "Good for"],
          [
            ["Neutral", "Plain, balanced", "Default. Works everywhere."],
            ["Friendly", "Warm, approachable", "Slack, Discord, casual emails."],
            ["Formal", "Strict, distant", "Legal, official correspondence."],
            ["Casual", "Loose, conversational", "Notes to yourself, internal chat."],
            ["Enthusiastic", "Energetic, upbeat", "Announcements, marketing copy."],
          ],
        ),
        h("Cycle with Ctrl + scroll"),
        p("Hover the pill and Ctrl + scroll to cycle tones without opening Settings. See [[scroll-shortcuts|Scroll shortcuts]]."),
        image("Tone selector in Settings → Output", "16/9", { win: { light: "/assets/help/tones/selector-light.png", dark: "/assets/help/tones/selector-dark.png" }, mac: { light: "/assets/help/app-settings/output-light.png", dark: "/assets/help/app-settings/output-dark.png" } }),
      ],
      it: [
        p("I toni sono modificatori, non stili. Scegli prima uno stile (Correct, Professional, ...) e poi un tono. Stesso contenuto, registro diverso."),
        table(
          ["Tono", "Sensazione", "Quando usarlo"],
          [
            ["Neutral", "Piano, bilanciato", "Default. Funziona ovunque."],
            ["Friendly", "Caldo, accogliente", "Slack, Discord, email informali."],
            ["Formal", "Rigido, distante", "Corrispondenza legale, ufficiale."],
            ["Casual", "Sciolto, da chiacchierata", "Appunti per te, chat interne."],
            ["Enthusiastic", "Energico, su di giri", "Annunci, copy marketing."],
          ],
        ),
        h("Cambia con Ctrl + scroll"),
        p("Hover sulla pill e Ctrl + scroll per ciclare i toni senza aprire le impostazioni. Vedi [[scroll-shortcuts|Scroll shortcuts]]."),
        image("Selettore del tono in Impostazioni → Output", "16/9", { win: { light: "/assets/help/tones/selector-light.png", dark: "/assets/help/tones/selector-dark.png" }, mac: { light: "/assets/help/app-settings/output-light.png", dark: "/assets/help/app-settings/output-dark.png" } }),
      ],
    },
  },

  {
    slug: "custom-prompts",
    category: "ai-styles",
    icon: "📝",
    title: {
      en: "Write your own system prompt",
      it: "Scrivi il tuo prompt di sistema",
    },
    summary: {
      en: "Pick the Custom style and paste any system prompt. Dimmy uses it for every dictation until you change it.",
      it: "Scegli lo stile Custom e incolla un prompt di sistema. Dimmy lo usa per ogni dettatura finché non lo cambi.",
    },
    tags: ["custom", "prompt", "system", "llm", "style", "advanced"],
    blocks: {
      en: [
        steps([
          "Open Settings → Output.",
          "Pick the Custom style.",
          "Paste your system prompt in the box below.",
          "Save. From now on every dictation goes through your prompt before being pasted.",
        ]),
        h("Example prompts"),
        code("You are a copy editor. Fix punctuation and grammar without changing the meaning or the voice. Keep contractions. Do not add or remove sentences. Output the rewritten text only.", "text"),
        code("Rewrite the input as a code comment. Use imperative tone. Wrap lines at 80 columns. Output the comment block only, including comment markers for the surrounding language.", "text"),
        code("Translate the input to French. Keep proper nouns. If the input already is French, leave it unchanged. Output the translation only.", "text"),
        callout("tip", "End every system prompt with Output the rewritten text only. or similar. Otherwise the LLM may add explanations that get pasted into your text."),
        h("Variables"),
        p("Custom prompts can include {{tone}} as a placeholder. Dimmy replaces it with the selected tone before sending. Lets you reuse the same prompt across tones."),
      ],
      it: [
        steps([
          "Apri Impostazioni → Output.",
          "Scegli lo stile Custom.",
          "Incolla il tuo prompt di sistema nel riquadro sotto.",
          "Salva. Da ora ogni dettatura passa per il tuo prompt prima di essere incollata.",
        ]),
        h("Esempi di prompt"),
        code("Sei un copy editor. Sistema punteggiatura e grammatica senza cambiare il significato o la voce. Mantieni le contrazioni. Non aggiungere o togliere frasi. Restituisci solo il testo riscritto.", "text"),
        code("Riscrivi l'input come un commento di codice. Usa il tono imperativo. Vai a capo a 80 colonne. Restituisci solo il blocco commento, incluso il delimitatore del linguaggio circostante.", "text"),
        code("Traduci l'input in francese. Mantieni i nomi propri. Se l'input è già in francese, lascialo invariato. Restituisci solo la traduzione.", "text"),
        callout("tip", "Chiudi sempre il prompt con Restituisci solo il testo riscritto. o equivalente. Altrimenti l'LLM aggiunge spiegazioni che finiscono incollate nel tuo testo."),
        h("Variabili"),
        p("I prompt custom possono includere {{tone}} come placeholder. Dimmy lo sostituisce con il tono selezionato prima dell'invio. Così riusi lo stesso prompt con toni diversi."),
      ],
    },
  },

  {
    slug: "filler-removal",
    category: "ai-styles",
    icon: "🧹",
    title: {
      en: "Strip filler words automatically",
      it: "Rimuovi i riempitivi automaticamente",
    },
    summary: {
      en: "Dimmy can drop \"um\", \"uh\", \"basically\", \"cioè\" before paste. Works in 6 languages, independent of the LLM pass.",
      it: "Dimmy può togliere \"um\", \"uh\", \"basically\", \"cioè\" prima dell'incolla. Funziona in 6 lingue, indipendentemente dall'LLM.",
    },
    tags: ["filler", "clean", "um", "uh", "cioè", "polish", "settings"],
    blocks: {
      en: [
        p("Filler removal runs between transcription and LLM enhancement. It uses a hand-tuned list of verbal filler words and conservative regex rules: it only removes things it is sure about, never rewrites the meaning."),
        h("Supported languages"),
        list([
          "English (um, uh, basically, like, you know, I mean, sort of, kind of)",
          "Italian (cioè, tipo, praticamente, ecco, insomma)",
          "Spanish (eh, este, o sea, pues)",
          "French (euh, ben, du coup, en fait)",
          "German (ähm, halt, also, sozusagen)",
          "Portuguese (tipo, né, ahn, então)",
        ]),
        h("Turning it on"),
        steps([
          "Open Settings → General.",
          "Toggle Filler removal on.",
          "Save.",
        ]),
        h("Works without the LLM"),
        p("Even with the LLM pass set to Off, filler removal still runs. Useful when you want clean text without paying for a cloud LLM."),
        image("Settings → General → Filler removal toggle", "16/9", { win: { light: "/assets/help/filler-removal/toggle-light.png", dark: "/assets/help/filler-removal/toggle-dark.png" }, mac: { light: "/assets/help/app-settings/output-light.png", dark: "/assets/help/app-settings/output-dark.png" } }),
      ],
      it: [
        p("La rimozione dei riempitivi avviene tra la trascrizione e l'enhancement LLM. Usa una lista artigianale di parole di riempimento e regex conservative: rimuove solo ciò di cui è sicura, mai riscrive il significato."),
        h("Lingue supportate"),
        list([
          "Inglese (um, uh, basically, like, you know, I mean, sort of, kind of)",
          "Italiano (cioè, tipo, praticamente, ecco, insomma)",
          "Spagnolo (eh, este, o sea, pues)",
          "Francese (euh, ben, du coup, en fait)",
          "Tedesco (ähm, halt, also, sozusagen)",
          "Portoghese (tipo, né, ahn, então)",
        ]),
        h("Come attivarla"),
        steps([
          "Apri Impostazioni → Generale.",
          "Attiva il toggle Rimozione filler.",
          "Salva.",
        ]),
        h("Funziona senza LLM"),
        p("Anche con il passaggio LLM impostato a Off, la rimozione dei riempitivi gira lo stesso. Utile quando vuoi un testo pulito senza pagare un LLM cloud."),
        image("Impostazioni → Generale → toggle Rimozione filler", "16/9", { win: { light: "/assets/help/filler-removal/toggle-light.png", dark: "/assets/help/filler-removal/toggle-dark.png" }, mac: { light: "/assets/help/app-settings/output-light.png", dark: "/assets/help/app-settings/output-dark.png" } }),
      ],
    },
  },

  // ---------- Providers & Models ----------
  {
    slug: "local-mode",
    category: "providers",
    icon: "🏠",
    title: {
      en: "Local mode: offline by default",
      it: "Modalità locale: offline di default",
    },
    summary: {
      en: "Dimmy ships with Whisper running on your device. No API key, no internet, no per-minute cost. Works on a plane.",
      it: "Dimmy include Whisper che gira sul tuo dispositivo. Niente API key, niente internet, zero costi a minuto. Funziona in aereo.",
    },
    tags: ["local", "offline", "whisper", "default", "privacy", "free"],
    blocks: {
      en: [
        callout("info", "Local mode is the default. You don't need to do anything to use it. Cloud providers are opt-in."),
        p("On first launch Dimmy downloads a Whisper model (around 78 MB for base-q8_0). After that, all transcription happens on your machine. The model uses your CPU or GPU; on Apple Silicon it runs through Metal, on NVIDIA it can use CUDA, on Vulkan-capable Windows GPUs it accelerates too."),
        h("What runs locally"),
        list([
          "Speech-to-text via whisper.cpp.",
          "Filler removal (no model, just regex).",
          "LLM enhancement, optional, if you enable the on-device model. See [[local-llm|Optional on-device LLM]].",
          "Everything else: history, settings, key storage.",
        ]),
        h("Performance"),
        p("On a recent Mac, local Whisper transcribes a 10-second clip in roughly 0.6 seconds. On a 4-year-old laptop, around 1.5 to 2 seconds. With GPU acceleration, you get sub-second results for short clips on most hardware."),
        image("Local benchmark chart: latency by hardware and clip length", "16/9"),
        h("When to use cloud instead"),
        list([
          "You record long sessions (10+ minutes) and want them done in seconds.",
          "Your device is old or under-powered.",
          "You want absolute top-tier accuracy on noisy audio. Cloud Whisper Large v3 still has the edge.",
        ]),
      ],
      it: [
        callout("info", "La modalità locale è quella di default. Non devi fare niente per usarla. I provider cloud sono opt-in."),
        p("Al primo avvio Dimmy scarica un modello Whisper (circa 78 MB per base-q8_0). Dopo, tutta la trascrizione avviene sul tuo computer. Il modello usa CPU o GPU; su Apple Silicon gira via Metal, su NVIDIA può usare CUDA, su GPU Windows con Vulkan accelera anche lì."),
        h("Cosa gira in locale"),
        list([
          "Speech-to-text via whisper.cpp.",
          "Rimozione filler (niente modello, solo regex).",
          "Enhancement LLM, opzionale, se attivi il modello on-device. Vedi [[local-llm|LLM on-device opzionale]].",
          "Tutto il resto: cronologia, impostazioni, storage chiavi.",
        ]),
        h("Prestazioni"),
        p("Su un Mac recente, Whisper locale trascrive un clip da 10 secondi in circa 0.6 secondi. Su un laptop di 4 anni fa, attorno a 1.5-2 secondi. Con accelerazione GPU, sotto al secondo per clip brevi su quasi tutto l'hardware."),
        image("Grafico benchmark locale: latenza per hardware e durata clip", "16/9"),
        h("Quando usare invece il cloud"),
        list([
          "Registri sessioni lunghe (10+ minuti) e le vuoi finite in secondi.",
          "Il tuo device è vecchio o poco potente.",
          "Vuoi massima accuratezza assoluta su audio rumoroso. Whisper Large v3 in cloud ha ancora il vantaggio.",
        ]),
      ],
    },
  },

  {
    slug: "cloud-providers",
    category: "providers",
    icon: "☁️",
    title: {
      en: "Cloud providers compared",
      it: "Provider cloud a confronto",
    },
    summary: {
      en: "Groq is fastest, OpenAI is the gold standard, Deepgram leads on streaming. All optional. Bring your own key.",
      it: "Groq è il più veloce, OpenAI è lo standard, Deepgram è leader sullo streaming. Tutti opzionali. Porti la tua key.",
    },
    tags: ["cloud", "providers", "groq", "openai", "deepgram", "gemini", "anthropic", "openrouter", "together", "fireworks", "stt", "llm"],
    blocks: {
      en: [
        p("Dimmy supports 8 cloud providers, plus a Custom endpoint for any OpenAI-compatible API. You bring the key, Dimmy talks to the API. We never proxy your traffic."),
        table(
          ["Provider", "Type", "Free tier", "Best for"],
          [
            ["Groq", "STT + LLM", "Yes, rate-limited", "Recommended. Sub-second on Whisper Large turbo, very fast Llama 3.3 70B."],
            ["OpenAI", "STT + LLM", "Pay-per-use", "Highest accuracy on noisy audio (whisper-1). GPT-5.5 for LLM."],
            ["Deepgram", "STT only", "$200 free credits", "Real-time streaming. Lowest end-to-end latency."],
            ["Gemini", "STT + LLM", "Yes", "Long-context LLM (Gemini 3.1 Pro). Gemini 3.5 Flash for speed."],
            ["Anthropic", "LLM only", "Pay-per-use", "Claude Opus 4.8 or Sonnet 4.6 for the LLM pass."],
            ["OpenRouter", "LLM only", "Yes (free models)", "Try any open-weight LLM (Llama 3.3, DeepSeek, ...). One key, 100+ models."],
            ["Together", "STT + LLM", "Pay-per-use", "Llama 3.3 70B Turbo. Parakeet TDT v3 for STT."],
            ["Fireworks", "STT + LLM", "Pay-per-use", "Kimi K2 for LLM. Whisper v3 Turbo for STT."],
            ["Custom", "STT + LLM", "Yours", "Any OpenAI-compatible URL. Self-hosted, alternate provider."],
          ],
        ),
        h("Adding a provider"),
        p("Open Settings → Providers & keys and find the provider card. Add your API key in the key field. The key is stored encrypted on your device. See [[api-keys|Add your API key]]. The On-device card on the same page lists your local models with a green check next to the ones already downloaded, see [[whisper-models|Choose a Whisper model]]."),
        h("Mixing local + cloud"),
        p("You can run STT locally and LLM via cloud (or vice versa). For example: local Whisper for transcription (private), Claude Haiku for the LLM rewrite. Settings let you pick independently per pipeline stage."),
        callout("info", "All cloud calls are logged to your Dimmy log file with the provider name (never the key, never the payload). Check the log if you want to audit."),
      ],
      it: [
        p("Dimmy supporta 8 provider cloud, più un endpoint Custom per qualsiasi API OpenAI-compatibile. La key è tua, Dimmy parla direttamente con l'API. Non facciamo proxy del tuo traffico."),
        table(
          ["Provider", "Tipo", "Free tier", "Quando usarlo"],
          [
            ["Groq", "STT + LLM", "Sì, rate-limited", "Consigliato. Whisper Large turbo sotto al secondo, Llama 3.3 70B velocissimo."],
            ["OpenAI", "STT + LLM", "Pay-per-use", "Accuratezza massima su audio rumoroso (whisper-1). GPT-5.5 per l'LLM."],
            ["Deepgram", "Solo STT", "200$ di credito", "Streaming real-time. Latenza end-to-end minima."],
            ["Gemini", "STT + LLM", "Sì", "LLM a contesto lungo (Gemini 3.1 Pro). Gemini 3.5 Flash per la velocità."],
            ["Anthropic", "Solo LLM", "Pay-per-use", "Claude Opus 4.8 o Sonnet 4.6 per il passaggio LLM."],
            ["OpenRouter", "Solo LLM", "Sì (modelli free)", "Provi qualsiasi LLM open-weight (Llama 3.3, DeepSeek, ...). Una key, 100+ modelli."],
            ["Together", "STT + LLM", "Pay-per-use", "Llama 3.3 70B Turbo per LLM. Parakeet TDT v3 per STT."],
            ["Fireworks", "STT + LLM", "Pay-per-use", "Kimi K2 per LLM. Whisper v3 Turbo per STT."],
            ["Custom", "STT + LLM", "La tua", "Qualsiasi URL OpenAI-compatibile. Self-host o provider alternativo."],
          ],
        ),
        h("Aggiungere un provider"),
        p("Apri Impostazioni → Provider e chiavi e trova la card del provider. Inserisci la API key nel campo apposito. La key è salvata cifrata sul tuo device. Vedi [[api-keys|Aggiungi la tua API key]]. La card On-device nella stessa pagina elenca i tuoi modelli locali con un check verde accanto a quelli già scaricati, vedi [[whisper-models|Scegli un modello Whisper]]."),
        h("Mix local + cloud"),
        p("Puoi tenere STT locale e LLM via cloud (o viceversa). Per esempio: Whisper locale per la trascrizione (privato), Claude Haiku per la riscrittura LLM. Le impostazioni permettono di scegliere indipendentemente per ogni stadio."),
        callout("info", "Tutte le chiamate cloud finiscono nel log di Dimmy con il nome del provider (mai la key, mai il payload). Controlla il log se vuoi fare audit."),
      ],
    },
  },

  {
    slug: "api-keys",
    category: "providers",
    icon: "🔑",
    title: {
      en: "Add your API key",
      it: "Aggiungi la tua API key",
    },
    summary: {
      en: "Open Settings → Providers & keys, find the provider card, paste the key. It is encrypted on your machine. You can update keys at any time.",
      it: "Apri Impostazioni → Provider e chiavi, trova la card del provider, incolla la key. Viene cifrata sul tuo computer. Puoi aggiornare le key in qualsiasi momento.",
    },
    tags: ["api key", "key", "credentials", "groq", "openai", "settings", "security"],
    blocks: {
      en: [
        steps([
          "Open the provider's console: console.groq.com/keys for Groq, platform.openai.com/api-keys for OpenAI, and so on.",
          "Create a new API key. Copy it once (most consoles don't show it again).",
          "Open Dimmy → Settings → Providers & keys.",
          "Click the card for your provider to expand it.",
          "Paste the key in the key field and click Connect.",
          "The card header shows a connected status pill when the key is accepted.",
        ]),
        image("Settings → Providers & keys page with provider cards and status pills", "16/9", { win: { light: "/assets/help/api-keys/providers-light.png", dark: "/assets/help/api-keys/providers-dark.png" }, mac: { light: "/assets/help/app-settings/providers-light.png", dark: "/assets/help/app-settings/providers-dark.png" } }),
        h("Where the key lives"),
        list([
          "Encrypted at rest in ~/.config/dimmy/keys.enc (or %APPDATA%\\dimmy\\keys.enc on Windows).",
          "AES-256-GCM with a key derived from your machine. No OS keyring popup.",
          "Decrypted only in memory when Dimmy needs to call the provider.",
          "Sent only to the provider domain. Hardcoded host allowlist.",
        ]),
        h("Multiple keys"),
        p("Each provider has its own card with its own key field. You can keep keys for Groq, OpenAI, Anthropic, and others simultaneously. Each card shows what the provider can do: speech to text, rewrite, recap."),
        callout("info", "Read more about key storage: [[api-keys-storage|How API keys are stored]] and [[/privacy|Privacy policy]]."),
      ],
      it: [
        steps([
          "Apri la console del provider: console.groq.com/keys per Groq, platform.openai.com/api-keys per OpenAI, e così via.",
          "Crea una nuova API key. Copiala subito (la maggior parte delle console non la rimostra più).",
          "Apri Dimmy → Impostazioni → Provider e chiavi.",
          "Clicca sulla card del provider per espanderla.",
          "Incolla la key nel campo apposito e clicca Connect.",
          "L'intestazione della card mostra una status pill di connessione quando la key è accettata.",
        ]),
        image("Pagina Impostazioni → Provider e chiavi con card dei provider e status pill", "16/9", { win: { light: "/assets/help/api-keys/providers-light.png", dark: "/assets/help/api-keys/providers-dark.png" }, mac: { light: "/assets/help/app-settings/providers-light.png", dark: "/assets/help/app-settings/providers-dark.png" } }),
        h("Dove vive la key"),
        list([
          "Cifrata a riposo in ~/.config/dimmy/keys.enc (o %APPDATA%\\dimmy\\keys.enc su Windows).",
          "AES-256-GCM con chiave derivata dalla macchina. Niente popup del keyring di sistema.",
          "Decifrata solo in memoria quando Dimmy deve chiamare il provider.",
          "Inviata solo al dominio del provider. Allowlist di host hardcoded.",
        ]),
        h("Più key contemporaneamente"),
        p("Ogni provider ha la sua card con il proprio campo per la key. Puoi tenere key per Groq, OpenAI, Anthropic e altri insieme. Ogni card mostra cosa può fare il provider: speech to text, riscrittura, recap."),
        callout("info", "Approfondimento sullo storage delle key: [[/privacy|Privacy policy]]."),
      ],
    },
  },

  {
    slug: "whisper-models",
    category: "providers",
    icon: "📦",
    title: {
      en: "Choose a Whisper model",
      it: "Scegli un modello Whisper",
    },
    summary: {
      en: "Smaller is faster but less accurate. base-q8_0 is the default. large-v3-turbo is the top tier on-device.",
      it: "Più piccolo è più veloce ma meno accurato. base-q8_0 è il default. large-v3-turbo è il top on-device.",
    },
    tags: ["whisper", "model", "local", "stt", "ggml", "settings", "download"],
    blocks: {
      en: [
        p("Open Settings → Models. You see the full list of Whisper variants with size, speed estimate, and download status. The active model is highlighted."),
        image("Settings → Models with the model list and download buttons", "16/9", { win: { light: "/assets/help/whisper-models/list-light.png", dark: "/assets/help/whisper-models/list-dark.png" }, mac: { light: "/assets/help/app-settings/providers-light.png", dark: "/assets/help/app-settings/providers-dark.png" } }),
        table(
          ["Model", "Size", "Speed", "Accuracy"],
          [
            ["tiny", "~40 MB", "fastest", "low"],
            ["base-q8_0", "~78 MB", "very fast", "good (default)"],
            ["small-q8_0", "~250 MB", "fast", "great"],
            ["medium-q8_0", "~770 MB", "medium", "very good"],
            ["large-v3-turbo-q8_0", "~870 MB", "fast", "top tier"],
            ["large-v3", "~3 GB", "slow", "top tier"],
          ],
        ),
        h("Quantization"),
        p("Models tagged q8_0 are 8-bit quantized. They give roughly the same accuracy as the full-precision version (2 to 3 % drop) at about half the size and twice the speed. Default everywhere on-device."),
        h("Download flow"),
        steps([
          "Pick a model from the list, click Download.",
          "Progress bar shows the current MB/MB.",
          "Once finished, the model becomes active automatically.",
          "Previous models stay on disk until you click Remove.",
        ]),
        callout("info", "In the Voice model picker each model that is already on disk shows a green check next to its name. Models you have not downloaded yet show their size instead. So you can tell at a glance which ones are ready. Parakeet uses the same green check. The on-device LLM picker on the Output page behaves the same way, see [[local-llm|the on-device LLM]]."),
        callout("tip", "Try base-q8_0 first. If accuracy isn't enough, jump to large-v3-turbo-q8_0. The mediums are rarely worth it."),
      ],
      it: [
        p("Apri Impostazioni → Modelli. Vedi la lista completa delle varianti Whisper con dimensione, stima di velocità e stato del download. Il modello attivo è evidenziato."),
        image("Impostazioni → Modelli con la lista e i pulsanti di download", "16/9", { win: { light: "/assets/help/whisper-models/list-light.png", dark: "/assets/help/whisper-models/list-dark.png" }, mac: { light: "/assets/help/app-settings/providers-light.png", dark: "/assets/help/app-settings/providers-dark.png" } }),
        table(
          ["Modello", "Dimensione", "Velocità", "Accuratezza"],
          [
            ["tiny", "~40 MB", "il più veloce", "bassa"],
            ["base-q8_0", "~78 MB", "molto veloce", "buona (default)"],
            ["small-q8_0", "~250 MB", "veloce", "ottima"],
            ["medium-q8_0", "~770 MB", "media", "molto buona"],
            ["large-v3-turbo-q8_0", "~870 MB", "veloce", "top tier"],
            ["large-v3", "~3 GB", "lento", "top tier"],
          ],
        ),
        h("Quantizzazione"),
        p("I modelli marcati q8_0 sono quantizzati a 8-bit. Danno più o meno la stessa accuratezza della versione full-precision (perdita del 2-3 %), a circa metà della dimensione e doppio della velocità. Default ovunque on-device."),
        h("Flusso di download"),
        steps([
          "Scegli un modello dalla lista, clicca Scarica.",
          "La barra di progresso mostra MB/MB.",
          "A fine download il modello diventa attivo automaticamente.",
          "I modelli precedenti restano su disco finché non clicchi Rimuovi.",
        ]),
        callout("info", "Nel picker dei modelli in Voce, ogni modello già su disco mostra un check verde accanto al nome. Quelli che non hai ancora scaricato mostrano invece la dimensione. Così capisci a colpo d'occhio quali sono pronti. Parakeet usa lo stesso check verde. Il picker dell'LLM on-device nella pagina Output si comporta allo stesso modo, vedi [[local-llm|l'LLM on-device]]."),
        callout("tip", "Prova prima base-q8_0. Se l'accuratezza non basta, salta direttamente a large-v3-turbo-q8_0. I medium raramente valgono la candela."),
      ],
    },
  },

  {
    slug: "local-llm",
    category: "providers",
    icon: "🧠",
    title: {
      en: "Optional on-device LLM",
      it: "LLM on-device opzionale",
    },
    summary: {
      en: "Run the LLM enhancement pass locally via llama.cpp. No cloud, no key, no per-token cost. Pick a model to match your GPU memory.",
      it: "Esegui il passaggio LLM in locale via llama.cpp. Niente cloud, niente key, zero costi per token. Scegli il modello in base alla memoria GPU.",
    },
    tags: ["local llm", "gemma", "phi-4", "on device", "offline", "advanced", "llama.cpp", "12b", "vram"],
    blocks: {
      en: [
        p("By default the LLM pass uses a cloud provider (or is Off). Optionally, Dimmy can run an on-device LLM via llama.cpp. The default model is Phi-4 Mini Q4 (2.5 GB, 3.8B params), a compact instruction-following model. The Settings → Output model picker lists all available models so you can trade speed for quality."),
        callout("info", "On-device LLM is a separate build flag (local-llm Cargo feature). Pre-built installers on dimmy.app include it. If you build from source, pass --features local-llm."),
        h("Enable it"),
        steps([
          "Open Settings → Output → Local LLM model.",
          "Pick a model from the list and click Download.",
          "Pick On-device LLM as the active LLM in Settings → Output → LLM provider.",
          "Run a dictation. The pill shows the style icon while the model processes the text.",
        ]),
        p("In the picker, models already on disk show a green check next to their name, exactly like the [[whisper-models|Voice model picker]]. The ones you have not downloaded yet show their size instead."),
        h("Available models"),
        table(
          ["Model", "Size", "VRAM needed", "Notes"],
          [
            ["Phi-4 Mini Q4", "2.5 GB", "3 GB", "Default. Fast, multilingual, 3.8B params."],
            ["Gemma 4 E2B Q4", "3.1 GB", "4 GB", "Good quality, fits 4 GB VRAM, 5B params."],
            ["Gemma 4 E2B Q5", "3.7 GB", "4 GB", "Better quality than Q4, still fits 4 GB."],
            ["Gemma 4 E4B Q3", "4.1 GB", "4 GB+", "8B params at 3-bit. May spill to CPU on 4 GB cards."],
            ["Gemma 4 E4B Q4", "5.0 GB", "6 GB+", "Best balance for 6 GB cards, 8B params."],
            ["Gemma 4 E4B Q8", "8.2 GB", "10 GB+", "Maximum quality, 8B high-precision."],
            ["Gemma 4 12B Q4", "7.1 GB", "9 GB+", "Highest quality Gemma 4, 12B dense. Slow on 4 GB cards."],
            ["Gemma 4 12B Q2 (compact)", "4.7 GB", "4 GB+", "12B at 2-bit. Closest the 12B gets to a 4 GB card; some CPU spill."],
          ]
        ),
        h("Performance"),
        list([
          "Apple Silicon: Metal acceleration, around 50 tok/s on M2.",
          "NVIDIA GPU: CUDA, around 80-120 tok/s on RTX 3060 and up.",
          "AMD/Intel GPU: Vulkan, around 30-50 tok/s.",
          "CPU only: works but slow (5-10 tok/s).",
        ]),
        h("Trade-offs vs cloud"),
        p("Local LLM is fully private and free, but less capable than cloud Claude or GPT-4o. For Correct and Summarize styles, the smaller models are fine. For complex Prompt or Elaborate, cloud is noticeably better. The 12B model narrows that gap but needs more VRAM and is slower."),
        callout("tip", "Grammar fix, summarize, and recap use greedy decoding for stable output. Creative styles (Gen-Z, Emoji, Imbruttito) use probabilistic sampling, so results vary each run."),
      ],
      it: [
        p("Di default il passaggio LLM usa un provider cloud (oppure è Off). In alternativa, Dimmy può eseguire un LLM on-device via llama.cpp. Il modello di default è Phi-4 Mini Q4 (2,5 GB, 3,8B parametri), un modello compatto ottimizzato per seguire istruzioni. Il picker in Impostazioni → Output elenca tutti i modelli disponibili così puoi bilanciare velocità e qualità."),
        callout("info", "L'LLM on-device è dietro un flag di build (feature Cargo local-llm). Gli installer ufficiali su dimmy.app lo includono. Se compili da sorgente, passa --features local-llm."),
        h("Come attivarlo"),
        steps([
          "Apri Impostazioni → Output → Local LLM model.",
          "Scegli un modello dalla lista e clicca Scarica.",
          "Scegli On-device LLM come LLM attivo in Impostazioni → Output → Provider LLM.",
          "Avvia una dettatura. La pill mostra l'icona dello stile mentre il modello processa il testo.",
        ]),
        p("Nel picker, i modelli già su disco mostrano un check verde accanto al nome, esattamente come nel [[whisper-models|picker dei modelli in Voce]]. Quelli che non hai ancora scaricato mostrano invece la dimensione."),
        h("Modelli disponibili"),
        table(
          ["Modello", "Dimensione", "VRAM necessaria", "Note"],
          [
            ["Phi-4 Mini Q4", "2,5 GB", "3 GB", "Default. Veloce, multilingua, 3,8B parametri."],
            ["Gemma 4 E2B Q4", "3,1 GB", "4 GB", "Buona qualità, entra in 4 GB VRAM, 5B parametri."],
            ["Gemma 4 E2B Q5", "3,7 GB", "4 GB", "Qualità migliore del Q4, entra ancora in 4 GB."],
            ["Gemma 4 E4B Q3", "4,1 GB", "4 GB+", "8B parametri a 3 bit. Può sforare su CPU con 4 GB."],
            ["Gemma 4 E4B Q4", "5,0 GB", "6 GB+", "Miglior bilanciamento per GPU da 6 GB, 8B parametri."],
            ["Gemma 4 E4B Q8", "8,2 GB", "10 GB+", "Qualità massima, 8B ad alta precisione."],
            ["Gemma 4 12B Q4", "7,1 GB", "9 GB+", "Gemma 4 di qualità più alta, 12B denso. Lento su 4 GB."],
            ["Gemma 4 12B Q2 (compact)", "4,7 GB", "4 GB+", "12B a 2 bit. Il più vicino al 12B per GPU da 4 GB; spilla in parte su CPU."],
          ]
        ),
        h("Prestazioni"),
        list([
          "Apple Silicon: accelerazione Metal, circa 50 tok/s su M2.",
          "GPU NVIDIA: CUDA, 80-120 tok/s da RTX 3060 in su.",
          "GPU AMD/Intel: Vulkan, 30-50 tok/s.",
          "Solo CPU: funziona ma lento (5-10 tok/s).",
        ]),
        h("Trade-off rispetto al cloud"),
        p("L'LLM locale è completamente privato e gratis, ma meno potente di Claude in cloud o GPT-4o. Per gli stili Correct e Summarize, i modelli più piccoli vanno bene. Per Prompt o Elaborate complessi, il cloud è notevolmente meglio. Il modello 12B riduce il gap ma richiede più VRAM ed è più lento."),
        callout("tip", "Correzione grammaticale, riassunto e recap usano il decoding greedy per output stabile. Gli stili creativi (Gen-Z, Emoji, Imbruttito) usano il campionamento probabilistico, quindi i risultati variano a ogni esecuzione."),
      ],
    },
  },

  // ---------- History & Privacy ----------
  {
    slug: "history-search",
    category: "history-privacy",
    icon: "📜",
    title: {
      en: "Browse and search your history",
      it: "Sfoglia e cerca nella tua cronologia",
    },
    summary: {
      en: "Every transcription is saved locally and searchable with full-text. Stats show count, time saved, words dictated.",
      it: "Ogni trascrizione viene salvata in locale e cercabile in full-text. Le statistiche mostrano numero, tempo risparmiato, parole dettate.",
    },
    tags: ["history", "search", "transcriptions", "fts", "stats", "sqlite"],
    blocks: {
      en: [
        p("Open Settings → History. You see every transcription in reverse-chronological order with timestamp, provider used, style applied, and a preview of the text. Click any row to expand and see the full transcription."),
        image("Settings → History with the list and a row expanded", "16/9", { win: { light: "/assets/help/history-search/list-light.png", dark: "/assets/help/history-search/list-dark.png" }, mac: { light: "/assets/help/app-settings/history-light.png", dark: "/assets/help/app-settings/history-dark.png" } }),
        h("Search"),
        p("The search bar at the top is full-text. It matches across the transcription text, the style name, the language, and the provider. Press Enter to apply, Esc to clear."),
        h("Filters"),
        list([
          "By provider (Local, Groq, OpenAI, ...).",
          "By style (Correct, Summarize, ...).",
          "By language (12+ ISO codes).",
          "By date range.",
        ]),
        h("Actions on a row"),
        list([
          "Copy: copy the transcription text to clipboard.",
          "Re-paste: paste it into the focused app.",
          "Delete: remove this single entry.",
          "Reapply: re-run the LLM pass with a different style.",
        ]),
        h("Stats"),
        p("The Stats tab shows totals: count of transcriptions, total audio time, total words dictated, average time saved per transcription compared to typing. Numbers are calculated locally from the same SQLite database."),
        callout("info", "Everything in History lives in ~/.config/dimmy/history.db (SQLite + FTS5). It never leaves your device."),
      ],
      it: [
        p("Apri Impostazioni → Cronologia. Vedi ogni trascrizione in ordine cronologico inverso con timestamp, provider usato, stile applicato e un'anteprima del testo. Clicca una riga per espanderla e vedere la trascrizione intera."),
        image("Impostazioni → Cronologia con la lista e una riga espansa", "16/9", { win: { light: "/assets/help/history-search/list-light.png", dark: "/assets/help/history-search/list-dark.png" }, mac: { light: "/assets/help/app-settings/history-light.png", dark: "/assets/help/app-settings/history-dark.png" } }),
        h("Ricerca"),
        p("La search bar in alto è full-text. Cerca nel testo della trascrizione, nel nome dello stile, nella lingua e nel provider. Invio per applicare, Esc per pulire."),
        h("Filtri"),
        list([
          "Per provider (Local, Groq, OpenAI, ...).",
          "Per stile (Correct, Summarize, ...).",
          "Per lingua (12+ codici ISO).",
          "Per range di date.",
        ]),
        h("Azioni su una riga"),
        list([
          "Copia: copia il testo della trascrizione negli appunti.",
          "Re-incolla: incolla nell'app attiva.",
          "Elimina: rimuovi questa singola voce.",
          "Riapplica: rilancia il passaggio LLM con uno stile diverso.",
        ]),
        h("Statistiche"),
        p("Il tab Statistiche mostra i totali: numero di trascrizioni, tempo audio totale, parole dettate, tempo medio risparmiato rispetto a digitare. I numeri sono calcolati in locale sullo stesso database SQLite."),
        callout("info", "Tutta la cronologia vive in ~/.config/dimmy/history.db (SQLite + FTS5). Non lascia mai il tuo dispositivo."),
      ],
    },
  },

  {
    slug: "telemetry",
    category: "history-privacy",
    icon: "📊",
    title: {
      en: "Telemetry: what's sent, how to disable",
      it: "Telemetria: cosa viene inviato, come disattivarla",
    },
    summary: {
      en: "Anonymous, opt-out. Event names and numbers only, never audio, never text, never API keys. Two independent toggles.",
      it: "Anonima, opt-out. Solo nomi di eventi e numeri, mai audio, mai testo, mai API key. Due interruttori indipendenti.",
    },
    tags: ["telemetry", "analytics", "privacy", "posthog", "sentry", "disable", "opt-out"],
    blocks: {
      en: [
        p("Dimmy ships with anonymous opt-out telemetry. Two destinations, both in EU data centres, both GDPR-aligned: PostHog EU for usage analytics, Sentry EU for crash reports. Each one has its own toggle."),
        h("What we send"),
        list([
          "App version, OS, CPU architecture.",
          "Event names (app.started, transcription.completed, llm.applied, ...).",
          "Numbers and durations (audio length in seconds, processing time in ms, word count).",
          "Provider category tags (local, groq, openai, ...) but never the URL, never the API key.",
          "Which transcription engine ran, as a category tag on transcription.completed (batch, deepgram_stream, local_stream, chunked_caption).",
          "model.download_completed: which kind of local model finished downloading (whisper, llm, parakeet) and whether it succeeded. Never the model path or filename.",
          "consent.logged: which step the meeting recording-consent gate reached (shown, accepted, cancelled, announced, declined), so we can measure drop-off. Never the participant names, the spoken announcement, or any meeting content. Ties to [[use-meeting-recaps|meeting recaps]].",
          "Crash stack traces (truncated and secret-redacted).",
        ]),
        h("What we never send"),
        list([
          "The audio you record.",
          "The text of any transcription.",
          "Any prompt or LLM output.",
          "API keys, even in error messages.",
          "Your IP, hostname, or username.",
          "File paths beyond a categorical tag.",
        ]),
        h("Disable it"),
        steps([
          "Open Settings → Privacy.",
          "Toggle Send anonymous usage data off (stops PostHog).",
          "Toggle Send crash reports off (stops Sentry).",
          "Both take effect immediately. Already-sent events cannot be recalled.",
        ]),
        image("Settings → Privacy with the two telemetry toggles", "16/9", { win: { light: "/assets/help/telemetry/toggles-light.png", dark: "/assets/help/telemetry/toggles-dark.png" }, mac: { light: "/assets/help/app-settings/privacy-light.png", dark: "/assets/help/app-settings/privacy-dark.png" } }),
        h("Audit it yourself"),
        p("Every telemetry call is logged locally with [telemetry] prefix. Open your Dimmy log file and grep for [telemetry] to see exactly what was sent and when. See [[/privacy|Privacy policy]] for the full breakdown."),
        callout("info", "Want even more detail? The [[/privacy|Privacy policy]] has every event name with its payload, mirrored from the live Rust source."),
      ],
      it: [
        p("Dimmy include una telemetria anonima opt-out. Due destinazioni, entrambe in data center europei, entrambe conformi GDPR: PostHog EU per gli analytics di utilizzo, Sentry EU per i crash report. Ognuna con il suo interruttore."),
        h("Cosa inviamo"),
        list([
          "Versione app, sistema operativo, architettura CPU.",
          "Nomi degli eventi (app.started, transcription.completed, llm.applied, ...).",
          "Numeri e durate (durata audio in secondi, tempo di elaborazione in ms, conteggio parole).",
          "Categoria del provider (local, groq, openai, ...) ma mai URL, mai API key.",
          "Quale engine di trascrizione ha lavorato, come tag categorico su transcription.completed (batch, deepgram_stream, local_stream, chunked_caption).",
          "model.download_completed: quale tipo di modello locale ha finito di scaricarsi (whisper, llm, parakeet) e se è riuscito. Mai il percorso o il nome del file del modello.",
          "consent.logged: a quale passo è arrivato il gate di consenso alla registrazione della riunione (shown, accepted, cancelled, announced, declined), per misurare il drop-off. Mai i nomi dei partecipanti, l'annuncio pronunciato o alcun contenuto della riunione. Legato ai [[use-meeting-recaps|recap delle riunioni]].",
          "Stack trace dei crash (troncati e ripuliti dai segreti).",
        ]),
        h("Cosa non inviamo mai"),
        list([
          "L'audio che registri.",
          "Il testo di nessuna trascrizione.",
          "Nessun prompt o output LLM.",
          "Le API key, neanche nei messaggi di errore.",
          "Il tuo IP, hostname o username.",
          "Percorsi di file oltre a un tag categorico.",
        ]),
        h("Come disattivarla"),
        steps([
          "Apri Impostazioni → Privacy.",
          "Disattiva Invia dati di utilizzo anonimi (ferma PostHog).",
          "Disattiva Invia report di crash (ferma Sentry).",
          "Entrambi hanno effetto immediato. Eventi già inviati non possono essere ritirati.",
        ]),
        image("Impostazioni → Privacy con i due toggle di telemetria", "16/9", { win: { light: "/assets/help/telemetry/toggles-light.png", dark: "/assets/help/telemetry/toggles-dark.png" }, mac: { light: "/assets/help/app-settings/privacy-light.png", dark: "/assets/help/app-settings/privacy-dark.png" } }),
        h("Verifica tu stesso"),
        p("Ogni chiamata di telemetria viene loggata in locale con prefisso [telemetry]. Apri il log di Dimmy e cerca [telemetry] per vedere esattamente cosa è stato inviato e quando. Vedi la [[/privacy|Privacy policy]] per il dettaglio completo."),
        callout("info", "Vuoi ancora più dettaglio? La [[/privacy|Privacy policy]] elenca ogni evento con il suo payload, allineato al codice Rust live."),
      ],
    },
  },

  // ---------- Troubleshooting ----------
  {
    slug: "mic-and-hotkey",
    category: "troubleshooting",
    icon: "🎤",
    title: {
      en: "Mic or hotkey not working",
      it: "Microfono o scorciatoia non funzionano",
    },
    summary: {
      en: "Check OS permissions first. Then check hotkey conflicts. The pill tells you which one of the two is failing.",
      it: "Controlla prima i permessi del sistema operativo. Poi i conflitti di scorciatoia. La pill ti dice quale dei due sta fallendo.",
    },
    tags: ["troubleshooting", "microphone", "hotkey", "not working", "permission", "conflict"],
    blocks: {
      en: [
        h("If the pill stays idle when you press the hotkey"),
        steps([
          "Open Settings → Shortcut. Press your hotkey while looking at the page. If the page doesn't react, another app is intercepting the hotkey.",
          "Look for system-wide shortcuts that match (Windows: Settings → Keyboard. macOS: System Settings → Keyboard → Shortcuts).",
          "Look for app-level shortcuts that match (e.g. some games grab Win + Alt for in-game overlays).",
          "Change Dimmy's hotkey to a different combo: see [[hotkey-change|Change your hotkey]].",
        ]),
        h("If the pill goes red right after recording starts"),
        p("That's a microphone error. Hover the pill to see the exact reason."),
        steps([
          "Check the microphone permission in your OS settings (see [[permissions|Permissions]]).",
          "Check that the selected microphone is the right one in Settings → Audio. Some laptops default to a HDMI mic when a monitor is plugged in.",
          "Test the microphone outside Dimmy: macOS QuickTime → New Audio Recording, Windows Voice Recorder, Linux gnome-sound-recorder.",
          "If the test mic works elsewhere but not in Dimmy, restart Dimmy. The audio device list is cached at launch.",
        ]),
        image("Pill in error state with hover tooltip showing the reason", "16/9"),
        h("If recording works but transcription is empty"),
        p("See [[transcription-issues|Empty, wrong, or slow transcription]]."),
      ],
      it: [
        h("Se la pill resta idle quando premi la scorciatoia"),
        steps([
          "Apri Impostazioni → Scorciatoia. Premi la scorciatoia guardando la pagina. Se la pagina non reagisce, un'altra app sta intercettando la scorciatoia.",
          "Cerca scorciatoie globali corrispondenti (Windows: Impostazioni → Tastiera. macOS: Impostazioni di sistema → Tastiera → Scorciatoie).",
          "Cerca scorciatoie a livello app (alcuni giochi catturano Win + Alt per gli overlay).",
          "Cambia la scorciatoia di Dimmy con una combo diversa: vedi [[hotkey-change|Cambia la tua scorciatoia]].",
        ]),
        h("Se la pill diventa rossa subito dopo l'inizio della registrazione"),
        p("È un errore microfono. Passa sopra la pill per vedere il motivo esatto."),
        steps([
          "Controlla il permesso microfono nelle impostazioni del sistema operativo (vedi [[permissions|Permessi]]).",
          "Controlla che il microfono selezionato sia quello giusto in Impostazioni → Audio. Alcuni laptop scelgono di default il mic HDMI quando attacchi un monitor.",
          "Testa il microfono fuori da Dimmy: macOS QuickTime → Nuova registrazione audio, Windows Registratore vocale, Linux gnome-sound-recorder.",
          "Se il mic funziona altrove ma non in Dimmy, riavvia Dimmy. La lista dei device audio è cachata al lancio.",
        ]),
        image("Pill in stato di errore con tooltip che mostra il motivo", "16/9"),
        h("Se la registrazione funziona ma la trascrizione è vuota"),
        p("Vedi [[transcription-issues|Trascrizione vuota, sbagliata o lenta]]."),
      ],
    },
  },

  {
    slug: "transcription-issues",
    category: "troubleshooting",
    icon: "🗣️",
    title: {
      en: "Empty, wrong, or slow transcription",
      it: "Trascrizione vuota, sbagliata o lenta",
    },
    summary: {
      en: "Three different problems, three checks: silence in the audio, wrong language detected, model or provider mismatch.",
      it: "Tre problemi diversi, tre controlli: silenzio nell'audio, lingua sbagliata, modello o provider non adatto.",
    },
    tags: ["transcription", "empty", "wrong", "slow", "accuracy", "language", "model"],
    blocks: {
      en: [
        h("If the transcription is empty"),
        list([
          "Did the waveform move while you were talking? If not, the audio was silent. Check microphone settings.",
          "Did you talk for less than 0.5 seconds? Dimmy's anti-hallucination guard skips clips that short.",
          "Is the system mic muted? Some laptops have a hardware mute switch on F4 or similar.",
        ]),
        h("If the transcription is in the wrong language"),
        list([
          "Open Settings → General → Language. If it's set to Auto-detect, switch to your specific language. Auto-detect needs at least 30 seconds of clear audio to get short utterances right.",
          "If you mix languages in one clip, the most-spoken language wins. Speak more of the target language to bias detection.",
          "If you mostly dictate Italian, set Language = Italian. Same for English. Auto is best when you really alternate.",
        ]),
        h("If the transcription is inaccurate"),
        list([
          "Upgrade the Whisper model. base-q8_0 is the default; large-v3-turbo-q8_0 catches finer nuance. See [[whisper-models|Choose a Whisper model]].",
          "Switch to a cloud provider for one-off accurate transcription. See [[cloud-providers|Cloud providers compared]].",
          "Reduce background noise. Air conditioners, fans, and street noise hurt accuracy more than mic quality.",
          "Speak closer to the microphone. 15 to 30 cm is the sweet spot for most laptop mics."
        ]),
        h("If the transcription is slow"),
        list([
          "On-device: pick a smaller model, or switch to a cloud provider (Groq is sub-second on most clips).",
          "Check GPU acceleration is on (Settings → Models → Show acceleration). If your GPU is listed but not active, restart Dimmy.",
          "On a battery-saving Windows laptop, plug it in. Some integrated GPUs throttle aggressively on battery.",
        ]),
        image("Transcription Stats showing slow runs and fast runs by provider", "16/9", { win: { light: "/assets/help/transcription-issues/stats-light.png", dark: "/assets/help/transcription-issues/stats-dark.png" } }),
      ],
      it: [
        h("Se la trascrizione è vuota"),
        list([
          "La waveform si è mossa mentre parlavi? Se no, l'audio era muto. Controlla il microfono.",
          "Hai parlato meno di 0.5 secondi? L'anti-allucinazione di Dimmy salta i clip troppo brevi.",
          "Il microfono di sistema è mutato? Alcuni laptop hanno un mute hardware su F4 o simili.",
        ]),
        h("Se la trascrizione è nella lingua sbagliata"),
        list([
          "Apri Impostazioni → Generale → Lingua. Se è su Auto-detect, scegli una lingua specifica. L'auto-detect ha bisogno di almeno 30 secondi di audio chiaro per fare bene sulle frasi brevi.",
          "Se mescoli lingue in un clip, vince la più parlata. Parla di più della lingua target per spingere la detection.",
          "Se detti soprattutto italiano, imposta Lingua = Italiano. Stesso per inglese. Auto è meglio quando alterni davvero.",
        ]),
        h("Se la trascrizione è inaccurata"),
        list([
          "Passa a un modello Whisper più grosso. base-q8_0 è il default; large-v3-turbo-q8_0 prende le sfumature. Vedi [[whisper-models|Scegli un modello Whisper]].",
          "Passa a un provider cloud per un colpo solo di trascrizione accurata. Vedi [[cloud-providers|Provider cloud a confronto]].",
          "Riduci il rumore di fondo. Aria condizionata, ventole e rumore di strada peggiorano più della qualità del mic.",
          "Parla più vicino al microfono. 15-30 cm è la distanza ottimale per quasi tutti i mic da laptop.",
        ]),
        h("Se la trascrizione è lenta"),
        list([
          "On-device: scegli un modello più piccolo, o passa a un provider cloud (Groq è sotto al secondo su quasi ogni clip).",
          "Controlla che l'accelerazione GPU sia attiva (Impostazioni → Modelli → Mostra accelerazione). Se la GPU è in lista ma non attiva, riavvia Dimmy.",
          "Su laptop Windows in risparmio batteria, attaccalo alla corrente. Alcune GPU integrate fanno throttling pesante a batteria.",
        ]),
        image("Statistiche trascrizione con run lente e veloci per provider", "16/9", { win: { light: "/assets/help/transcription-issues/stats-light.png", dark: "/assets/help/transcription-issues/stats-dark.png" } }),
      ],
    },
  },

  {
    slug: "install-issues",
    category: "troubleshooting",
    icon: "⚠️",
    title: {
      en: "Install warnings: macOS Gatekeeper, Windows SmartScreen, Linux AppImage",
      it: "Avvisi di installazione: macOS Gatekeeper, Windows SmartScreen, Linux AppImage",
    },
    summary: {
      en: "The OS may warn the first time you run Dimmy. These warnings are expected for indie apps. Here's how to bypass them safely.",
      it: "Il sistema operativo può avvisare la prima volta che lanci Dimmy. Sono avvisi normali per app indie. Ecco come passarci sopra in sicurezza.",
    },
    tags: ["gatekeeper", "smartscreen", "appimage", "install", "warning", "security", "macos", "windows", "linux"],
    blocks: {
      en: [
        h("macOS: \"Dimmy can't be opened\" (Gatekeeper)"),
        p("Dimmy is built with a free Apple Developer ID, not yet notarised. Gatekeeper shows a warning the first time. To allow it:"),
        steps([
          "Right-click Dimmy.app in Applications (or the DMG) → Open.",
          "A second dialog appears with an Open button. Click it. Future launches will not warn.",
          "If you only see a Cancel button, open System Settings → Privacy & Security and click Open Anyway at the bottom.",
        ]),
        image("Right-click → Open dialog on macOS", "16/9"),
        callout("info", "Notarisation is on the roadmap. Until then, this two-step bypass is the standard workflow for new indie macOS apps."),
        h("Windows: SmartScreen \"Windows protected your PC\""),
        steps([
          "The installer is signed by KonradDallaOrg, but the certificate is new. SmartScreen learns to trust new signatures over a few weeks of installs.",
          "Click More info at the top of the dialog.",
          "Click Run anyway.",
          "Installation continues normally.",
        ]),
        image("SmartScreen dialog with More info link", "16/9"),
        h("Linux: AppImage permission denied"),
        p("AppImages need execute permission before they can run. Do it once:"),
        code("chmod +x Dimmy-linux-x86_64.AppImage\n./Dimmy-linux-x86_64.AppImage", "bash"),
        callout("info", "Some distros sandbox AppImages by default (e.g. Fedora with bubblewrap). If Dimmy can't open the microphone, integrate it via your DE's AppImage launcher or run with --no-sandbox."),
      ],
      it: [
        h("macOS: \"Dimmy non può essere aperto\" (Gatekeeper)"),
        p("Dimmy è firmato con un Apple Developer ID gratuito, non ancora notarised. Gatekeeper avvisa la prima volta. Per permetterlo:"),
        steps([
          "Click destro su Dimmy.app in Applicazioni (o dal DMG) → Apri.",
          "Compare un secondo dialog con un pulsante Apri. Cliccalo. I lanci successivi non avvisano più.",
          "Se vedi solo Annulla, apri Impostazioni di sistema → Privacy e sicurezza e clicca Apri comunque in fondo.",
        ]),
        image("Dialog click destro → Apri su macOS", "16/9"),
        callout("info", "La notarizzazione è in roadmap. Nel frattempo, questo bypass in due passi è il flusso standard per le nuove app indie macOS."),
        h("Windows: SmartScreen \"Windows ha protetto il PC\""),
        steps([
          "L'installer è firmato da KonradDallaOrg, ma il certificato è nuovo. SmartScreen impara a fidarsi delle firme nuove dopo qualche settimana di installazioni.",
          "Clicca Ulteriori informazioni in alto.",
          "Clicca Esegui comunque.",
          "L'installazione prosegue normalmente.",
        ]),
        image("Dialog SmartScreen con il link Ulteriori informazioni", "16/9"),
        h("Linux: AppImage permission denied"),
        p("Gli AppImage hanno bisogno del permesso di esecuzione prima di partire. Fallo una volta:"),
        code("chmod +x Dimmy-linux-x86_64.AppImage\n./Dimmy-linux-x86_64.AppImage", "bash"),
        callout("info", "Alcune distro sandboxano gli AppImage di default (es. Fedora con bubblewrap). Se Dimmy non riesce ad aprire il microfono, integralo con il launcher AppImage del DE o avvialo con --no-sandbox."),
      ],
    },
  },

  // ---------- Settings Reference ----------
  {
    slug: "settings-overview",
    category: "settings-reference",
    icon: "🗺️",
    title: {
      en: "Settings overview: every tab, in one map",
      it: "Panoramica Impostazioni: ogni tab, in una mappa",
    },
    summary: {
      en: "Right-click the pill → Settings. Ten tabs grouped by purpose. Use this as the index to find anything you can configure.",
      it: "Click destro sulla pill → Impostazioni. Dieci tab raggruppati per scopo. Usalo come indice per trovare qualsiasi impostazione.",
    },
    tags: ["settings", "tabs", "configuration", "overview", "reference", "map", "preferences", "options"],
    blocks: {
      en: [
        p("Settings opens from three places: right-click the pill, click the tray/menu-bar icon → Settings, or open the app from the dock/start menu. All paths reach the same window."),
        image("Settings window with sidebar showing all ten tabs", "16/9", { win: { light: "/assets/help/settings-overview/sidebar-light.png", dark: "/assets/help/settings-overview/sidebar-dark.png" }, mac: { light: "/assets/help/app-settings/home-light.png", dark: "/assets/help/app-settings/home-dark.png" } }),
        table(
          ["Tab", "What lives here", "Deep dive"],
          [
            ["General", "STT mode (local/cloud), language, filler removal.", "[[local-mode|Local mode]] · [[language|Language]] · [[filler-removal|Filler]]"],
            ["Audio", "Microphone selection, input preprocessing.", "[[audio-input|Audio input]]"],
            ["Models", "Browse, download, pick Whisper and local LLM models.", "[[whisper-models|Whisper models]] · [[local-llm|Local LLM]]"],
            ["Shortcut", "Hotkey combo, toggle vs hold-to-record.", "[[hotkey-change|Change hotkey]] · [[hotkey-modes|Modes]]"],
            ["Output", "LLM style, tone, custom prompts.", "[[styles|Styles]] · [[tones|Tones]] · [[custom-prompts|Custom prompts]]"],
            ["Overlay", "Pill position, opacity, waveform, scroll gestures.", "[[pill-position|Pill position]] · [[scroll-shortcuts|Scroll]]"],
            ["History", "Past transcriptions, full-text search, actions.", "[[history-search|History]]"],
            ["Privacy", "Telemetry toggles, reset anonymous ID, log location.", "[[telemetry|Telemetry]]"],
            ["Permissions", "Microphone and accessibility status, quick links to OS settings.", "[[permissions|Permissions]]"],
            ["Stats", "Total dictations, time saved, words dictated.", "[[stats|Stats]]"],
            ["About", "App version, update check, links, license.", "[[about-and-updates|About & updates]]"],
          ],
        ),
        callout("tip", "If you don't see a tab listed here, you're probably on an older build. Open About to check for an update."),
        h("Where settings are saved"),
        list([
          "macOS / Linux: ~/.config/dimmy/settings.json",
          "Windows: %APPDATA%\\dimmy\\settings.json",
          "API keys live in keys.enc next to settings.json (encrypted). See [[api-keys|API keys]].",
        ]),
      ],
      it: [
        p("Le Impostazioni si aprono da tre posti: click destro sulla pill, click sull'icona tray/menu-bar → Impostazioni, o lanciando l'app dal dock/menu start. Tutti i percorsi arrivano alla stessa finestra."),
        image("Finestra Impostazioni con sidebar che mostra i dieci tab", "16/9", { win: { light: "/assets/help/settings-overview/sidebar-light.png", dark: "/assets/help/settings-overview/sidebar-dark.png" }, mac: { light: "/assets/help/app-settings/home-light.png", dark: "/assets/help/app-settings/home-dark.png" } }),
        table(
          ["Tab", "Cosa contiene", "Approfondimento"],
          [
            ["Generale", "Modalità STT (locale/cloud), lingua, rimozione filler.", "[[local-mode|Modalità locale]] · [[language|Lingua]] · [[filler-removal|Filler]]"],
            ["Audio", "Selezione microfono, preprocessing input.", "[[audio-input|Input audio]]"],
            ["Modelli", "Sfoglia, scarica, scegli i modelli Whisper e LLM locale.", "[[whisper-models|Modelli Whisper]] · [[local-llm|LLM locale]]"],
            ["Scorciatoia", "Combo della scorciatoia, toggle vs tieni-premuto.", "[[hotkey-change|Cambia scorciatoia]] · [[hotkey-modes|Modalità]]"],
            ["Output", "Stile LLM, tono, prompt custom.", "[[styles|Stili]] · [[tones|Toni]] · [[custom-prompts|Prompt custom]]"],
            ["Overlay", "Posizione pill, opacità, waveform, gesture di scroll.", "[[pill-position|Posizione pill]] · [[scroll-shortcuts|Scroll]]"],
            ["Cronologia", "Trascrizioni passate, ricerca full-text, azioni.", "[[history-search|Cronologia]]"],
            ["Privacy", "Toggle telemetria, reset anonymous ID, percorso log.", "[[telemetry|Telemetria]]"],
            ["Permessi", "Stato microfono e accessibilità, link rapidi alle impostazioni di sistema.", "[[permissions|Permessi]]"],
            ["Statistiche", "Totale dettature, tempo risparmiato, parole dettate.", "[[stats|Statistiche]]"],
            ["Info", "Versione app, check aggiornamenti, link, licenza.", "[[about-and-updates|Info e aggiornamenti]]"],
          ],
        ),
        callout("tip", "Se non vedi un tab elencato qui, probabilmente sei su una build vecchia. Apri Info per controllare gli aggiornamenti."),
        h("Dove sono salvate le impostazioni"),
        list([
          "macOS / Linux: ~/.config/dimmy/settings.json",
          "Windows: %APPDATA%\\dimmy\\settings.json",
          "Le API key vivono in keys.enc accanto a settings.json (cifrate). Vedi [[api-keys|API key]].",
        ]),
      ],
    },
  },

  {
    slug: "audio-input",
    category: "settings-reference",
    icon: "🎤",
    title: {
      en: "Audio input: pick a mic and tune preprocessing",
      it: "Input audio: scegli un microfono e regola il preprocessing",
    },
    summary: {
      en: "Settings → Audio. Select the input device, monitor the level meter, toggle highpass, VAD, and AGC. Defaults are usually right.",
      it: "Impostazioni → Audio. Seleziona il device di input, controlla il VU meter, attiva o disattiva highpass, VAD e AGC. I default vanno bene quasi sempre.",
    },
    tags: ["audio", "microphone", "mic", "input", "device", "settings", "vad", "agc", "highpass", "preprocessing", "noise"],
    blocks: {
      en: [
        h("Input device"),
        p("Settings → Audio → Input device. Lists every microphone the OS knows about. Bluetooth headsets, USB mics, built-in laptop mics, audio interfaces."),
        steps([
          "Pick a device from the dropdown.",
          "Watch the live VU meter on the right while you speak. Bars should bounce in the green zone.",
          "If the meter is flat, the OS gave Dimmy the wrong device (some laptops default to HDMI when a monitor is plugged in).",
          "Click Test to record a 3-second clip and play it back. Confirms the right mic is selected.",
        ]),
        image("Audio tab with the device dropdown open and the live VU meter beside it", "16/9", { win: { light: "/assets/help/audio-input/device-vu-light.png", dark: "/assets/help/audio-input/device-vu-dark.png" }, mac: { light: "/assets/help/app-settings/voice-light.png", dark: "/assets/help/app-settings/voice-dark.png" } }),
        h("Audio preprocessing"),
        p("Dimmy preprocesses every clip before sending it to the STT engine. The defaults are tuned to match what whisper.cpp likes."),
        list([
          "Highpass filter at 80 Hz: removes rumble, fans, traffic. Always recommended.",
          "VAD (voice activity detection): skips silent stretches at the start and end of the clip. Saves cloud STT cost.",
          "AGC (automatic gain control): boosts quiet voices, tames loud ones. Use it if you switch between whisper-talking and normal volume.",
          "NaN-safe sample clamp: keeps every sample in [-1.0, 1.0]. Always on, not user-toggleable. Prevents one bad sample from crashing Whisper.",
        ]),
        callout("tip", "If you have a really good external mic in a quiet room, try turning AGC off. The unprocessed signal can be slightly more accurate on Whisper."),
        h("Bluetooth caveat"),
        p("Bluetooth headsets often drop into the 8 kHz HFP profile when an app opens the mic, even though they support 48 kHz A2DP for output. The audio sounds tinny. Dimmy upsamples to 16 kHz before STT, which is enough for Whisper, but accuracy drops noticeably compared to a USB or built-in mic."),
      ],
      it: [
        h("Device di input"),
        p("Impostazioni → Audio → Device di input. Elenca tutti i microfoni che il sistema operativo conosce. Cuffie Bluetooth, microfoni USB, mic integrati del laptop, schede audio."),
        steps([
          "Scegli un device dal dropdown.",
          "Guarda il VU meter live sulla destra mentre parli. Le barre devono saltellare nella zona verde.",
          "Se il meter è piatto, il sistema operativo ha dato a Dimmy il device sbagliato (alcuni laptop scelgono HDMI quando attacchi un monitor).",
          "Clicca Test per registrare un clip di 3 secondi e riascoltarlo. Conferma che il mic giusto è selezionato.",
        ]),
        image("Tab Audio con il dropdown del device aperto e il VU meter live accanto", "16/9", { win: { light: "/assets/help/audio-input/device-vu-light.png", dark: "/assets/help/audio-input/device-vu-dark.png" }, mac: { light: "/assets/help/app-settings/voice-light.png", dark: "/assets/help/app-settings/voice-dark.png" } }),
        h("Preprocessing audio"),
        p("Dimmy preprocessa ogni clip prima di mandarlo al motore STT. I default sono tarati su quello che whisper.cpp gradisce."),
        list([
          "Filtro highpass a 80 Hz: toglie rumble, ventole, traffico. Sempre consigliato.",
          "VAD (voice activity detection): salta gli stacchi silenziosi all'inizio e alla fine del clip. Risparmia costo STT cloud.",
          "AGC (automatic gain control): alza le voci basse, calma quelle forti. Utile se alterni tra sussurro e voce normale.",
          "Clamp NaN-safe dei sample: tiene ogni sample in [-1.0, 1.0]. Sempre attivo, non disattivabile. Evita che un sample sballato crashi Whisper.",
        ]),
        callout("tip", "Se hai un mic esterno di qualità in una stanza silenziosa, prova a disattivare AGC. Il segnale non processato a volte è leggermente più accurato per Whisper."),
        h("Avvertenza Bluetooth"),
        p("Le cuffie Bluetooth spesso scendono al profilo HFP a 8 kHz quando un'app apre il microfono, anche se supportano A2DP 48 kHz in output. L'audio suona tinny. Dimmy fa l'upsample a 16 kHz prima dell'STT, abbastanza per Whisper, ma l'accuratezza scende rispetto a un mic USB o integrato."),
      ],
    },
  },

  {
    slug: "language",
    category: "settings-reference",
    icon: "🌍",
    title: {
      en: "Pick the dictation language",
      it: "Scegli la lingua di dettatura",
    },
    summary: {
      en: "Auto-detect or pin a specific language. 99 languages via Whisper. Affects transcription and filler removal.",
      it: "Auto-detect o fissa una lingua specifica. 99 lingue via Whisper. Influenza trascrizione e rimozione filler.",
    },
    tags: ["language", "languages", "auto-detect", "italiano", "english", "français", "deutsch", "español", "português", "multilingual", "settings"],
    blocks: {
      en: [
        p("Settings → General → Language sets the language Whisper assumes when transcribing. It also tells the filler-remover which word list to use."),
        h("Auto-detect (default)"),
        p("Whisper inspects the first second or two of audio and picks a language. Works well for clips longer than 30 seconds in a single language. For short clips, auto-detect can be fragile; pin a language if you mostly dictate in one."),
        h("Pin a language"),
        steps([
          "Open Settings → General → Language.",
          "Pick a language from the dropdown.",
          "Save.",
        ]),
        h("Languages covered"),
        p("Whisper supports 99 languages. Filler removal is currently in 6: English, Italian, Spanish, French, German, Portuguese. The other 93 still get transcribed correctly, they just don't have hand-tuned filler lists yet."),
        table(
          ["Code", "Language", "Filler list"],
          [
            ["en", "English", "Yes"],
            ["it", "Italian", "Yes"],
            ["es", "Spanish", "Yes"],
            ["fr", "French", "Yes"],
            ["de", "German", "Yes"],
            ["pt", "Portuguese", "Yes"],
            ["ja", "Japanese", "No"],
            ["zh", "Chinese (Mandarin)", "No"],
            ["ar", "Arabic", "No"],
            ["…", "and 90 more", "No"],
          ],
        ),
        callout("info", "Languages list mirrors whisper.cpp's official language tokens. If a language isn't behaving, file an issue: [[/help/install-issues|GitHub issues]]."),
      ],
      it: [
        p("Impostazioni → Generale → Lingua imposta la lingua che Whisper assume durante la trascrizione. Indica anche al filler-remover quale lista di parole usare."),
        h("Auto-detect (default)"),
        p("Whisper ispeziona i primi uno o due secondi di audio e sceglie una lingua. Funziona bene per clip oltre i 30 secondi in una sola lingua. Per clip brevi, l'auto-detect può essere fragile; fissa una lingua se detti per lo più in una sola."),
        h("Fissa una lingua"),
        steps([
          "Apri Impostazioni → Generale → Lingua.",
          "Scegli una lingua dal dropdown.",
          "Salva.",
        ]),
        h("Lingue supportate"),
        p("Whisper supporta 99 lingue. La rimozione filler è attualmente in 6: inglese, italiano, spagnolo, francese, tedesco, portoghese. Le altre 93 vengono comunque trascritte correttamente, semplicemente non hanno ancora liste di filler artigianali."),
        table(
          ["Codice", "Lingua", "Lista filler"],
          [
            ["en", "Inglese", "Sì"],
            ["it", "Italiano", "Sì"],
            ["es", "Spagnolo", "Sì"],
            ["fr", "Francese", "Sì"],
            ["de", "Tedesco", "Sì"],
            ["pt", "Portoghese", "Sì"],
            ["ja", "Giapponese", "No"],
            ["zh", "Cinese (Mandarino)", "No"],
            ["ar", "Arabo", "No"],
            ["…", "e altre 90", "No"],
          ],
        ),
        callout("info", "La lista lingue rispecchia i token ufficiali di whisper.cpp. Se una lingua si comporta male, apri una issue."),
      ],
    },
  },

  {
    slug: "stats",
    category: "settings-reference",
    icon: "📊",
    title: {
      en: "Stats: count, time saved, words dictated",
      it: "Statistiche: conteggio, tempo risparmiato, parole dettate",
    },
    summary: {
      en: "Settings → Stats. Aggregate numbers computed from your local history. Time saved is the difference between speaking and typing the same text.",
      it: "Impostazioni → Statistiche. Numeri aggregati calcolati dalla tua cronologia locale. Il tempo risparmiato è la differenza tra parlare e digitare lo stesso testo.",
    },
    tags: ["stats", "statistics", "time saved", "words", "count", "numbers", "history", "metrics", "productivity"],
    blocks: {
      en: [
        image("Stats tab showing total dictations, time saved, words dictated, charts by week", "16/9", { win: { light: "/assets/help/stats/dashboard-light.png", dark: "/assets/help/stats/dashboard-dark.png" } }),
        h("What's tracked"),
        list([
          "Total dictations since install.",
          "Total audio seconds captured.",
          "Total words dictated (counted from the final, post-LLM text).",
          "Average words per minute speaking.",
          "Time saved vs typing (audio seconds vs estimated typing-at-40-wpm seconds for the same word count).",
          "Most-used style and tone.",
          "Most-used provider.",
        ]),
        h("Charts"),
        p("By-week dictations, words per day, accuracy proxy (transcriptions that triggered Reapply, suggesting the first pass missed something). All rendered locally from your history.db."),
        h("Reset"),
        p("Settings → Stats → Reset stats wipes only the aggregates. Your history is untouched. Useful if you want to start counting from a new project or month."),
        callout("info", "Stats are computed from the same SQLite database that powers [[history-search|History]]. Nothing is ever uploaded."),
      ],
      it: [
        image("Tab Statistiche con totale dettature, tempo risparmiato, parole dettate, grafici per settimana", "16/9", { win: { light: "/assets/help/stats/dashboard-light.png", dark: "/assets/help/stats/dashboard-dark.png" } }),
        h("Cosa viene tracciato"),
        list([
          "Totale dettature dall'installazione.",
          "Totale secondi di audio catturati.",
          "Totale parole dettate (contate sul testo finale dopo LLM).",
          "Parole per minuto medie parlando.",
          "Tempo risparmiato vs digitazione (secondi di audio vs secondi stimati per digitare a 40 wpm lo stesso numero di parole).",
          "Stile e tono più usati.",
          "Provider più usato.",
        ]),
        h("Grafici"),
        p("Dettature per settimana, parole per giorno, proxy di accuratezza (trascrizioni che hanno fatto scattare Riapplica, suggerendo che il primo passaggio aveva perso qualcosa). Tutto renderizzato in locale dal tuo history.db."),
        h("Reset"),
        p("Impostazioni → Statistiche → Reset stats azzera solo gli aggregati. La cronologia resta intatta. Utile se vuoi ricominciare a contare da un nuovo progetto o mese."),
        callout("info", "Le statistiche sono calcolate dallo stesso database SQLite che alimenta la [[history-search|Cronologia]]. Niente viene mai caricato."),
      ],
    },
  },

  {
    slug: "about-and-updates",
    category: "settings-reference",
    icon: "ℹ️",
    title: {
      en: "About: version, updates, links",
      it: "Info: versione, aggiornamenti, link",
    },
    summary: {
      en: "Settings → About shows the current version, runs an update check, and links to the repo, license, and acknowledgements.",
      it: "Impostazioni → Info mostra la versione attuale, lancia un check aggiornamenti e linka al repo, alla licenza e ai ringraziamenti.",
    },
    tags: ["about", "update", "updates", "version", "auto-update", "release", "changelog", "license"],
    blocks: {
      en: [
        image("About tab with version number, Check for updates button, and link list", "16/9", { win: { light: "/assets/help/about-and-updates/about-tab-light.png", dark: "/assets/help/about-and-updates/about-tab-dark.png" }, mac: { light: "/assets/help/app-settings/about-light.png", dark: "/assets/help/app-settings/about-dark.png" } }),
        h("What you see"),
        list([
          "App version (e.g. 0.6.27).",
          "Last update check timestamp.",
          "Check for updates button: queries GitHub releases.",
          "Install update button: shown only when an update is available.",
          "Links: GitHub repo, releases, license, privacy, acknowledgements.",
        ]),
        h("How updates work"),
        list([
          "Windows: Velopack auto-update. The app fetches the new installer in the background and applies it on next launch. No admin prompt.",
          "macOS: in-app updater drops the new .app next to the old one and relaunches.",
          "Linux: AppImage. Click Install update to download the new AppImage; replace the old file manually.",
        ]),
        h("Check on a schedule"),
        p("Dimmy checks once every 24 hours after launch. You can disable that in Settings → About → Auto-check for updates. If you turn it off, use the Check for updates button to do it on demand."),
        h("Get older versions"),
        p("Every release is on GitHub: [github.com/KonradDallaOrg/dimmy/releases](https://github.com/KonradDallaOrg/dimmy/releases). Each tag has installers for all three platforms and a SHA-256 checksum."),
        callout("info", "Pre-release builds (staging-latest) are published continuously for testers. Treat them as unstable; they may eat your hamster."),
      ],
      it: [
        image("Tab Info con numero di versione, pulsante Controlla aggiornamenti, e lista link", "16/9", { win: { light: "/assets/help/about-and-updates/about-tab-light.png", dark: "/assets/help/about-and-updates/about-tab-dark.png" }, mac: { light: "/assets/help/app-settings/about-light.png", dark: "/assets/help/app-settings/about-dark.png" } }),
        h("Cosa vedi"),
        list([
          "Versione app (es. 0.6.27).",
          "Timestamp dell'ultimo controllo aggiornamenti.",
          "Pulsante Controlla aggiornamenti: interroga le release GitHub.",
          "Pulsante Installa aggiornamento: visibile solo se c'è un aggiornamento disponibile.",
          "Link: repo GitHub, release, licenza, privacy, ringraziamenti.",
        ]),
        h("Come funzionano gli aggiornamenti"),
        list([
          "Windows: auto-update Velopack. L'app scarica il nuovo installer in background e lo applica al prossimo avvio. Nessun prompt admin.",
          "macOS: l'updater integrato mette la nuova .app accanto alla vecchia e riavvia.",
          "Linux: AppImage. Click su Installa aggiornamento per scaricare il nuovo AppImage; sostituisci il vecchio file a mano.",
        ]),
        h("Controllo programmato"),
        p("Dimmy controlla una volta ogni 24 ore dopo il lancio. Puoi disattivarlo in Impostazioni → Info → Auto-check aggiornamenti. Se lo disattivi, usa il pulsante Controlla aggiornamenti per farlo a mano."),
        h("Versioni vecchie"),
        p("Ogni release è su GitHub: [github.com/KonradDallaOrg/dimmy/releases](https://github.com/KonradDallaOrg/dimmy/releases). Ogni tag ha gli installer per tutte e tre le piattaforme e uno SHA-256."),
        callout("info", "Le build pre-release (staging-latest) escono in continuo per i tester. Trattale come instabili: potrebbero mangiarti il criceto."),
      ],
    },
  },

  {
    slug: "pause-dimmy",
    category: "settings-reference",
    icon: "⏸️",
    title: {
      en: "Pause Dimmy temporarily",
      it: "Metti in pausa Dimmy temporaneamente",
    },
    summary: {
      en: "Disable the hotkey without quitting the app. Useful during screen recordings, presentations, or focus blocks.",
      it: "Disattiva la scorciatoia senza chiudere l'app. Utile durante screen recording, presentazioni o blocchi di focus.",
    },
    tags: ["pause", "disable", "stop", "quiet", "presentation", "tray", "menu bar"],
    blocks: {
      en: [
        h("From the tray / menu-bar icon"),
        steps([
          "Click the tray icon (Windows / Linux) or menu-bar icon (macOS).",
          "Click Pause Dimmy.",
          "The pill goes dim and the hotkey is ignored. The icon switches to a striped version to remind you Dimmy is paused.",
          "Click the icon again → Resume Dimmy.",
        ]),
        h("From the pill"),
        p("Right-click the pill → Pause. Same effect."),
        callout("tip", "Pause is per-process, not persisted. Restarting Dimmy resumes it. For a permanent off, quit Dimmy from the tray menu."),
        h("What pause stops"),
        list([
          "Global hotkey listener.",
          "Microphone access (the OS green dot turns off).",
          "Any in-flight transcription is cancelled cleanly.",
        ]),
        h("What pause does not stop"),
        list([
          "The pill is still visible (faded). Hide it from Settings → Overlay.",
          "Update checks. They run in the background.",
          "The tray icon. It stays put so you can resume.",
        ]),
      ],
      it: [
        h("Dall'icona tray / menu-bar"),
        steps([
          "Clicca l'icona nel tray (Windows / Linux) o nella menu-bar (macOS).",
          "Clicca Pausa Dimmy.",
          "La pill si attenua e la scorciatoia viene ignorata. L'icona passa a una versione a strisce per ricordarti che Dimmy è in pausa.",
          "Clicca di nuovo l'icona → Riprendi Dimmy.",
        ]),
        h("Dalla pill"),
        p("Click destro sulla pill → Pausa. Stesso effetto."),
        callout("tip", "La pausa è per-processo, non persistita. Riavviando Dimmy si riattiva. Per uno spegnimento definitivo, esci da Dimmy dal menu del tray."),
        h("Cosa la pausa ferma"),
        list([
          "Listener globale della scorciatoia.",
          "Accesso microfono (il pallino verde del sistema operativo si spegne).",
          "Eventuali trascrizioni in corso vengono cancellate in modo pulito.",
        ]),
        h("Cosa la pausa non ferma"),
        list([
          "La pill resta visibile (sbiadita). Nascondila da Impostazioni → Overlay.",
          "I check aggiornamenti. Girano in background.",
          "L'icona del tray. Resta lì così puoi riprendere.",
        ]),
      ],
    },
  },

  // ---------- Use Cases ----------
  {
    slug: "use-ai-prompts",
    category: "use-cases",
    icon: "🤖",
    title: {
      en: "Write prompts for ChatGPT, Claude, Cursor, Claude Code",
      it: "Scrivi prompt per ChatGPT, Claude, Cursor, Claude Code",
    },
    summary: {
      en: "Speak a paragraph of context in 10 seconds, paste into your AI tool. Use the Prompt style to get a clean, ready-to-send prompt.",
      it: "Parla un paragrafo di contesto in 10 secondi, incolla nel tuo strumento AI. Usa lo stile Prompt per ottenere un prompt pulito e pronto.",
    },
    tags: ["chatgpt", "claude", "cursor", "claude code", "ai", "llm", "prompt", "prompts", "anthropic", "openai", "gpt", "use case"],
    blocks: {
      en: [
        callout("tip", "Prompts are where dictation pays back the most. Speaking is around 3x faster than typing for paragraphs of context, and the Prompt style strips conversational debris automatically."),
        video("Recording: spoken context → Prompt style → pasted into Claude in Cursor"),
        h("The recipe"),
        steps([
          "Open your AI tool: chat.openai.com, claude.ai, Cursor, Zed, Claude Code in the terminal.",
          "Click into the prompt box so the cursor is blinking there.",
          "Set the LLM style to Prompt (Settings → Output → Style: Prompt, or scroll on the pill).",
          "Press the hotkey, speak your context like you'd explain it to a colleague, release.",
          "The pasted text is now reshaped: clear instructions, no \"um\", no rambling.",
        ]),
        h("What the Prompt style does"),
        list([
          "Removes filler and false starts (\"so basically...\", \"like I was saying...\").",
          "Restructures into instruction → context → constraints → expected output.",
          "Drops first-person framing (\"can you...\") in favour of imperative (\"do this...\").",
          "Keeps technical terms, file names, library names, and quoted strings verbatim.",
        ]),
        h("Examples"),
        p("You said:"),
        code("So like, I have this React component, it's the ProductCard one, and it keeps re-rendering every time the parent re-renders. I think maybe I need useMemo or something but I'm not sure. Can you help me figure out the right fix and explain why?", "text"),
        p("The Prompt style turns that into:"),
        code("Diagnose why ProductCard (React) re-renders on every parent render. Recommend a fix (useMemo, React.memo, callback identity, etc.) with reasoning. Output: short diagnosis, then the patch.", "text"),
        callout("info", "Pair with a [[custom-prompts|Custom prompt]] when you always want a specific format (e.g. \"always include the file path in the response\")."),
      ],
      it: [
        callout("tip", "I prompt sono dove la dettatura rende di più. Parlare è circa 3x più veloce che digitare per paragrafi di contesto, e lo stile Prompt rimuove automaticamente il rumore conversazionale."),
        video("Registrazione: contesto parlato → stile Prompt → incollato in Claude dentro Cursor"),
        h("La ricetta"),
        steps([
          "Apri il tuo strumento AI: chat.openai.com, claude.ai, Cursor, Zed, Claude Code in terminale.",
          "Clicca nel campo del prompt così il cursore lampeggia lì.",
          "Imposta lo stile LLM su Prompt (Impostazioni → Output → Stile: Prompt, o scrolla sulla pill).",
          "Premi la scorciatoia, parla il contesto come lo spiegheresti a un collega, rilascia.",
          "Il testo incollato è già riformato: istruzioni chiare, niente \"um\", niente divagazioni.",
        ]),
        h("Cosa fa lo stile Prompt"),
        list([
          "Rimuove filler e false partenze (\"insomma...\", \"come dicevo...\").",
          "Ristruttura in istruzione → contesto → vincoli → output atteso.",
          "Toglie la prima persona (\"puoi...\") in favore dell'imperativo (\"fai...\").",
          "Mantiene termini tecnici, nomi di file, nomi di librerie e stringhe quotate testuali.",
        ]),
        h("Esempi"),
        p("Hai detto:"),
        code("Allora ho questo componente React, è il ProductCard, e continua a ri-renderizzarsi ogni volta che il padre si ri-renderizza. Penso magari mi serva useMemo o qualcosa, non sono sicuro. Mi aiuti a capire il fix giusto e perché?", "text"),
        p("Lo stile Prompt lo trasforma in:"),
        code("Diagnostica perché ProductCard (React) si ri-renderizza a ogni render del padre. Raccomanda un fix (useMemo, React.memo, identità della callback, ecc.) con motivazione. Output: diagnosi breve, poi la patch.", "text"),
        callout("info", "Accoppia con un [[custom-prompts|prompt custom]] quando vuoi sempre un formato specifico (es. \"includi sempre il percorso del file nella risposta\")."),
      ],
    },
  },

  {
    slug: "use-meeting-recaps",
    category: "use-cases",
    icon: "🗒️",
    title: {
      en: "Record a meeting, get an AI recap",
      it: "Registra una riunione, ottieni un recap AI",
    },
    summary: {
      en: "Dimmy Meeting records the call, transcribes it live, and writes a structured recap with action items. All inside Dimmy, on Windows and Mac.",
      it: "Dimmy Meeting registra la chiamata, la trascrive in tempo reale e scrive un recap strutturato con action item. Tutto dentro Dimmy, su Windows e Mac.",
    },
    tags: ["recap", "meeting", "notes", "notion", "transcript", "action items", "loopback", "summary", "call detection", "consent", "meeting type", "export", "obsidian"],
    blocks: {
      en: [
        p("Dimmy has a dedicated \"Dimmy Meeting\" window. It records both sides of a call (your mic plus the system audio), transcribes it live, and on stop writes a structured recap with action items. The audio, the transcript, and the recap all stay on your machine."),
        h("Start a meeting"),
        p("Two ways in."),
        list([
          "Open the \"Dimmy Meeting\" window yourself: the tray menu has \"Open Meeting…\" on Windows, the app menu has it on macOS.",
          "Let Dimmy notice the call. When your mic goes live (reinforced by a known app: Teams, Zoom, Google Meet, Discord, Slack, Webex, Skype, Whereby) Dimmy pops a \"Dimmy Call Detected\" prompt with \"Record now\", \"Not now\", and \"Never\".",
        ]),
        p("On the Idle screen there is a checkbox, \"Generate recap + action items on stop\", on by default. Leave it on and the recap writes itself the moment you stop."),
        h("Recording consent"),
        p("Before any audio is captured, Dimmy shows a recording-consent notice. It fires every time, whether you started manually or accepted the call-detector prompt."),
        p("The notice reads: \"You are about to record audio that may include other people. Confirm you have informed all participants and obtained their consent. In some regions (the EU and several US states) this is required by law.\""),
        p("Two buttons: \"I have consent, start\" and \"Cancel\" (Cancel is the safe default). If you cancel, nothing is recorded. If you confirm, Dimmy reads the announcement aloud via text-to-speech and copies a ready-to-paste chat message to your clipboard so you can drop it into the call for remote participants."),
        callout("info", "This matters in all-party consent jurisdictions: the EU under GDPR, and US states such as California, Florida, and Illinois. Each confirmation is logged locally to a consent.jsonl audit file in your config folder."),
        h("While it records"),
        p("During the meeting the window shows a red Recording bar with a timer, a live waveform, the live transcript in roughly 15-second chunks, and a Notes tab where you can drop timestamped notes. Use \"Pause\"/\"Resume\" to skip a section, and \"Stop & finish\" to end."),
        p("Closing the window does not stop the recording. The pill is your indicator that it is still going; reopen the window to re-attach."),
        callout("warn", "On macOS, Dimmy needs the system-audio-recording permission to capture the other side of the call. If it is off, the window shows a banner, \"System audio isn't being captured\", with an \"Open System Settings\" button. Without it you only record your own mic."),
        h("The recap"),
        p("Click \"Stop & finish\" (or stop from the pill, or from the auto \"Stop & recap\" popup) and Dimmy generates the recap automatically. It opens in the in-app Done view as a structured document."),
        image("The recap open in Dimmy's in-app Done view, with TL;DR, highlights, and action items", "16/9", { win: { light: "/assets/help/use-meeting-recaps/done-view-light.png", dark: "/assets/help/use-meeting-recaps/done-view-dark.png" }, mac: { light: "/assets/help/use-meeting-recaps/done-view-mac-light.png", dark: "/assets/help/use-meeting-recaps/done-view-mac-dark.png" } }),
        list([
          "TL;DR, Context, Highlights (with MM:SS timestamps), Key decisions, Action items, Open questions, Risks & blockers, Next steps.",
          "The title is auto-generated. You can edit it.",
          "Copy the recap as markdown, or regenerate the transcript or the recap.",
        ]),
        p("The recap model is a picker that defaults to \"Auto\". Auto walks your connected providers and picks the best flagship it finds: Claude Opus 4.8, then GPT-5.5, then Gemini 3.1 Pro (on macOS it can also use local Gemma). If none are connected it falls back to your normal dictation LLM."),
        h("Meeting type"),
        p("Dimmy classifies each recap into a meeting type and tunes its emphasis to match, the way Notion's typed templates do. The type never changes the structure: the recap keeps the same section contract. It only shifts which sections fill in and which stay empty (empty sections auto-hide). A 1:1 leans on feedback and personal commitments, a standup organizes by person and surfaces blockers, an interview stays factual and avoids inventing a verdict."),
        p("The classified type shows as a Notion-style chip under the recap title, with a friendly label. The chip is hidden when the type is left on Auto (unclassified)."),
        p("Classification defaults to \"Auto-detect\": the model reads the transcript and picks the type. A picker on the Done view, default \"Auto-detect\", lets you force a specific type and regenerate the recap with that emphasis. The full set of labels:"),
        list([
          "Auto-detect (the default, model classifies)",
          "1:1",
          "Standup / status",
          "Planning",
          "Technical / design review",
          "Brainstorming",
          "Interview (hiring)",
          "Customer call",
          "Lecture / talk",
          "General (neutral fallback)",
        ]),
        h("Send it where you work"),
        list([
          "Copy recap: the full recap as markdown, ready to paste anywhere.",
          "Send to Notion: connect Notion with your own integration token (Settings → Integrations), then pick a destination page or database. See [[integrations-notion|Send recaps to Notion]].",
          "Recap with Claude Desktop: available only if the Claude MCP extension is installed. It opens Claude to write the recap back through Dimmy's MCP tools. See [[integrations-claude-desktop|Connect Claude Desktop]].",
          "Open meeting folder: jumps to the audio, transcript, and recap files on disk for that one meeting.",
        ]),
        h("Auto-export recaps to a folder"),
        p("Dimmy can drop a copy of every recap into a folder you pick, as a markdown file. On Windows it is in Settings → Meetings, the card \"Export recaps to a folder\". On macOS it is in Settings → Output, the \"Export recaps\" group, the \"Export folder\" row. The help text reads: \"Save a copy of each recap as a markdown file here. Point it at an Obsidian vault or a Google Drive, Dropbox or OneDrive folder to sync your recaps for free.\""),
        p("After each recap saves, Dimmy copies recap.md into that folder as \"<title> (<meeting-id>).md\". The meeting-id keeps a regenerate of the same meeting overwriting its own file, while two meetings that share a title never clobber each other. There is no OAuth and no sign-in: point it at a synced folder and you get free Obsidian, Drive, Dropbox, or OneDrive sync. It is best-effort, so a folder that is offline or unplugged never breaks the recap. Leave it empty to keep recaps inside the app only."),
        callout("info", "This is not the same as \"Open meeting folder\". That button opens the per-meeting artifact folder (audio, transcript, recap) for one meeting. The export folder is one shared destination where every meeting's recap.md is copied as a named markdown file."),
        h("Past meetings and audio files"),
        p("Every meeting is kept in the \"Meetings\" sidebar: title, date, duration, and a check when a recap exists. Search it, reopen any meeting, or delete one. You can also feed an existing recording with \"Transcribe a file\" and get the same recap flow."),
      ],
      it: [
        p("Dimmy ha una finestra dedicata, \"Dimmy Meeting\". Registra entrambi i lati di una chiamata (il tuo microfono più l'audio di sistema), la trascrive in tempo reale e allo stop scrive un recap strutturato con action item. L'audio, la trascrizione e il recap restano tutti sul tuo computer."),
        h("Avvia un meeting"),
        p("Due strade."),
        list([
          "Apri tu la finestra \"Dimmy Meeting\": dal menu del tray con \"Open Meeting…\" su Windows, dal menu dell'app su macOS.",
          "Lascia che sia Dimmy a notare la chiamata. Quando il microfono va in uso (rafforzato da un'app nota: Teams, Zoom, Google Meet, Discord, Slack, Webex, Skype, Whereby) Dimmy mostra un avviso \"Dimmy Call Detected\" con \"Record now\", \"Not now\" e \"Never\".",
        ]),
        p("Nella schermata Idle c'è una casella, \"Generate recap + action items on stop\", attiva di default. Lasciala attiva e il recap si scrive da solo nel momento in cui fermi."),
        h("Consenso alla registrazione"),
        p("Prima che venga catturato qualsiasi audio, Dimmy mostra un avviso di consenso alla registrazione. Compare ogni volta, sia che tu abbia avviato manualmente sia che tu abbia accettato l'avviso del call-detector."),
        p("Il testo dell'avviso è: \"You are about to record audio that may include other people. Confirm you have informed all participants and obtained their consent. In some regions (the EU and several US states) this is required by law.\""),
        p("Due pulsanti: \"I have consent, start\" e \"Cancel\" (Cancel è il default sicuro). Se annulli, non viene registrato nulla. Se confermi, Dimmy legge l'avviso ad alta voce via sintesi vocale e copia negli appunti un messaggio già pronto, così puoi incollarlo nella chat della chiamata per i partecipanti remoti."),
        callout("info", "Questo è rilevante nelle giurisdizioni con consenso di tutte le parti: l'UE sotto GDPR e stati USA come California, Florida e Illinois. Ogni conferma viene registrata localmente in un file di audit consent.jsonl nella tua cartella di configurazione."),
        h("Mentre registra"),
        p("Durante il meeting la finestra mostra una barra rossa Recording con un timer, una waveform live, la trascrizione in tempo reale in blocchi di circa 15 secondi e un tab Notes dove puoi lasciare note con timestamp. Usa \"Pause\"/\"Resume\" per saltare una parte e \"Stop & finish\" per chiudere."),
        p("Chiudere la finestra non ferma la registrazione. La pill ti segnala che è ancora in corso; riapri la finestra per riagganciarti."),
        callout("warn", "Su macOS, Dimmy ha bisogno del permesso di registrazione dell'audio di sistema per catturare l'altro lato della chiamata. Se è disattivato, la finestra mostra un banner, \"System audio isn't being captured\", con un pulsante \"Open System Settings\". Senza, registri solo il tuo microfono."),
        h("Il recap"),
        p("Clicca \"Stop & finish\" (o ferma dalla pill, o dal popup automatico \"Stop & recap\") e Dimmy genera il recap in automatico. Si apre nel Done view dentro l'app come documento strutturato."),
        image("Il recap aperto nel Done view dentro Dimmy, con TL;DR, highlights e action item", "16/9", { win: { light: "/assets/help/use-meeting-recaps/done-view-light.png", dark: "/assets/help/use-meeting-recaps/done-view-dark.png" }, mac: { light: "/assets/help/use-meeting-recaps/done-view-mac-light.png", dark: "/assets/help/use-meeting-recaps/done-view-mac-dark.png" } }),
        list([
          "TL;DR, Context, Highlights (con timestamp MM:SS), Key decisions, Action items, Open questions, Risks & blockers, Next steps.",
          "Il titolo è generato in automatico. Puoi modificarlo.",
          "Copia il recap come markdown, oppure rigenera la trascrizione o il recap.",
        ]),
        p("Il modello del recap è un selettore con default \"Auto\". Auto scorre i provider che hai collegato e sceglie il miglior flagship che trova: Claude Opus 4.8, poi GPT-5.5, poi Gemini 3.1 Pro (su macOS può usare anche Gemma in locale). Se non ne hai collegato nessuno, ripiega sull'LLM che usi per la dettatura."),
        h("Tipo di meeting"),
        p("Dimmy classifica ogni recap in un tipo di meeting e ne adatta l'enfasi di conseguenza, come fanno i template tipizzati di Notion. Il tipo non cambia mai la struttura: il recap mantiene lo stesso contratto di sezioni. Sposta solo quali sezioni si riempiono e quali restano vuote (le sezioni vuote si nascondono da sole). Un 1:1 punta su feedback e impegni personali, uno standup organizza per persona e mette in evidenza i blocker, un'interview resta fattuale ed evita di inventare un verdetto."),
        p("Il tipo classificato compare come una chip in stile Notion sotto il titolo del recap, con un'etichetta leggibile. La chip è nascosta quando il tipo resta su Auto (non classificato)."),
        p("La classificazione è di default \"Auto-detect\": il modello legge la trascrizione e sceglie il tipo. Un selettore nel Done view, default \"Auto-detect\", ti permette di forzare un tipo specifico e rigenerare il recap con quell'enfasi. L'elenco completo delle etichette:"),
        list([
          "Auto-detect (il default, il modello classifica)",
          "1:1",
          "Standup / status",
          "Planning",
          "Technical / design review",
          "Brainstorming",
          "Interview (hiring)",
          "Customer call",
          "Lecture / talk",
          "General (fallback neutro)",
        ]),
        h("Mandalo dove lavori"),
        list([
          "Copy recap: il recap completo come markdown, pronto da incollare ovunque.",
          "Send to Notion: collega Notion con il tuo integration token (Impostazioni → Integrazioni), poi scegli una pagina o un database di destinazione. Vedi [[integrations-notion|Manda i recap in Notion]].",
          "Recap with Claude Desktop: disponibile solo se l'estensione MCP di Claude è installata. Apre Claude per riscrivere il recap tramite i tool MCP di Dimmy. Vedi [[integrations-claude-desktop|Collega Claude Desktop]].",
          "Open meeting folder: apre i file di audio, trascrizione e recap su disco di quel singolo meeting.",
        ]),
        h("Esporta i recap in una cartella"),
        p("Dimmy può lasciare una copia di ogni recap in una cartella che scegli tu, come file markdown. Su Windows è in Impostazioni → Meetings, la card \"Export recaps to a folder\". Su macOS è in Impostazioni → Output, il gruppo \"Export recaps\", la riga \"Export folder\". Il testo di aiuto recita: \"Save a copy of each recap as a markdown file here. Point it at an Obsidian vault or a Google Drive, Dropbox or OneDrive folder to sync your recaps for free.\""),
        p("Dopo ogni salvataggio del recap, Dimmy copia recap.md in quella cartella come \"<title> (<meeting-id>).md\". Il meeting-id fa sì che una rigenerazione dello stesso meeting sovrascriva il proprio file, mentre due meeting con lo stesso titolo non si calpestano mai a vicenda. Niente OAuth e niente login: punta a una cartella sincronizzata e ottieni sync gratuito con Obsidian, Drive, Dropbox o OneDrive. È best-effort, quindi una cartella offline o scollegata non rompe mai il recap. Lascia vuoto per tenere i recap solo dentro l'app."),
        callout("info", "Non è la stessa cosa di \"Open meeting folder\". Quel pulsante apre la cartella degli artifact di un singolo meeting (audio, trascrizione, recap). La cartella di export è un'unica destinazione condivisa dove il recap.md di ogni meeting viene copiato come file markdown con un nome."),
        h("Meeting passati e file audio"),
        p("Ogni meeting resta nella sidebar \"Meetings\": titolo, data, durata e una spunta quando esiste un recap. Cercala, riapri qualsiasi meeting o cancellane uno. Puoi anche dare in pasto una registrazione esistente con \"Transcribe a file\" e ottenere lo stesso flusso di recap."),
      ],
    },
  },

  {
    slug: "use-email",
    category: "use-cases",
    icon: "✉️",
    title: {
      en: "Draft emails in Gmail, Outlook, Apple Mail",
      it: "Scrivi email in Gmail, Outlook, Apple Mail",
    },
    summary: {
      en: "Pick a tone, dictate the body in 30 seconds, paste, send. The Professional style handles greetings and sign-offs.",
      it: "Scegli un tono, detta il corpo in 30 secondi, incolla, invia. Lo stile Professional gestisce saluti e firme.",
    },
    tags: ["email", "gmail", "outlook", "apple mail", "drafting", "write", "professional", "use case", "messaging"],
    blocks: {
      en: [
        h("Setup"),
        list([
          "Style: Professional or Correct (Professional adds structure, Correct keeps your phrasing).",
          "Tone: friendly for clients, formal for legal, neutral for the rest.",
          "Hotkey mode: hold for short replies, toggle for long emails.",
        ]),
        h("The recipe"),
        steps([
          "Open Gmail, Outlook, or Apple Mail. Click into the body of a new email.",
          "Press the hotkey. Start with the recipient (the LLM uses it for greetings): \"Hi Sarah, thanks for the proposal yesterday.\"",
          "Talk through your message. Don't worry about punctuation, the LLM adds it.",
          "Release. The pasted text is structured: greeting, body, closing, sign-off.",
        ]),
        image("Gmail compose window with a freshly-dictated message pasted in", "16/9"),
        h("Tone examples"),
        table(
          ["Tone", "Greeting", "Body opener", "Sign-off"],
          [
            ["Formal", "Dear Sarah,", "I am writing to…", "Best regards,"],
            ["Friendly", "Hi Sarah!", "Thanks for…", "Cheers,"],
            ["Neutral", "Hi Sarah,", "Following up on…", "Thanks,"],
            ["Casual", "Sarah —", "Quick one,", "Talk soon"],
            ["Enthusiastic", "Hi Sarah! 🎉", "Loved your proposal! Here are…", "Excited to chat!"],
          ],
        ),
        callout("tip", "If you find the LLM adds too much fluff, switch from Professional to Correct. Correct keeps your voice and just fixes grammar."),
      ],
      it: [
        h("Setup"),
        list([
          "Stile: Professional o Correct (Professional aggiunge struttura, Correct tiene la tua voce).",
          "Tono: friendly per clienti, formal per il legale, neutral per il resto.",
          "Modalità scorciatoia: hold per risposte brevi, toggle per email lunghe.",
        ]),
        h("La ricetta"),
        steps([
          "Apri Gmail, Outlook o Apple Mail. Clicca nel corpo di una nuova email.",
          "Premi la scorciatoia. Inizia dal destinatario (l'LLM lo usa per i saluti): \"Ciao Sara, grazie per la proposta di ieri.\"",
          "Parla la tua email. Non preoccuparti della punteggiatura, l'LLM la aggiunge.",
          "Rilascia. Il testo incollato è strutturato: saluto, corpo, chiusura, firma.",
        ]),
        image("Finestra di composizione Gmail con messaggio appena dettato e incollato", "16/9"),
        h("Esempi di tono"),
        table(
          ["Tono", "Saluto", "Apertura corpo", "Firma"],
          [
            ["Formal", "Gentile Sara,", "Le scrivo per…", "Cordiali saluti,"],
            ["Friendly", "Ciao Sara!", "Grazie per…", "Un abbraccio,"],
            ["Neutral", "Ciao Sara,", "Riprendo il discorso su…", "Grazie,"],
            ["Casual", "Sara —", "Veloce veloce,", "A presto"],
            ["Enthusiastic", "Ciao Sara! 🎉", "Adoro la tua proposta! Ecco…", "Non vedo l'ora di sentirci!"],
          ],
        ),
        callout("tip", "Se trovi che l'LLM aggiunga troppi fronzoli, passa da Professional a Correct. Correct mantiene la tua voce e sistema solo la grammatica."),
      ],
    },
  },

  {
    slug: "use-code-comments",
    category: "use-cases",
    icon: "💻",
    title: {
      en: "Code comments and PR descriptions",
      it: "Commenti di codice e descrizioni di PR",
    },
    summary: {
      en: "Talk through what you changed and why. Use a Custom prompt that formats the result as a code comment or a PR body.",
      it: "Parla di cosa hai cambiato e perché. Usa un Custom prompt che formatta il risultato come commento di codice o body di PR.",
    },
    tags: ["code", "comments", "pr description", "pull request", "vscode", "cursor", "zed", "xcode", "jetbrains", "github", "use case"],
    blocks: {
      en: [
        h("Setup for code comments"),
        p("Configure a Custom prompt that turns whatever you dictate into a code comment block:"),
        code("Rewrite the input as a code comment block. Use imperative tone. Wrap at 80 columns. Pick the right comment marker for the surrounding language, default to // if unsure. Output the comment block only.", "text"),
        h("Setup for PR descriptions"),
        p("Use a separate Custom prompt with this preset:"),
        code("Rewrite as a GitHub PR description. Sections in order: Summary (2-3 sentences), What changed (bulleted), Why (1-2 sentences), Risks (bulleted, can be empty), Test plan (bulleted checkbox list). Markdown headings with ##. Output the description only.", "text"),
        h("The recipe (code comment)"),
        steps([
          "Click on the line above the function you want to document.",
          "Press the hotkey. Talk through what the function does, why, edge cases, gotchas.",
          "Release. The LLM rewrites it into a tidy comment block at the right indentation.",
        ]),
        h("The recipe (PR description)"),
        steps([
          "Open the GitHub PR description box (or `gh pr create --body-file -`).",
          "Press the hotkey. Walk through the change.",
          "Release. The text lands as a well-structured PR description.",
        ]),
        image("VS Code with a freshly-dictated comment block above a function", "16/9"),
        callout("tip", "Switch Custom prompts on the fly: Settings → Output → Custom. You can copy/paste between the comment prompt and the PR prompt as you go."),
      ],
      it: [
        h("Setup per commenti di codice"),
        p("Configura un prompt Custom che trasforma quello che detti in un blocco di commento:"),
        code("Riscrivi l'input come blocco di commento di codice. Tono imperativo. A capo a 80 colonne. Scegli il delimitatore di commento giusto per il linguaggio intorno, default // se in dubbio. Restituisci solo il blocco di commento.", "text"),
        h("Setup per descrizioni di PR"),
        p("Usa un secondo prompt Custom con questa preset:"),
        code("Riscrivi come descrizione di PR GitHub. Sezioni in ordine: Sommario (2-3 frasi), Cosa cambia (bullet), Perché (1-2 frasi), Rischi (bullet, può essere vuoto), Test plan (lista checkbox). Heading markdown con ##. Restituisci solo la descrizione.", "text"),
        h("La ricetta (commento di codice)"),
        steps([
          "Clicca sulla riga sopra la funzione che vuoi documentare.",
          "Premi la scorciatoia. Parla di cosa fa la funzione, perché, edge case, gotcha.",
          "Rilascia. L'LLM la riscrive in un blocco di commento pulito, indentato giusto.",
        ]),
        h("La ricetta (descrizione PR)"),
        steps([
          "Apri il campo descrizione della PR su GitHub (o `gh pr create --body-file -`).",
          "Premi la scorciatoia. Racconta la modifica.",
          "Rilascia. Il testo arriva come descrizione PR ben strutturata.",
        ]),
        image("VS Code con un blocco commento appena dettato sopra una funzione", "16/9"),
        callout("tip", "Cambia prompt Custom al volo: Impostazioni → Output → Custom. Puoi fare copia/incolla tra il prompt commento e quello PR mentre lavori."),
      ],
    },
  },

  {
    slug: "use-multilingual",
    category: "use-cases",
    icon: "🌐",
    title: {
      en: "Multilingual workflows",
      it: "Workflow multilingua",
    },
    summary: {
      en: "Switch languages mid-dictation. Translate as you speak. Use auto-detect when you really alternate, pinned when you mostly stay in one.",
      it: "Cambia lingua a metà dettatura. Traduci mentre parli. Auto-detect quando alterni davvero, fissata quando resti in una.",
    },
    tags: ["multilingual", "translation", "translate", "italian", "english", "language switching", "use case", "multilanguage"],
    blocks: {
      en: [
        h("Pattern 1: mix-and-match"),
        p("If you genuinely alternate languages clip by clip (Italian to your team, English to a client), keep Language on Auto-detect. Whisper picks the dominant language per clip."),
        h("Pattern 2: translate on the fly"),
        p("Stay in your native language, output a different one. Use a Custom prompt:"),
        code("Translate the input to English. Keep proper nouns, brand names, and technical terms verbatim. If the input is already English, leave it unchanged. Output the translation only.", "text"),
        list([
          "Speak Italian, paste English.",
          "Speak English, paste German.",
          "Speak whatever, get a single target language out.",
        ]),
        h("Pattern 3: Italian humour"),
        p("Style: Imbruttito. Speaks Italian, paste rewritten in the Milanese grumpy style. It is a humour style; not for client emails."),
        callout("tip", "If auto-detect picks the wrong language on a short clip, the result is gibberish. Pin the language (Settings → General) for short utterances in one language."),
        h("Pattern 4: keyboard layout independence"),
        p("Dimmy is keyboard-layout agnostic. You can be on a QWERTY laptop in a French AZERTY environment and dictation still works: the hotkey listens for modifier keys by hardware position, not by layout."),
      ],
      it: [
        h("Pattern 1: alterna lingue"),
        p("Se alterni davvero lingue clip per clip (italiano col team, inglese col cliente), tieni Lingua su Auto-detect. Whisper sceglie la lingua dominante per ogni clip."),
        h("Pattern 2: traduci al volo"),
        p("Resta nella tua lingua madre, fai uscire un'altra lingua. Usa un prompt Custom:"),
        code("Traduci l'input in inglese. Mantieni nomi propri, brand, termini tecnici testuali. Se l'input è già in inglese, lascialo invariato. Restituisci solo la traduzione.", "text"),
        list([
          "Parli italiano, incolli inglese.",
          "Parli inglese, incolli tedesco.",
          "Parli qualsiasi cosa, esce una sola lingua target.",
        ]),
        h("Pattern 3: umorismo italiano"),
        p("Stile: Imbruttito. Parli italiano, incolli in stile imbruttito milanese. È uno stile umoristico; non per email a clienti."),
        callout("tip", "Se l'auto-detect sbaglia lingua su un clip corto, il risultato è incomprensibile. Fissa la lingua (Impostazioni → Generale) per frasi brevi in una sola lingua."),
        h("Pattern 4: indipendenza dal layout di tastiera"),
        p("Dimmy è agnostico al layout della tastiera. Puoi avere un laptop QWERTY in un ambiente francese AZERTY e la dettatura funziona lo stesso: la scorciatoia ascolta i modificatori per posizione hardware, non per layout."),
      ],
    },
  },

  {
    slug: "use-accessibility",
    category: "use-cases",
    icon: "♿",
    title: {
      en: "Accessibility, RSI, hands-busy contexts",
      it: "Accessibilità, RSI, contesti a mani occupate",
    },
    summary: {
      en: "If typing hurts or isn't an option, dictation becomes your primary input. Hold-vs-toggle hotkey, hands-free workflow, screen-reader compatible.",
      it: "Se digitare fa male o non è un'opzione, la dettatura diventa il tuo input principale. Scorciatoia hold-vs-toggle, workflow a mani libere, compatibile con screen reader.",
    },
    tags: ["accessibility", "rsi", "carpal tunnel", "voice", "hands free", "disability", "dyslexia", "screen reader", "voiceover", "ergonomics", "use case"],
    blocks: {
      en: [
        p("Voice input is a serious input modality, not a novelty. Plenty of Dimmy users dictate full work days because typing hurts, because they have dyslexia, because their hands are doing something else (cooking, holding a baby, driving where legal)."),
        h("RSI and carpal tunnel"),
        list([
          "Use Toggle mode (Settings → Shortcut → Mode: Toggle). Avoid holding any key for long stretches.",
          "Bind the hotkey to a foot pedal if you have one. Most pedals emit key codes; Dimmy doesn't care where the keys came from.",
          "Pair with a Custom prompt that polishes punctuation, so you don't have to insert it manually with a mouse.",
        ]),
        h("Dyslexia"),
        list([
          "Use Style: Correct. It fixes spelling without changing your phrasing.",
          "Pin the language (Settings → General). Auto-detect can be more fragile for shorter clips.",
          "Keep filler removal on; it strips false starts that often trip spell-checkers later.",
        ]),
        h("Screen reader compatibility"),
        list([
          "The pill is decorative; everything important is reachable via Settings.",
          "Settings is a standard native control panel (WinUI on Windows, AppKit on macOS, GTK on Linux). Native screen readers work out of the box.",
          "Pasted text lands in the focused control, so the screen reader announces it as if you typed.",
        ]),
        callout("info", "If you hit an accessibility blocker, please open a GitHub issue tagged accessibility. We treat them as priority bugs."),
        h("Hands-busy contexts"),
        list([
          "Cooking: bind the hotkey to a Bluetooth volume button on a kitchen speaker.",
          "Driving (where legal): tether to a Bluetooth headset; long-press the headset button to bind it as the hotkey.",
          "Parenting: voice notes while holding a child; Toggle mode avoids fumbling.",
        ]),
      ],
      it: [
        p("L'input vocale è una modalità di input seria, non una stranezza. Molti utenti di Dimmy dettano intere giornate di lavoro perché digitare fa male, perché hanno dislessia, perché le mani sono occupate (cucinare, tenere un bambino, guidare dove è legale)."),
        h("RSI e tunnel carpale"),
        list([
          "Usa la modalità Toggle (Impostazioni → Scorciatoia → Modalità: Toggle). Evita di tenere premuto un tasto a lungo.",
          "Assegna la scorciatoia a un pedale se ne hai uno. Quasi tutti i pedali emettono codici tasto; Dimmy non si interessa di dove arrivano.",
          "Accoppia a un prompt Custom che pulisce la punteggiatura, così non devi inserirla a mano col mouse.",
        ]),
        h("Dislessia"),
        list([
          "Usa lo Stile: Correct. Sistema l'ortografia senza cambiare la tua voce.",
          "Fissa la lingua (Impostazioni → Generale). L'auto-detect può essere più fragile sui clip corti.",
          "Tieni attiva la rimozione filler; toglie le false partenze che a volte mandano in tilt i controllori ortografici dopo.",
        ]),
        h("Compatibilità con screen reader"),
        list([
          "La pill è decorativa; tutto l'importante è raggiungibile dalle Impostazioni.",
          "Le Impostazioni sono un pannello nativo standard (WinUI su Windows, AppKit su macOS, GTK su Linux). Gli screen reader nativi funzionano subito.",
          "Il testo incollato finisce nel controllo attivo, così lo screen reader lo annuncia come se avessi digitato.",
        ]),
        callout("info", "Se trovi un blocco di accessibilità, apri una issue GitHub con tag accessibility. Le trattiamo come bug prioritari."),
        h("Contesti a mani occupate"),
        list([
          "Cucina: assegna la scorciatoia a un tasto volume Bluetooth di uno speaker da cucina.",
          "Guida (dove legale): collega a un auricolare Bluetooth; pressione lunga del tasto auricolare come scorciatoia.",
          "Genitori: voice note mentre tieni un bambino; modalità Toggle evita di armeggiare.",
        ]),
      ],
    },
  },

  // ---------- Integrations ----------
  {
    slug: "integrations-claude-desktop",
    category: "integrations",
    icon: "🪟",
    title: {
      en: "Connect Claude Desktop to Dimmy (MCP bridge)",
      it: "Collega Claude Desktop a Dimmy (bridge MCP)",
    },
    summary: {
      en: "One-click wizard installs a small MCP server. Ask Claude Desktop about your meetings, dictations, and let it write recaps back into Dimmy.",
      it: "Un wizard one-click installa un piccolo server MCP. Chiedi a Claude Desktop dei tuoi meeting, dettature, e lascia che scriva i recap dentro Dimmy.",
    },
    tags: ["claude desktop", "mcp", "anthropic", "integration", "bridge", "recap", "extension", "meetings"],
    blocks: {
      en: [
        p("Dimmy ships a tiny standalone binary called dimmy-mcp. It speaks the Model Context Protocol (MCP), the open standard Anthropic uses to let Claude talk to local apps. Once connected, Claude Desktop can list your recent meetings, read a transcript, fetch Dimmy's recap template, and save a finished recap back into the meeting folder. The bridge is local-only and runs on demand: no extra account, no extra API key. It works on both Windows and macOS."),
        image("Claude Desktop showing a Dimmy meeting recap generated via MCP", "16/9"),
        h("What Claude Desktop can do once connected"),
        list([
          "List your recent meetings (title, duration, timestamp).",
          "Pull the full transcript of a specific meeting.",
          "Fetch Dimmy's house recap template (so the output uses the format you customised in Settings).",
          "Save a generated recap as recap.md inside the meeting folder. Dimmy's UI picks it up automatically.",
        ]),
        callout("info", "The bridge exposes these tools: dimmy_get_recent_meetings, dimmy_get_meeting, dimmy_get_recap_template, dimmy_save_recap. There is also dimmy_get_recent_dictations, but in the current version it returns a \"not exposed yet\" message, so dictation queries don't work over the bridge yet."),
        h("Prerequisites"),
        list([
          "Dimmy 0.6.51 or newer (the bridge first shipped in stable 0.6.51).",
          "Claude Desktop installed and signed in (Pro, Team, Max, or Enterprise).",
          "Both apps installed on the same machine.",
        ]),
        h("Setup: the Connect wizard"),
        steps([
          "Open Dimmy and go to Settings → Integrations (same tab name on Windows and macOS).",
          "Find the Claude Desktop (MCP) card. If it doesn't show a green check, click Connect Claude Desktop.",
          "Step 1 checks that Claude Desktop is installed. Step 2 registers Dimmy: it copies dimmy-mcp into Claude's extensions folder and writes the manifest. Step 3 asks you to restart Claude Desktop, then waits for the first heartbeat.",
          "Fully quit Claude Desktop, because it only spawns MCP servers at startup. Cmd+Q on macOS; on Windows use the system-tray icon → Quit. Closing the window is not enough. Then reopen it.",
          "Open a new chat. Type \"List my last 2 Dimmy meetings.\" If Claude calls the tool and answers, you're connected.",
        ]),
        carousel({
          win: [{ src: "/assets/help/integrations-claude-desktop/wizard.png" }],
          mac: [
            { src: { light: "/assets/help/integrations-claude-desktop/wizard-step1-light.png", dark: "/assets/help/integrations-claude-desktop/wizard-step1-dark.png" } },
            { src: { light: "/assets/help/integrations-claude-desktop/wizard-step2-light.png", dark: "/assets/help/integrations-claude-desktop/wizard-step2-dark.png" } },
            { src: { light: "/assets/help/integrations-claude-desktop/wizard-step3-light.png", dark: "/assets/help/integrations-claude-desktop/wizard-step3-dark.png" } },
          ],
        }, "Connect Claude Desktop wizard"),
        h("Where the bridge lives"),
        p("Claude Desktop has two install layouts. New installs use the Microsoft Store (MSIX) build with a containerised data folder; older installs use the classic layout. Dimmy installs into whichever it detects."),
        table(
          ["OS / install", "Extensions folder"],
          [
            ["macOS", "~/Library/Application Support/Claude/Claude Extensions/dimmy/"],
            ["Windows (Store / MSIX)", "%LOCALAPPDATA%\\Packages\\Claude_pzs8sxrjxfjjc\\LocalCache\\Roaming\\Claude\\Claude Extensions\\dimmy\\"],
            ["Windows (classic)", "%APPDATA%\\Claude\\Claude Extensions\\dimmy\\"],
          ],
        ),
        p("Inside the dimmy folder you'll find manifest.json, icon.png, and the dimmy-mcp binary. A small enable flag (dimmy.json) lives next to it in a sibling Claude Extensions Settings folder, not inside the dimmy folder. Disconnecting removes the dimmy folder; reconnecting recreates it."),
        callout("info", "MCP logs are written by Claude Desktop, not Dimmy. On macOS they're at ~/Library/Logs/Claude/mcp-server-dimmy.log. On Windows they're under the same Claude data folder shown above (the Store build puts them inside the containerised Roaming\\Claude\\logs\\ path)."),
        h("One-click recap from a meeting"),
        p("After a meeting transcription completes, open the Done view. The Recap with Claude Desktop button (the small Claude icon, visible only once the bridge is connected) opens a fresh Claude chat with a prefilled prompt. The prompt tells Claude to fetch the template, read the transcript, write a recap, and save it back. Claude follows the steps and Dimmy's sidebar updates with the saved recap."),
        code(
          "Recap Dimmy meeting `<ID>`.\n\n1. Call `dimmy_get_recap_template` to fetch Dimmy's house format.\n2. Call `dimmy_get_meeting` with id `<ID>` to read the transcript.\n3. Produce a recap that follows the template's rules exactly (first line is a Markdown H1 title in the transcript's language).\n4. Call `dimmy_save_recap` with id `<ID>` and your recap markdown to persist it back into Dimmy.\n5. Confirm to me once saved.",
          "text",
        ),
        video("Click Recap with Claude Desktop on a completed meeting, watch Claude call the tools, see the recap appear in Dimmy's Done view"),
        h("Useful prompts to try"),
        code(
          "List my last 5 Dimmy meetings with title and duration.\n\nSummarise the meeting from <date> in three bullet points.\n\nUsing the Dimmy recap template, write a recap for meeting <id> and save it back.\n\nWhat decisions did I make in last week's meetings?\n\nDraft an email to the team based on the transcript of <meeting-title>.",
          "text",
        ),
        h("Privacy"),
        list([
          "The bridge only runs while Claude Desktop is open and has spawned it. It exits when Claude exits.",
          "All meeting data stays on your disk. Claude Desktop receives only what you explicitly ask about in a prompt.",
          "Disconnecting (Settings → Integrations → Disconnect) deletes the dimmy folder from Claude Extensions. On macOS, restart Claude Desktop afterwards.",
        ]),
        callout("info", "Full privacy details are in [[telemetry|Telemetry]] and the [[/privacy|Privacy policy]]."),
        h("Troubleshooting"),
        list([
          "Claude doesn't see the tools: fully quit Claude Desktop (not just close the window) and reopen. MCP servers are loaded once at startup.",
          "Wizard fails at \"binary not found\": reinstall Dimmy. The dimmy-mcp binary ships next to the app; an interrupted install can miss it.",
          "Connected but no heartbeat: the most common cause is a corporate antivirus that blocks an unsigned binary. Allowlist dimmy-mcp.",
          "Claude calls the tool but returns empty: you have no meetings yet. Record one, then retry.",
        ]),
        callout("tip", "Prefer the terminal? You can point the Claude CLI at the same binary. See [[integrations-mcp-claude-cli|Use Dimmy's MCP server from Claude CLI]]."),
      ],
      it: [
        p("Dimmy include un piccolo binario standalone chiamato dimmy-mcp. Parla il Model Context Protocol (MCP), lo standard aperto che Anthropic usa per far dialogare Claude con le app locali. Una volta collegato, Claude Desktop può elencare i tuoi meeting recenti, leggere una trascrizione, recuperare il template di recap di Dimmy, e salvare un recap finito nella cartella del meeting. Il bridge è solo locale e parte a richiesta: nessun account aggiuntivo, nessuna API key extra. Funziona sia su Windows che su macOS."),
        image("Claude Desktop che mostra il recap di un meeting Dimmy generato via MCP", "16/9"),
        h("Cosa può fare Claude Desktop una volta collegato"),
        list([
          "Elencare i tuoi meeting recenti (titolo, durata, data).",
          "Leggere la trascrizione completa di uno specifico meeting.",
          "Recuperare il template di recap di Dimmy (così l'output segue il formato che hai personalizzato in Impostazioni).",
          "Salvare un recap generato come recap.md nella cartella del meeting. La UI di Dimmy lo prende su al volo.",
        ]),
        callout("info", "Il bridge espone questi tool: dimmy_get_recent_meetings, dimmy_get_meeting, dimmy_get_recap_template, dimmy_save_recap. Esiste anche dimmy_get_recent_dictations, ma nella versione attuale risponde con un messaggio \"non ancora esposto\", quindi le query sulle dettature via bridge non funzionano ancora."),
        h("Prerequisiti"),
        list([
          "Dimmy 0.6.51 o successivo (il bridge è arrivato nella stable 0.6.51).",
          "Claude Desktop installato e loggato (Pro, Team, Max o Enterprise).",
          "Entrambe le app installate sulla stessa macchina.",
        ]),
        h("Setup: il wizard di collegamento"),
        steps([
          "Apri Dimmy e vai in Impostazioni → Integrazioni (stesso nome del tab su Windows e macOS).",
          "Trova la card Claude Desktop (MCP). Se non mostra un check verde, clicca Connect Claude Desktop.",
          "Lo step 1 verifica che Claude Desktop sia installato. Lo step 2 registra Dimmy: copia dimmy-mcp nella cartella estensioni di Claude e scrive il manifest. Lo step 3 ti chiede di riavviare Claude Desktop, poi attende il primo heartbeat.",
          "Chiudi del tutto Claude Desktop, perché avvia i server MCP solo all'avvio. Cmd+Q su macOS; su Windows usa l'icona nel system-tray → Quit. Chiudere solo la finestra non basta. Poi riaprilo.",
          "Apri una nuova chat. Scrivi \"Elenca i miei ultimi 2 meeting Dimmy.\" Se Claude chiama il tool e risponde, sei collegato.",
        ]),
        carousel({
          win: [{ src: "/assets/help/integrations-claude-desktop/wizard.png" }],
          mac: [
            { src: { light: "/assets/help/integrations-claude-desktop/wizard-step1-light.png", dark: "/assets/help/integrations-claude-desktop/wizard-step1-dark.png" } },
            { src: { light: "/assets/help/integrations-claude-desktop/wizard-step2-light.png", dark: "/assets/help/integrations-claude-desktop/wizard-step2-dark.png" } },
            { src: { light: "/assets/help/integrations-claude-desktop/wizard-step3-light.png", dark: "/assets/help/integrations-claude-desktop/wizard-step3-dark.png" } },
          ],
        }, "Wizard Connect Claude Desktop"),
        h("Dove vive il bridge"),
        p("Claude Desktop ha due layout di installazione. Le installazioni nuove usano la build Microsoft Store (MSIX) con cartella dati containerizzata; quelle vecchie usano il layout classico. Dimmy installa in quella che rileva."),
        table(
          ["OS / installazione", "Cartella estensioni"],
          [
            ["macOS", "~/Library/Application Support/Claude/Claude Extensions/dimmy/"],
            ["Windows (Store / MSIX)", "%LOCALAPPDATA%\\Packages\\Claude_pzs8sxrjxfjjc\\LocalCache\\Roaming\\Claude\\Claude Extensions\\dimmy\\"],
            ["Windows (classico)", "%APPDATA%\\Claude\\Claude Extensions\\dimmy\\"],
          ],
        ),
        p("Nella cartella dimmy trovi manifest.json, icon.png, e il binario dimmy-mcp. Un piccolo flag di attivazione (dimmy.json) sta accanto, in una cartella sorella Claude Extensions Settings, non dentro la cartella dimmy. Disconnettere rimuove la cartella dimmy; ricollegare la ricrea."),
        callout("info", "I log MCP li scrive Claude Desktop, non Dimmy. Su macOS sono in ~/Library/Logs/Claude/mcp-server-dimmy.log. Su Windows stanno sotto la stessa cartella dati di Claude mostrata sopra (la build Store li mette nel percorso containerizzato Roaming\\Claude\\logs\\)."),
        h("Recap one-click da un meeting"),
        p("Quando una trascrizione finisce, apri la Done view del meeting. Il pulsante Recap con Claude Desktop (la piccola icona di Claude, visibile solo dopo aver collegato il bridge) apre una chat Claude nuova con un prompt precompilato. Il prompt dice a Claude di recuperare il template, leggere la trascrizione, scrivere un recap, e salvarlo. Claude segue i passi e la sidebar di Dimmy si aggiorna col recap salvato."),
        code(
          "Recap Dimmy meeting `<ID>`.\n\n1. Call `dimmy_get_recap_template` to fetch Dimmy's house format.\n2. Call `dimmy_get_meeting` with id `<ID>` to read the transcript.\n3. Produce a recap that follows the template's rules exactly (first line is a Markdown H1 title in the transcript's language).\n4. Call `dimmy_save_recap` with id `<ID>` and your recap markdown to persist it back into Dimmy.\n5. Confirm to me once saved.",
          "text",
        ),
        video("Clicca Recap con Claude Desktop su un meeting completato, guarda Claude chiamare i tool, vedi il recap apparire nella Done view di Dimmy"),
        h("Prompt utili da provare"),
        code(
          "Elenca i miei ultimi 5 meeting Dimmy con titolo e durata.\n\nRiassumi il meeting del <data> in tre bullet.\n\nUsa il template di recap Dimmy e scrivi un recap per il meeting <id>, poi salvalo.\n\nQuali decisioni ho preso nei meeting della scorsa settimana?\n\nScrivi una mail al team basata sulla trascrizione di <titolo-meeting>.",
          "text",
        ),
        h("Privacy"),
        list([
          "Il bridge gira solo quando Claude Desktop è aperto e lo ha avviato. Si chiude quando Claude si chiude.",
          "Tutti i dati dei meeting restano sul tuo disco. Claude Desktop riceve solo ciò che chiedi esplicitamente in un prompt.",
          "Disconnettere (Impostazioni → Integrazioni → Disconnect) cancella la cartella dimmy dalle Claude Extensions. Su macOS, riavvia Claude Desktop dopo.",
        ]),
        callout("info", "Dettagli completi sulla privacy in [[telemetry|Telemetria]] e nella [[/privacy|Privacy policy]]."),
        h("Risoluzione problemi"),
        list([
          "Claude non vede i tool: chiudi del tutto Claude Desktop (non solo la finestra) e riaprilo. I server MCP vengono caricati una volta all'avvio.",
          "Wizard fallisce con \"binary not found\": reinstalla Dimmy. Il binario dimmy-mcp viene spedito accanto all'app; un'installazione interrotta può non averlo.",
          "Collegato ma nessun heartbeat: causa più frequente è un antivirus aziendale che blocca un binario non firmato. Metti dimmy-mcp in allowlist.",
          "Claude chiama il tool ma torna vuoto: non hai ancora meeting registrati. Registrane uno e riprova.",
        ]),
        callout("tip", "Preferisci il terminale? Puoi puntare la Claude CLI allo stesso binario. Vedi [[integrations-mcp-claude-cli|Usa il server MCP di Dimmy da Claude CLI]]."),
      ],
    },
  },

  {
    slug: "integrations-claude-cli",
    category: "integrations",
    icon: "⌨️",
    title: {
      en: "Use your Claude subscription via Claude CLI (no API key)",
      it: "Usa il tuo abbonamento Claude tramite Claude CLI (niente API key)",
    },
    summary: {
      en: "If you already pay for Claude Pro, Team, or Max, route Dimmy's LLM rewrites and recaps through the local claude CLI. No API key, no per-token cost.",
      it: "Se già paghi Claude Pro, Team o Max, indirizza le riscritture LLM e i recap di Dimmy tramite la CLI claude locale. Niente API key, niente costo per token.",
    },
    tags: ["claude cli", "claude code", "anthropic", "subscription", "pro", "max", "team", "no api key", "node", "npm", "provider"],
    blocks: {
      en: [
        p("Dimmy can run Anthropic's official claude CLI as a subprocess and use it as the LLM provider for style rewrites and meeting recaps. The CLI owns your login session (your Pro / Team / Max plan), and Dimmy only talks to its stdin/stdout. Dimmy never reads your credentials file."),
        callout("info", "This is the LLM provider feature. It's separate from the [[integrations-claude-desktop|Claude Desktop MCP bridge]] (which lets Claude read your Dimmy meetings) and the [[integrations-mcp-claude-cli|Dimmy MCP from Claude CLI]] recipe (which points the terminal at Dimmy's data)."),
        h("Prerequisites"),
        list([
          "An active Claude Pro, Team, Max, or Enterprise plan.",
          "Node.js 18 or newer. Get the LTS from nodejs.org. npm ships with it.",
          "A browser, for the sign-in flow.",
        ]),
        h("Install the CLI"),
        code(
          "npm install -g @anthropic-ai/claude-code",
          "bash",
        ),
        p("Open a NEW terminal (so PATH refreshes) and verify it's there:"),
        code(
          "claude --version",
          "bash",
        ),
        callout("tip", "If you see \"command not found\" after the install, your shell PATH didn't refresh. Close every terminal window and open a fresh one. On Windows the npm global entry is %APPDATA%\\npm."),
        h("Sign in"),
        p("Easiest path: let Dimmy do it. Open the Claude Code card in Dimmy (see below) and click Sign in via browser. Dimmy launches the CLI's login and watches for it to complete. You can also just run claude in a terminal the first time and follow its sign-in prompt."),
        p("Quick sanity check that the CLI answers:"),
        code(
          "echo \"say pong\" | claude --print",
          "bash",
        ),
        h("Turn it on in Dimmy"),
        p("The wording differs slightly per platform, but in both cases the connection status lives on Settings → Integrations and the provider switch lives on Settings → Output."),
        table(
          ["", "macOS", "Windows"],
          [
            ["Pick the provider", "Settings → Output → provider \"Claude Code (subscription — Pro/Team/Max)\"", "Settings → Output → provider Anthropic, then turn on the \"Use Anthropic subscription\" toggle"],
            ["For recaps", "Same provider applies to recaps", "Turn on \"Use Anthropic subscription for recap\" under Recap"],
            ["Connection card", "Settings → Integrations, \"Anthropic — Claude Code subscription\" group", "Settings → Integrations, \"ANTHROPIC SUBSCRIPTION\" group"],
          ],
        ),
        steps([
          "Open the Claude Code connection card on Settings → Integrations.",
          "If it's not green yet, click Sign in via browser and finish the login.",
          "Flip on the subscription provider/toggle as in the table above.",
          "Press your hotkey and dictate a sentence with an LLM style active. The result now comes from your Claude subscription.",
        ]),
        image("Settings → Integrations: the Claude Code subscription card showing a green connected state", "16/9", { win: { light: "/assets/help/integrations-claude-cli/card-light.png", dark: "/assets/help/integrations-claude-cli/card-dark.png" }, mac: { light: "/assets/help/app-settings/integrations-light.png", dark: "/assets/help/app-settings/integrations-dark.png" } }),
        carousel({
          win: [{ src: "/assets/help/integrations-claude-cli/wizard.png" }],
          mac: [
            { src: { light: "/assets/help/integrations-claude-cli/wizard-step1-light.png", dark: "/assets/help/integrations-claude-cli/wizard-step1-dark.png" } },
            { src: { light: "/assets/help/integrations-claude-cli/wizard-step2-light.png", dark: "/assets/help/integrations-claude-cli/wizard-step2-dark.png" } },
            { src: { light: "/assets/help/integrations-claude-cli/wizard-step3-light.png", dark: "/assets/help/integrations-claude-cli/wizard-step3-dark.png" } },
          ],
        }, "Connect Claude Code wizard"),
        callout("info", "On the subscription provider, Dimmy uses Claude Opus 4.8. For meeting recaps you can separately choose the Anthropic recap model: Opus 4.8, Sonnet 4.6, or Haiku 4.5. There is no free-form model dropdown for the Claude Code provider itself."),
        h("What this affects"),
        list([
          "Style rewrites (Correct, Summarize, Elaborate, Prompt, and friends). Every dictation that passes through an LLM style now uses your subscription.",
          "Meeting recaps, when you've enabled the subscription for recap.",
          "Custom prompts you defined in [[custom-prompts|Custom prompts]]. They keep working, only the provider changes.",
        ]),
        h("What this does NOT affect"),
        list([
          "STT (speech-to-text). That still runs locally (Whisper) or via your chosen STT provider.",
          "Telemetry. Dimmy records aggregate events (status probed, login completed, invocation success / failure) with no prompt or response content. See [[telemetry|Telemetry]].",
          "Other AI tools on your machine. Dimmy spawns its own subprocess; it does not interfere with claude when you use it manually.",
        ]),
        h("Gotchas"),
        list([
          "Always open a fresh terminal AFTER npm install. Windows PATH only picks up the new entry in new shells.",
          "Corporate networks (Zscaler, Netskope, etc.) can break the sign-in callback. If login hangs or fails with a TLS error, try from a personal network to confirm.",
          "nvm users: install the CLI with the same Node version you use day-to-day. Switching versions loses global packages.",
          "If you sign out of Claude in another tool, the CLI session goes too. Sign in again from the Dimmy card.",
        ]),
        callout("warn", "If the card still shows not connected after you signed in, click Refresh on the card (or Recheck inside the setup wizard) to re-probe. Dimmy caches where the claude binary lives until you hit refresh, so a fresh install sometimes needs one nudge."),
        h("Cost and quotas"),
        p("Dimmy makes one CLI call per LLM action (one rewrite, one recap). Each call counts against your subscription's usage. There is no separate Dimmy quota: the CLI talks to Anthropic with your account."),
      ],
      it: [
        p("Dimmy può avviare la CLI ufficiale claude di Anthropic come sottoprocesso e usarla come provider LLM per le riscritture di stile e i recap dei meeting. La CLI possiede la tua sessione di login (il tuo piano Pro / Team / Max), e Dimmy parla solo con il suo stdin/stdout. Dimmy non legge mai il tuo file di credenziali."),
        callout("info", "Questa è la feature provider LLM. È separata dal [[integrations-claude-desktop|bridge MCP per Claude Desktop]] (che fa leggere a Claude i tuoi meeting Dimmy) e dalla ricetta [[integrations-mcp-claude-cli|MCP di Dimmy da Claude CLI]] (che punta il terminale ai dati di Dimmy)."),
        h("Prerequisiti"),
        list([
          "Un piano Claude Pro, Team, Max o Enterprise attivo.",
          "Node.js 18 o successivo. Scarica la LTS da nodejs.org. npm è incluso.",
          "Un browser, per il flusso di accesso.",
        ]),
        h("Installa la CLI"),
        code(
          "npm install -g @anthropic-ai/claude-code",
          "bash",
        ),
        p("Apri un terminale NUOVO (così PATH si aggiorna) e verifica:"),
        code(
          "claude --version",
          "bash",
        ),
        callout("tip", "Se vedi \"command not found\" dopo l'install, la PATH della shell non si è aggiornata. Chiudi tutti i terminali e aprine uno nuovo. Su Windows la entry globale di npm è %APPDATA%\\npm."),
        h("Accedi"),
        p("Via più facile: lascia fare a Dimmy. Apri la card Claude Code in Dimmy (vedi sotto) e clicca Sign in via browser. Dimmy avvia il login della CLI e aspetta che si completi. In alternativa lancia claude in un terminale la prima volta e segui il prompt di accesso."),
        p("Sanity check rapido che la CLI risponda:"),
        code(
          "echo \"say pong\" | claude --print",
          "bash",
        ),
        h("Attivalo in Dimmy"),
        p("Il testo cambia un po' tra le piattaforme, ma in entrambe lo stato della connessione sta in Impostazioni → Integrazioni e l'interruttore del provider sta in Impostazioni → Output."),
        table(
          ["", "macOS", "Windows"],
          [
            ["Scegli il provider", "Impostazioni → Output → provider \"Claude Code (subscription — Pro/Team/Max)\"", "Impostazioni → Output → provider Anthropic, poi attiva il toggle \"Use Anthropic subscription\""],
            ["Per i recap", "Lo stesso provider vale per i recap", "Attiva \"Use Anthropic subscription for recap\" sotto Recap"],
            ["Card di connessione", "Impostazioni → Integrazioni, gruppo \"Anthropic — Claude Code subscription\"", "Impostazioni → Integrazioni, gruppo \"ANTHROPIC SUBSCRIPTION\""],
          ],
        ),
        steps([
          "Apri la card di connessione Claude Code in Impostazioni → Integrazioni.",
          "Se non è ancora verde, clicca Sign in via browser e completa il login.",
          "Attiva il provider/toggle dell'abbonamento come nella tabella sopra.",
          "Premi la scorciatoia e detta una frase con uno stile LLM attivo. Il risultato ora arriva dal tuo abbonamento Claude.",
        ]),
        image("Impostazioni → Integrazioni: la card abbonamento Claude Code in stato connesso (verde)", "16/9", { win: { light: "/assets/help/integrations-claude-cli/card-light.png", dark: "/assets/help/integrations-claude-cli/card-dark.png" }, mac: { light: "/assets/help/app-settings/integrations-light.png", dark: "/assets/help/app-settings/integrations-dark.png" } }),
        carousel({
          win: [{ src: "/assets/help/integrations-claude-cli/wizard.png" }],
          mac: [
            { src: { light: "/assets/help/integrations-claude-cli/wizard-step1-light.png", dark: "/assets/help/integrations-claude-cli/wizard-step1-dark.png" } },
            { src: { light: "/assets/help/integrations-claude-cli/wizard-step2-light.png", dark: "/assets/help/integrations-claude-cli/wizard-step2-dark.png" } },
            { src: { light: "/assets/help/integrations-claude-cli/wizard-step3-light.png", dark: "/assets/help/integrations-claude-cli/wizard-step3-dark.png" } },
          ],
        }, "Wizard Connect Claude Code"),
        callout("info", "Sul provider abbonamento, Dimmy usa Claude Opus 4.8. Per i recap dei meeting puoi scegliere a parte il modello Anthropic: Opus 4.8, Sonnet 4.6 o Haiku 4.5. Non c'è un dropdown a testo libero per il provider Claude Code in sé."),
        h("Cosa cambia"),
        list([
          "Le riscritture di stile (Correct, Summarize, Elaborate, Prompt, e affini). Ogni dettatura che passa da uno stile LLM usa ora il tuo abbonamento.",
          "I recap dei meeting, quando hai attivato l'abbonamento per il recap.",
          "I prompt custom definiti in [[custom-prompts|Prompt custom]]. Continuano a funzionare, cambia solo il provider.",
        ]),
        h("Cosa NON cambia"),
        list([
          "STT (speech-to-text). Continua a girare in locale (Whisper) o via il provider STT che hai scelto.",
          "Telemetria. Dimmy registra eventi aggregati (stato sondato, login completato, invocazione riuscita / fallita) senza contenuto del prompt o della risposta. Vedi [[telemetry|Telemetria]].",
          "Altri strumenti AI sulla tua macchina. Dimmy avvia un suo sottoprocesso; non interferisce con claude quando lo usi a mano.",
        ]),
        h("Cose da sapere"),
        list([
          "Apri sempre un terminale nuovo DOPO npm install. La PATH di Windows aggiorna la nuova entry solo nelle shell nuove.",
          "Reti aziendali (Zscaler, Netskope, ecc.) possono rompere il callback di accesso. Se il login si blocca o errora con TLS, prova da una rete personale per confermare.",
          "Utenti nvm: installa la CLI con la stessa versione di Node che usi tutti i giorni. Cambiare versione perde i pacchetti globali.",
          "Se ti slogghi da Claude in un altro strumento, anche la sessione della CLI salta. Riaccedi dalla card di Dimmy.",
        ]),
        callout("warn", "Se la card mostra ancora non connesso dopo l'accesso, clicca Refresh sulla card (o Recheck dentro il wizard di setup) per ri-sondare. Dimmy mette in cache dove sta il binario claude finché non fai refresh, quindi un'installazione nuova a volte ha bisogno di una spinta."),
        h("Costo e quote"),
        p("Dimmy fa una chiamata CLI per azione LLM (una riscrittura, un recap). Ogni chiamata conta sull'utilizzo del tuo abbonamento. Non c'è una quota Dimmy separata: la CLI parla con Anthropic usando il tuo account."),
      ],
    },
  },

  {
    slug: "integrations-mcp-claude-cli",
    category: "integrations",
    icon: "🔧",
    title: {
      en: "Use Dimmy's MCP server from Claude CLI (advanced)",
      it: "Usa il server MCP di Dimmy da Claude CLI (avanzato)",
    },
    summary: {
      en: "Dimmy's MCP bridge has a one-click setup for Claude Desktop. There's no built-in button for the terminal, but you can point the Claude CLI at the same binary by hand. Here's how.",
      it: "Il bridge MCP di Dimmy ha un setup one-click per Claude Desktop. Non c'è un pulsante dedicato per il terminale, ma puoi puntare la Claude CLI allo stesso binario a mano. Ecco come.",
    },
    tags: ["mcp", "claude cli", "claude code", "config", "claude mcp add", "tools", "terminal", "json", "stdio", "advanced"],
    blocks: {
      en: [
        callout("warn", "This is an advanced, manual recipe. Dimmy ships a one-click wizard for [[integrations-claude-desktop|Claude Desktop]] only. Using the binary from the terminal is unofficial: it works because dimmy-mcp is a plain stdio MCP server, but Dimmy doesn't manage this wiring for you and may move the binary between versions."),
        p("dimmy-mcp is the same small binary the Claude Desktop wizard installs. It speaks the Model Context Protocol over stdio and reads your meetings straight from disk, so any MCP client can run it, including the claude command from Claude Code."),
        callout("info", "Finish [[integrations-claude-cli|the Claude CLI setup]] first. This recipe assumes claude --version works and you're signed in. The MCP binary itself ships on Windows and macOS; there is no Linux build of dimmy-mcp."),
        h("Step 1: locate the dimmy-mcp binary"),
        p("Two reliable ways to get a path. Simplest: connect Claude Desktop once (the wizard copies the binary into a known folder). Or point at the copy inside the installed app."),
        table(
          ["Source", "macOS", "Windows"],
          [
            ["Inside the app", "/Applications/Dimmy.app/Contents/Resources/dimmy-mcp", "next to Dimmy.exe, e.g. C:\\Users\\<you>\\AppData\\Local\\Dimmy\\current\\dimmy-mcp.exe"],
            ["After connecting Claude Desktop", "~/Library/Application Support/Claude/Claude Extensions/dimmy/dimmy-mcp", "%LOCALAPPDATA%\\Packages\\Claude_pzs8sxrjxfjjc\\LocalCache\\Roaming\\Claude\\Claude Extensions\\dimmy\\dimmy-mcp.exe"],
          ],
        ),
        callout("tip", "Verify the path before wiring it up: run the binary directly. It should start and wait on stdin (Ctrl+C to quit). If it prints an error about a missing config dir, launch Dimmy once first."),
        h("Step 2: add it to Claude CLI"),
        p("Use claude mcp add. The important detail: all flags come BEFORE the server name, and a -- separates the name from the command. Use --scope user so Dimmy is available in every project, not just the current folder."),
        code(
          "# macOS\nclaude mcp add --scope user dimmy -- /Applications/Dimmy.app/Contents/Resources/dimmy-mcp\n\n# Windows (use the real, expanded path to dimmy-mcp.exe)\nclaude mcp add --scope user dimmy -- \"C:\\Users\\<you>\\AppData\\Local\\Dimmy\\current\\dimmy-mcp.exe\"",
          "bash",
        ),
        h("Or edit the config by hand"),
        p("Claude Code stores MCP servers in ~/.claude.json (user / local scope), not in a config.json. Project-scoped servers go in a .mcp.json file at the repo root. Add dimmy as a sibling under mcpServers; keep any servers already there."),
        code(
          "{\n  \"mcpServers\": {\n    \"dimmy\": {\n      \"type\": \"stdio\",\n      \"command\": \"/Applications/Dimmy.app/Contents/Resources/dimmy-mcp\",\n      \"args\": [],\n      \"env\": {}\n    }\n  }\n}",
          "json",
        ),
        h("Step 3: verify it loaded"),
        code(
          "claude mcp list\nclaude mcp get dimmy",
          "bash",
        ),
        p("dimmy should appear as connected. Inside a claude session you can also run /mcp to see live status. If it shows failed, run the binary directly to read the first stderr line: a missing Dimmy config dir is the usual cause."),
        h("Step 4: use it from the terminal"),
        code(
          "claude\n\n> List my last 5 Dimmy meetings.\n> Read the transcript of meeting <id> and summarise the action items.\n> Fetch the Dimmy recap template, write a recap for meeting <id>, and save it back.",
          "bash",
        ),
        h("The tools you get"),
        table(
          ["Tool", "What it does", "Typical use"],
          [
            ["dimmy_get_recent_meetings", "List recent meetings (id, title, ts, duration).", "\"Show me my last 10 meetings.\""],
            ["dimmy_get_meeting", "Full transcript + metadata + existing recap.", "\"Read the transcript of <id>.\""],
            ["dimmy_get_recap_template", "Dimmy's recap Markdown template.", "Called automatically before producing a recap."],
            ["dimmy_save_recap", "Write recap.md back into the meeting folder.", "\"Save this recap.\""],
            ["dimmy_get_recent_dictations", "Listed, but returns a \"not exposed yet\" message in the current version.", "Not usable yet."],
          ],
        ),
        h("Stack it with other MCP servers"),
        p("MCP is composable: Claude CLI can talk to several servers in one session. Common pairings:"),
        list([
          "Dimmy + Notion MCP → \"Summarise my last meeting and create a Notion page in <database>.\" See [[integrations-notion|Send recaps to Notion]].",
          "Dimmy + Filesystem MCP → \"Read meeting <id>, then save the recap to ~/Documents/recaps/<title>.md.\"",
          "Dimmy + GitHub MCP → \"Open an issue in <repo> based on the action items in my last standup.\"",
        ]),
        h("Troubleshooting"),
        list([
          "claude mcp list shows failed: run the binary directly from a terminal; the first stderr line names the cause (missing config dir, no permission on the meeting folder, etc.).",
          "Tool calls return empty: you have no meetings yet. Record one to verify the wiring.",
          "Stale data: dimmy-mcp reads from disk on every call. If values look old, your meeting folder might be on a synced drive that hasn't refreshed yet.",
          "Audit log: every call lands in Dimmy's config dir as mcp.calls.log (macOS ~/Library/Application Support/dimmy/, Windows %APPDATA%\\dimmy\\). Check it to confirm a tool was invoked.",
        ]),
        callout("info", "Desktop and CLI can both point at the binary at once. Each MCP client spawns its own copy; the binary is stateless and reads from disk, so there's no conflict."),
      ],
      it: [
        callout("warn", "Questa è una ricetta avanzata e manuale. Dimmy spedisce un wizard one-click solo per [[integrations-claude-desktop|Claude Desktop]]. Usare il binario dal terminale è non ufficiale: funziona perché dimmy-mcp è un normale server MCP su stdio, ma Dimmy non gestisce questo cablaggio al posto tuo e può spostare il binario tra una versione e l'altra."),
        p("dimmy-mcp è lo stesso piccolo binario che installa il wizard di Claude Desktop. Parla il Model Context Protocol su stdio e legge i tuoi meeting direttamente dal disco, quindi qualunque client MCP può avviarlo, incluso il comando claude di Claude Code."),
        callout("info", "Completa prima [[integrations-claude-cli|il setup di Claude CLI]]. Questa ricetta dà per scontato che claude --version funzioni e che tu sia loggato. Il binario MCP è spedito su Windows e macOS; non esiste una build Linux di dimmy-mcp."),
        h("Step 1: trova il binario dimmy-mcp"),
        p("Due modi affidabili per avere un percorso. Il più semplice: collega Claude Desktop una volta (il wizard copia il binario in una cartella nota). Oppure punta alla copia dentro l'app installata."),
        table(
          ["Sorgente", "macOS", "Windows"],
          [
            ["Dentro l'app", "/Applications/Dimmy.app/Contents/Resources/dimmy-mcp", "accanto a Dimmy.exe, es. C:\\Users\\<tu>\\AppData\\Local\\Dimmy\\current\\dimmy-mcp.exe"],
            ["Dopo aver collegato Claude Desktop", "~/Library/Application Support/Claude/Claude Extensions/dimmy/dimmy-mcp", "%LOCALAPPDATA%\\Packages\\Claude_pzs8sxrjxfjjc\\LocalCache\\Roaming\\Claude\\Claude Extensions\\dimmy\\dimmy-mcp.exe"],
          ],
        ),
        callout("tip", "Verifica il percorso prima di cablarlo: lancia il binario direttamente. Dovrebbe partire e restare in attesa su stdin (Ctrl+C per uscire). Se stampa un errore su una config dir mancante, avvia Dimmy una volta prima."),
        h("Step 2: aggiungilo a Claude CLI"),
        p("Usa claude mcp add. Dettaglio importante: tutti i flag vanno PRIMA del nome del server, e un -- separa il nome dal comando. Usa --scope user così Dimmy è disponibile in ogni progetto, non solo nella cartella corrente."),
        code(
          "# macOS\nclaude mcp add --scope user dimmy -- /Applications/Dimmy.app/Contents/Resources/dimmy-mcp\n\n# Windows (usa il percorso vero ed espanso a dimmy-mcp.exe)\nclaude mcp add --scope user dimmy -- \"C:\\Users\\<tu>\\AppData\\Local\\Dimmy\\current\\dimmy-mcp.exe\"",
          "bash",
        ),
        h("O modifica la config a mano"),
        p("Claude Code salva i server MCP in ~/.claude.json (scope user / local), non in un config.json. I server scoped al progetto vanno in un file .mcp.json nella root della repo. Aggiungi dimmy come voce fratella sotto mcpServers; tieni i server già presenti."),
        code(
          "{\n  \"mcpServers\": {\n    \"dimmy\": {\n      \"type\": \"stdio\",\n      \"command\": \"/Applications/Dimmy.app/Contents/Resources/dimmy-mcp\",\n      \"args\": [],\n      \"env\": {}\n    }\n  }\n}",
          "json",
        ),
        h("Step 3: verifica che sia caricato"),
        code(
          "claude mcp list\nclaude mcp get dimmy",
          "bash",
        ),
        p("dimmy dovrebbe comparire come connected. Dentro una sessione claude puoi anche lanciare /mcp per vedere lo stato live. Se mostra failed, lancia il binario direttamente per leggere la prima riga di stderr: una config dir di Dimmy mancante è la causa tipica."),
        h("Step 4: usalo dal terminale"),
        code(
          "claude\n\n> Elenca i miei ultimi 5 meeting Dimmy.\n> Leggi la trascrizione del meeting <id> e riassumi le action item.\n> Recupera il template di recap Dimmy, scrivi un recap per il meeting <id>, e salvalo.",
          "bash",
        ),
        h("I tool che ottieni"),
        table(
          ["Tool", "Cosa fa", "Uso tipico"],
          [
            ["dimmy_get_recent_meetings", "Elenca i meeting recenti (id, titolo, ts, durata).", "\"Mostrami gli ultimi 10 meeting.\""],
            ["dimmy_get_meeting", "Trascrizione completa + metadata + recap esistente.", "\"Leggi la trascrizione di <id>.\""],
            ["dimmy_get_recap_template", "Il template Markdown di recap di Dimmy.", "Chiamato automaticamente prima di produrre un recap."],
            ["dimmy_save_recap", "Scrive recap.md nella cartella del meeting.", "\"Salva questo recap.\""],
            ["dimmy_get_recent_dictations", "Elencato, ma nella versione attuale risponde \"non ancora esposto\".", "Non ancora usabile."],
          ],
        ),
        h("Componilo con altri server MCP"),
        p("MCP è componibile: Claude CLI può parlare con più server nella stessa sessione. Combinazioni utili:"),
        list([
          "Dimmy + MCP Notion → \"Riassumi il mio ultimo meeting e crea una pagina Notion in <database>.\" Vedi [[integrations-notion|Manda i recap in Notion]].",
          "Dimmy + MCP Filesystem → \"Leggi il meeting <id>, poi salva il recap in ~/Documents/recap/<titolo>.md.\"",
          "Dimmy + MCP GitHub → \"Apri una issue in <repo> partendo dalle action item del mio ultimo standup.\"",
        ]),
        h("Risoluzione problemi"),
        list([
          "claude mcp list mostra failed: lancia il binario direttamente da terminale; la prima riga di stderr nomina la causa (config dir mancante, niente permessi sulla cartella meeting, ecc.).",
          "Le chiamate ai tool tornano vuote: non hai ancora meeting. Registrane uno per verificare il cablaggio.",
          "Dati vecchi: dimmy-mcp legge dal disco a ogni chiamata. Se i valori sembrano vecchi, la cartella meeting potrebbe essere su un drive sincronizzato non ancora aggiornato.",
          "Audit log: ogni chiamata finisce nella config dir di Dimmy come mcp.calls.log (macOS ~/Library/Application Support/dimmy/, Windows %APPDATA%\\dimmy\\). Controllalo per confermare che un tool sia stato invocato.",
        ]),
        callout("info", "Desktop e CLI possono puntare al binario contemporaneamente. Ogni client MCP avvia la propria copia; il binario è stateless e legge dal disco, quindi non c'è conflitto."),
      ],
    },
  },

  {
    slug: "integrations-notion",
    category: "integrations",
    icon: "📓",
    title: {
      en: "Send meeting recaps to Notion",
      it: "Manda i recap dei meeting in Notion",
    },
    summary: {
      en: "Dimmy has a built-in Notion integration. Connect once with your own integration token, pick a destination page or database, then send any recap with one button (or auto-send every meeting).",
      it: "Dimmy ha un'integrazione Notion integrata. Colleghi una volta con il tuo token di integrazione, scegli una pagina o database di destinazione, poi mandi qualsiasi recap con un pulsante (o auto-invii ogni meeting).",
    },
    tags: ["notion", "integration", "recap", "meeting", "workflow", "knowledge base", "second brain", "token", "auto-send", "send to notion"],
    blocks: {
      en: [
        p("Notion is one of the most popular places to keep meeting recaps. Dimmy talks to it directly: it uploads your recap markdown to a page or database you choose, using your own Notion integration token. No Dimmy server sits in the middle, and it works the same on Windows and macOS."),
        image("Notion page receiving a Dimmy-generated meeting recap", "16/9"),
        h("Connect Notion (one-time setup)"),
        p("Dimmy uses a private (internal) Notion integration token. The Connect wizard walks you through it. Open Dimmy → Settings → Integrations → Notion → Connect Notion."),
        h("Step 1: prepare your Notion workspace"),
        steps([
          "Open the Notion integrations page (the wizard has an Open Notion integrations button, or go to notion.so/my-integrations).",
          "Click New integration, name it Dimmy, pick your workspace, save.",
          "Copy the Internal Integration Secret. That's your token (it looks like ntn_… on newer tokens, or secret_… on older ones).",
          "Open the Notion page or database you want recaps to land in. Click ··· → Connections → add your new Dimmy integration. Until you do this, Dimmy sees zero pages.",
        ]),
        callout("warn", "This last step is the one people miss. The token alone grants nothing. You must add the integration to each page or database via ··· → Connections, otherwise the destination list comes back empty."),
        h("Step 2: paste your token"),
        steps([
          "Paste the token into the wizard's token field.",
          "Click Verify. Dimmy pings Notion and shows \"Connected as <bot> in <workspace>\" on success.",
        ]),
        callout("info", "Tokens stay on this device, encrypted in Dimmy's local keystore. They never appear in config.json and are never sent to Dimmy's servers."),
        h("Step 3: pick a destination"),
        steps([
          "Click Refresh list. Dimmy shows every page and database your integration can see.",
          "Pick one from the dropdown. That's where recaps will be created.",
          "If your page isn't listed, you skipped the Connections step above. Add the integration to it in Notion, then Refresh again.",
        ]),
        carousel({
          win: [{ src: "/assets/help/integrations-notion/wizard.png" }],
          mac: [
            { src: { light: "/assets/help/integrations-notion/wizard-step1-light.png", dark: "/assets/help/integrations-notion/wizard-step1-dark.png" } },
            { src: { light: "/assets/help/integrations-notion/wizard-step2-light.png", dark: "/assets/help/integrations-notion/wizard-step2-dark.png" } },
            { src: { light: "/assets/help/integrations-notion/wizard-step3-light.png", dark: "/assets/help/integrations-notion/wizard-step3-dark.png" } },
          ],
        }, "Connect Notion wizard"),
        h("Send a recap"),
        p("Open a finished meeting's Done view. Click the Send recap to Notion button (the Notion mark in the toolbar). Dimmy creates a new page from the recap markdown under your chosen destination and shows a confirmation with an Open in Notion button."),
        video("Click Send recap to Notion on a completed meeting, then click Open in Notion to see the new page"),
        callout("tip", "No recap yet? Click the (Re)generate recap button on the Done view first (it runs the LLM over the transcript), then send. You can also tidy the recap text before sending."),
        h("Auto-send every meeting"),
        p("If you want every recap in Notion without clicking, turn on Settings → Integrations → Notion → the auto-send toggle. When on, each meeting's recap uploads to your destination as soon as the recap finishes. When off, you send per meeting from the Done view."),
        h("Good to know"),
        list([
          "Free Notion accounts work. There are no per-plan API limits, only Notion's standard rate limit (about 3 requests/second).",
          "Only the recap markdown leaves your machine when you (or auto-send) trigger an upload. The token and destination stay on device.",
          "Notion parses the markdown server-side, so headings, bullets, tables, and code fences come through as real Notion blocks.",
          "Disconnect any time: Settings → Integrations → Notion → Disconnect. Dimmy forgets the token and destination; your Notion content is untouched.",
        ]),
        h("Bonus: dictate straight into Notion"),
        p("Separate from recaps, you can dictate into any Notion text field like any other app. Click into a page, press your Dimmy hotkey, speak, release. Pair it with the Summarize style for brain dumps that become bullets. See [[use-meeting-recaps|Long voice notes that become structured recaps]]."),
        h("Advanced: let Claude build richer Notion pages"),
        p("The built-in integration creates one page per recap. If you want Claude to do more (set page properties, file under a specific database, combine several meetings), you can connect Notion's own MCP server to Claude alongside [[integrations-mcp-claude-cli|Dimmy's MCP]] and ask in plain language."),
        list([
          "In Claude Desktop: open Settings → Connectors, add Notion's hosted MCP at https://mcp.notion.com/mcp, and sign in. (Same per-page sharing rule applies: add the integration to the pages you want Claude to touch.)",
          "In Claude CLI: claude mcp add --transport http --scope user notion https://mcp.notion.com/mcp",
        ]),
        p("Then chain Dimmy and Notion in one prompt, for example:"),
        code(
          "Read my last Dimmy meeting (dimmy_get_recent_meetings, then dimmy_get_meeting). Write a recap with dimmy_get_recap_template. Then create a Notion page in my \"Meetings\" database with that recap as the body, the meeting title as the title, and today's date in the Date property.",
          "text",
        ),
        h("Troubleshooting"),
        list([
          "Destination list is empty: you haven't added the Dimmy integration to any page. In Notion, open the target page → ··· → Connections → add Dimmy, then Refresh.",
          "Verify fails: re-copy the Internal Integration Secret (it's easy to grab a truncated string). Make sure you copied from the right integration.",
          "\"Notion not connected\" when sending: finish the Connect wizard first (token + destination). The Send button can't do anything without both.",
          "Page created but looks thin: very deeply nested markdown can flatten. Keep the recap [[custom-prompts|template]] to 2 levels of bullets.",
        ]),
        callout("tip", "Want a fully hands-off loop? Turn on auto-send, set the meeting recap [[integrations-claude-cli|provider]] to your Claude subscription, and every meeting ends as a polished page in Notion without a click."),
      ],
      it: [
        p("Notion è uno dei posti più amati per tenere i recap dei meeting. Dimmy ci parla direttamente: carica il markdown del tuo recap in una pagina o database che scegli tu, usando il tuo token di integrazione Notion. Nessun server Dimmy in mezzo, e funziona uguale su Windows e macOS."),
        image("Pagina Notion che riceve un recap di meeting generato da Dimmy", "16/9"),
        h("Collega Notion (setup una tantum)"),
        p("Dimmy usa un token di integrazione Notion privato (interno). Il wizard di collegamento ti ci porta. Apri Dimmy → Impostazioni → Integrazioni → Notion → Connect Notion."),
        h("Step 1: prepara il tuo workspace Notion"),
        steps([
          "Apri la pagina delle integrazioni Notion (il wizard ha un pulsante Open Notion integrations, oppure vai su notion.so/my-integrations).",
          "Clicca New integration, chiamala Dimmy, scegli il workspace, salva.",
          "Copia l'Internal Integration Secret. È il tuo token (assomiglia a ntn_… sui token nuovi, o secret_… su quelli vecchi).",
          "Apri la pagina o database Notion dove vuoi che atterrino i recap. Clicca ··· → Connections → aggiungi la tua nuova integrazione Dimmy. Finché non lo fai, Dimmy non vede nessuna pagina.",
        ]),
        callout("warn", "Quest'ultimo step è quello che tutti saltano. Il token da solo non dà accesso a niente. Devi aggiungere l'integrazione a ogni pagina o database via ··· → Connections, altrimenti la lista delle destinazioni torna vuota."),
        h("Step 2: incolla il token"),
        steps([
          "Incolla il token nel campo del wizard.",
          "Clicca Verify. Dimmy pinga Notion e mostra \"Connected as <bot> in <workspace>\" se riesce.",
        ]),
        callout("info", "I token restano su questo dispositivo, cifrati nel keystore locale di Dimmy. Non compaiono mai in config.json e non vengono mai inviati ai server di Dimmy."),
        h("Step 3: scegli una destinazione"),
        steps([
          "Clicca Refresh list. Dimmy mostra ogni pagina e database che la tua integrazione può vedere.",
          "Scegline una dal dropdown. È lì che verranno creati i recap.",
          "Se la tua pagina non è in lista, hai saltato lo step Connections sopra. Aggiungi l'integrazione alla pagina in Notion, poi fai di nuovo Refresh.",
        ]),
        carousel({
          win: [{ src: "/assets/help/integrations-notion/wizard.png" }],
          mac: [
            { src: { light: "/assets/help/integrations-notion/wizard-step1-light.png", dark: "/assets/help/integrations-notion/wizard-step1-dark.png" } },
            { src: { light: "/assets/help/integrations-notion/wizard-step2-light.png", dark: "/assets/help/integrations-notion/wizard-step2-dark.png" } },
            { src: { light: "/assets/help/integrations-notion/wizard-step3-light.png", dark: "/assets/help/integrations-notion/wizard-step3-dark.png" } },
          ],
        }, "Wizard Connect Notion"),
        h("Manda un recap"),
        p("Apri la Done view di un meeting finito. Clicca il pulsante Send recap to Notion (il marchio Notion nella toolbar). Dimmy crea una nuova pagina dal markdown del recap sotto la destinazione scelta e mostra una conferma con un pulsante Open in Notion."),
        video("Clicca Send recap to Notion su un meeting completato, poi Open in Notion per vedere la pagina nuova"),
        callout("tip", "Nessun recap ancora? Clicca prima il pulsante (Re)generate recap nella Done view (lancia l'LLM sulla trascrizione), poi manda. Puoi anche sistemare il testo del recap prima di inviarlo."),
        h("Auto-invio di ogni meeting"),
        p("Se vuoi ogni recap in Notion senza cliccare, attiva Impostazioni → Integrazioni → Notion → il toggle di auto-invio. Quando è on, il recap di ogni meeting si carica sulla tua destinazione appena finisce. Quando è off, invii per singolo meeting dalla Done view."),
        h("Da sapere"),
        list([
          "Gli account Notion gratuiti funzionano. Non ci sono limiti API per piano, solo il rate limit standard di Notion (circa 3 richieste/secondo).",
          "Quando tu (o l'auto-invio) lanci un upload, lascia la macchina solo il markdown del recap. Token e destinazione restano sul dispositivo.",
          "Notion fa il parsing del markdown lato server, quindi heading, bullet, tabelle e blocchi di codice arrivano come veri blocchi Notion.",
          "Disconnetti quando vuoi: Impostazioni → Integrazioni → Notion → Disconnect. Dimmy dimentica token e destinazione; i tuoi contenuti Notion restano intatti.",
        ]),
        h("Bonus: detta dritto in Notion"),
        p("A parte i recap, puoi dettare in qualunque campo di testo di Notion come in ogni altra app. Clicca su una pagina, premi la scorciatoia di Dimmy, parla, rilascia. Accoppia con lo stile Summarize per brain dump che diventano bullet. Vedi [[use-meeting-recaps|Voice note lunghe che diventano recap strutturati]]."),
        h("Avanzato: lascia che Claude costruisca pagine Notion più ricche"),
        p("L'integrazione integrata crea una pagina per recap. Se vuoi che Claude faccia di più (impostare property della pagina, archiviare in un database specifico, unire più meeting), puoi collegare il server MCP di Notion a Claude insieme al [[integrations-mcp-claude-cli|MCP di Dimmy]] e chiedere in linguaggio naturale."),
        list([
          "In Claude Desktop: apri Impostazioni → Connectors, aggiungi l'MCP hostato di Notion su https://mcp.notion.com/mcp, e loggati. (Vale la stessa regola di condivisione per pagina: aggiungi l'integrazione alle pagine che vuoi far toccare a Claude.)",
          "In Claude CLI: claude mcp add --transport http --scope user notion https://mcp.notion.com/mcp",
        ]),
        p("Poi concatena Dimmy e Notion in un solo prompt, per esempio:"),
        code(
          "Leggi il mio ultimo meeting Dimmy (dimmy_get_recent_meetings, poi dimmy_get_meeting). Scrivi un recap con dimmy_get_recap_template. Poi crea una pagina Notion nel mio database \"Meetings\" con quel recap come corpo, il titolo del meeting come titolo, e la data di oggi nella property Date.",
          "text",
        ),
        h("Risoluzione problemi"),
        list([
          "La lista destinazioni è vuota: non hai aggiunto l'integrazione Dimmy a nessuna pagina. In Notion, apri la pagina target → ··· → Connections → aggiungi Dimmy, poi Refresh.",
          "Verify fallisce: ri-copia l'Internal Integration Secret (è facile prenderne una versione troncata). Assicurati di copiarlo dall'integrazione giusta.",
          "\"Notion not connected\" all'invio: completa prima il wizard di collegamento (token + destinazione). Il pulsante Send non può fare nulla senza entrambi.",
          "Pagina creata ma scarna: markdown troppo annidato può appiattirsi. Tieni il [[custom-prompts|template]] di recap a 2 livelli di bullet.",
        ]),
        callout("tip", "Vuoi un loop completamente a mani libere? Attiva l'auto-invio, imposta il [[integrations-claude-cli|provider]] del recap sul tuo abbonamento Claude, e ogni meeting finisce come una pagina rifinita in Notion senza un click."),
      ],
    },
  },

  {
    slug: "integrations-codex-cli",
    category: "integrations",
    icon: "🟢",
    title: {
      en: "Use your ChatGPT subscription via Codex (no API key)",
      it: "Usa il tuo abbonamento ChatGPT tramite Codex (niente API key)",
    },
    summary: {
      en: "If you already pay for ChatGPT Plus, Pro, Team, Business, or Enterprise, route Dimmy's LLM rewrites and recaps through the local codex CLI. No API key, no per-token cost.",
      it: "Se già paghi ChatGPT Plus, Pro, Team, Business o Enterprise, indirizza le riscritture LLM e i recap di Dimmy tramite la CLI codex locale. Niente API key, niente costo per token.",
    },
    tags: ["codex", "chatgpt", "openai", "subscription", "plus", "pro", "team", "enterprise", "no api key", "npm", "provider", "recap"],
    blocks: {
      en: [
        p("Dimmy can run OpenAI's official codex CLI as a subprocess and use it as the LLM provider for style rewrites and meeting recaps. The CLI owns your login session (your ChatGPT Plus / Pro / Team / Business / Enterprise plan), and Dimmy only talks to its stdin/stdout. Dimmy never reads your credentials file."),
        callout("info", "This is the OpenAI sibling of the [[integrations-claude-cli|Claude subscription via Claude CLI]] feature. Same idea, different vendor: spend your existing ChatGPT plan instead of an OpenAI API key."),
        h("Prerequisites"),
        list([
          "An active paid ChatGPT plan: Plus, Pro, Team, Business, or Enterprise. A free ChatGPT account won't work for Codex.",
          "The codex CLI installed. It ships as a native binary, so Node.js is optional.",
          "A browser, for the sign-in flow.",
        ]),
        h("Install the CLI"),
        p("If you have Node.js, the fastest path is npm:"),
        code(
          "npm install -g @openai/codex",
          "bash",
        ),
        p("No Node.js? Grab the native installer from OpenAI (developers.openai.com/codex/cli). Open a NEW terminal so PATH refreshes, then verify it's there:"),
        code(
          "codex --version",
          "bash",
        ),
        callout("tip", "After installing on Windows, you may need to restart Dimmy so the new PATH is picked up. The native Windows installer drops codex.exe under %LOCALAPPDATA%\\Programs\\OpenAI\\Codex\\bin and only updates the registry PATH for future shells. Dimmy looks there directly, but a full restart is the sure fix if Recheck still shows \"not found\"."),
        h("Sign in"),
        p("Easiest path: let Dimmy do it. Open the ChatGPT (Codex) card in Dimmy (see below) and click Sign in with ChatGPT. Dimmy launches codex login in a terminal, you complete the ChatGPT login in your browser, and Dimmy detects when it's done. You can also just run codex login in a terminal yourself."),
        callout("info", "Dimmy spawns the codex CLI and uses its stored login. It never reads ~/.codex/auth.json: that file belongs to the CLI. Dimmy only checks that you're signed in. Use of your ChatGPT plan this way is subject to OpenAI's terms of service."),
        h("Turn it on in Dimmy"),
        p("The connection card lives on Settings → Integrations in the \"OpenAI subscription\" group. Where you flip the provider on differs slightly per platform."),
        table(
          ["", "macOS", "Windows"],
          [
            ["Connection card", "Settings → Integrations, \"OpenAI subscription\" group, the \"ChatGPT (Codex) subscription\" card", "Settings → Integrations, \"OPENAI SUBSCRIPTION\" group, the \"ChatGPT (Codex)\" card"],
            ["Turn it on", "On the card, flip \"Use ChatGPT (Codex) for recap and rewrite\"", "Settings → Output → LLM, turn on \"Use ChatGPT subscription\""],
            ["For recaps", "Same toggle covers recaps", "Settings → Output → Recap, turn on \"Use ChatGPT subscription for recap\""],
          ],
        ),
        steps([
          "Open the ChatGPT (Codex) card on Settings → Integrations. If nothing is installed yet, click Set up wizard for the guided install + sign-in walkthrough.",
          "If it's not signed in, click Sign in with ChatGPT and finish the browser login.",
          "Click Test (Test connection on Windows) to send a tiny ping through codex and confirm it answers end-to-end.",
          "Flip on the subscription toggle as in the table above.",
          "Press your hotkey and dictate a sentence with an LLM style active. The result now comes from your ChatGPT subscription.",
        ]),
        image("Settings → Integrations: the ChatGPT (Codex) subscription card showing a green signed-in state", "16/9", { win: { light: "/assets/help/integrations-codex-cli/card-light.png", dark: "/assets/help/integrations-codex-cli/card-dark.png" }, mac: { light: "/assets/help/app-settings/integrations-light.png", dark: "/assets/help/app-settings/integrations-dark.png" } }),
        carousel({
          mac: [
            { src: { light: "/assets/help/integrations-codex-cli/wizard-step1-light.png", dark: "/assets/help/integrations-codex-cli/wizard-step1-dark.png" } },
            { src: { light: "/assets/help/integrations-codex-cli/wizard-step2-light.png", dark: "/assets/help/integrations-codex-cli/wizard-step2-dark.png" } },
          ],
        }, "Connect ChatGPT (Codex) wizard"),
        callout("warn", "Linux has no Settings UI for this. The codex routing exists in Dimmy's shared core, but there is no card or wizard on the Linux build, so there's no in-app way to turn it on. This integration is Windows and macOS only today. (Same caveat as [[command-mode|Command Mode]] and [[use-meeting-recaps|meeting recaps]].)"),
        h("Which model runs"),
        p("When you use the card's toggle, Dimmy points the LLM at codex://default, so Codex uses its own configured default model. If instead you keep the OpenAI provider selected and turn on the subscription toggle, Dimmy passes the OpenAI model you picked to codex. There's no separate Dimmy model dropdown on the Codex card itself."),
        h("What this affects"),
        list([
          "Style rewrites (Correct, Summarize, Elaborate, Prompt, and friends). Every dictation that passes through an LLM style now uses your subscription.",
          "Meeting recaps, when the subscription toggle is on (one toggle on macOS, the separate recap toggle on Windows).",
          "Custom prompts you defined in [[custom-prompts|Custom prompts]]. They keep working, only the provider changes.",
        ]),
        h("What this does NOT affect"),
        list([
          "STT (speech-to-text). That still runs locally (Whisper) or via your chosen STT provider. This integration is LLM-only.",
          "Telemetry. Dimmy records aggregate events (status probed, login spawned, invocation success / failure) with no prompt or response content. See [[telemetry|Telemetry]].",
          "Other AI tools on your machine. Dimmy spawns its own subprocess; it does not interfere with codex when you use it manually.",
        ]),
        h("Cost and quotas"),
        p("Dimmy makes one CLI call per LLM action (one rewrite, one recap). Each call counts against your ChatGPT plan's usage. There is no separate Dimmy quota: the CLI talks to OpenAI with your account."),
        callout("info", "Prefer Anthropic? The same pattern works with your Claude plan. See [[integrations-claude-cli|Use your Claude subscription via Claude CLI]]."),
      ],
      it: [
        p("Dimmy può avviare la CLI ufficiale codex di OpenAI come sottoprocesso e usarla come provider LLM per le riscritture di stile e i recap dei meeting. La CLI possiede la tua sessione di login (il tuo piano ChatGPT Plus / Pro / Team / Business / Enterprise), e Dimmy parla solo con il suo stdin/stdout. Dimmy non legge mai il tuo file di credenziali."),
        callout("info", "Questa è la versione OpenAI della feature [[integrations-claude-cli|abbonamento Claude tramite Claude CLI]]. Stessa idea, vendor diverso: spendi il tuo piano ChatGPT esistente invece di una API key OpenAI."),
        h("Prerequisiti"),
        list([
          "Un piano ChatGPT a pagamento attivo: Plus, Pro, Team, Business o Enterprise. Un account ChatGPT gratuito non funziona con Codex.",
          "La CLI codex installata. È spedita come binario nativo, quindi Node.js è opzionale.",
          "Un browser, per il flusso di accesso.",
        ]),
        h("Installa la CLI"),
        p("Se hai Node.js, la via più rapida è npm:"),
        code(
          "npm install -g @openai/codex",
          "bash",
        ),
        p("Niente Node.js? Scarica l'installer nativo da OpenAI (developers.openai.com/codex/cli). Apri un terminale NUOVO così PATH si aggiorna, poi verifica:"),
        code(
          "codex --version",
          "bash",
        ),
        callout("tip", "Dopo l'installazione su Windows, potresti dover riavviare Dimmy perché la nuova PATH venga letta. L'installer nativo Windows mette codex.exe sotto %LOCALAPPDATA%\\Programs\\OpenAI\\Codex\\bin e aggiorna la PATH nel registro solo per le shell future. Dimmy guarda lì direttamente, ma un riavvio completo è la soluzione sicura se Recheck mostra ancora \"not found\"."),
        h("Accedi"),
        p("Via più facile: lascia fare a Dimmy. Apri la card ChatGPT (Codex) in Dimmy (vedi sotto) e clicca Sign in with ChatGPT. Dimmy avvia codex login in un terminale, tu completi il login ChatGPT nel browser, e Dimmy rileva quando hai finito. In alternativa lancia codex login in un terminale a mano."),
        callout("info", "Dimmy avvia la CLI codex e usa il suo login salvato. Non legge mai ~/.codex/auth.json: quel file è della CLI. Dimmy controlla solo che tu sia loggato. Usare il tuo piano ChatGPT in questo modo è soggetto ai termini di servizio di OpenAI."),
        h("Attivalo in Dimmy"),
        p("La card di connessione sta in Impostazioni → Integrazioni nel gruppo \"OpenAI subscription\". Dove attivi il provider cambia un po' tra le piattaforme."),
        table(
          ["", "macOS", "Windows"],
          [
            ["Card di connessione", "Impostazioni → Integrazioni, gruppo \"OpenAI subscription\", la card \"ChatGPT (Codex) subscription\"", "Impostazioni → Integrazioni, gruppo \"OPENAI SUBSCRIPTION\", la card \"ChatGPT (Codex)\""],
            ["Attivalo", "Sulla card, attiva \"Use ChatGPT (Codex) for recap and rewrite\"", "Impostazioni → Output → LLM, attiva \"Use ChatGPT subscription\""],
            ["Per i recap", "Lo stesso toggle copre i recap", "Impostazioni → Output → Recap, attiva \"Use ChatGPT subscription for recap\""],
          ],
        ),
        steps([
          "Apri la card ChatGPT (Codex) in Impostazioni → Integrazioni. Se non è ancora installato nulla, clicca Set up wizard per la procedura guidata di install + accesso.",
          "Se non sei loggato, clicca Sign in with ChatGPT e completa il login nel browser.",
          "Clicca Test (Test connection su Windows) per mandare un piccolo ping tramite codex e confermare che risponde end-to-end.",
          "Attiva il toggle dell'abbonamento come nella tabella sopra.",
          "Premi la scorciatoia e detta una frase con uno stile LLM attivo. Il risultato ora arriva dal tuo abbonamento ChatGPT.",
        ]),
        image("Impostazioni → Integrazioni: la card abbonamento ChatGPT (Codex) in stato loggato (verde)", "16/9", { win: { light: "/assets/help/integrations-codex-cli/card-light.png", dark: "/assets/help/integrations-codex-cli/card-dark.png" }, mac: { light: "/assets/help/app-settings/integrations-light.png", dark: "/assets/help/app-settings/integrations-dark.png" } }),
        carousel({
          mac: [
            { src: { light: "/assets/help/integrations-codex-cli/wizard-step1-light.png", dark: "/assets/help/integrations-codex-cli/wizard-step1-dark.png" } },
            { src: { light: "/assets/help/integrations-codex-cli/wizard-step2-light.png", dark: "/assets/help/integrations-codex-cli/wizard-step2-dark.png" } },
          ],
        }, "Wizard Connect ChatGPT (Codex)"),
        callout("warn", "Linux non ha una UI nelle Impostazioni per questo. Il routing codex esiste nel core condiviso di Dimmy, ma non c'è card né wizard nella build Linux, quindi non c'è un modo in-app per attivarlo. Questa integrazione oggi è solo Windows e macOS. (Stesso caveat di [[command-mode|Command Mode]] e dei [[use-meeting-recaps|recap dei meeting]].)"),
        h("Quale modello gira"),
        p("Quando usi il toggle della card, Dimmy punta l'LLM su codex://default, quindi Codex usa il suo modello di default configurato. Se invece tieni selezionato il provider OpenAI e attivi il toggle dell'abbonamento, Dimmy passa a codex il modello OpenAI che hai scelto. Non c'è un dropdown del modello separato di Dimmy sulla card Codex."),
        h("Cosa cambia"),
        list([
          "Le riscritture di stile (Correct, Summarize, Elaborate, Prompt, e affini). Ogni dettatura che passa da uno stile LLM usa ora il tuo abbonamento.",
          "I recap dei meeting, quando il toggle dell'abbonamento è attivo (un solo toggle su macOS, il toggle recap separato su Windows).",
          "I prompt custom definiti in [[custom-prompts|Prompt custom]]. Continuano a funzionare, cambia solo il provider.",
        ]),
        h("Cosa NON cambia"),
        list([
          "STT (speech-to-text). Continua a girare in locale (Whisper) o via il provider STT che hai scelto. Questa integrazione è solo LLM.",
          "Telemetria. Dimmy registra eventi aggregati (stato sondato, login avviato, invocazione riuscita / fallita) senza contenuto del prompt o della risposta. Vedi [[telemetry|Telemetria]].",
          "Altri strumenti AI sulla tua macchina. Dimmy avvia un suo sottoprocesso; non interferisce con codex quando lo usi a mano.",
        ]),
        h("Costo e quote"),
        p("Dimmy fa una chiamata CLI per azione LLM (una riscrittura, un recap). Ogni chiamata conta sull'utilizzo del tuo piano ChatGPT. Non c'è una quota Dimmy separata: la CLI parla con OpenAI usando il tuo account."),
        callout("info", "Preferisci Anthropic? Lo stesso schema funziona col tuo piano Claude. Vedi [[integrations-claude-cli|Usa il tuo abbonamento Claude tramite Claude CLI]]."),
      ],
    },
  },
];

// =============================================================
// Convenience lookups
// =============================================================
const HELP_ARTICLE_BY_SLUG = Object.fromEntries(HELP_ARTICLES.map((a) => [a.slug, a]));
const HELP_ARTICLES_BY_CATEGORY = HELP_CATEGORIES.reduce((acc, c) => {
  acc[c.id] = HELP_ARTICLES.filter((a) => a.category === c.id);
  return acc;
}, {});

window.HelpContent = {
  HELP_CATEGORIES,
  HELP_ARTICLES,
  HELP_ARTICLE_BY_SLUG,
  HELP_ARTICLES_BY_CATEGORY,
};
