Ctrl K
ComunidadGuías…

index.html

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
<!DOCTYPE html>
<html lang="en">
<head>
  <!-- Content-Security-Policy. GitHub Pages serves no custom headers, so the
       policy has to travel in the markup (PRODUCT_BLUEPRINT 4.2, block F).
       Note two limits of the meta form: frame-ancestors and report-uri are
       ignored here, they exist only as real headers.
       'unsafe-inline' is present for both script and style and is a deliberate
       compromise, not an oversight: the pages carry inline <style> plus dozens
       of style attributes, which no hash can cover, and two inline scripts one
       of which differs per page. Hashes would make every later edit break the
       page silently. On static pages with no user input the value left is
       bounding WHERE external code, connections and frames may come from, and
       that part is strict. -->
  <meta http-equiv="Content-Security-Policy" content="default-src 'self'; base-uri 'self'; object-src 'none'; script-src 'self' 'unsafe-inline' https://cdn.vemetric.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self' https://hub.vemetric.com; frame-src 'none'; form-action 'self'; upgrade-insecure-requests" />
  <!-- Language: English is canonical, the switch happens client-side towards a
       published translation only. Rule and rationale: PROJECT_BLUEPRINT 3.0quinquies.
       Loaded in <head>, before rendered content, so nobody sees a flash of the
       wrong language. -->
  <script src="/languages.js"></script>
  <script src="/lang_switch.js"></script>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" />
  <link rel="apple-touch-icon" href="/apple-touch-icon.png" />
  <title>Spendif.ai: Your unified bank ledger, on your computer</title>
  <meta name="description" content="Spendif.ai automatically aggregates movements files from different banks into a single ledger: no duplicates, no subscriptions, no sending your data to anyone." />
  <meta property="og:title" content="Spendif.ai: Your unified bank ledger" />
  <meta property="og:description" content="A personal financial ledger with public source code, running on your computer. Your data stays yours." />
  <meta property="og:type" content="website" />

<!-- SEO/GEO (managed) -->
  <link rel="canonical" href="https://spendif.ai/" />
  <link rel="alternate" hreflang="en" href="https://spendif.ai/" />
  <link rel="alternate" hreflang="it" href="https://spendif.ai/it/" />
  <link rel="alternate" hreflang="de" href="https://spendif.ai/de/" />
  <link rel="alternate" hreflang="es" href="https://spendif.ai/es/" />
  <link rel="alternate" hreflang="fr" href="https://spendif.ai/fr/" />
  <link rel="alternate" hreflang="ja" href="https://spendif.ai/ja/" />
  <link rel="alternate" hreflang="nl" href="https://spendif.ai/nl/" />
  <link rel="alternate" hreflang="pl" href="https://spendif.ai/pl/" />
  <link rel="alternate" hreflang="pt" href="https://spendif.ai/pt/" />
  <link rel="alternate" hreflang="x-default" href="https://spendif.ai/" />
  <meta name="robots" content="index,follow" />
  <meta property="og:url" content="https://spendif.ai/" />
  <meta property="og:site_name" content="Spendif.ai" />
  <meta property="og:locale" content="en_US" />
  <meta property="og:locale:alternate" content="it_IT" />
  <meta property="og:locale:alternate" content="de_DE" />
  <meta property="og:locale:alternate" content="es_ES" />
  <meta property="og:locale:alternate" content="fr_FR" />
  <meta property="og:locale:alternate" content="ja_JP" />
  <meta property="og:locale:alternate" content="nl_NL" />
  <meta property="og:locale:alternate" content="pl_PL" />
  <meta property="og:locale:alternate" content="pt_PT" />
  <meta property="og:image" content="https://spendif.ai/og-image.en.png" />
  <meta property="og:image:width" content="1200" />
  <meta property="og:image:height" content="630" />
  <meta name="twitter:image" content="https://spendif.ai/og-image.en.png" />
  <meta name="twitter:card" content="summary_large_image" />
  <meta name="twitter:title" content="Spendif.ai: Your unified bank ledger" />
  <meta name="twitter:description" content="Spendif.ai automatically aggregates movements files from different banks into a single ledger: no duplicates, no subscriptions, no sending your data to anyone." />
  <script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "SoftwareApplication",
    "name": "Spendif.ai",
    "applicationCategory": "FinanceApplication",
    "operatingSystem": "Windows, macOS, Linux",
    "description": "Spendif.ai automatically aggregates movements files from different banks into a single ledger: no duplicates, no subscriptions, no sending your data to anyone.",
    "url": "https://spendif.ai/",
    "inLanguage": "en",
    "isAccessibleForFree": true,
    "offers": {
      "@type": "Offer",
      "price": "0",
      "priceCurrency": "EUR"
    },
    "license": "https://github.com/spendifai/spendif-ai/blob/main/LICENSE",
    "author": {
      "@type": "Organization",
      "name": "Spendif.ai",
      "url": "https://github.com/spendifai/spendif-ai"
    }
  }
  </script>
  <!-- /SEO/GEO -->

  <!-- Vemetric Analytics -->
  <script>
    window.vmtrcq = window.vmtrcq || [];
    window.vmtrc = window.vmtrc || function (){window.vmtrcq.push(Array.prototype.slice.call(arguments))};
  </script>
  <script defer src="https://cdn.vemetric.com/main.js" id="vmtrc-scr" data-token="o10JyrtkgQ8RAn1q"></script>

  <style>
    /* Language menu. lang_switch.js is copied from the blueprint and fills
       [data-lang-switcher] with bare <a> elements, so it is wrapped rather than
       modified: a native details element needs no JavaScript of its own and works
       keyboard and by touch, unlike a hover menu.
       Why a menu and not a row: the rule requires each language written in its
       own name, and nine full names do not fit a navbar. Collapsed, one name
       shows. The closed label is hard-coded per page because a static page
       already knows its own language. */
    .lang-menu {
      position: relative;
      margin-left: 1rem;
      font-size: 0.78rem;
    }
    .lang-menu > summary {
      list-style: none;
      cursor: pointer;
      display: inline-flex;
      align-items: center;
      gap: 0.35rem;
      padding: 0.2rem 0.55rem;
      border: 1px solid var(--border);
      border-radius: 6px;
      color: var(--muted);
      white-space: nowrap;
    }
    .lang-menu > summary::-webkit-details-marker { display: none; }
    .lang-menu > summary:hover,
    .lang-menu[open] > summary { color: var(--text); border-color: var(--blue); }
    .lang-menu [data-lang-switcher] {
      position: absolute;
      right: 0;
      top: calc(100% + 0.35rem);
      z-index: 50;
      display: flex;
      flex-direction: column;
      min-width: 9.5rem;
      padding: 0.3rem;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: 8px;
      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
    }
    .lang-menu [data-lang-switcher] a {
      color: var(--muted);
      text-decoration: none;
      padding: 0.35rem 0.6rem;
      border-radius: 4px;
      white-space: nowrap;
    }
    .lang-menu [data-lang-switcher] a:hover { color: var(--text); background: var(--surface2); }
    /* The language you are already reading is the closed label: repeating it
       inside the menu would offer a link to where you already are. */
    .lang-menu [data-lang-switcher] a[aria-current] { display: none; }
    /* Without JavaScript the list stays empty, and an empty menu is worse than
       no menu: the reader correctly stays on the page they landed on. */
    .lang-menu:has([data-lang-switcher]:empty) { display: none; }
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

    :root {
      --bg:       #0d1117;
      --surface:  #161b22;
      --surface2: #21262d;
      --border:   #30363d;
      --blue:     #58a6ff;
      --green:    #3fb950;
      --purple:   #bc8cff;
      --orange:   #e3b341;
      --red:      #f85149;
      --text:     #e6edf3;
      --muted:    #8b949e;
      --radius:   12px;
    }

    html { scroll-behavior: smooth; }

    body {
      background: var(--bg);
      color: var(--text);
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
      font-size: 16px;
      line-height: 1.6;
    }

    /* ── NAV ─────────────────────────────────────────────── */
    nav {
      position: sticky;
      top: 0;
      z-index: 100;
      background: rgba(13,17,23,0.85);
      backdrop-filter: blur(12px);
      border-bottom: 1px solid var(--border);
      padding: 0 2rem;
      display: flex;
      align-items: center;
      justify-content: space-between;
      height: 56px;
    }
    .nav-logo {
      font-weight: 700;
      font-size: 1.15rem;
      color: var(--text);
      text-decoration: none;
      display: flex;
      align-items: center;
      gap: 0.5rem;
    }
    .nav-logo span { color: var(--blue); }
    .nav-links {
      display: flex;
      gap: 1.5rem;
      list-style: none;
    }
    .nav-links a {
      color: var(--muted);
      text-decoration: none;
      font-size: 0.9rem;
      transition: color .2s;
    }
    .nav-links a:hover { color: var(--text); }
    .nav-cta {
      background: var(--blue);
      color: #0d1117 !important;
      padding: 0.4rem 1rem;
      border-radius: 6px;
      font-weight: 600;
      transition: opacity .2s !important;
    }
    .nav-cta:hover { opacity: .85; }

    /* ── HERO ────────────────────────────────────────────── */
    .hero {
      padding: 6rem 2rem 5rem;
      text-align: center;
      position: relative;
      overflow: hidden;
    }
    .hero::before {
      content: '';
      position: absolute;
      inset: 0;
      background:
        radial-gradient(ellipse 80% 60% at 50% -10%, rgba(88,166,255,.12), transparent),
        radial-gradient(ellipse 60% 40% at 80% 80%, rgba(63,185,80,.06), transparent);
      pointer-events: none;
    }
    .hero-badge {
      display: inline-block;
      border: 1px solid var(--border);
      background: var(--surface);
      color: var(--muted);
      font-size: 0.78rem;
      padding: 0.3rem 0.9rem;
      border-radius: 100px;
      margin-bottom: 1.5rem;
      letter-spacing: .03em;
    }
    .hero-badge strong { color: var(--green); }
    h1 {
      font-size: clamp(2rem, 5vw, 3.4rem);
      font-weight: 800;
      line-height: 1.15;
      letter-spacing: -.02em;
      max-width: 820px;
      margin: 0 auto 1.25rem;
    }
    h1 .accent { color: var(--blue); }
    .hero-sub {
      font-size: clamp(1rem, 2vw, 1.2rem);
      color: var(--muted);
      max-width: 580px;
      margin: 0 auto 2.5rem;
    }
    .hero-actions {
      display: flex;
      gap: 1rem;
      justify-content: center;
      flex-wrap: wrap;
    }
    .btn {
      display: inline-flex;
      align-items: center;
      gap: .5rem;
      padding: .7rem 1.6rem;
      border-radius: 8px;
      font-size: .95rem;
      font-weight: 600;
      text-decoration: none;
      transition: opacity .2s, transform .15s;
      cursor: pointer;
      border: none;
    }
    .btn:hover { opacity: .85; transform: translateY(-1px); }
    .btn-primary { background: var(--blue); color: #0d1117; }
    .btn-secondary {
      background: var(--surface2);
      color: var(--text);
      border: 1px solid var(--border);
    }
    .hero-note {
      margin-top: 2.5rem;
      color: var(--muted);
      font-size: .85rem;
    }

    /* ── TRUST BAR ───────────────────────────────────────── */
    .trust-bar {
      border-top: 1px solid var(--border);
      border-bottom: 1px solid var(--border);
      padding: 1.2rem 2rem;
      display: flex;
      justify-content: center;
      gap: 3rem;
      flex-wrap: wrap;
    }
    .trust-item {
      display: flex;
      align-items: center;
      gap: .5rem;
      color: var(--muted);
      font-size: .875rem;
    }
    .trust-item .ico { font-size: 1rem; }

    /* ── SECTIONS ────────────────────────────────────────── */
    section { padding: 5rem 2rem; }
    .container { max-width: 1100px; margin: 0 auto; }
    .section-label {
      font-size: .75rem;
      font-weight: 700;
      letter-spacing: .12em;
      text-transform: uppercase;
      color: var(--blue);
      margin-bottom: .75rem;
    }
    h2 {
      font-size: clamp(1.6rem, 3vw, 2.2rem);
      font-weight: 800;
      letter-spacing: -.02em;
      line-height: 1.2;
      margin-bottom: 1rem;
    }
    .section-sub {
      color: var(--muted);
      font-size: 1.05rem;
      max-width: 580px;
      margin-bottom: 3rem;
    }

    /* ── PROBLEM ─────────────────────────────────────────── */
    .problem-grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 1.5rem;
      margin-top: 3rem;
    }
    .problem-card {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 1.75rem;
    }
    .problem-card.highlight {
      border-color: rgba(248,81,73,.35);
      background: rgba(248,81,73,.05);
    }
    .problem-card h3 {
      font-size: 1.05rem;
      font-weight: 700;
      margin-bottom: .6rem;
      display: flex;
      align-items: center;
      gap: .5rem;
    }
    .problem-card p { color: var(--muted); font-size: .95rem; }

    /* ── STEPS ───────────────────────────────────────────── */
    /* ── Schermate di prodotto ─────────────────────────────────────────── */
    .shots { display: grid; gap: 1.25rem; margin-top: 2rem; }
    .shots figure { margin: 0; }
    .shots img {
      width: 100%; height: auto; display: block;
      border: 1px solid var(--border); border-radius: var(--radius);
      box-shadow: 0 8px 28px rgba(0,0,0,.35);
    }
    .shots figcaption {
      color: var(--muted); font-size: 0.9rem; margin-top: 0.6rem; text-align: center;
    }
    @media (min-width: 900px) {
      .shots { grid-template-columns: 1fr 1fr; }
      .shots figure:first-child { grid-column: 1 / -1; }
      .shots.two { grid-template-columns: 1fr; }
    }

    .steps {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 1.5rem;
      counter-reset: steps;
    }
    .step {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 2rem;
      position: relative;
      overflow: hidden;
    }
    .step::before {
      counter-increment: steps;
      content: counter(steps);
      position: absolute;
      top: -10px;
      right: 16px;
      font-size: 5rem;
      font-weight: 900;
      color: var(--border);
      line-height: 1;
      pointer-events: none;
      user-select: none;
    }
    .step h3 {
      font-size: 1.05rem;
      font-weight: 700;
      margin-bottom: .75rem;
      color: var(--blue);
    }
    .step p { color: var(--muted); font-size: .95rem; }

    /* ── DIFFERENTIATORS ─────────────────────────────────── */
    .diff-grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 1.5rem;
    }
    .diff-card {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 1.75rem;
    }
    .diff-card .tag {
      display: inline-block;
      font-size: .7rem;
      font-weight: 700;
      letter-spacing: .08em;
      text-transform: uppercase;
      background: rgba(88,166,255,.1);
      color: var(--blue);
      border: 1px solid rgba(88,166,255,.25);
      padding: .2rem .6rem;
      border-radius: 4px;
      margin-bottom: .9rem;
    }
    .diff-card h3 {
      font-size: 1.05rem;
      font-weight: 700;
      margin-bottom: .6rem;
    }
    .diff-card p { color: var(--muted); font-size: .93rem; }
    .cascade-list {
      list-style: none;
      margin-top: .75rem;
      display: flex;
      flex-direction: column;
      gap: .4rem;
    }
    .cascade-list li {
      display: flex;
      gap: .6rem;
      color: var(--muted);
      font-size: .9rem;
    }
    .cascade-list li .num {
      flex-shrink: 0;
      width: 20px;
      height: 20px;
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: .7rem;
      font-weight: 700;
      margin-top: 2px;
    }

    /* ── PRIVACY ─────────────────────────────────────────── */
    .privacy-section { background: var(--surface); }
    .privacy-grid {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 1.5rem;
    }
    .privacy-card {
      background: var(--bg);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 1.75rem;
      text-align: center;
    }
    .privacy-card .ico-big {
      font-size: 2.5rem;
      margin-bottom: 1rem;
    }
    .privacy-card h3 { font-size: 1rem; font-weight: 700; margin-bottom: .5rem; }
    .privacy-card p { color: var(--muted); font-size: .9rem; }
    .pii-chips {
      display: flex;
      flex-wrap: wrap;
      gap: .5rem;
      justify-content: center;
      margin-top: .75rem;
    }
    .pii-chip {
      font-family: 'SFMono-Regular', Consolas, monospace;
      font-size: .75rem;
      background: rgba(248,81,73,.1);
      border: 1px solid rgba(248,81,73,.25);
      color: #f0a8a8;
      padding: .2rem .55rem;
      border-radius: 4px;
    }

    /* ── FOR WHO ─────────────────────────────────────────── */
    .audience-grid {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 1.5rem;
    }
    .audience-card {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 1.75rem;
      display: flex;
      gap: 1rem;
    }
    .audience-card .ico-circle {
      flex-shrink: 0;
      width: 44px;
      height: 44px;
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 1.3rem;
      margin-top: .1rem;
    }
    .audience-card h3 { font-size: 1rem; font-weight: 700; margin-bottom: .4rem; }
    .audience-card p { color: var(--muted); font-size: .9rem; }

    /* ── FEATURES TABLE ──────────────────────────────────── */
    .features-grid {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 1px;
      background: var(--border);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      overflow: hidden;
    }
    .feature-row {
      background: var(--surface);
      padding: 1.1rem 1.5rem;
      display: flex;
      gap: 1rem;
    }
    .feature-row .feature-name {
      font-weight: 600;
      font-size: .9rem;
      min-width: 190px;
      flex-shrink: 0;
      color: var(--text);
    }
    .feature-row .feature-desc {
      color: var(--muted);
      font-size: .88rem;
    }

    /* ── STACK ───────────────────────────────────────────── */
    .stack-grid {
      display: flex;
      flex-wrap: wrap;
      gap: .75rem;
      margin-bottom: 2rem;
    }
    .stack-badge {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: 8px;
      padding: .6rem 1.1rem;
      display: flex;
      align-items: center;
      gap: .5rem;
      font-size: .9rem;
    }
    .stack-badge strong { color: var(--text); }
    .stack-badge span { color: var(--muted); font-size: .82rem; }

    /* ── INSTALL ─────────────────────────────────────────── */
    .install-section { background: var(--surface); }
    .os-tabs {
      display: flex;
      gap: .5rem;
      margin-bottom: 1rem;
    }
    .os-tab {
      padding: .35rem 1rem;
      border: 1px solid var(--border);
      border-radius: 6px;
      background: transparent;
      color: var(--muted);
      font-size: .85rem;
      cursor: pointer;
      transition: all .2s;
    }
    .os-tab.active {
      background: var(--blue);
      border-color: var(--blue);
      color: #fff;
    }
    .os-panel { display: none; }
    .os-panel.active { display: block; }
    .install-dev-link {
      margin-top: 1.2rem;
      font-size: .85rem;
      color: var(--muted);
    }
    .install-dev-link a { color: var(--blue); }
    .code-block {
      background: #010409;
      border: 1px solid var(--border);
      border-radius: var(--radius);
      overflow: hidden;
      margin: 2rem 0;
    }
    .code-header {
      background: var(--surface2);
      border-bottom: 1px solid var(--border);
      padding: .6rem 1rem;
      display: flex;
      align-items: center;
      gap: .5rem;
    }
    .code-dots { display: flex; gap: .4rem; }
    .code-dots span {
      width: 12px;
      height: 12px;
      border-radius: 50%;
    }
    .code-dots .d1 { background: #ff5f57; }
    .code-dots .d2 { background: #febc2e; }
    .code-dots .d3 { background: #28c840; }
    .code-label { color: var(--muted); font-size: .8rem; margin-left: .3rem; }
    .copy-btn {
      margin-left: auto;
      background: transparent;
      border: 1px solid var(--border);
      color: var(--muted);
      font-size: .75rem;
      padding: .2rem .6rem;
      border-radius: 5px;
      cursor: pointer;
      transition: color .2s, border-color .2s;
    }
    .copy-btn:hover { color: var(--text); border-color: var(--muted); }
    .code-body {
      padding: 1.5rem;
      font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
      font-size: .88rem;
      line-height: 1.8;
      overflow-x: auto;
    }
    .code-body .p  { color: #8b949e; }  /* prompt */
    .code-body .c  { color: #79c0ff; }  /* command */
    .code-body .a  { color: #a5d6ff; }  /* args */
    .code-body .co { color: #6a737d; }  /* comment */

    .install-post {
      color: var(--muted);
      font-size: .95rem;
    }
    .install-post strong { color: var(--text); }

    /* ── PIPELINE ────────────────────────────────────────── */
    .pipeline-box {
      background: #010409;
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 1.5rem 2rem;
      font-family: 'SFMono-Regular', Consolas, monospace;
      font-size: .83rem;
      line-height: 1.9;
      overflow-x: auto;
      color: var(--muted);
    }
    .pipeline-box .ph { color: var(--blue); }
    .pipeline-box .ar { color: var(--border); }
    .pipeline-box .label { color: var(--text); }
    .pipeline-box .note { color: #6a737d; }

    /* ── ROADMAP ─────────────────────────────────────────── */
    .roadmap-list {
      list-style: none;
      display: flex;
      flex-direction: column;
      gap: .75rem;
    }
    .roadmap-list li {
      display: flex;
      align-items: center;
      gap: .9rem;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: 8px;
      padding: .9rem 1.25rem;
      color: var(--muted);
      font-size: .95rem;
    }
    .roadmap-list li .dot {
      width: 8px;
      height: 8px;
      border-radius: 50%;
      background: var(--border);
      flex-shrink: 0;
    }

    /* ── CONTRIBUTE ──────────────────────────────────────── */
    .contribute-grid {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 1.5rem;
    }
    .contribute-card {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius);
      padding: 1.5rem;
    }
    .contribute-card h3 { font-size: .95rem; font-weight: 700; margin-bottom: .5rem; }
    .contribute-card p { color: var(--muted); font-size: .88rem; }

    /* ── FOOTER ──────────────────────────────────────────── */
    footer {
      border-top: 1px solid var(--border);
      padding: 2.5rem 2rem;
      text-align: center;
      color: var(--muted);
      font-size: .87rem;
    }
    footer a { color: var(--blue); text-decoration: none; }
    footer a:hover { text-decoration: underline; }
    footer .disclaimer {
      max-width: 640px;
      margin: 1rem auto 0;
      font-size: .8rem;
      line-height: 1.7;
      opacity: .7;
    }

    /* ── DIVIDER ─────────────────────────────────────────── */
    .divider { border: none; border-top: 1px solid var(--border); margin: 0; }

    /* ── FADE-IN ANIMATION ───────────────────────────────── */
    .fade-in {
      opacity: 0;
      transform: translateY(24px);
      transition: opacity .55s ease, transform .55s ease;
    }
    .fade-in.visible {
      opacity: 1;
      transform: none;
    }

    /* ── RESPONSIVE ──────────────────────────────────────── */
    @media (max-width: 768px) {
      .problem-grid,
      .steps,
      .diff-grid,
      .privacy-grid,
      .audience-grid,
      .features-grid,
      .contribute-grid { grid-template-columns: 1fr; }

      .nav-links { display: none; }
      .hero { padding: 4rem 1.25rem 3rem; }
      section { padding: 3.5rem 1.25rem; }
      .trust-bar { gap: 1.5rem; }
    }

    /* ── LANG SWITCHER ────────────────────────────────────── */
    /* FAQ (generated by scripts/gen_faq.py) */
    .faq-list { display: flex; flex-direction: column; gap: .75rem; }
    .faq-item { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); }
    .faq-item summary { cursor: pointer; padding: 1.1rem 1.4rem; font-weight: 600; font-size: .95rem;
      list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 1rem; }
    .faq-item summary::-webkit-details-marker { display: none; }
    .faq-item summary::after { content: "+"; color: var(--blue); font-size: 1.3rem; line-height: 1; flex-shrink: 0; }
    .faq-item[open] summary::after { content: "‘2"; }
    .faq-item p { color: var(--muted); font-size: .9rem; line-height: 1.65; padding: 0 1.4rem 1.25rem; margin: 0; }
    /* /FAQ */
  </style>
  <!-- FAQ JSON-LD (generated by scripts/gen_faq.py) -->
  <script type="application/ld+json">
  {
      "@context": "https://schema.org",
      "@type": "FAQPage",
      "inLanguage": "en",
      "url": "https://spendif.ai/",
      "mainEntity": [
          {
              "@type": "Question",
              "name": "My bank already does this: what is Spendif.ai for?",
              "acceptedAnswer": {
                  "@type": "Answer",
                  "text": "Your bank only sees its own accounts: a current account, a card, PayPal and Satispay are enough never to have one picture. Spendif.ai puts them together, from different banks too, and shows the period you choose on one page. The categories are yours, not the bank's: on an Amazon or PayPal purchase \"shopping\" says nothing. And you can give your expenses a context, home, holiday or work, which the bank does not know."
              }
          },
          {
              "@type": "Question",
              "name": "What is the best way to use it?",
              "acceptedAnswer": {
                  "@type": "Answer",
                  "text": "Four steps. Load the statements of all your accounts. Give a category to the counterparts with the most movements, at least the first 10, which usually cover most of your spending. Tick the expenses you have a receipt for, online ones too as soon as the email arrives, with date and amount. Check what is left, mostly transfers, account by account."
              }
          },
          {
              "@type": "Question",
              "name": "Does Spendif.ai connect to my bank?",
              "acceptedAnswer": {
                  "@type": "Answer",
                  "text": "No, never. No Open Banking, no PSD2, no banking password. You download the transaction file from your bank yourself, as CSV or XLSX, and drop it into the app."
              }
          },
          {
              "@type": "Question",
              "name": "Does my data leave my computer?",
              "acceptedAnswer": {
                  "@type": "Answer",
                  "text": "No. Spendif.ai keeps everything in a local SQLite database under ~/.spendifai/, and works with no connection. If you choose to use a remote LLM, IBANs and names are stripped from the descriptions before anything is sent."
              }
          },
          {
              "@type": "Question",
              "name": "What does it cost? Is it free forever?",
              "acceptedAnswer": {
                  "@type": "Answer",
                  "text": "Today Spendif.ai is free for personal use, with no subscription and no hidden costs. The source code is public and you can read it. A paid version with extra features may come later: the version you installed will keep working, and your data stays in a file on your computer that you can take with you whenever you want."
              }
          },
          {
              "@type": "Question",
              "name": "Do I need an account?",
              "acceptedAnswer": {
                  "@type": "Answer",
                  "text": "No. No email, no sign-up, no password to recover. You install the app and use it."
              }
          },
          {
              "@type": "Question",
              "name": "Which systems does it run on?",
              "acceptedAnswer": {
                  "@type": "Answer",
                  "text": "Windows, Linux, and macOS 12 Monterey or later on Apple Silicon (M1 or newer). There is no Intel Mac build."
              }
          },
          {
              "@type": "Question",
              "name": "Which banks are supported?",
              "acceptedAnswer": {
                  "@type": "Answer",
                  "text": "Any bank that lets you export transactions as CSV or XLSX. Spendif.ai detects the format on its own, and you can import files from different banks together."
              }
          },
          {
              "@type": "Question",
              "name": "What happens if I import the same file twice?",
              "acceptedAnswer": {
                  "@type": "Answer",
                  "text": "Nothing bad: transactions already in the ledger are not duplicated. You can re-import the same file as many times as you like."
              }
          },
          {
              "@type": "Question",
              "name": "Is there a phone app?",
              "acceptedAnswer": {
                  "@type": "Answer",
                  "text": "No, Spendif.ai is a desktop application. A companion app for recording cash spending only is planned, but it has no date."
              }
          }
      ]
  }
  </script>
  <!-- /FAQ JSON-LD -->
</head>
<body>

<!-- ── NAV ──────────────────────────────────────────────────────────────── -->
<nav>
  <a class="nav-logo" href="#"><svg width="22" height="22" viewBox="0 0 108 108" style="vertical-align:-4px;margin-right:5px" aria-hidden="true"><rect x="54" y="16" width="42" height="16" rx="5" fill="#2F9E7F"/><rect x="12" y="40" width="42" height="16" rx="5" fill="#C9603A"/><rect x="24" y="64" width="30" height="16" rx="5" fill="#4A73C4"/><rect x="4" y="88" width="50" height="16" rx="5" fill="#D69A2E"/></svg>Spendif<span>.</span>ai</a>
  <ul class="nav-links">
    <li><a href="#how-it-works">How it works</a></li>
    <li><a href="#privacy">Privacy</a></li>
    <li><a href="#features">Features</a></li>
    <li><a href="#developer">Developer</a></li>
    <li><a href="https://github.com/spendifai/spendif-ai" target="_blank" class="nav-cta" rel="noopener noreferrer">GitHub ↗</a></li>
  </ul>
    <details class="lang-menu">
      <summary>🌐 English</summary>
      <nav data-lang-switcher aria-label="Language"></nav>
    </details>
</nav>

<!-- ── HERO ─────────────────────────────────────────────────────────────── -->
<section class="hero">
  <div class="hero-badge">Public source · <strong>Offline-first</strong> · No subscription</div>
  <h1>Your <span class="accent">unified</span> bank ledger,<br>on your computer</h1>
  <p class="hero-sub">
    Import files from all your banks. Spendif.ai merges them, eliminates double-counting,
    classifies every transaction, and your data never leaves your disk.
  </p>
  <div class="hero-actions">
    <a class="btn btn-primary" href="#install">▶ Install now</a>
    <a class="btn btn-secondary" href="https://github.com/spendifai/spendif-ai" target="_blank" rel="noopener noreferrer">
      <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
      View on GitHub
    </a>
  </div>
  <p class="hero-note">Python · Streamlit · SQLite · Ollama · no account required</p>
</section>

<!-- ── TRUST BAR ─────────────────────────────────────────────────────────── -->
<div class="trust-bar">
  <div class="trust-item"><span class="ico">🔒</span> Data only on your computer</div>
  <div class="trust-item"><span class="ico">🔁</span> Idempotent SHA-256 import</div>
  <div class="trust-item"><span class="ico">🏦</span> Multi-bank, multi-format</div>
  <div class="trust-item"><span class="ico">🤖</span> Local or cloud AI with PII redaction</div>
  <div class="trust-item"><span class="ico">🧪</span> 199 tests, zero external dependencies</div>
</div>

<!-- ── PROBLEM ──────────────────────────────────────────────────────────── -->
<section id="problema">
  <div class="container">
    <div class="section-label">The problem</div>
    <h2>Three banks, three files, one mess</h2>
    <p class="section-sub">
      Every month: download, open Excel, paste, fix the signs, find the duplicates.
      And every time something doesn't add up.
    </p>

    <div class="problem-grid fade-in">
      <div class="problem-card">
        <h3>😩 The monthly routine everyone hates</h3>
        <p>Three movements files from three different banking portals, incompatible CSV formats,
        dates in different formats, amounts with random signs. Merging them by hand takes hours
        and always produces errors.</p>
      </div>
      <div class="problem-card highlight">
        <h3>🔴 The problem of all problems: double-counting</h3>
        <p>The supermarket purchase appears in the credit card statement <em>and</em> in the current account
        as a monthly aggregate charge. Adding everything up, your expenses look double
        what they actually are. No common tool solves this automatically.</p>
      </div>
      <div class="problem-card">
        <h3>🔄 Internal transfers that distort your balance</h3>
        <p>A wire transfer to a savings account is not an expense. But if you import both accounts,
        the same transaction appears twice: as an outflow from the current account and as an inflow on the savings account.</p>
      </div>
      <div class="problem-card">
        <h3>📋 The categorisation that never ends</h3>
        <p>Classifying 300 transactions per month by hand is a job. Cloud apps do it,
        but they send your banking data to their servers and charge you a monthly subscription.</p>
      </div>
    </div>
  </div>
</section>

<hr class="divider">

<!-- ── HOW IT WORKS ──────────────────────────────────────────────────────── -->
<section id="how-it-works">
  <div class="container">
    <div class="section-label">How it works</div>
    <h2>Three steps, no black magic</h2>
    <p class="section-sub">No banking integrations, no account, no per-file configuration.</p>

    <div class="steps fade-in">
      <div class="step">
        <h3>Download files from your bank</h3>
        <p>Export movements files as CSV or XLSX from your bank's portal.
        Works with any bank: Spendif.ai automatically detects
        the format with no manual configuration.</p>
      </div>
      <div class="step">
        <h3>Drag them into Spendif.ai and click Process</h3>
        <p>Select all files at once, even from different banks, even from different years.
        Spendif.ai detects the document type, corrects signs, eliminates double-counting
        between card and account, and classifies every transaction.</p>
      </div>
      <div class="step">
        <h3>See where your money goes</h3>
        <p>The unified ledger shows everything in one place: charts, filters, export,
        and the certainty that every euro is counted <strong>exactly once</strong>.</p>
      </div>
    </div>
  </div>
</section>

<hr class="divider">

<!-- ── DIFFERENTIATORS ───────────────────────────────────────────────────── -->
<hr class="divider">

<!-- ── SCHERMATE DI PRODOTTO ─────────────────────────────────────────────── -->
<section id="schermate">
  <div class="container">
    <div class="section-label">What it looks like</div>
    <h2>The product, not a mockup</h2>
    <p class="section-sub">Three screens of the running app. The data shown is sample data.</p>

    <div class="shots fade-in">
      <figure>
        <img src="/assets/screenshots/app-home-en.webp" width="1600" height="1548" loading="lazy" decoding="async"
             alt="Spendif.ai home screen: monthly income chart and income-to-expense flow diagram">
        <figcaption>Home: monthly income and the income → expense flow</figcaption>
      </figure>
      <figure>
        <img src="/assets/screenshots/app-categories-en.webp" width="1600" height="939" loading="lazy" decoding="async"
             alt="Spendif.ai analytics: expense distribution donut by category and category-subcategory treemap">
        <figcaption>Analytics: expense distribution by category, and the category → subcategory treemap</figcaption>
      </figure>
      <figure>
        <img src="/assets/screenshots/app-review-en.webp" width="1600" height="813" loading="lazy" decoding="async"
             alt="Spendif.ai correction panel: transaction picker, new category and the option to save a deterministic rule">
        <figcaption>Review: fix one transaction, apply the same fix to every identical one, or save it as a rule</figcaption>
      </figure>
    </div>
  </div>
</section>

<section id="algoritmi">
  <div class="container">
    <div class="section-label">What no one else does automatically</div>
    <h2>Algorithms that solve real problems</h2>
    <p class="section-sub">This is not a generic budgeting app. It is designed around the specific problems of people with multiple bank accounts.</p>

    <div class="diff-grid fade-in">
      <div class="diff-card">
        <div class="tag">RF-03</div>
        <h3>Credit card-current account reconciliation</h3>
        <p>When the credit card charges the monthly amount to the current account,
        Spendif.ai recognises the relationship and removes the double-counting automatically.</p>
        <p style="margin-top:.75rem; color: var(--muted); font-size:.88rem;">
          Time window ±45 days · 3 matching phases:
          sliding window → subset sum for split amounts → partial reconciliation
        </p>
      </div>
      <div class="diff-card">
        <div class="tag">RF-04</div>
        <h3>Internal transfer detection</h3>
        <p>A wire transfer from a current account to a savings account is neither an expense nor
        income: it is an internal transfer. Spendif.ai recognises it by comparing
        amounts, dates, and account holder names in the descriptions, even if the two files
        were imported at different times.</p>
      </div>
      <div class="diff-card">
        <div class="tag">Dedup</div>
        <h3>Idempotent deduplication</h3>
        <p>Every transaction has a unique ID calculated from its content (SHA-256).
        If you import the same file twice, nothing happens.
        You can re-import your entire transaction history without fear of duplicates.</p>
      </div>
      <div class="diff-card">
        <div class="tag">Categories</div>
        <h3>Cascading hybrid classification</h3>
        <p>Categorisation uses four levels in sequence:</p>
        <ul class="cascade-list">
          <li><span class="num">1</span><span><strong>Your rules</strong>: "CONAD" → Groceries (applied retroactively)</span></li>
          <li><span class="num">2</span><span><strong>Static regex</strong>: predefined patterns for common categories</span></li>
          <li><span class="num">3</span><span><strong>LLM</strong>: for everything else, local or cloud AI</span></li>
          <li><span class="num">4</span><span><strong>Fallback</strong>: "To review" if everything else fails</span></li>
        </ul>
      </div>
    </div>
  </div>
</section>

<hr class="divider">

<!-- ── PRIVACY ───────────────────────────────────────────────────────────── -->
<section id="privacy" class="privacy-section">
  <div class="container">
    <div class="section-label">Privacy</div>
    <h2>Your data stays yours. Seriously.</h2>
    <p class="section-sub">It is not just a slogan. It is the architecture.</p>

    <div class="privacy-grid fade-in">
      <div class="privacy-card">
        <div class="ico-big">🏠</div>
        <h3>Offline-first by default</h3>
        <p>Spendif.ai uses <strong>Ollama locally</strong> by default: an AI engine that runs
        on your computer, with no internet connection. Your movements files never
        leave your disk.</p>
      </div>
      <div class="privacy-card">
        <div class="ico-big">🛡️</div>
        <h3>Automatic PII redaction</h3>
        <p>If you use OpenAI or Claude, Spendif.ai automatically removes all
        identifying data before any remote call:</p>
        <div class="pii-chips">
          <span class="pii-chip">IBAN → &lt;ACCOUNT_ID&gt;</span>
          <span class="pii-chip">PAN → &lt;CARD_ID&gt;</span>
          <span class="pii-chip">Tax ID → &lt;FISCAL_ID&gt;</span>
          <span class="pii-chip">Name → fictitious alias</span>
        </div>
        <p style="margin-top:.75rem; font-size:.83rem; color:var(--muted)">
          If the check fails, the call is blocked, not silently degraded.
        </p>
      </div>
      <div class="privacy-card">
        <div class="ico-big">💾</div>
        <h3>Portable local database</h3>
        <p>Data is stored in a SQLite file on your computer. You can copy it, move it,
        back it up like any other file. No mandatory cloud,
        no account, no subscription.</p>
      </div>
    </div>
  </div>
</section>

<hr class="divider">

<!-- ── FOR WHO ───────────────────────────────────────────────────────────── -->
<section id="per-chi">
  <div class="container">
    <div class="section-label">Who Spendif.ai is for</div>
    <h2>Not for everyone. For those who want real control.</h2>
    <p class="section-sub">Four profiles that find in Spendif.ai something alternatives do not offer.</p>

    <div class="audience-grid fade-in">
      <div class="audience-card">
        <div class="ico-circle">🏦</div>
        <div>
          <h3>People with accounts at multiple banks</h3>
          <p>Current account + credit card + savings account + trading account?
          Spendif.ai unifies them all into a single ledger without having to do anything manually.</p>
        </div>
      </div>
      <div class="audience-card">
        <div class="ico-circle">📊</div>
        <div>
          <h3>People who track their finances seriously</h3>
          <p>If you use Excel for your expenses, Spendif.ai can replace that routine:
          you import the files once, Spendif.ai unifies and classifies, you review
          only the exceptions.</p>
        </div>
      </div>
      <div class="audience-card">
        <div class="ico-circle">🔐</div>
        <div>
          <h3>People who do not trust the cloud</h3>
          <p>No mandatory remote backend, no account, no registration.
          Your banking data stays where it belongs: on your computer.</p>
        </div>
      </div>
      <div class="audience-card">
        <div class="ico-circle">👨‍💻</div>
        <div>
          <h3>Developers</h3>
          <p>Python project with a public codebase, modular architecture, LLM pipeline on structured data,
          full test suite. A starting point for experimenting or
          building custom integrations.</p>
        </div>
      </div>
    </div>
  </div>
</section>

<hr class="divider">

<!-- ── FEATURES ──────────────────────────────────────────────────────────── -->
<section id="features">
  <div class="container">
    <div class="section-label">Features</div>
    <h2>Everything you need, nothing more</h2>
    <br>

    <div class="features-grid fade-in">
      <div class="feature-row">
        <span class="feature-name">Multi-bank import</span>
        <span class="feature-desc">CSV and XLSX from any bank</span>
      </div>
      <div class="feature-row">
        <span class="feature-name">Auto-detect format</span>
        <span class="feature-desc">No manual configuration for each file type</span>
      </div>
      <div class="feature-row">
        <span class="feature-name">Unified ledger</span>
        <span class="feature-desc">All transactions in chronological order, filterable by date / account / category / context</span>
      </div>
      <div class="feature-row">
        <span class="feature-name">Automatic classification</span>
        <span class="feature-desc">15 expense categories + 7 income categories with subcategories</span>
      </div>
      <div class="feature-row">
        <span class="feature-name">Customisable taxonomy</span>
        <span class="feature-desc">Add / edit categories without restarting the app</span>
      </div>
      <div class="feature-row">
        <span class="feature-name">Deterministic rules</span>
        <span class="feature-desc">"ESSELUNGA → Groceries" rules applied retroactively</span>
      </div>
      <div class="feature-row">
        <span class="feature-name">Interactive analytics</span>
        <span class="feature-desc">7 charts: monthly trend, cumulative balance, category pie, top 10 merchants</span>
      </div>
      <div class="feature-row">
        <span class="feature-name">Life contexts</span>
        <span class="feature-desc">Segment expenses by Work / Vacation / Daily life</span>
      </div>
      <div class="feature-row">
        <span class="feature-name">Check List</span>
        <span class="feature-desc">Month × account pivot table: see which months you have not imported yet</span>
      </div>
      <div class="feature-row">
        <span class="feature-name">Export</span>
        <span class="feature-desc">Standalone HTML (with charts), CSV, XLSX</span>
      </div>
      <div class="feature-row">
        <span class="feature-name">Configurable LLM</span>
        <span class="feature-desc">Ollama, OpenAI, Claude, Groq, Gemini, LM Studio, any compatible API</span>
      </div>
      <div class="feature-row">
        <span class="feature-name">PII sanitization</span>
        <span class="feature-desc">Automatic IBAN / card number / tax ID / name protection before remote calls</span>
      </div>
    </div>
  </div>
</section>

<hr class="divider">

<!-- ── INSTALL ───────────────────────────────────────────────────────────── -->
<section id="install" class="install-section">
  <div class="container">
    <div class="section-label">Installation</div>
    <h2>One command, app ready</h2>
    <p class="section-sub">Native desktop app with local AI included. No Docker, no Terminal kept open.</p>

    <p style="text-align:center;margin:1.5rem 0 2.5rem;">
      <a id="dl-primary" href="https://spendif.ai/getting-started.html" style="display:inline-block;background:var(--blue);color:#fff;padding:0.75rem 1.5rem;border-radius:8px;font-weight:600;text-decoration:none;">📥 Download installer (DMG · MSIX · .deb · .rpm)</a><br>
      <span id="dl-primary-file" style="display:block;color:var(--muted);font-size:0.8rem;margin-top:0.4rem;font-family:monospace;"></span>
      <span style="color:var(--muted);font-size:0.9rem;">Step-by-step guide with screenshots → <a href="https://spendif.ai/getting-started.html">install &amp; first launch</a></span>
    </p>

    <p style="text-align:center;color:var(--muted);margin-bottom:1.5rem;">or, from the terminal:</p>

    <div class="os-tabs">
      <button class="os-tab active" onclick="switchOS('mac')">🍎 macOS</button>
      <button class="os-tab" onclick="switchOS('deb')">🐧 Debian / Ubuntu</button>
      <button class="os-tab" onclick="switchOS('rhel')">🎩 Fedora / RHEL</button>
    </div>

    <!-- macOS -->
    <div class="os-panel active" id="panel-mac">
      <div class="code-block fade-in">
        <div class="code-header">
          <div class="code-dots">
            <span class="d1"></span><span class="d2"></span><span class="d3"></span>
          </div>
          <span class="code-label">bash</span>
          <button class="copy-btn" onclick="copyCode(this, 'mac')">Copy</button>
        </div>
        <div class="code-body">
          <div><span class="p">$ </span><span class="c">brew</span><span class="a"> tap spendifai/spendifai</span></div>
          <div><span class="p">$ </span><span class="c">brew</span><span class="a"> trust --cask spendifai/spendifai/spendifai</span></div>
          <div><span class="p">$ </span><span class="c">brew</span><span class="a"> install --cask spendifai</span></div>
        </div>
      </div>
    </div>

    <!-- Debian / Ubuntu -->
    <div class="os-panel" id="panel-deb">
      <div class="code-block fade-in">
        <div class="code-header">
          <div class="code-dots">
            <span class="d1"></span><span class="d2"></span><span class="d3"></span>
          </div>
          <span class="code-label">bash</span>
          <button class="copy-btn" onclick="copyCode(this, 'deb')">Copy</button>
        </div>
        <div class="code-body">
          <div><span class="p">$ </span><span class="c">curl</span><span class="a"> -fsSL https://raw.githubusercontent.com/spendifai/spendif-ai/main/packaging/linux/install-debian.sh | bash</span></div>
        </div>
      </div>
    </div>

    <!-- Fedora / RHEL -->
    <div class="os-panel" id="panel-rhel">
      <div class="code-block fade-in">
        <div class="code-header">
          <div class="code-dots">
            <span class="d1"></span><span class="d2"></span><span class="d3"></span>
          </div>
          <span class="code-label">bash</span>
          <button class="copy-btn" onclick="copyCode(this, 'rhel')">Copy</button>
        </div>
        <div class="code-body">
          <div><span class="p">$ </span><span class="c">curl</span><span class="a"> -fsSL https://raw.githubusercontent.com/spendifai/spendif-ai/main/packaging/linux/install-redhat.sh | bash</span></div>
        </div>
      </div>
    </div>

    <p class="install-post">
      The script detects your hardware, downloads the optimal AI model for your RAM (1-7 GB) and sets everything up: <strong>zero intervention</strong>.<br>
      The app appears in Launchpad / Start Menu / file manager, ready to use.
    </p>

    <p class="install-dev-link">
      Developer or manual install? →
      <a href="https://github.com/spendifai/spendif-ai/blob/main/docs/installazione.en.md" target="_blank" rel="noopener noreferrer">Full guide</a>
    </p>

    <!-- ── Docker (alternative) ──────────────────────────────────────── -->
    <div style="margin-top: 2.5rem; padding-top: 2rem; border-top: 1px solid var(--border);">
      <h3 style="color: var(--blue); margin-bottom: 0.5rem;">🐳 Prefer Docker?</h3>
      <p style="color: var(--muted); margin-bottom: 1.2rem;">
        Only <a href="https://www.docker.com/products/docker-desktop/" target="_blank" style="color:var(--blue)" rel="noopener noreferrer">Docker Desktop</a> required. Official container from GitHub Container Registry, browser at <strong>http://localhost:8501</strong>.
      </p>

      <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1rem;">
        <div style="background: var(--surface2); border-radius: 8px; padding: 1rem;">
          <strong style="color: var(--text);">🍎 macOS / 🐧 Linux</strong>
          <div class="code-block" style="margin-top: 0.5rem;">
            <div class="code-body" style="font-size: 0.85rem;">
              <div><span class="c">curl</span> -fsSL https://raw.githubusercontent.com/spendifai/spendif-ai/main/installer/install.sh | bash</div>
            </div>
          </div>
        </div>

        <div style="background: var(--surface2); border-radius: 8px; padding: 1rem;">
          <strong style="color: var(--text);">🪟 Windows</strong>
          <div class="code-block" style="margin-top: 0.5rem;">
            <div class="code-body" style="font-size: 0.85rem;">
              <div><span class="c">irm</span> https://raw.githubusercontent.com/spendifai/spendif-ai/main/installer/install.ps1 | iex</div>
            </div>
          </div>
        </div>
      </div>
    </div>

  </div>
</section>

<!-- ── Community / support ─────────────────────────────────────────────── -->
<div style="text-align: center; padding: 2.5rem 1rem 1rem; max-width: 760px; margin: 0 auto;">
  <p style="color: var(--muted); font-size: 0.95rem; line-height: 1.8;">
    🆘 <strong style="color: var(--text);">Need help?</strong> <a href="https://github.com/spendifai/spendif-ai/issues" target="_blank" rel="noopener noreferrer">Open an issue on GitHub</a>: bugs, questions, feature requests.<br>
    ✉️ Prefer email? Write to <a href="mailto:support@spendif.ai">support@spendif.ai</a>.<br>
    ⭐ <strong style="color: var(--text);">Like Spendif.ai?</strong> <a href="https://github.com/spendifai/spendif-ai" target="_blank" rel="noopener noreferrer">Give us a star</a>: it helps us reach the official package registries (Homebrew Core, winget).
  </p>
</div>

<hr class="divider">

<!-- FAQ (generated by scripts/gen_faq.py) -->
<section id="faq">
  <div class="container">
    <div class="section-label">FAQ</div>
    <h2>The questions I get most</h2>
    <p class="section-sub">What people ask before installing it.</p>

    <div class="faq-list fade-in">
      <details class="faq-item" open>
        <summary>My bank already does this: what is Spendif.ai for?</summary>
        <p>Your bank only sees its own accounts: a current account, a card, PayPal and Satispay are enough never to have one picture. Spendif.ai puts them together, from different banks too, and shows the period you choose on one page. The categories are yours, not the bank's: on an Amazon or PayPal purchase "shopping" says nothing. And you can give your expenses a context, home, holiday or work, which the bank does not know.</p>
      </details>
      <details class="faq-item">
        <summary>What is the best way to use it?</summary>
        <p>Four steps. Load the statements of all your accounts. Give a category to the counterparts with the most movements, at least the first 10, which usually cover most of your spending. Tick the expenses you have a receipt for, online ones too as soon as the email arrives, with date and amount. Check what is left, mostly transfers, account by account.</p>
      </details>
      <details class="faq-item">
        <summary>Does Spendif.ai connect to my bank?</summary>
        <p>No, never. No Open Banking, no PSD2, no banking password. You download the transaction file from your bank yourself, as CSV or XLSX, and drop it into the app.</p>
      </details>
      <details class="faq-item">
        <summary>Does my data leave my computer?</summary>
        <p>No. Spendif.ai keeps everything in a local SQLite database under ~/.spendifai/, and works with no connection. If you choose to use a remote LLM, IBANs and names are stripped from the descriptions before anything is sent.</p>
      </details>
      <details class="faq-item">
        <summary>What does it cost? Is it free forever?</summary>
        <p>Today Spendif.ai is free for personal use, with no subscription and no hidden costs. The source code is public and you can read it. A paid version with extra features may come later: the version you installed will keep working, and your data stays in a file on your computer that you can take with you whenever you want.</p>
      </details>
      <details class="faq-item">
        <summary>Do I need an account?</summary>
        <p>No. No email, no sign-up, no password to recover. You install the app and use it.</p>
      </details>
      <details class="faq-item">
        <summary>Which systems does it run on?</summary>
        <p>Windows, Linux, and macOS 12 Monterey or later on Apple Silicon (M1 or newer). There is no Intel Mac build.</p>
      </details>
      <details class="faq-item">
        <summary>Which banks are supported?</summary>
        <p>Any bank that lets you export transactions as CSV or XLSX. Spendif.ai detects the format on its own, and you can import files from different banks together.</p>
      </details>
      <details class="faq-item">
        <summary>What happens if I import the same file twice?</summary>
        <p>Nothing bad: transactions already in the ledger are not duplicated. You can re-import the same file as many times as you like.</p>
      </details>
      <details class="faq-item">
        <summary>Is there a phone app?</summary>
        <p>No, Spendif.ai is a desktop application. A companion app for recording cash spending only is planned, but it has no date.</p>
      </details>
    </div>
  </div>
</section>

<hr class="divider">
<!-- /FAQ -->

<!-- ── STACK ─────────────────────────────────────────────────────────────── -->
<section id="stack">
  <div class="container">
    <div class="section-label">Tech stack</div>
    <h2>Mature technologies, no exotic dependencies</h2>
    <p class="section-sub">No LLM framework (no LangChain): AI backends use the official SDKs directly.</p>

    <div class="stack-grid fade-in">
      <div class="stack-badge"><strong>Python 3.13</strong> <span>+ pandas</span></div>
      <div class="stack-badge"><strong>Streamlit</strong> <span>web interface</span></div>
      <div class="stack-badge"><strong>SQLite</strong> <span>+ SQLAlchemy</span></div>
      <div class="stack-badge"><strong>Pydantic v2</strong> <span>schema validation</span></div>
      <div class="stack-badge"><strong>Plotly</strong> <span>interactive charts</span></div>
      <div class="stack-badge"><strong>uv</strong> <span>package manager</span></div>
      <div class="stack-badge"><strong>Ollama</strong> <span>local AI</span></div>
      <div class="stack-badge"><strong>chardet</strong> <span>encoding detection</span></div>
      <div class="stack-badge"><strong>openpyxl</strong> <span>Excel parsing</span></div>
    </div>
  </div>
</section>

<hr class="divider">

<!-- ── DEVELOPER ─────────────────────────────────────────────────────────── -->
<section id="developer">
  <div class="container">
    <div class="section-label">For developers</div>
    <h2>Modular architecture, full test suite</h2>

    <div class="pipeline-box fade-in">
<span class="ph">CSV/XLSX File</span>
  <span class="ar">→</span> <span class="label">Pre-processing</span>       <span class="note">(strip sparse rows, drop metadata columns)</span>
  <span class="ar">→</span> <span class="label">Schema classifier</span>    <span class="note">(SHA-256 fingerprint → LLM if new schema)</span>
  <span class="ar">→</span> <span class="label">Normalizer</span>            <span class="note">(encoding, parse_amount Decimal, SHA-256 tx_id)</span>
  <span class="ar">→</span> <span class="label">RF-03 Reconciler</span>     <span class="note">(credit card-current account, 3 phases)</span>
  <span class="ar">→</span> <span class="label">RF-04 Detector</span>       <span class="note">(internal transfers, symbolic matching)</span>
  <span class="ar">→</span> <span class="label">Description cleaner</span>   <span class="note">(LLM: noise → canonical text)</span>
  <span class="ar">→</span> <span class="label">Categorizer</span>           <span class="note">(rules → regex → LLM → fallback)</span>
  <span class="ar">→</span> <span class="label">Database</span>              <span class="note">(SQLAlchemy, idempotent upsert)</span>
    </div>

    <br>

    <div class="contribute-grid fade-in">
      <div class="contribute-card">
        <h3>🔌 New LLM backends</h3>
        <p>Implement <code>LLMBackend</code> (3 methods) and register it in <code>BackendFactory</code>. Works with any OpenAI-compatible API.</p>
      </div>
      <div class="contribute-card">
        <h3>🏦 New bank formats</h3>
        <p>Flow 2 recognises them automatically via LLM without code changes. The schema is saved and reused in subsequent imports.</p>
      </div>
      <div class="contribute-card">
        <h3>🏷️ New categories</h3>
        <p>From the Taxonomy page, without touching the code. The taxonomy is fully configurable from the interface.</p>
      </div>
      <div class="contribute-card">
        <h3>🚀 REST API</h3>
        <p>The <code>process_file()</code> pipeline is completely separate from the UI: it can be exposed via FastAPI without changes.</p>
      </div>
    </div>

    <br>
    <div class="code-block fade-in">
      <div class="code-header">
        <div class="code-dots">
          <span class="d1"></span><span class="d2"></span><span class="d3"></span>
        </div>
        <span class="code-label">bash: test suite</span>
      </div>
      <div class="code-body">
        <div><span class="p">$ </span><span class="c">uv run pytest</span><span class="a"> tests/ -v</span>         <span class="co"># 199 tests, zero external dependencies</span></div>
        <div><span class="p">$ </span><span class="c">uv run pytest</span><span class="a"> tests/ --cov=core</span>  <span class="co"># coverage of business logic layer</span></div>
      </div>
    </div>
  </div>
</section>

<hr class="divider">

<!-- ── ROADMAP ───────────────────────────────────────────────────────────── -->
<section id="roadmap">
  <div class="container">
    <div class="section-label">Roadmap</div>
    <h2>What is coming</h2>
    <br>
    <ul class="roadmap-list fade-in">
      <li><span class="dot"></span>PDF support: native parsing of PDF movements files</li>
      <li><span class="dot"></span>Monthly budget per category with alerting</li>
      <li><span class="dot"></span>Automatic import via Open Banking (PSD2)</li>
      <li><span class="dot"></span>REST API for external integrations</li>
      <li><span class="dot"></span>Multi-user version with authentication</li>
      <li><span class="dot"></span>Mobile app: ledger and analytics viewer</li>
      <li><span class="dot"></span>Publication on <strong>Homebrew Core</strong>: install without adding the tap</li>
      <li><span class="dot"></span>Distribution via <strong>winget</strong> (Windows): <code>winget install SpendifAi.SpendifAi</code></li>
    </ul>
  </div>
</section>

<hr class="divider">

<!-- ── CONTRIBUTE ────────────────────────────────────────────────────────── -->
<section id="contribuire">
  <div class="container">
    <div class="section-label">Public source</div>
    <h2>Contributions are welcome</h2>
    <p class="section-sub">Areas where contributions are most useful:</p>

    <div class="contribute-grid fade-in">
      <div class="contribute-card">
        <h3>🏦 New bank formats</h3>
        <p>If your bank is not automatically recognised, open an issue with an anonymised CSV sample.</p>
      </div>
      <div class="contribute-card">
        <h3>🧪 UI tests</h3>
        <p>The suite covers the business logic layer but not yet the Streamlit interface. There is room to contribute.</p>
      </div>
      <div class="contribute-card">
        <h3>🌍 Internationalisation</h3>
        <p>The UI is already internationalised in five languages (IT, EN, FR, DE, ES). There is scope to add more.</p>
      </div>
      <div class="contribute-card">
        <h3>⚡ Performance</h3>
        <p>Batch categorisation is the bottleneck with a local LLM. There is room for parallelisation.</p>
      </div>
    </div>

    <br>
    <div style="text-align:center; margin-top: 1rem;">
      <a class="btn btn-primary" href="https://github.com/spendifai/spendif-ai" target="_blank" rel="noopener noreferrer">
        <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
        Go to GitHub
      </a>
    </div>
  </div>
</section>

<!-- ── FOOTER ─────────────────────────────────────────────────────────────── -->
<footer>
  <p>
    <strong>Spendif.ai</strong> has public source code under the PolyForm Noncommercial licence:
    <a href="https://github.com/spendifai/spendif-ai" target="_blank" rel="noopener noreferrer">github.com/spendifai/spendif-ai</a>
  </p>
  <p class="disclaimer">
    Spendif.ai is not a cloud service. It is a program that runs on your computer.
    Your banking data is never sent to third-party servers, unless you explicitly choose
    a remote LLM backend: in that case, all identifying data is
    removed before transmission.
  </p>
</footer>

<script>
  /* Fade-in on scroll */
  const observer = new IntersectionObserver(entries => {
    entries.forEach(e => {
      if (e.isIntersecting) {
        e.target.classList.add('visible');
        observer.unobserve(e.target);
      }
    });
  }, { threshold: 0.12 });
  document.querySelectorAll('.fade-in').forEach(el => observer.observe(el));

  /* OS tab switcher */
  function switchOS(os) {
    document.querySelectorAll('.os-tab').forEach(t => t.classList.remove('active'));
    document.querySelectorAll('.os-panel').forEach(p => p.classList.remove('active'));
    document.getElementById('panel-' + os).classList.add('active');
    event.currentTarget.classList.add('active');
  }

  /* Copy install command */
  const installCmds = {
    mac:  'brew tap spendifai/spendifai\nbrew trust --cask spendifai/spendifai/spendifai\nbrew install --cask spendifai',
    deb:  'curl -fsSL https://raw.githubusercontent.com/spendifai/spendif-ai/main/packaging/linux/install-debian.sh | bash',
    rhel: 'curl -fsSL https://raw.githubusercontent.com/spendifai/spendif-ai/main/packaging/linux/install-redhat.sh | bash'
  };
  function copyCode(btn, os) {
    navigator.clipboard.writeText(installCmds[os] || installCmds.mac).then(() => {
      btn.textContent = 'Copied ✓';
      setTimeout(() => btn.textContent = 'Copy', 2000);
    });
  }
</script>

<!-- One-click download: point the install button at the file for the visitor's
     system. Detection is local, so nothing here depends on the network; with
     JavaScript off the button keeps its href to the download page, which lists
     every system. The label stays as the page wrote it - it is translated, the
     file name is not - and the file name is shown underneath instead. -->
<script>
(function () {
  var BASE = 'https://github.com/spendifai/spendif-ai/releases/latest/download/';
  var FILE = { mac: 'SpendifAi-arm64.dmg', win: 'SpendifAi.msix', deb: 'spendifai_amd64.deb', rpm: 'spendifai.rpm', arch: 'spendifai.pkg.tar.zst' };

  var ua = navigator.userAgent || '';
  var plat = (navigator.userAgentData && navigator.userAgentData.platform) || navigator.platform || '';
  var os = null;
  if (!/Android|iPhone|iPad|iPod/i.test(ua)) {
    if (/Mac/i.test(plat) || /Mac OS X/i.test(ua)) os = 'mac';
    else if (/Win/i.test(plat) || /Windows/i.test(ua)) os = 'win';
    else if (/Linux|X11/i.test(plat + ' ' + ua)) {
      // Most browsers say nothing about the distribution. When one does,
      // use it; otherwise the .deb is the safe default it always was.
      if (/Arch|Manjaro|EndeavourOS/i.test(ua)) os = 'arch';
      else os = /Fedora|Red Hat|CentOS|Rocky|Alma|SUSE/i.test(ua) ? 'rpm' : 'deb';
    }
  }

  var btn = document.getElementById('dl-primary');
  if (!btn || !os) return;
  btn.href = BASE + FILE[os];
  var name = document.getElementById('dl-primary-file');
  if (name) name.textContent = FILE[os];
})();
</script>
</body>
</html>