diff --git a/.easignore b/.easignore new file mode 100644 index 0000000..0d4e09f --- /dev/null +++ b/.easignore @@ -0,0 +1,8 @@ +.agents/ +.claude/ +node_modules/ +server/ +greenlns-landing/ +landing/ +*.sqlite +*.sqlite-* diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..cca9329 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,307 @@ +# Universal AI Coding Agent Workflow (Codex / Gemini / Claude) + +## Workflow Orchestration + +### 1. Plan Mode Default +- Enter planning mode for ANY non-trivial task (3+ steps or architecture decisions) +- Analyze the codebase before making changes +- Break problems into clear subtasks +- Produce an implementation plan before writing code +- If assumptions are uncertain, inspect files or run tools first +- Prefer incremental progress over large rewrites + +Plan format: + +PLAN +1. Understand the task +2. Identify affected files +3. Design the implementation +4. Implement step-by-step +5. Verify results + + +--- + +# Multi-Agent Strategy + +### 2. Agent Decomposition + +Use specialized agents for complex work. + +Core roles: + +- Orchestrator Agent +- Research Agent +- Implementation Agent +- Test Agent +- Code Review Agent +- Debug Agent +- Documentation Agent + +Rules: +- One responsibility per agent +- Prefer parallel execution +- Agents should operate on independent files when possible +- The orchestrator coordinates execution + + +--- + +# Agent Responsibilities + +### Orchestrator Agent +- analyzes the user request +- creates task list +- assigns tasks to agents +- merges results + +### Research Agent +- scans repository +- searches dependencies +- analyzes architecture +- produces context summary + +### Implementation Agent +- writes code +- edits files +- follows project conventions +- implements features + +### Test Agent +- writes tests +- verifies functionality +- checks edge cases + +### Code Review Agent +- reviews diffs +- checks maintainability +- suggests improvements + +### Debug Agent +- analyzes logs +- identifies root causes +- implements fixes + +### Documentation Agent +- updates docs +- writes README sections +- explains new features + + +--- + +# Execution Pipeline + +### 3. Execution Phases + +PHASE 1 — Discovery +- explore repository +- load relevant files +- understand architecture + +PHASE 2 — Planning +- generate implementation plan +- break plan into tasks + +PHASE 3 — Task Creation + +Create tasks like: + +[ ] analyze codebase +[ ] implement feature +[ ] add tests +[ ] review code +[ ] update documentation + +PHASE 4 — Implementation +- execute tasks sequentially or in parallel +- commit progress + +PHASE 5 — Verification +- run tests +- check logs +- verify feature works + +PHASE 6 — Review +- review code quality +- refactor if necessary + +PHASE 7 — Documentation +- document changes + + +--- + +# Verification System + +### 4. Verification Before Done + +Never mark a task complete without proof. + +Checks: +- code compiles +- feature works +- tests pass +- no new errors introduced + +Ask: + +"Would a senior engineer approve this implementation?" + + +--- + +# Autonomous Debugging + +### 5. Autonomous Bug Fixing + +When encountering a bug: + +1. analyze error message +2. inspect stack trace +3. identify root cause +4. implement fix +5. verify with tests + +Rules: +- Never apply random fixes +- Always understand the root cause first + + +--- + +# Context Management + +### 6. Context Awareness + +Before implementing anything: + +- load relevant files +- inspect dependencies +- understand architecture +- read configuration files + +Always maintain awareness of: + +- system architecture +- data flow +- dependencies + + +--- + +# Memory System + +### 7. Persistent Memory + +Store long-term knowledge in: + +memory/ +- project_summary.md +- architecture.md +- lessons.md +- coding_standards.md + +This prevents repeated mistakes. + + +--- + +# Learning Loop + +### 8. Self-Improvement + +After errors or corrections: + +Update: + +tasks/lessons.md + +Include: +- mistake pattern +- root cause +- prevention rule + +Example: + +Lesson: +Always validate API responses before processing them. + + +--- + +# Safety Rules + +### 9. Safety + +Never perform dangerous actions automatically. + +Rules: + +- never delete files without confirmation +- avoid modifying production configuration automatically +- create backups before large refactors +- avoid irreversible operations + + +--- + +# Iteration Control + +### 10. Infinite Loop Protection + +If the same error happens more than 3 times: + +STOP + +- re-evaluate the strategy +- re-plan the solution +- choose a different debugging approach + + +--- + +# Core Engineering Principles + +### Simplicity First +Prefer the simplest solution that works. + +### Root Cause Fixes +Always fix the underlying problem, not symptoms. + +### Minimal Impact +Touch the smallest amount of code possible. + +### Maintainability +Code should remain readable and maintainable. + + +--- + +# Final Rule + +Before delivering a solution ask: + +Is this solution correct, maintainable, and verifiable? + +If not: + +Refine it before presenting it. + + +--- + +# Recommended File Usage + +You can place this workflow in one of the following files: + +AGENT_WORKFLOW.md +CLAUDE.md +AGENTS.md + +This allows it to be used by: + +- Claude Code Agent Teams +- Codex CLI +- Gemini Code Assist +- Cursor Agents \ No newline at end of file diff --git a/AKTUELLE_PFLANZEN.md b/AKTUELLE_PFLANZEN.md new file mode 100644 index 0000000..317243c --- /dev/null +++ b/AKTUELLE_PFLANZEN.md @@ -0,0 +1,588 @@ +# GreenLens — Launch Strategy + +*Last updated: 2026-03-01* + +--- + +## Überblick + +GreenLens ist eine B2C Mobile App (iOS & Android) mit Freemium-Modell. Ziel: maximale Download-Zahlen, schnelle Aktivierung, Conversion zu GreenLens Pro. + +**Launch-Ziel:** App Store Präsenz aufbauen → Early Adopter-Community wachsen lassen → viralen Loop durch "Shazam für Pflanzen"-Effekt auslösen. + +--- + +## Phase 1: Soft Launch (jetzt) + +**Ziel:** Erste echte Nutzer, erster Feedback-Loop, App Store Rating aufbauen. + +### Aktionen + +- [ ] App Store Listing optimieren: klare Tagline, Screenshots mit Scan-Demo, kurzes Preview-Video +- [ ] Google Play Listing parallel aufsetzen +- [ ] Friends & Family + Pflanzen-Enthusiasten aus dem persönlichen Netzwerk einladen +- [ ] Feedback aktiv einsammeln: Was klappt nicht? Was fehlt? +- [ ] Ziel: 10–20 ehrliche App Store Reviews als Social Proof-Fundament + +### Owned Channel aufbauen + +- **E-Mail-Liste** starten — In-App Opt-in: "Neuigkeiten & Pflanzen-Tipps" +- Einfache Landing Page mit E-Mail Capture: greenlns.app (oder Subdomain) + +--- + +## Phase 2: Beta Launch (Monat 1–2) + +**Ziel:** Buzz erzeugen, Warteliste aufbauen, erste Presse/Creator-Erwähnungen sichern. + +### Owned Channels + +- **Blog / Content:** 2–3 SEO-Artikel zu Top-Suchintentionen: + - "Welche Pflanze ist das?" → Scan-Feature demonstrieren + - "Pflanze geht ein — was tun?" → Health Diagnosis Feature + - "Monstera pflegen" → Personalized Care Plan Feature +- **E-Mail:** Wöchentlicher "Pflanzen-Tipp" an Liste → niedrige Hürde für Signup + +### Rented Channels (1–2 Fokus-Plattformen) + +**Instagram / TikTok** (primär): +- Format: Vorher/Nachher-Videos — "Meine Pflanze stirbt" → Scan → Diagnose → Rettung +- Format: "Rate the plant" — Community errät Pflanzennamen, App gibt Auflösung +- Jeder Post endet mit CTA: Link in Bio → App Store + +**Reddit** (sekundär): +- Aktiv in r/houseplants, r/plantclinic, r/IndoorGarden +- Wert zuerst liefern (Pflanzenfragen beantworten), dann App organisch erwähnen +- Kein Spam — Community zuerst + +### Borrowed Channels + +| Zielgruppe | Kanal | Ansatz | +|------------|-------|--------| +| Pflanzen-YouTuber (DE) | YouTube | Kostenloses Pro-Abo + persönliche Nachricht; kein bezahlter Deal | +| Plant-Influencer Instagram | Instagram | Micro-Influencer (10k–100k), nischig, hohe Engagement-Rate | +| Garten-/Pflanzenpodcasts | Podcasts | Pitch: "Wir lösen das Problem X für eure Hörer" | +| Pflanzen-Newsletter | Newsletter | Sponsored Feature oder Co-Marketing | + +**Outreach-Vorlage:** +> "Hey [Name], ich bin Gründer von GreenLens — einer App, die Pflanzen per KI in Sekunden identifiziert und personalisierte Pflegepläne erstellt. Ich schicke dir gerne einen Pro-Zugang, einfach um zu sehen ob du's nützlich findest. Kein Deal, kein Druck." + +--- + +## Phase 3: Full Launch — Product Hunt (Monat 2–3) + +**Ziel:** Tech Early Adopters erreichen, Credibility-Boost, Backlinks, internationale Sichtbarkeit. + +### Vorbereitung (4 Wochen vorher) + +- [ ] Product Hunt Profil anlegen und aktiv werden (kommentieren, voten) +- [ ] Listing vorbereiten: + - **Tagline:** "Scan any plant. Get instant ID + personalized care plan." + - **Kurzbeschreibung:** Das Shazam für Pflanzen — powered by Botanical Intelligence + - Screenshots: Hero-Screen, Scan-Flow, Health Diagnosis, My Garden + - Demo-Video: 60 Sekunden, zeigt kompletten Scan-bis-Pflege-Flow +- [ ] Hunter suchen — jemanden mit Reichweite auf Product Hunt +- [ ] Unterstützer mobilisieren: bestehende E-Mail-Liste, Freunde, Investoren + +### Launch Day + +- [ ] Um 00:01 PST live schalten +- [ ] Ganztägig alle Kommentare beantworten (in Englisch) +- [ ] Announcement-E-Mail an gesamte Liste senden +- [ ] Social Posts auf allen Kanälen +- [ ] Team bereit für Support und Engagement + +### Launch Day E-Mail + +**Betreff:** "Wir sind live auf Product Hunt 🌿" + +> Hey [Name], +> +> Heute ist der Tag — GreenLens ist live auf Product Hunt! +> +> Wenn dir die App gefällt, würde ein Upvote und ein Kommentar wirklich helfen. Es dauert 30 Sekunden: +> +> [Zum Product Hunt Listing →] +> +> Danke, dass du von Anfang an dabei warst. +> +> — [Gründer Name] + +--- + +## Phase 4: Post-Launch Momentum (Monat 3+) + +### Sofortmaßnahmen nach Launch + +- [ ] Onboarding-E-Mail-Sequenz aktivieren (→ `/email-sequence` Skill nutzen) +- [ ] App Store Reviews aktiv einsammeln: In-App-Prompt nach erstem erfolgreichen Scan +- [ ] Vergleichsseiten erstellen: "GreenLens vs PictureThis", "GreenLens vs PlantNet" +- [ ] Launch in nächstem E-Mail-Roundup erwähnen + +### Laufende Launch-Momente (alle 4–6 Wochen) + +Jedes neue Feature ist ein eigener Mini-Launch: + +| Update-Typ | Marketing-Aufwand | +|------------|------------------| +| Neues Major Feature (z.B. Offline-Modus) | E-Mail + Social + In-App + Blog | +| Neue Pflanzenarten im Katalog | Social Post + Changelog | +| UI-Verbesserung | In-App-Banner | +| Bug Fix | Changelog (signalisiert aktive Entwicklung) | + +--- + +## ORB-Kanal-Übersicht für GreenLens + +### Owned (aufbauen, Priorität 1) +| Kanal | Zweck | Ziel | +|-------|-------|------| +| E-Mail-Liste | Direkter Draht zu Nutzern | 1.000 Subscriber in Monat 3 | +| Blog (SEO) | Organischer Traffic via Pflanzenfragen | 5k Visits/Monat in Monat 6 | + +### Rented (nutzen, nicht abhängig sein) +| Kanal | Format | Ziel | +|-------|--------|------| +| Instagram / TikTok | Scan-Videos, Pflanzen-Content | 5k Follower in Monat 6 | +| Reddit | Community-Wert, organische Erwähnungen | Laufend | +| App Store / Play Store | ASO-optimiertes Listing | Top 10 in "Plant" Kategorie | + +### Borrowed (aktiv angehen) +| Kanal | Kontakt-Ziel | Timeline | +|-------|-------------|----------| +| 3–5 DE Plant-YouTuber | Pro-Zugang + persönliche Nachricht | Monat 1 | +| 10 Micro-Influencer Instagram | Kooperation oder Affiliate | Monat 2 | +| 2–3 Garten-Podcasts | Interview-Pitch | Monat 2–3 | + +--- + +## Viraler Loop + +Das Kernprodukt hat natürliches Sharing-Potenzial: + +``` +Nutzer scannt Pflanze → beeindruckendes Ergebnis → +Screenshot/Video teilt sich leicht → +"Was ist das für eine App?" → neuer Download +``` + +**Fördern durch:** +- Share-Button direkt nach dem Scan-Ergebnis ("Zeig deinen Freunden, was das ist") +- "My Garden" shareable machen — schöner Export/Share-Screen +- Refer-a-Friend: 1 Monat Pro gratis für jeden eingeladenen Nutzer der sich anmeldet + +--- + +## Launch Checklist + +### Pre-Launch +- [ ] App Store & Play Store Listing optimiert (Screenshots, Video, Beschreibung) +- [ ] Landing Page mit E-Mail Capture live +- [ ] E-Mail-Liste gestartet +- [ ] Instagram/TikTok Profil aktiv +- [ ] 5 Outreach-E-Mails an Plant-Creator raus +- [ ] Product Hunt Listing vorbereitet +- [ ] Analytics/Tracking in der App aktiv (Onboarding-Funnel, Scan-Events) + +### Launch Day +- [ ] Product Hunt live +- [ ] Announcement E-Mail an Liste +- [ ] Social Posts +- [ ] Team verfügbar für Comments & Support + +### Post-Launch +- [ ] Onboarding-E-Mail-Sequenz läuft +- [ ] In-App Review-Prompt nach erstem Scan +- [ ] Vergleichsseiten live +- [ ] Nächster Feature-Launch geplant + +--- + +## Metriken + +| Metric | Ziel Monat 1 | Ziel Monat 3 | Ziel Monat 6 | +|--------|-------------|-------------|-------------| +| App Downloads | 500 | 5.000 | 25.000 | +| E-Mail-Liste | 200 | 1.000 | 5.000 | +| App Store Rating | 4.0+ | 4.3+ | 4.5+ | +| Pro Conversion | — | 3–5% | 5–8% | +| Product Hunt | — | Launch geplant | Ergebnis | + +--- + +--- + +# GreenLens — Onboarding E-Mail-Sequenz + +*Ziel: Nutzer von erstem Download bis zum Pro-Upgrade aktivieren.* + +--- + +## Sequenz-Übersicht + +| # | Timing | Ziel | Typ | +|---|--------|------|-----| +| 1 | Sofort nach Signup | Willkommen + ersten Scan triggern | Aktivierung | +| 2 | Tag 1 (kein Scan) | Erinnerung + Hemmschwelle senken | Aktivierung | +| 3 | Tag 3 | "My Garden" Feature einführen | Feature-Education | +| 4 | Tag 7 | Health Diagnosis vorstellen | Feature-Education | +| 5 | Tag 10 | Social Proof + Pro-Teaser | Conversion-Vorbereitung | +| 6 | Tag 14 | Pro-Upgrade Angebot | Conversion | +| 7 | Tag 21 (kein Upgrade) | Letzter Pro-Nudge + Wert-Recap | Conversion | +| 8 | Tag 30 (inaktiv) | Re-Engagement | Retention | + +--- + +## E-Mail 1 — Willkommen (Sofort nach Signup) + +**Betreff:** "Willkommen im Urban Jungle 🌿" +**Von:** [Gründer Vorname] von GreenLens + +> Hey [Name], +> +> schön, dass du dabei bist! +> +> GreenLens wurde gebaut für alle, die ihre Pflanzen lieben — aber manchmal nicht wissen, was ihnen fehlt. Das ändert sich jetzt. +> +> **Dein erster Schritt:** +> Fotografiere eine Pflanze in deiner Nähe. Irgendeine. Schau was passiert. +> +> [Jetzt erste Pflanze scannen →] +> +> Über 20.000 Arten erkannt — in unter einer Sekunde. +> +> Viel Spaß, +> [Name] +> GreenLens + +**Technische Details:** +- Trigger: E-Mail-Signup oder App-Download +- Ziel-Aktion: Erster Scan +- Ton: Warm, persönlich, keine Feature-Liste + +--- + +## E-Mail 2 — Erinnerung Tag 1 (nur wenn kein Scan) + +**Betreff:** "Hast du schon eine Pflanze in der Nähe? 🪴" + +> Hey [Name], +> +> gestern hast du dich bei GreenLens angemeldet — aber noch keine Pflanze gescannt. +> +> Kein Druck. Aber falls du kurz in der Nähe einer Pflanze bist: +> +> Öffne die App → Kamera → Tippen. Das war's. +> +> Du musst nichts wissen. Die App sagt dir alles. +> +> [App öffnen →] +> +> [Name] + +**Hinweis:** Nur senden wenn Event `first_scan_completed = false`. Nicht senden wenn bereits gescannt. + +--- + +## E-Mail 3 — "My Garden" einführen (Tag 3) + +**Betreff:** "Bau dir deinen digitalen Pflanzengarten" + +> Hey [Name], +> +> hast du gewusst, dass du nach jedem Scan deine Pflanze zu "Mein Garten" hinzufügen kannst? +> +> Das gibt dir: +> - Persönliche Gießerinnerungen für jede Pflanze +> - Pflege-History auf einen Blick +> - Fotos & Notizen an einem Ort +> +> Dein Urban Jungle, komplett organisiert. +> +> [Pflanze zu Mein Garten hinzufügen →] +> +> [Name] + +--- + +## E-Mail 4 — Health Diagnosis vorstellen (Tag 7) + +**Betreff:** "Warum werden die Blätter braun? 🍂" + +> Hey [Name], +> +> braune Blattspitzen, hängende Blätter, gelbe Flecken — fast jeder Pflanzenbesitzer kennt das. Und die meiste Zeit weiß man einfach nicht warum. +> +> GreenLens erkennt das sofort: +> +> **Zu wenig Wasser** → Monstera mit braunen Spitzen → Erholung in 2 Tagen +> **Zu viel Wasser** → Alocasia mit hängenden Blättern → Wurzeln gerettet +> **Schädlinge** → Ficus mit Spinnmilben → Behandlung nach 1 Scan +> +> Einfach die kranke Pflanze fotografieren. Die App sagt dir was fehlt — und was zu tun ist. +> +> [Pflanze jetzt diagnostizieren →] +> +> [Name] + +--- + +## E-Mail 5 — Social Proof + Pro-Teaser (Tag 10) + +**Betreff:** "Was andere Urban Jungle Fans sagen 🌱" + +> Hey [Name], +> +> hier ein paar Dinge, die uns Nutzer in letzter Zeit geschrieben haben: +> +> *"Es ist wie Shazam, aber für Pflanzen."* +> *"Endlich weiß ich was meine Pflanzen alle heißen."* +> *"Hat mir in Sekunden gesagt was mit meiner Monstera nicht stimmt."* +> +> Wir arbeiten gerade an Features, die GreenLens noch besser machen: +> - Pflegehistorie über mehrere Monate +> - Synchronisation deiner Sammlung über alle Geräte +> - Unbegrenzte Diagnosen ohne Limit +> +> Das alles kommt mit **GreenLens Pro** — dazu mehr in ein paar Tagen. +> +> [Name] + +--- + +## E-Mail 6 — Pro-Upgrade Angebot (Tag 14) + +**Betreff:** "Dein Urban Jungle verdient mehr 🌿" + +> Hey [Name], +> +> du nutzt GreenLens jetzt seit zwei Wochen. Zeit für ein ehrliches Angebot. +> +> **GreenLens Pro** gibt dir: +> +> ✓ Vollständige Pflegehistorie für jede Pflanze +> ✓ Geräteübergreifende Synchronisation deiner Sammlung +> ✓ Unbegrenzte Health-Diagnosen +> ✓ Erweiterte Standort-Pflegetipps +> ✓ Kein Limit bei Scans +> +> Als Early User bekommst du **30% Rabatt im ersten Monat** — automatisch angewandt. +> +> [GreenLens Pro holen →] +> +> Das Angebot gilt 7 Tage. +> +> [Name] + +**Technische Details:** +- Nur senden wenn `pro_subscriber = false` +- Discount-Code oder In-App Deeplink mit Auto-Apply +- Ablaufdatum im E-Mail explizit nennen + +--- + +## E-Mail 7 — Letzter Pro-Nudge (Tag 21, kein Upgrade) + +**Betreff:** "Letzte Chance: 30% Rabatt läuft heute ab" + +> Hey [Name], +> +> kurze Erinnerung — dein Early-User-Rabatt auf GreenLens Pro läuft heute ab. +> +> Falls du dir noch unsicher bist: Du kannst jederzeit kündigen, keine langen Laufzeiten. +> +> Was du bekommst: alle Pro-Features, Pflegehistorie, unbegrenzte Diagnosen. +> Was du riskierst: nichts. +> +> [Jetzt Pro holen — 30% Rabatt →] +> +> Nach heute gilt der normale Preis. +> +> [Name] + +--- + +## E-Mail 8 — Re-Engagement (Tag 30, inaktiv) + +**Betreff:** "Deine Pflanzen vermissen dich 🌿" + +> Hey [Name], +> +> du warst eine Weile nicht in GreenLens. Alles okay mit deinem Urban Jungle? +> +> Falls du Fragen hast, oder etwas nicht funktioniert hat — antworte einfach auf diese E-Mail. Wir lesen alles. +> +> Ansonsten: Schau kurz rein. Vielleicht hat eine deiner Pflanzen gerade genau jetzt Pflege nötig. +> +> [App öffnen →] +> +> [Name] + +--- + +## Sequenz-Regeln + +| Regel | Detail | +|-------|--------| +| Sende-Frequenz | Max. 2 E-Mails pro Woche | +| Stopp-Bedingung | Pro-Upgrade → Sequenz pausieren, in Pro-Onboarding wechseln | +| Personalisierung | [Name] überall; idealerweise Pflanzenname aus erstem Scan | +| Ton | Immer von einer echten Person (Gründer), kein Corporate-Speak | +| Unsubscribe | Immer sichtbar — respektiere die Entscheidung | + +--- + +--- + +# GreenLens — Landing Page CRO + +*Ziel: Besucher der Landing Page zu App-Downloads konvertieren.* + +--- + +## Aktuelle Seiten-Struktur & Optimierungen + +### Hero Section + +**Aktuell:** "Your Urban Jungle, perfectly cared for" + +**Optimierungsempfehlungen:** + +Teste diese drei Varianten gegeneinander (A/B-Test): + +| Variante | Headline | Rationale | +|----------|----------|-----------| +| A (aktuell) | "Your Urban Jungle, perfectly cared for" | Aspirational, Identity-based | +| B | "Scan any plant. Know exactly how to care for it." | Funktional, Problem-Solution | +| C | "Why is my plant dying? Find out in 1 second." | Pain-first, Search-Intent-Match | + +**Variante C** dürfte am stärksten konvertieren für kalten Traffic — trifft den emotionalen Schmerzpunkt direkt. + +**Subheadline verbessern:** +Aktuell: *"Scan any plant, get instant identification and personalized care plans – powered by AI."* + +Besser: *"Point your camera at any plant — GreenLens tells you exactly what it is and how to keep it alive. Free on iOS & Android."* + +Warum: Konkreteres "point your camera" erzeugt mentales Bild; "keep it alive" trifft den eigentlichen JTBD. + +**CTA Button:** +- Primär: "Download kostenlos" oder "Jetzt gratis laden" (Freemium betonen, Hürde senken) +- Sekundär: "App ansehen" → Demo-Video oder Screenshot-Slider + +**Above the fold checklist:** +- [ ] App Store + Google Play Badges sichtbar (nicht nur ein CTA-Button) +- [ ] "Kostenlos" / "Free" explizit in oder unter dem CTA +- [ ] Eine Zeile Social Proof: "Über [X] Pflanzen bereits identifiziert" oder "4.8★ im App Store" +- [ ] Kein Autoplay-Video (mobile) + +--- + +### Problem-Agitation Section + +**Empfehlung: Vor dem Feature-Abschnitt eine explizite Problem-Section einfügen.** + +``` +Headline: "Kenn das Gefühl?" + +• "Ich hab keine Ahnung was das für eine Pflanze ist." +• "Meine Pflanze geht ein und ich weiß nicht warum." +• "Ich vergesse immer zu gießen." +• "Google gibt mir 10 verschiedene Antworten." + +→ GreenLens löst das. In einer Sekunde. +``` + +Warum: Besucher müssen sich erstmal erkannt fühlen, bevor Features relevant werden. + +--- + +### Features Section + +**Aktuell:** "Everything your Urban Jungle needs" + +**Verbesserungen:** + +Jedes Feature als Nutzen formulieren, nicht als Funktion: + +| Aktuell (Funktion) | Besser (Nutzen) | +|---------------------|-----------------| +| "AI Plant Identification" | "Sag nie wieder 'keine Ahnung was das ist'" | +| "Smart Reminders" | "Vergiss nie wieder zu gießen" | +| "Health Diagnosis" | "Stopp das Raten — wissen warum deine Pflanze leidet" | +| "20,000+ species" | "Egal welche Pflanze — GreenLens kennt sie" | + +**Feature-Demo:** Für jedes Feature einen animierten GIF oder kurzen Screen-Recording einbauen. Besucher müssen das Produkt "fühlen" können ohne es zu downloaden. + +--- + +### Social Proof Section + +**Was fehlt (aktuell noch kein echter Social Proof):** + +Sobald erste Reviews vorhanden: + +- App Store Rating prominent zeigen (Sterne + Anzahl Reviews) +- 2–3 kurze Nutzer-Zitate, spezifisch und real: + - ❌ "Super App, sehr empfehlenswert!" (generisch, wirkt fake) + - ✅ "Hab endlich rausgefunden dass meine Monstera zu viel Wasser bekommt. Blätter sind schon wieder grün." — Anna K., München +- "X Pflanzen bereits gescannt" als Live-Counter oder statische Zahl + +--- + +### How It Works Section + +**Aktuell:** 4-Schritt-Prozess — gut. Folgende Anpassungen: + +- Schritt 1–2 visuell betonen (das ist der "Magic Moment") +- Unter Schritt 4 direkt CTA platzieren — nicht erst nach dem nächsten Abschnitt +- Mobile: Steps als swipeable Carousel (nicht als langer Scroll) + +--- + +### FAQ Section + +**Bestehende FAQs sind gut. Ergänzen:** + +| Frage | Antwort | +|-------|---------| +| "Muss ich mich registrieren?" | "Nein — einfach App laden und sofort scannen. Konto optional." | +| "Was kostet Pro?" | Konkreten Preis nennen — Unklarheit über Kosten ist Conversion-Killer | +| "Funktioniert es bei Pflanzen im Freien / Gartenblumen?" | "Ja — über 20.000 Arten inkl. Gartenpflanzen, Kräuter, Gemüse, Bäume." | + +--- + +### CTA Section (Bottom) + +**Aktuell:** "Join the Jungle" — gut, passt zur Brand. + +**Optimierungen:** +- Konkrete Zahl einfügen: "Schließ dich [X] Pflanzenliebhabern an" +- Beide Store-Badges nebeneinander, groß +- Unter den Badges: "Kostenlos · Keine Kreditkarte · Sofort loslegen" +- Optional: QR-Code für Desktop-Besucher die auf Mobile downloaden wollen + +--- + +## Technische CRO-Basics + +| Punkt | Status | Empfehlung | +|-------|--------|-----------| +| Page Speed | Prüfen | Ziel: <2,5s LCP auf Mobile | +| Mobile-First | Pflicht | 70%+ Traffic kommt von Mobile | +| App Store Badge Links | Pflicht | UTM-Parameter für Attribution | +| Analytics | Einrichten | Scroll-Depth, CTA-Klicks, Store-Badge-Klicks tracken | +| Heatmap | Empfohlen | Hotjar / Microsoft Clarity (kostenlos) | + +--- + +## Priorisierte Maßnahmen + +| Priorität | Maßnahme | Aufwand | Impact | +|-----------|----------|---------|--------| +| 1 | Headline A/B-Test (Variante C) | Niedrig | Hoch | +| 2 | "Kostenlos" explizit in CTA | Minimal | Hoch | +| 3 | Problem-Section vor Features einfügen | Niedrig | Hoch | +| 4 | Features als Nutzen formulieren | Niedrig | Mittel | +| 5 | Social Proof Section aufbauen (sobald Reviews da) | Mittel | Hoch | +| 6 | App Store Badges + QR-Code prominent | Niedrig | Mittel | +| 7 | Feature-GIFs / Screen-Recordings | Mittel | Mittel | diff --git a/ALLE_PFLANZEN.md b/ALLE_PFLANZEN.md new file mode 100644 index 0000000..aaba4c8 --- /dev/null +++ b/ALLE_PFLANZEN.md @@ -0,0 +1,483 @@ +# Alle vorhandenen Pflanzen + +Erstellt am: 2026-03-11 +Gesamtzahl: 240 + +- Aasblume (Stapelia grandiflora) - /plants/stapelia-grandiflora--aasblume--b87af483.webp +- Adromischus (Adromischus cristatus) - /plants/adromischus-cristatus--adromischus--9b24b9fc.webp +- Afrikanisches Veilchen (Saintpaulia ionantha) - /plants/saintpaulia-ionantha--afrikanisches-veilchen--bc75f4a8.webp +- Agave (Agave americana) - /plants/agave-americana--agave--3b197a68.webp +- Aglaoneme (Aglaonema commutatum) - /plants/aglaonema-commutatum--aglaoneme--7928abe4.webp +- Aloe Vera (Aloe vera) - /plants/aloe-vera--206a00f6.webp +- Alpenveilchen (Cyclamen persicum) - /plants/cyclamen-persicum--alpenveilchen--42e9e354.webp +- Amazona-Taro (Alocasia amazonica) - /plants/alocasia-amazonica--amazona-taro--e1c87d71.webp +- Arnika (Arnica montana) - /plants/arnica-montana--arnika--285e6ea8.webp +- Aubergine (Solanum melongena) - /plants/solanum-melongena--aubergine--5f3bad2f.webp +- Baldrian (Valeriana officinalis) - /plants/valeriana-officinalis--baldrian--7bc7a2ae.webp +- Bambusrohr (Bambusa vulgaris) - /plants/bambusa-vulgaris--bambusrohr--620e47a2.webp +- Bananenpflanze (Musa acuminata) - /plants/musa-acuminata--bananenpflanze--0a6a2ad8.webp +- Basilikum (Ocimum basilicum) - /plants/ocimum-basilicum--basilikum--cdc33445.webp +- Bergpalme (Chamaedorea elegans) - /plants/chamaedorea-elegans--bergpalme--05a6cf35.webp +- Billbergia (Billbergia nutans) - /plants/billbergia-nutans--billbergia--a659ab7f.webp +- Birkenfeige (Ficus benjamina) - /plants/ficus-benjamina--birkenfeige--399b661c.webp +- Blauer Kreuzkraut (Senecio serpens) - /plants/senecio-serpens--blauer-kreuzkraut--4ec1f347.webp +- Blaues Kanaelfarn (Phlebodium aureum) - /plants/phlebodium-aureum--blaues-kanaelfarn--a630296a.webp +- Bleistiftkaktus (Euphorbia tirucalli) - /plants/euphorbia-tirucalli--bleistiftkaktus--2760cacf.webp +- Bleiwurz (Plumbago auriculata) - /plants/plumbago-auriculata--bleiwurz--a1ea78f5.webp +- Blumenschilfrohr (Canna indica) - /plants/canna-indica--blumenschilfrohr--adfa9705.webp +- Blutroter Storchschnabel (Geranium sanguineum) - /plants/geranium-sanguineum--blutroter-storchschnabel--9d8300fb.webp +- Bogenhanf (Sansevieria trifasciata) - /plants/sansevieria-trifasciata--bogenhanf--4ba42e15.webp +- Bonsai-Feige (Ficus retusa) - /plants/ficus-retusa--bonsai-feige--dff4fbd3.webp +- Bougainvillea (Bougainvillea spectabilis) - /plants/bougainvillea-spectabilis--bougainvillea--0d84eedd.webp +- Brutblatt (Kalanchoe daigremontiana) - /plants/kalanchoe-daigremontiana--brutblatt--5b643bf7.webp +- Buntblatt (Caladium bicolor) - /plants/caladium-bicolor--buntblatt--d052df1e.webp +- Calibrachoa (Calibrachoa hybrida) - /plants/calibrachoa-hybrida--calibrachoa--18b44d0e.webp +- Calla (Zantedeschia aethiopica) - /plants/zantedeschia-aethiopica--calla--c739da85.webp +- Callisia (Callisia repens) - /plants/callisia-repens--callisia--65401a5e.webp +- Cattleya-Orchidee (Cattleya labiata) - /plants/cattleya-labiata--cattleya-orchidee--91962802.webp +- Chili (Capsicum annuum) - /plants/capsicum-annuum--chili--dabf0f0e.webp +- Chinesische Faecherpalme (Livistona chinensis) - /plants/livistona-chinensis--chinesische-facherpalme--773e43a2.webp +- Chinesische Rose (Rosa chinensis) - /plants/rosa-chinensis--chinesische-rose--2c0514b0.webp +- Chinesischer Blauregen (Wisteria sinensis) - /plants/wisteria-sinensis--chinesischer-blauregen--8887793e.webp +- Christusdorn (Euphorbia milii) - /plants/euphorbia-milii--christusdorn--f647812e.webp +- Chrysantheme (Chrysanthemum indicum) - /plants/chrysanthemum-indicum--chrysantheme--f3f1b7ad.webp +- Columnea (Columnea gloriosa) - /plants/columnea-gloriosa--columnea--3fd247d6.webp +- Cryptanthus (Cryptanthus bivittatus) - /plants/cryptanthus-bivittatus--cryptanthus--0300865d.webp +- Ctenanthe (Ctenanthe burle-marxii) - /plants/ctenanthe-burle-marxii--ctenanthe--aaacfef1.webp +- Dahlie (Dahlia pinnata) - /plants/dahlia-pinnata--dahlie--34a69e35.webp +- Dendrobium (Dendrobium nobile) - /plants/dendrobium-nobile--dendrobium--a29be123.webp +- Dieffenbachie (Dieffenbachia seguine) - /plants/dieffenbachia-seguine--dieffenbachie--755822dd.webp +- Dischidia (Dischidia ruscifolia) - /plants/dischidia-ruscifolia--dischidia--962061db.webp +- Drachenbaum (Dracaena marginata) - /plants/dracaena-marginata--drachenbaum--ae46a13c.webp +- Drehfrucht (Streptocarpus hybridus) - /plants/streptocarpus-hybridus--drehfrucht--d30e3476.webp +- Dudleya (Dudleya brittonii) - /plants/dudleya-brittonii--dudleya--be6042d1.webp +- Duftsteinrich (Lobularia maritima) - /plants/lobularia-maritima--duftsteinrich--309e832f.webp +- Echeverie (Echeveria elegans) - /plants/echeveria-elegans--echeverie--71f5556f.webp +- Echter Lavendel (Lavandula angustifolia) - /plants/lavandula-angustifolia--echter-lavendel--cfd090c5.webp +- Efeu (Hedera helix) - /plants/hedera-helix--efeu--cebdfbf1.webp +- Efeu-Geranie (Pelargonium peltatum) - /plants/pelargonium-peltatum--efeu-geranie--8cd609cc.webp +- Efeutute (Epipremnum aureum) - /plants/epipremnum-aureum--efeutute--29871648.webp +- Einblatt (Spathiphyllum wallisii) - /plants/spathiphyllum-wallisii--einblatt--6ff28539.webp +- Erdbeere (Fragaria ananassa) - /plants/fragaria-ananassa--erdbeere--4a97a911.webp +- Eselschwanz (Sedum morganianum) - /plants/sedum-morganianum--eselschwanz--f6256abc.webp +- Faecherahorn (Acer palmatum) - /plants/acer-palmatum--faecherahorn--388b6858.webp +- Fass-Kaktus (Ferocactus cylindraceus) - /plants/ferocactus-cylindraceus--fass-kaktus--ef5c90b1.webp +- Fatsia (Fatsia japonica) - /plants/fatsia-japonica--fatsia--425270ac.webp +- Fettkraut (Pinguicula grandiflora) - /plants/pinguicula-grandiflora--fettkraut--8ec9dead.webp +- Flamingoblume (Anthurium andraeanum) - /plants/anthurium-andraeanum--flamingoblume--2087000b.webp +- Flammen-Bromelie (Vriesea splendens) - /plants/vriesea-splendens--flammen-bromelie--debc6faa.webp +- Fleissiges Lieschen (Impatiens walleriana) - /plants/impatiens-walleriana--fleissiges-lieschen--5816f930.webp +- Forellen-Begonie (Begonia maculata) - /plants/begonia-maculata--forellen-begonie--5cce47c8.webp +- Frauenhaarfarn (Adiantum raddianum) - /plants/adiantum-raddianum--frauenhaarfarn--d47cef0b.webp +- Fuchsie (Fuchsia hybrida) - /plants/fuchsia-hybrida--fuchsie--93ef43c2.webp +- Gardenie (Gardenia jasminoides) - /plants/gardenia-jasminoides--gardenie--f8284265.webp +- Gasteria (Gasteria carinata) - /plants/gasteria-carinata--gasteria--b27de8c8.webp +- Gebet-Pflanze (Maranta leuconeura) - /plants/maranta-leuconeura--gebet-pflanze--e50f6916.webp +- Geigenfeige (Ficus lyrata) - /plants/ficus-lyrata--geigenfeige--c025bb04.webp +- Geisterpflanze (Graptopetalum paraguayense) - /plants/graptopetalum-paraguayense--geisterpflanze--9584de97.webp +- Gerbera (Gerbera jamesonii) - /plants/gerbera-jamesonii--gerbera--f17eec14.webp +- Geweihfarn (Platycerium bifurcatum) - /plants/platycerium-bifurcatum--geweihfarn--991495f9.webp +- Gloxinie (Gloxinia speciosa) - /plants/gloxinia-speciosa--gloxinie--8a73752c.webp +- Goldene Tonne (Echinocactus grusonii) - /plants/echinocactus-grusonii--goldene-tonne--d5268f53.webp +- Goldener Bambus (Phyllostachys aurea) - /plants/phyllostachys-aurea--goldener-bambus--e05d0c9f.webp +- Goldfruchtpalme (Dypsis lutescens) - /plants/dypsis-lutescens--goldfruchtpalme--890812c2.webp +- Granatapfelbaum (Punica granatum) - /plants/punica-granatum--granatapfelbaum--facf4f0c.webp +- Grosse Brennessel (Urtica dioica) - /plants/urtica-dioica--grosse-brennessel--b2ed905e.webp +- Grosse Strahlenaralie (Schefflera actinophylla) - /plants/schefflera-actinophylla--grosse-strahlenaralie--a69cdd16.webp +- Gruene Minze (Mentha spicata) - /plants/mentha-spicata--gruene-minze--7cb727ef.webp +- Gruenlilie (Chlorophytum comosum) - /plants/chlorophytum-comosum--gruenlilie--e48be10b.webp +- Guave (Psidium guajava) - /plants/psidium-guajava--guave--5d507482.webp +- Gummibaum (Ficus elastica) - /plants/ficus-elastica--gummibaum--925b35e7.webp +- Gurke (Cucumis sativus) - /plants/cucumis-sativus--gurke--3b96fd46.webp +- Guzmania (Guzmania lingulata) - /plants/guzmania-lingulata--guzmania--63fafdcb.webp +- Hange-Birke (Betula pendula) - /plants/betula-pendula--hange-birke--aff0bb68.webp +- Hasenohren-Kaktus (Opuntia microdasys) - /plants/opuntia-microdasys--hasenohren-kaktus--de2a7439.webp +- Heliamphora (Heliamphora nutans) - /plants/heliamphora-nutans--heliamphora--16977b41.webp +- Heliconia (Heliconia psittacorum) - /plants/heliconia-psittacorum--heliconia--15bad812.webp +- Herzblatt-Philodendron (Philodendron hederaceum) - /plants/philodendron-hederaceum--herzblatt-philodendron--54360959.webp +- Herzkette (Ceropegia woodii) - /plants/ceropegia-woodii--herzkette--b51fb231.webp +- Hibiskus (Hibiscus rosa-sinensis) - /plants/hibiscus-rosa-sinensis--hibiskus--9e6d8b54.webp +- Hyazinthe (Hyacinthus orientalis) - /plants/hyacinthus-orientalis--hyazinthe--2c07af5d.webp +- Indische Azalee (Azalea indica) - /plants/azalea-indica--indische-azalee--fe6e49a3.webp +- Ingwer (Zingiber officinale) - /plants/zingiber-officinale--ingwer--597975c9.webp +- Jadepflanze (Crassula ovata) - /plants/crassula-ovata--jadepflanze--3ac94122.webp +- Japanische Aucube (Aucuba japonica) - /plants/aucuba-japonica--japanische-aucube--c4bcd588.webp +- Japanische Azalee (Rhododendron simsii) - /plants/rhododendron-simsii--japanische-azalee--ef16f2c0.webp +- Jasmin (Jasminum polyanthum) - /plants/jasminum-polyanthum--jasmin--14162cf1.webp +- Johanniskraut (Hypericum perforatum) - /plants/hypericum-perforatum--johanniskraut--9bdb2ebc.webp +- Kaffeestrauch (Coffea arabica) - /plants/coffea-arabica--kaffeestrauch--a5ffdda3.webp +- Kalanchoe (Kalanchoe blossfeldiana) - /plants/kalanchoe-blossfeldiana--kalanchoe--e040640f.webp +- Kamelie (Camellia japonica) - /plants/camellia-japonica--kamelie--6a23eb3f.webp +- Kamille (Chamomilla recutita) - /plants/chamomilla-recutita--kamille--0bffdb72.webp +- Kaninchen-Ohren (Kalanchoe tomentosa) - /plants/kalanchoe-tomentosa--kaninchen-ohren--2c3b1e90.webp +- Kannenpflanze (Nepenthes alata) - /plants/nepenthes-alata--kannenpflanze--30016442.webp +- Kap-Aloe (Aloe arborescens) - /plants/aloe-arborescens--kap-aloe--2c4f60ef.webp +- Kap-Aloe (ferox) (Aloe ferox) - /plants/aloe-ferox--kap-aloe-ferox--e78c3f65.webp +- Karotte (Daucus carota) - /plants/daucus-carota--karotte--85d90d33.webp +- Kentia-Palme (Howea forsteriana) - /plants/howea-forsteriana--kentia-palme--f2c205ea.webp +- Keulenlilie (Cordyline australis) - /plants/cordyline-australis--keulenlilie--31be351b.webp +- Kleeblume (Oxalis triangularis) - /plants/oxalis-triangularis--kleeblume--9080763b.webp +- Kleine Wachsblume (Hoya bella) - /plants/hoya-bella--kleine-wachsblume--db73dcff.webp +- Knollen-Begonie (Begonia tuberhybrida) - /plants/begonia-tuberhybrida--knollen-begonie--7d9dfd00.webp +- Koenigin der Nacht (Epiphyllum oxypetalum) - /plants/epiphyllum-oxypetalum--koenigin-der-nacht--7ecd1979.webp +- Koenigs-Protea (Protea cynaroides) - /plants/protea-cynaroides--koenigs-protea--2186e16d.webp +- Koenigsbegonie (Begonia rex) - /plants/begonia-rex--koenigsbegonie--b6083f44.webp +- Konophytum (Conophytum calculus) - /plants/conophytum-calculus--konophytum--4c3a116e.webp +- Korallenkaktus (Rhipsalis baccifera) - /plants/rhipsalis-baccifera--korallenkaktus--3097b146.webp +- Korbmarante (Calathea orbifolia) - /plants/calathea-orbifolia--korbmarante--fdc40419.webp +- Kotyledon (Cotyledon orbiculata) - /plants/cotyledon-orbiculata--kotyledon--e61a1c1a.webp +- Krokus (Crocus vernus) - /plants/crocus-vernus--krokus--31f51b70.webp +- Kurkuma (Curcuma longa) - /plants/curcuma-longa--kurkuma--cb270150.webp +- Lebende Steine (Lithops julii) - /plants/lithops-julii--lebende-steine--939c0d2c.webp +- Lila Tradescantia (Tradescantia pallida) - /plants/tradescantia-pallida--lila-tradescantia--fa444b81.webp +- Lippenstiftpflanze (Aeschynanthus radicans) - /plants/aeschynanthus-radicans--lippenstiftpflanze--c0f3a18c.webp +- Luftpflanze (Tillandsia ionantha) - /plants/tillandsia-ionantha--luftpflanze--c221d48d.webp +- Madagaskar-Jasmin (Stephanotis floribunda) - /plants/stephanotis-floribunda--madagaskar-jasmin--f5b3e914.webp +- Maisstrauch (Dracaena fragrans) - /plants/dracaena-fragrans--maisstrauch--107c7d0f.webp +- Mammillaria (Mammillaria zeilmanniana) - /plants/mammillaria-zeilmanniana--mammillaria--ee6d834e.webp +- Mangold (Beta vulgaris) - /plants/beta-vulgaris--mangold--7fb88006.webp +- Marmor-Efeutute (Epipremnum aureum Marble Queen) - /plants/epipremnum-aureum-marble-queen--marmor-efeutute--1d6745d9.webp +- Mexikanische Faecherpalme (Washingtonia robusta) - /plants/washingtonia-robusta--mexikanische-facherpalme--ced2cfe1.webp +- Mini-Monstera (Rhaphidophora tetrasperma) - /plants/rhaphidophora-tetrasperma--mini-monstera--8698ef03.webp +- Mond-Kaktus (Gymnocalycium mihanovichii) - /plants/gymnocalycium-mihanovichii--mond-kaktus--c7e6e78b.webp +- Mondstein-Pflanze (Pachyphytum oviferum) - /plants/pachyphytum-oviferum--mondstein-pflanze--66cf2adc.webp +- Monstera (Monstera deliciosa) - /plants/monstera-deliciosa--monstera--17b8209e.webp +- Monstera adansonii (Monstera adansonii) - /plants/monstera-adansonii--911eb5ba.webp +- Monstera obliqua (Monstera obliqua) - /plants/monstera-obliqua--8ab6f307.webp +- Moos-Crassula (Crassula muscosa) - /plants/crassula-muscosa--moos-crassula--41420e37.webp +- Muschelingwer (Alpinia zerumbet) - /plants/alpinia-zerumbet--muschelingwer--f0c5c11e.webp +- Neon-Efeutute (Epipremnum pinnatum Neon) - /plants/epipremnum-pinnatum-neon--neon-efeutute--3e91b575.webp +- Neoregelia (Neoregelia carolinae) - /plants/neoregelia-carolinae--neoregelia--454c3c96.webp +- Neuguinea-Balsamine (Impatiens hawkeri) - /plants/impatiens-hawkeri--neuguinea-balsamine--4e5c7c8f.webp +- Oleander (Nerium oleander) - /plants/nerium-oleander--oleander--87c4b966.webp +- Orangenbaum (Citrus sinensis) - /plants/citrus-sinensis--orangenbaum--294e1722.webp +- Oregano (Origanum vulgare) - /plants/origanum-vulgare--oregano--33c6269c.webp +- Osterglocke (Narcissus pseudonarcissus) - /plants/narcissus-pseudonarcissus--osterglocke--32e917c0.webp +- Ostertrompete (Lilium longiflorum) - /plants/lilium-longiflorum--ostertrompete--4b791484.webp +- Papaya (Carica papaya) - /plants/carica-papaya--papaya--240dc331.webp +- Paradiesvogelblume (Strelitzia reginae) - /plants/strelitzia-reginae--paradiesvogelblume--3ee1f013.webp +- Paragraphenpflanze (Cyperus alternifolius) - /plants/cyperus-alternifolius--paragraphenpflanze--986a54bf.webp +- Passionsblume (Passiflora caerulea) - /plants/passiflora-caerulea--passionsblume--b8effb5e.webp +- Perlenschnur-Pflanze (Senecio rowleyanus) - /plants/senecio-rowleyanus--perlenschnur-pflanze--803d2b22.webp +- Peruanischer Fackelkaktus (Cereus peruvianus) - /plants/cereus-peruvianus--peruanischer-fackelkaktus--b087b5cf.webp +- Petersilie (Petroselinum crispum) - /plants/petroselinum-crispum--petersilie--23a7cb86.webp +- Petunie (Petunia hybrida) - /plants/petunia-hybrida--petunie--af7deb4f.webp +- Pfeilblatt (Syngonium podophyllum) - /plants/syngonium-podophyllum--pfeilblatt--ca7b7b9f.webp +- Pferdeschwanzpalme (Beaucarnea recurvata) - /plants/beaucarnea-recurvata--pferdeschwanzpalme--31691c81.webp +- Philodendron bipinnatifidum (Philodendron bipinnatifidum) - /plants/philodendron-bipinnatifidum--f7a662b8.webp +- Philodendron gloriosum (Philodendron gloriosum) - /plants/philodendron-gloriosum--059733a1.webp +- Primel (Primula vulgaris) - /plants/primula-vulgaris--primel--038312ee.webp +- Purpursonnentau (Sarracenia purpurea) - /plants/sarracenia-purpurea--purpursonnentau--38d9e604.webp +- Radieschen (Raphanus sativus) - /plants/raphanus-sativus--radieschen--797f22e6.webp +- Regenbogenmoos (Selaginella uncinata) - /plants/selaginella-uncinata--regenbogenmoos--fac3dec7.webp +- Riemenblatt (Clivia miniata) - /plants/clivia-miniata--riemenblatt--29bc76f5.webp +- Rippenpeperomie (Peperomia caperata) - /plants/peperomia-caperata--rippenpeperomie--b3a48151.webp +- Ritterstern (Hippeastrum hybrid) - /plants/hippeastrum-hybrid--ritterstern--82bc6dc8.webp +- Rosengeranie (Pelargonium graveolens) - /plants/pelargonium-graveolens--rosengeranie--d7f8a481.webp +- Rosmarin (Rosmarinus officinalis) - /plants/rosmarinus-officinalis--rosmarin--2791f58d.webp +- Roter Fingerhut (Digitalis purpurea) - /plants/digitalis-purpurea--roter-fingerhut--be177092.webp +- Roter Philodendron (Philodendron erubescens) - /plants/philodendron-erubescens--roter-philodendron--5d917978.webp +- Salat (Lactuca sativa) - /plants/lactuca-sativa--salat--7cd31564.webp +- Salbei (Salvia officinalis) - /plants/salvia-officinalis--salbei--9fe3bf8f.webp +- San-Pedro-Kaktus (Echinopsis pachanoi) - /plants/echinopsis-pachanoi--san-pedro-kaktus--7f1085bc.webp +- Satinpothos (Scindapsus pictus) - /plants/scindapsus-pictus--satinpothos--8991b0e9.webp +- Schafgarbe (Achillea millefolium) - /plants/achillea-millefolium--schafgarbe--a945b3a0.webp +- Schamkraut (Mimosa pudica) - /plants/mimosa-pudica--schamkraut--89ce823f.webp +- Schmetterlingsorchidee (Phalaenopsis amabilis) - /plants/phalaenopsis-amabilis--schmetterlingsorchidee--3c14cbf2.webp +- Schnittlauch (Allium schoenoprasum) - /plants/allium-schoenoprasum--schnittlauch--d820fe95.webp +- Schraubenbaum (Pandanus veitchii) - /plants/pandanus-veitchii--schraubenbaum--36aa501d.webp +- Schusterpflanze (Aspidistra elatior) - /plants/aspidistra-elatior--schusterpflanze--27471002.webp +- Schwarze Rose (Aeonium) (Aeonium arboreum) - /plants/aeonium-arboreum--schwarze-rose-aeonium--2fa8210f.webp +- Schwarzer Holunder (Sambucus nigra) - /plants/sambucus-nigra--schwarzer-holunder--fd1fe0a5.webp +- Schwertfarn (Nephrolepis exaltata) - /plants/nephrolepis-exaltata--schwertfarn--9049369c.webp +- Silber-Weide (Salix alba) - /plants/salix-alba--silber-weide--407a5b47.webp +- Silbervase (Aechmea fasciata) - /plants/aechmea-fasciata--silbervase--04efba01.webp +- Socotra-Wuestenrose (Adenium socotranum) - /plants/adenium-socotranum--socotra-wuestenrose--0118195c.webp +- Sonnenhut (Echinacea purpurea) - /plants/echinacea-purpurea--sonnenhut--cd110eab.webp +- Sonnentau (Drosera capensis) - /plants/drosera-capensis--sonnentau--7122f48c.webp +- Spanisches Moos (Tillandsia usneoides) - /plants/tillandsia-usneoides--spanisches-moos--80677975.webp +- Speckbaum (Portulacaria afra) - /plants/portulacaria-afra--speckbaum--b630ec3c.webp +- Spiegelpeperomie (Peperomia obtusifolia) - /plants/peperomia-obtusifolia--spiegelpeperomie--fffbf481.webp +- Spinat (Spinacia oleracea) - /plants/spinacia-oleracea--spinat--67379554.webp +- Stab-Palme (Rhapis excelsa) - /plants/rhapis-excelsa--stab-palme--3f2eded0.webp +- Stiefmuetterchen (Viola wittrockiana) - /plants/viola-wittrockiana--stiefmuetterchen--d2cb587c.webp +- Stiefmuetterchen-Orchidee (Miltoniopsis roezlii) - /plants/miltoniopsis-roezlii--stiefmuetterchen-orchidee--87379182.webp +- Strahlenaralie (Schefflera arboricola) - /plants/schefflera-arboricola--strahlenaralie--b445fcbb.webp +- Stromanthe (Stromanthe sanguinea) - /plants/stromanthe-sanguinea--stromanthe--a9ffe5b3.webp +- Studentenblume (Tagetes patula) - /plants/tagetes-patula--studentenblume--0da7d656.webp +- Suesskartoffel (Ipomoea batatas) - /plants/ipomoea-batatas--suesskartoffel--09695c9f.webp +- Tanzerinnen-Orchidee (Oncidium sphacelatum) - /plants/oncidium-sphacelatum--tanzerinnen-orchidee--79ae7545.webp +- Taro (Colocasia esculenta) - /plants/colocasia-esculenta--taro--d23c3d35.webp +- Teestrauch (Camellia sinensis) - /plants/camellia-sinensis--teestrauch--2c1d14da.webp +- Tempel-Baum (Plumeria rubra) - /plants/plumeria-rubra--tempel-baum--657d110b.webp +- Thymian (Thymus vulgaris) - /plants/thymus-vulgaris--thymian--64a6471c.webp +- Tiroler Keulenlilie (Cordyline fruticosa) - /plants/cordyline-fruticosa--tiroler-keulenlilie--4a44ec99.webp +- Tomate (Solanum lycopersicum) - /plants/solanum-lycopersicum--tomate--e68be402.webp +- Traubenhyazinthe (Muscari armeniacum) - /plants/muscari-armeniacum--traubenhyazinthe--bc818bf4.webp +- Triphylla-Fuchsie (Fuchsia triphylla) - /plants/fuchsia-triphylla--triphylla-fuchsie--822e8e3b.webp +- Tueipelfarn (Polypodium vulgare) - /plants/polypodium-vulgare--tueipelfarn--2e4f5046.webp +- Tueipelfarn (Microsorum) (Microsorum punctatum) - /plants/microsorum-punctatum--tueipelfarn-microsorum--77fa4bea.webp +- Tulpe (Tulipa gesneriana) - /plants/tulipa-gesneriana--tulpe--373bf645.webp +- Ufopflanze (Pilea peperomioides) - /plants/pilea-peperomioides--ufopflanze--6b60c68b.webp +- Vanda-Orchidee (Vanda coerulea) - /plants/vanda-coerulea--vanda-orchidee--d3b6fab1.webp +- Vanille (Vanilla planifolia) - /plants/vanilla-planifolia--vanille--39790d8a.webp +- Venusfliegenfalle (Dionaea muscipula) - /plants/dionaea-muscipula--venusfliegenfalle--fbcebf61.webp +- Vogelnest-Farn (Asplenium nidus) - /plants/asplenium-nidus--vogelnest-farn--c9fbbb3c.webp +- Wachsblume (Hoya carnosa) - /plants/hoya-carnosa--wachsblume--4da8fed5.webp +- Wandelroeschen (Lantana camara) - /plants/lantana-camara--wandelroeschen--b8fc5640.webp +- Wasserschlauch (Utricularia gibba) - /plants/utricularia-gibba--wasserschlauch--13643b06.webp +- Weihnachtskaktus (Schlumbergera truncata) - /plants/schlumbergera-truncata--weihnachtskaktus--c8f10c80.webp +- Weihnachtsstern (Euphorbia pulcherrima) - /plants/euphorbia-pulcherrima--weihnachtsstern--ce82aeac.webp +- Weisse Strelitzie (Strelitzia nicolai) - /plants/strelitzia-nicolai--weisse-strelitzie--30b92c65.webp +- Weisse Tradescantia (Tradescantia fluminensis) - /plants/tradescantia-fluminensis--weisse-tradescantia--ed8ecd20.webp +- Wermut (Artemisia absinthium) - /plants/artemisia-absinthium--wermut--26709c63.webp +- Wuestenrose (Adenium obesum) - /plants/adenium-obesum--wuestenrose--18b1b800.webp +- Yucca-Palme (Yucca elephantipes) - /plants/yucca-elephantipes--yucca-palme--1e34e66e.webp +- Zamioculcas (Zamioculcas zamiifolia) - /plants/zamioculcas-zamiifolia--zamioculcas--dd98f155.webp +- Zaubernuss (Hamamelis mollis) - /plants/hamamelis-mollis--zaubernuss--7ef3c16c.webp +- Zebra-Haworthie (Haworthia fasciata) - /plants/haworthia-fasciata--zebra-haworthie--e4e7e4db.webp +- Zebrakraut (Tradescantia zebrina) - /plants/tradescantia-zebrina--zebrakraut--1e9a096a.webp +- Zinnie (Zinnia elegans) - /plants/zinnia-elegans--zinnie--6d666757.webp +- Zitronenbaum (Citrus limon) - /plants/citrus-limon--zitronenbaum--100d9901.webp +- Zitronenmelisse (Melissa officinalis) - /plants/melissa-officinalis--zitronenmelisse--79ec1828.webp +- Zwergdattelpalme (Phoenix roebelenii) - /plants/phoenix-roebelenii--zwergdattelpalme--f83a8f6a.webp +- Zylindrischer Bogenhanf (Sansevieria cylindrica) - /plants/sansevieria-cylindrica--zylindrischer-bogenhanf--5b3a59b5.webp +- Zymbidium (Cymbidium lowianum) - /plants/cymbidium-lowianum--zymbidium--3ee7a3d5.webp + +## Moegliche zusaetzliche Pflanzen aus Internet-Recherche + +Recherche am: 2026-03-11 +Gesamtzahl neue Vorschlaege: 209 + +Kuratiert aus bekannten Pflanzenlisten und Garten-Guides. +Quellen: +- https://www.gardenersworld.com/plants/house-plants/ +- https://www.rhs.org.uk/plants/types/houseplants +- https://www.almanac.com/plant/growing-guides + +### Gemuese (45) + +- Kartoffel (Solanum tuberosum) +- Zwiebel (Allium cepa) +- Knoblauch (Allium sativum) +- Lauch (Allium ampeloprasum var. porrum) +- Fruehlingszwiebel (Allium fistulosum) +- Erbse (Pisum sativum) +- Buschbohne (Phaseolus vulgaris) +- Ackerbohne (Vicia faba) +- Mais (Zea mays) +- Brokkoli (Brassica oleracea var. italica) +- Blumenkohl (Brassica oleracea var. botrytis) +- Weisskohl (Brassica oleracea var. capitata) +- Rotkohl (Brassica oleracea var. capitata f. rubra) +- Rosenkohl (Brassica oleracea var. gemmifera) +- Gruenkohl (Brassica oleracea var. sabellica) +- Kohlrabi (Brassica oleracea var. gongylodes) +- Pak Choi (Brassica rapa subsp. chinensis) +- Chinakohl (Brassica rapa subsp. pekinensis) +- Steckruebe (Brassica napus subsp. napobrassica) +- Stangensellerie (Apium graveolens var. dulce) +- Knollensellerie (Apium graveolens var. rapaceum) +- Pastinake (Pastinaca sativa) +- Spargel (Asparagus officinalis) +- Artischocke (Cynara cardunculus var. scolymus) +- Rhabarber (Rheum rhabarbarum) +- Zucchini (Cucurbita pepo) +- Kuerbis (Cucurbita maxima) +- Butternut-Kuerbis (Cucurbita moschata) +- Okra (Abelmoschus esculentus) +- Endivie (Cichorium endivia) +- Chicoree (Cichorium intybus var. foliosum) +- Rucola (Eruca vesicaria) +- Brunnenkresse (Nasturtium officinale) +- Gartenkresse (Lepidium sativum) +- Fenchel (Foeniculum vulgare) +- Meerrettich (Armoracia rusticana) +- Topinambur (Helianthus tuberosus) +- Wirsing (Brassica oleracea var. sabauda) +- Sojabohne (Glycine max) +- Erdnuss (Arachis hypogaea) +- Kichererbse (Cicer arietinum) +- Linse (Lens culinaris) +- Quinoa (Chenopodium quinoa) +- Maniok (Manihot esculenta) +- Yam (Dioscorea alata) + +### Kraeuter (20) + +- Lorbeer (Laurus nobilis) +- Estragon (Artemisia dracunculus) +- Bohnenkraut (Satureja hortensis) +- Majoran (Origanum majorana) +- Kerbel (Anthriscus cerefolium) +- Liebstoeckel (Levisticum officinale) +- Zitronengras (Cymbopogon citratus) +- Zitronenverbene (Aloysia citrodora) +- Borretsch (Borago officinalis) +- Sauerampfer (Rumex acetosa) +- Stevia (Stevia rebaudiana) +- Katzenminze (Nepeta cataria) +- Currykraut (Helichrysum italicum) +- Shiso (Perilla frutescens) +- Schnittknoblauch (Allium tuberosum) +- Ysop (Hyssopus officinalis) +- Wasabi (Eutrema japonicum) +- Roemische Kamille (Chamaemelum nobile) +- Koriander (Coriandrum sativum) +- Dill (Anethum graveolens) + +### Obst (36) + +- Apfelbaum (Malus domestica) +- Birnbaum (Pyrus communis) +- Pfirsichbaum (Prunus persica) +- Pflaumenbaum (Prunus domestica) +- Kirschbaum (Prunus avium) +- Aprikosenbaum (Prunus armeniaca) +- Feigenbaum (Ficus carica) +- Olivenbaum (Olea europaea) +- Avocado (Persea americana) +- Weinrebe (Vitis vinifera) +- Heidelbeere (Vaccinium corymbosum) +- Himbeere (Rubus idaeus) +- Brombeere (Rubus fruticosus) +- Stachelbeere (Ribes uva-crispa) +- Johannisbeere (Ribes rubrum) +- Schwarze Johannisbeere (Ribes nigrum) +- Kiwi (Actinidia deliciosa) +- Mango (Mangifera indica) +- Ananas (Ananas comosus) +- Kokospalme (Cocos nucifera) +- Drachenfrucht (Selenicereus undatus) +- Passionsfrucht (Passiflora edulis) +- Litschi (Litchi chinensis) +- Grapefruit (Citrus paradisi) +- Mandarine (Citrus reticulata) +- Limette (Citrus aurantiifolia) +- Clementine (Citrus clementina) +- Maulbeere (Morus alba) +- Kaki (Diospyros kaki) +- Dattelpalme (Phoenix dactylifera) +- Mandelbaum (Prunus dulcis) +- Walnussbaum (Juglans regia) +- Haselnuss (Corylus avellana) +- Kastanie (Castanea sativa) +- Pekannussbaum (Carya illinoinensis) +- Macadamia (Macadamia integrifolia) + +### Blumen (61) + +- Sonnenblume (Helianthus annuus) +- Rose (Rosa x hybrida) +- Pfingstrose (Paeonia lactiflora) +- Bart-Iris (Iris germanica) +- Gaensebluemchen (Bellis perennis) +- Nelke (Dianthus caryophyllus) +- Loewenmaeulchen (Antirrhinum majus) +- Hortensie (Hydrangea macrophylla) +- Flieder (Syringa vulgaris) +- Kosmee (Cosmos bipinnatus) +- Kapuzinerkresse (Tropaeolum majus) +- Buntnessel (Plectranthus scutellarioides) +- Rittersporn (Delphinium elatum) +- Lupine (Lupinus polyphyllus) +- Stockrose (Alcea rosea) +- Prunkwinde (Ipomoea purpurea) +- Clematis (Clematis viticella) +- Duftwicke (Lathyrus odoratus) +- Hasengloeckchen (Hyacinthoides non-scripta) +- Maigloeckchen (Convallaria majalis) +- Gladiole (Gladiolus hortulanus) +- Ranunkel (Ranunculus asiaticus) +- Anemone (Anemone coronaria) +- Eisenkraut (Verbena bonariensis) +- Flammenblume (Phlox paniculata) +- Herbstaster (Symphyotrichum novi-belgii) +- Rudbeckie (Rudbeckia hirta) +- Feuersalbei (Salvia splendens) +- Freesie (Freesia refracta) +- Rhododendron (Rhododendron catawbiense) +- Geissblatt (Lonicera japonica) +- Arabischer Jasmin (Jasminum sambac) +- Margerite (Leucanthemum vulgare) +- Stehende Geranie (Pelargonium zonale) +- Eisbegonie (Begonia semperflorens-cultorum) +- Gartenbalsamine (Impatiens balsamina) +- Vergissmeinnicht (Myosotis sylvatica) +- Seidenpflanze (Asclepias tuberosa) +- Indianernessel (Monarda didyma) +- Bechermalve (Lavatera trimestris) +- Maedchenauge (Coreopsis tinctoria) +- Taglilie (Hemerocallis fulva) +- Lenzrose (Helleborus orientalis) +- Trompetenwinde (Campsis radicans) +- Mohn (Papaver rhoeas) +- Kalifornischer Mohn (Eschscholzia californica) +- Ringelblume (Calendula officinalis) +- Kornblume (Centaurea cyanus) +- Bartnelke (Dianthus barbatus) +- Mittagsgold (Gazania rigens) +- Heliotrop (Heliotropium arborescens) +- Koenigskerze (Verbascum thapsus) +- Ziertabak (Nicotiana alata) +- Fuchsschwanz (Amaranthus caudatus) +- Mehlsalbei (Salvia farinacea) +- Kokardenblume (Gaillardia aristata) +- Traenendes Herz (Lamprocapnos spectabilis) +- Hornveilchen (Viola cornuta) +- Nemesie (Nemesia strumosa) +- Kapmargerite (Osteospermum ecklonis) +- Shasta-Margerite (Leucanthemum x superbum) + +### Baeume und Straeucher (22) + +- Buchsbaum (Buxus sempervirens) +- Stechpalme (Ilex aquifolium) +- Magnolie (Magnolia grandiflora) +- Eiche (Quercus robur) +- Kiefer (Pinus sylvestris) +- Fichte (Picea abies) +- Zeder (Cedrus libani) +- Zypresse (Cupressus sempervirens) +- Eukalyptus (Eucalyptus globulus) +- Jacaranda (Jacaranda mimosifolia) +- Spitzahorn (Acer platanoides) +- Eberesche (Sorbus aucuparia) +- Robinie (Robinia pseudoacacia) +- Flammenbaum (Delonix regia) +- Ginkgo (Ginkgo biloba) +- Trompetenbaum (Catalpa bignonioides) +- Kirschlorbeer (Prunus laurocerasus) +- Forsythie (Forsythia x intermedia) +- Gartenhibiskus (Hibiscus syriacus) +- Weigelie (Weigela florida) +- Spierstrauch (Spiraea japonica) +- Schmetterlingsflieder (Buddleja davidii) + +### Zimmerpflanzen (25) + +- Kroton (Codiaeum variegatum) +- Alocasia zebrina (Alocasia zebrina) +- Nervenpflanze (Fittonia albivenis) +- Punktblatt (Hypoestes phyllostachya) +- Aluminium-Pflanze (Pilea cadierei) +- Wassermelonen-Peperomie (Peperomia argyreia) +- Raindrop-Peperomie (Peperomia polybotrya) +- Glueckskastanie (Pachira aquatica) +- Norfolk-Tanne (Araucaria heterophylla) +- Samt-Anthurie (Anthurium clarinervium) +- Kristall-Anthurie (Anthurium crystallinum) +- Falsche Aralie (Schefflera elegantissima) +- String of Bananas (Curio radicans) +- String of Dolphins (Curio x peregrinus) +- Bubikopf (Soleirolia soleirolii) +- Palmfarn (Cycas revoluta) +- Calathea lancifolia (Goeppertia insignis) +- Calathea ornata (Goeppertia ornata) +- Philodendron Brasil (Philodendron hederaceum 'Brasil') +- Philodendron Pink Princess (Philodendron erubescens 'Pink Princess') +- Philodendron Xanadu (Thaumatophyllum xanadu) +- Kaffeepflanze arabica nana (Coffea arabica 'Nana') +- Yucca aloifolia (Yucca aloifolia) +- Ficus microcarpa (Ficus microcarpa) +- Ficus altissima (Ficus altissima) diff --git a/App.tsx b/App.tsx deleted file mode 100644 index 19e62f8..0000000 --- a/App.tsx +++ /dev/null @@ -1,680 +0,0 @@ - -import React, { useState, useEffect, useRef } from 'react'; -import { Tab, Plant, IdentificationResult, Language } from './types'; -import { StorageService } from './services/storageService'; -import { PlantRecognitionService } from './services/plantRecognitionService'; -import { PlantDatabaseService } from './services/plantDatabaseService'; -import { getTranslation } from './utils/translations'; -import { TabBar } from './components/TabBar'; -import { PlantCard } from './components/PlantCard'; -import { PlantSkeleton } from './components/PlantSkeleton'; -import { ResultCard } from './components/ResultCard'; -import { PlantDetail } from './components/PlantDetail'; -import { Toast } from './components/Toast'; -import { Camera, Image as ImageIcon, HelpCircle, X, Settings as SettingsIcon, ScanLine, Leaf, Plus, Zap, Search, ArrowRight, ArrowLeft, Globe, ChevronDown, ChevronUp, Check, Cpu, BookOpen } from 'lucide-react'; - -const generateId = () => Math.random().toString(36).substr(2, 9); - -const App: React.FC = () => { - const [activeTab, setActiveTab] = useState(Tab.HOME); - const [plants, setPlants] = useState([]); - const [isDarkMode, setIsDarkMode] = useState(false); - const [language, setLanguage] = useState('de'); - const [isLoadingPlants, setIsLoadingPlants] = useState(true); - - // Search State - const [searchQuery, setSearchQuery] = useState(''); - - // Lexicon State - const [isLexiconOpen, setIsLexiconOpen] = useState(false); - const [lexiconSearchQuery, setLexiconSearchQuery] = useState(''); - - // Settings State - const [isLanguageDropdownOpen, setIsLanguageDropdownOpen] = useState(false); - - // Scanner Modal State - const [isScannerOpen, setIsScannerOpen] = useState(false); - const [selectedImage, setSelectedImage] = useState(null); - - // Analysis State - const [isAnalyzing, setIsAnalyzing] = useState(false); - const [analysisProgress, setAnalysisProgress] = useState(0); - const [analysisResult, setAnalysisResult] = useState(null); - - // Detail State - const [selectedPlant, setSelectedPlant] = useState(null); - - // Toast State - const [toast, setToast] = useState({ message: '', visible: false }); - - // Refs - const fileInputRef = useRef(null); - - // Derived state for translations - const t = getTranslation(language); - - useEffect(() => { - const loadData = async () => { - setIsLoadingPlants(true); - await new Promise(resolve => setTimeout(resolve, 800)); - setPlants(StorageService.getPlants()); - setLanguage(StorageService.getLanguage()); - setIsLoadingPlants(false); - }; - - loadData(); - - if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { - setIsDarkMode(true); - document.documentElement.classList.add('dark'); - } - }, []); - - const toggleDarkMode = () => { - setIsDarkMode(!isDarkMode); - if (!isDarkMode) { - document.documentElement.classList.add('dark'); - } else { - document.documentElement.classList.remove('dark'); - } - }; - - const changeLanguage = (lang: Language) => { - setLanguage(lang); - StorageService.saveLanguage(lang); - setIsLanguageDropdownOpen(false); - }; - - const handleImageSelect = (event: React.ChangeEvent) => { - const file = event.target.files?.[0]; - if (file) { - const reader = new FileReader(); - reader.onloadend = () => { - const base64String = reader.result as string; - setSelectedImage(base64String); - analyzeImage(base64String); - }; - reader.readAsDataURL(file); - } - }; - - const analyzeImage = async (imageUri: string) => { - setIsAnalyzing(true); - setAnalysisProgress(0); - setAnalysisResult(null); - - // Simulate realistic progress - const progressInterval = setInterval(() => { - setAnalysisProgress(prev => { - // Fast start - if (prev < 30) return prev + Math.random() * 8; - // Slower middle (processing) - if (prev < 70) return prev + Math.random() * 2; - // Stall at end (waiting for API) - if (prev < 90) return prev + 0.5; - return prev; - }); - }, 150); - - try { - // Pass the current language to the service - const result = await PlantRecognitionService.identify(imageUri, language); - - clearInterval(progressInterval); - setAnalysisProgress(100); - - // Short delay to allow user to see 100% completion - setTimeout(() => { - setAnalysisResult(result); - setIsAnalyzing(false); - }, 500); - - } catch (error) { - clearInterval(progressInterval); - console.error("Analysis failed", error); - alert("Fehler bei der Analyse."); - setSelectedImage(null); - setIsAnalyzing(false); - } - }; - - const showToast = (message: string) => { - setToast({ message, visible: true }); - }; - - const hideToast = () => { - setToast(prev => ({ ...prev, visible: false })); - }; - - const savePlant = () => { - if (analysisResult && selectedImage) { - const now = new Date().toISOString(); - const newPlant: Plant = { - id: generateId(), - name: analysisResult.name, - botanicalName: analysisResult.botanicalName, - imageUri: selectedImage, - dateAdded: now, - careInfo: analysisResult.careInfo, - lastWatered: now, - wateringHistory: [now], // Initialize history with the creation date/first watering - description: analysisResult.description, - notificationsEnabled: false // Default off - }; - - StorageService.savePlant(newPlant); - setPlants(StorageService.getPlants()); - closeScanner(); - - // Also close lexicon if open - setIsLexiconOpen(false); - - showToast(t.plantAddedSuccess); - } - }; - - const closeScanner = () => { - setIsScannerOpen(false); - setSelectedImage(null); - setAnalysisResult(null); - setIsAnalyzing(false); - setAnalysisProgress(0); - if (fileInputRef.current) fileInputRef.current.value = ''; - }; - - const openScanner = () => { - setIsScannerOpen(true); - }; - - const handlePlantClick = (plant: Plant) => { - setSelectedPlant(plant); - }; - - const closeDetail = () => { - setSelectedPlant(null); - }; - - const handleDeletePlant = (id: string) => { - StorageService.deletePlant(id); - setPlants(prev => prev.filter(p => p.id !== id)); - closeDetail(); - showToast(t.plantDeleted); - }; - - const handleUpdatePlant = (updatedPlant: Plant) => { - StorageService.updatePlant(updatedPlant); - setPlants(prev => prev.map(p => p.id === updatedPlant.id ? updatedPlant : p)); - setSelectedPlant(updatedPlant); - showToast(t.wateredSuccess); - }; - - // Lexicon Handling - const handleLexiconItemClick = (item: any) => { - // We treat this like a "Scan Result" for simplicity, reusing the ResultCard - setAnalysisResult(item); - setSelectedImage(item.imageUri); - // Since ResultCard is rendered conditionally based on analysisResult && selectedImage, - // we need to make sure the view is visible. - // We will render ResultCard inside the Lexicon view if selected. - }; - - const closeLexiconResult = () => { - setAnalysisResult(null); - setSelectedImage(null); - }; - - - // --- SCREENS --- - - const renderHome = () => ( -
-
-

{t.myPlants}

- -
- - {/* Filters */} -
- - -
- - {isLoadingPlants ? ( -
- {[1, 2, 3, 4].map((i) => ( - - ))} -
- ) : plants.length === 0 ? ( -
- -

{t.noPlants}

-
- ) : ( -
- {plants.map(plant => ( - handlePlantClick(plant)} t={t} /> - ))} -
- )} - - {/* FAB */} - -
- ); - - const renderSearch = () => { - const filteredPlants = plants.filter(p => - p.name.toLowerCase().includes(searchQuery.toLowerCase()) || - p.botanicalName.toLowerCase().includes(searchQuery.toLowerCase()) - ); - - const categories = [ - { name: t.catCareEasy, color: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400" }, - { name: t.catSucculents, color: "bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400" }, - { name: t.catLowLight, color: "bg-indigo-100 text-indigo-700 dark:bg-indigo-900/30 dark:text-indigo-400" }, - { name: t.catPetFriendly, color: "bg-rose-100 text-rose-700 dark:bg-rose-900/30 dark:text-rose-400" }, - { name: t.catAirPurifier, color: "bg-teal-100 text-teal-700 dark:bg-teal-900/30 dark:text-teal-400" }, - { name: t.catFlowering, color: "bg-fuchsia-100 text-fuchsia-700 dark:bg-fuchsia-900/30 dark:text-fuchsia-400" }, - ]; - - return ( -
-
-

{t.searchTitle}

- -
- - setSearchQuery(e.target.value)} - className="w-full bg-white dark:bg-stone-900 border border-stone-200 dark:border-stone-800 rounded-xl py-3 pl-12 pr-4 text-stone-900 dark:text-stone-100 focus:outline-none focus:ring-2 focus:ring-primary-500/50 placeholder:text-stone-400" - /> - {searchQuery && ( - - )} -
-
- - {searchQuery ? ( -
-

- {filteredPlants.length} {t.resultsInPlants} -

- {filteredPlants.length > 0 ? ( -
- {filteredPlants.map(plant => ( - handlePlantClick(plant)} t={t} /> - ))} -
- ) : ( -
-

{t.noResults}

-
- )} -
- ) : ( -
-

{t.categories}

-
- {categories.map((cat) => ( - - ))} -
- -
setIsLexiconOpen(true)} - className="mt-8 p-6 bg-gradient-to-br from-primary-600 to-primary-800 rounded-2xl text-white shadow-lg relative overflow-hidden cursor-pointer active:scale-[0.98] transition-transform" - > -
-

- - {t.lexiconTitle} -

-

{t.lexiconDesc}

- {t.browseLexicon} -
- -
-
- )} -
- ); - }; - - const renderLexicon = () => { - if (!isLexiconOpen) return null; - - // If we have a selected item from Lexicon, show ResultCard (Detail View) - if (analysisResult && selectedImage) { - return ( -
- -
- ); - } - - const lexiconPlants = PlantDatabaseService.searchPlants(lexiconSearchQuery, language); - - return ( -
- {/* Header */} -
- -

{t.lexiconTitle}

-
- - {/* Content */} -
- - {/* Search */} -
- - setLexiconSearchQuery(e.target.value)} - className="w-full bg-white dark:bg-stone-900 border border-stone-200 dark:border-stone-800 rounded-xl py-3 pl-12 pr-4 text-stone-900 dark:text-stone-100 focus:outline-none focus:ring-2 focus:ring-primary-500/50 placeholder:text-stone-400" - /> -
- - {/* Grid - NOW 3 COLUMNS */} -
- {lexiconPlants.map((plant, index) => ( - - ))} - {lexiconPlants.length === 0 && ( -
- {t.noResults} -
- )} -
-
-
- ); - }; - - const renderSettings = () => { - const languages: { code: Language; label: string }[] = [ - { code: 'de', label: 'Deutsch' }, - { code: 'en', label: 'English' }, - { code: 'es', label: 'Español' } - ]; - - const currentLangLabel = languages.find(l => l.code === language)?.label; - - return ( -
-

{t.settingsTitle}

- - {/* Dark Mode Settings */} -
- {t.darkMode} - -
- - {/* Language Settings (Dropdown Style) */} -
-
setIsLanguageDropdownOpen(!isLanguageDropdownOpen)} - > -
- - {t.language} -
- -
- {currentLangLabel} - {isLanguageDropdownOpen ? : } -
-
- - {/* Dropdown Content */} - {isLanguageDropdownOpen && ( -
-
- {languages.map((lang) => ( - - ))} -
-
- )} -
-
- ); - }; - - const renderScannerModal = () => { - if (!isScannerOpen) return null; - - // 1. Result View - if (analysisResult && selectedImage) { - return ( -
- -
- ); - } - - // 2. Scanner View - return ( -
- {/* Header */} -
- - {t.scanner} - -
- - {/* Main Camera Area */} -
- {selectedImage ? ( - - ) : ( -
- )} - - {/* Background Grid */} -
-
- - {/* Scan Frame */} -
- - {/* SHOW SELECTED IMAGE IN FRAME */} - {selectedImage && ( - Scan preview - )} - -
-
-
-
- - {/* Laser Line */} - {isAnalyzing || !selectedImage ? ( -
- ) : null} -
-
- - {/* Analyzing Sheet Overlay - Loading Animation */} - {isAnalyzing && ( -
-
- - {analysisProgress < 100 ? t.analyzing : t.result} - - - {Math.round(analysisProgress)}% - -
- - {/* Progress Bar */} -
-
-
- - {/* Stage Indicators */} -
-
-
- {t.localProcessing} -
- - {analysisProgress < 30 ? t.scanStage1 : analysisProgress < 75 ? t.scanStage2 : t.scanStage3} - -
-
- )} - - {/* Bottom Controls */} -
-
- - {t.gallery} -
- - - -
- - {t.help} -
- - -
-
- ); - }; - - return ( -
-
- {activeTab === Tab.HOME && renderHome()} - {activeTab === Tab.SETTINGS && renderSettings()} - {activeTab === Tab.SEARCH && renderSearch()} -
- - - - {/* Modal Layer for Detail View */} - {selectedPlant && ( - - )} - - {/* Modal Layer for Scanner */} - {renderScannerModal()} - - {/* Lexicon Overlay */} - {renderLexicon()} - - {/* Toast Notification */} - -
- ); -}; - -export default App; diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..b90af08 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,102 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Commands + +### Mobile App (Expo) +```bash +npm install # Install dependencies +npm run start # Start Expo dev server (offline mode) +npm run android # Start on Android +npm run ios # Start on iOS +npm run test # Run Jest tests +``` + +### Server (Express) +```bash +cd server +npm install +npm run start # Start Express server +npm run rebuild:batches # Rebuild plant catalog from batch constants +npm run diagnostics # Check duplicates and import audits +``` + +### Production Builds (EAS) +```bash +npx eas-cli build:version:set -p ios # Bump iOS build number +npx eas-cli build -p ios --profile production +npx eas-cli submit -p ios --latest # Submit to TestFlight +``` + +## Architecture + +### Mobile App +Expo Router with file-based routing. Entry point is `app/_layout.tsx`. + +- **`app/(tabs)/`** — Tab navigation: Home (`index.tsx`), Search, Profile +- **`app/scanner.tsx`** — Plant scan modal +- **`app/lexicon.tsx`** — Plant encyclopedia +- **`app/plant/`** — Plant detail screens +- **`app/auth/`** — Login / Signup screens +- **`app/onboarding.tsx`** — First-launch onboarding + +Global state lives in `context/AppContext.tsx` (plants, user, billing, language). + +### Services Layer (Mobile) +- `services/storageService.ts` — AsyncStorage persistence for user plants +- `services/plantRecognitionService.ts` — Calls `/v1/scan` on backend +- `services/plantDatabaseService.ts` — Local static plant data +- `services/authService.ts` — JWT auth against backend +- `services/backend/backendApiClient.ts` — HTTP client for all `/v1/*` calls +- `services/backend/mockBackendService.ts` — In-app mock if `EXPO_PUBLIC_BACKEND_URL` is not set + +### Backend (Express — `server/`) +Single `server/index.js` with all routes. Libs in `server/lib/`: + +- `sqlite.js` — SQLite wrapper (`openDatabase`, `run`, `get`, `all`) +- `plants.js` — Plant catalog CRUD + semantic search +- `auth.js` — JWT-based signup/login +- `billing.js` — Credits, idempotency, Stripe webhooks +- `openai.js` — Plant identification + health analysis via OpenAI +- `storage.js` — MinIO/S3 image upload (`uploadImage`, `ensureStorageBucket`) + +Key env vars for server: +``` +PLANT_DB_PATH # SQLite file path (default: server/data/greenlns.sqlite) +OPENAI_API_KEY +STRIPE_SECRET_KEY +JWT_SECRET +MINIO_ENDPOINT / MINIO_ACCESS_KEY / MINIO_SECRET_KEY / MINIO_BUCKET / MINIO_PUBLIC_URL +``` + +### Landing Page (`greenlns-landing/`) +Next.js 16 app with `output: 'standalone'` for Docker. Runs independently from the mobile app. + +Has its own `docker-compose.yml` that spins up: +- Next.js app (Landing Page) +- PostgreSQL 16 (persistent DB for the backend) +- MinIO (persistent image storage) +- Nginx (reverse proxy + SSL) + +### Infrastructure Plan +**Current state:** Server runs on Railway with SQLite (ephemeral). + +**Target state (not yet migrated):** +- Express Server moves OFF Railway → runs on the landing page server via `docker-compose.yml` +- PostgreSQL + MinIO replace SQLite + Railway hosting entirely + +**When migrating to PostgreSQL (do all of these together):** +1. Remove `server/lib/sqlite.js` and `server/data/` entirely +2. Remove Railway service for the Express server (no longer needed) +3. Add `pg` package to `server/package.json` +4. Replace all SQLite calls with `pg` and `DATABASE_URL` env var +5. Change all SQL placeholders from `?` to `$1, $2, ...` (SQLite → PostgreSQL syntax) +6. Add Express server as a service in `greenlens-landing/docker-compose.yml` +7. Use `JSONB` columns in PostgreSQL for nested data (e.g. `careInfo`, `categories`) instead of serialized strings — enables fast querying and filtering directly on JSON fields + +### Key Patterns +- SQL placeholders: SQLite uses `?`, PostgreSQL uses `$1, $2, ...` — important when migrating +- Translations: `utils/translations.ts` supports `de` / `en` / `es` +- Colors: `constants/Colors.ts` with light/dark mode tokens +- Image URIs: App sends base64 to `/v1/upload/image`, gets back a public MinIO URL diff --git a/README.md b/README.md index e36e573..be7bddf 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,92 @@ -
-GHBanner -
+# GreenLens -# Run and deploy your AI Studio app - -This contains everything you need to run your app locally. - -View your app in AI Studio: https://ai.studio/apps/drive/1cQZAaCmJNVx9ML_ZZV-F0gNCNhjSrgd8 - -## Run Locally - -**Prerequisites:** Node.js +Expo app for plant scanning, care tracking, lexicon browsing, and profile settings. +## Run locally 1. Install dependencies: - `npm install` -2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key -3. Run the app: - `npm run dev` + - `npm install` +2. Start Expo: + - `npm run start` + +## iOS TestFlight (EAS) + +Use these three commands in order: + +1. Set iOS build number: + - `npx eas-cli build:version:set -p ios` +2. Create production iOS build: + - `npx eas-cli build -p ios --profile production` +3. Submit latest iOS build to TestFlight: + - `npx eas-cli submit -p ios --latest` + +## Lexicon SQLite maintenance + +The server now uses a persistent SQLite database (`server/data/greenlns.sqlite`) and supports validated rebuilds. + +1. Install server dependencies: + - `cd server && npm install` +2. Run the server: + - `npm run start` +3. Rebuild plants from the local lexicon batch constants: + - `npm run rebuild:batches` +4. Check duplicates and import audits: + - `npm run diagnostics` + +For protected rebuild endpoints, set `PLANT_IMPORT_ADMIN_KEY` and send `x-admin-key` in requests. + +### Local plant images + +The lexicon now supports storing plant image paths in SQLite as local public paths instead of external URLs. + +Recommended structure: + +- Database field: `imageUri` +- Value example: `/plants/monstera-deliciosa.webp` +- File location on disk: `server/public/plants/monstera-deliciosa.webp` + +Notes: + +- The Express server serves `server/public/plants` at `/plants/*`. +- Remote `https://...` image URLs still work, so migration can be incremental. +- Keep the database focused on metadata and store only the image path, not binary blobs. + +## Billing and backend simulation + +The app now uses a backend API contract for paid AI features: + +- Scan AI (`/v1/scan`) +- Semantic AI search (`/v1/search/semantic`) +- Billing summary (`/v1/billing/summary`) +- Health check AI (`/v1/health-check`) + +The Node server in `server/index.js` now implements these `/v1` routes directly and uses: + +- `server/lib/openai.js` for OpenAI calls +- `server/lib/billing.js` for credit/billing/idempotency state + +If `EXPO_PUBLIC_BACKEND_URL` is not set, the app uses an in-app mock backend simulation for `/v1/*` API calls. +`EXPO_PUBLIC_PAYMENT_SERVER_URL` is used only for Stripe PaymentSheet calls (`/api/payment-sheet`). +The in-app mock backend provides: + +- Server-side style credit enforcement +- Atomic `consumeCredit()` behavior +- Idempotency-key handling +- Free and Pro monthly credit buckets +- Top-up purchase simulation +- RevenueCat/Stripe webhook simulation + +This makes it possible to build UI and flow now, then replace mock endpoints with a real backend later. + +## Production integration notes + +- Keep OpenAI keys only on the backend. +- Use app-store billing via RevenueCat or StoreKit/Play Billing. +- Forward entitlement updates to backend webhooks. +- Enforce credits on backend only; app should only display UX quota. +- Recommended backend env vars: + - `OPENAI_API_KEY` + - `OPENAI_SCAN_MODEL` (for example `gpt-5`) + - `OPENAI_HEALTH_MODEL` (for example `gpt-5`) + - `STRIPE_SECRET_KEY` + - `STRIPE_PUBLISHABLE_KEY` diff --git a/__tests__/components/Toast.test.tsx b/__tests__/components/Toast.test.tsx new file mode 100644 index 0000000..ebd5feb --- /dev/null +++ b/__tests__/components/Toast.test.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { render } from '@testing-library/react-native'; +import { Toast } from '../../components/Toast'; + +describe('Toast', () => { + it('renders message when visible', () => { + const { getByText } = render( + + ); + expect(getByText('Plant saved!')).toBeTruthy(); + }); + + it('does not render when not visible', () => { + const { queryByText } = render( + + ); + expect(queryByText('Plant saved!')).toBeNull(); + }); +}); diff --git a/__tests__/server/plantsImageUri.test.js b/__tests__/server/plantsImageUri.test.js new file mode 100644 index 0000000..dd6f6df --- /dev/null +++ b/__tests__/server/plantsImageUri.test.js @@ -0,0 +1,19 @@ +const { normalizeImageUri, toWikimediaFilePathUrl } = require('../../server/lib/plants'); + +describe('server plant image normalization', () => { + it('accepts local public plant paths', () => { + expect(normalizeImageUri('/plants/monstera-deliciosa.webp')).toBe('/plants/monstera-deliciosa.webp'); + expect(normalizeImageUri('plants/thumbs/monstera-deliciosa.webp')).toBe('/plants/thumbs/monstera-deliciosa.webp'); + }); + + it('rejects invalid local paths', () => { + expect(normalizeImageUri('/uploads/monstera.webp')).toBeNull(); + expect(normalizeImageUri('/plants/../../secret.webp')).toBeNull(); + }); + + it('converts Wikimedia thumbnail URLs to stable file-path URLs for API responses', () => { + expect( + toWikimediaFilePathUrl('https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Agave_americana_%28detail%29.jpg/330px-Agave_americana_%28detail%29.jpg'), + ).toBe('https://commons.wikimedia.org/wiki/Special:FilePath/Agave_americana_(detail).jpg'); + }); +}); diff --git a/__tests__/server/plantsSearch.test.js b/__tests__/server/plantsSearch.test.js new file mode 100644 index 0000000..277b7c5 --- /dev/null +++ b/__tests__/server/plantsSearch.test.js @@ -0,0 +1,159 @@ +const fs = require('fs'); +const os = require('os'); +const path = require('path'); + +const { closeDatabase, openDatabase, run } = require('../../server/lib/sqlite'); +const { ensurePlantSchema, getPlants } = require('../../server/lib/plants'); + +describe('server plant search ranking', () => { + let db; + let dbPath; + + beforeAll(async () => { + dbPath = path.join(os.tmpdir(), `greenlns-search-${Date.now()}.sqlite`); + db = await openDatabase(dbPath); + await ensurePlantSchema(db); + + const entries = [ + { + id: '1', + name: 'Snake Plant', + botanicalName: 'Sansevieria trifasciata', + imageUri: '/plants/snake-plant.webp', + imageStatus: 'ok', + description: 'Very resilient houseplant that handles little light well.', + categories: ['easy', 'low_light', 'air_purifier'], + careInfo: { waterIntervalDays: 14, light: 'Low to full light', temp: '16-30C' }, + confidence: 1, + }, + { + id: '2', + name: 'Spider Plant', + botanicalName: 'Chlorophytum comosum', + imageUri: '/plants/spider-plant.webp', + imageStatus: 'ok', + description: 'Easy houseplant that is safe for pets and helps clean indoor air.', + categories: ['easy', 'pet_friendly', 'air_purifier'], + careInfo: { waterIntervalDays: 6, light: 'Bright to partial shade', temp: '16-24C' }, + confidence: 1, + }, + { + id: '3', + name: 'Monstera', + botanicalName: 'Monstera deliciosa', + imageUri: '/plants/monstera.webp', + imageStatus: 'ok', + description: 'Popular indoor plant with large split leaves.', + categories: ['easy'], + careInfo: { waterIntervalDays: 7, light: 'Bright indirect light', temp: '18-24C' }, + confidence: 1, + }, + { + id: '4', + name: 'Easy Adan', + botanicalName: 'Adan botanica', + imageUri: '/plants/easy-adan.webp', + imageStatus: 'ok', + description: 'Pet friendly plant for low light corners.', + categories: ['succulent', 'low_light', 'pet_friendly'], + careInfo: { waterIntervalDays: 8, light: 'Partial shade', temp: '18-24C' }, + confidence: 1, + }, + { + id: '5', + name: 'Boston Fern', + botanicalName: 'Nephrolepis exaltata', + imageUri: '/plants/boston-fern.webp', + imageStatus: 'ok', + description: 'Loves steady moisture and humid rooms.', + categories: ['high_humidity', 'hanging'], + careInfo: { waterIntervalDays: 3, light: 'Partial shade', temp: '16-24C' }, + confidence: 1, + }, + { + id: '6', + name: 'Aloe Vera', + botanicalName: 'Aloe vera', + imageUri: '/plants/aloe-vera.webp', + imageStatus: 'ok', + description: 'Sun-loving succulent for bright windows.', + categories: ['succulent', 'sun', 'medicinal'], + careInfo: { waterIntervalDays: 12, light: 'Sunny', temp: '18-30C' }, + confidence: 1, + }, + ]; + + for (const entry of entries) { + await run( + db, + `INSERT INTO plants ( + id, + name, + botanicalName, + imageUri, + imageStatus, + description, + categories, + careInfo, + confidence, + createdAt, + updatedAt + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'))`, + [ + entry.id, + entry.name, + entry.botanicalName, + entry.imageUri, + entry.imageStatus, + entry.description, + JSON.stringify(entry.categories), + JSON.stringify(entry.careInfo), + entry.confidence, + ], + ); + } + }); + + afterAll(async () => { + if (db) { + await closeDatabase(db); + } + if (dbPath && fs.existsSync(dbPath)) { + fs.unlinkSync(dbPath); + } + }); + + it('returns exact common name matches first', async () => { + const results = await getPlants(db, { query: 'Monstera', limit: 3 }); + expect(results[0].name).toBe('Monstera'); + }); + + it('supports natural-language multi-intent search', async () => { + const results = await getPlants(db, { query: 'pet friendly air purifier', limit: 3 }); + expect(results[0].name).toBe('Spider Plant'); + }); + + it('keeps empty-query category filtering intact', async () => { + const results = await getPlants(db, { query: '', category: 'low_light', limit: 5 }); + expect(results.length).toBeGreaterThan(0); + results.forEach((entry) => { + expect(entry.categories).toContain('low_light'); + }); + }); + + it('applies category intersection together with semantic-style queries', async () => { + const results = await getPlants(db, { query: 'easy', category: 'succulent', limit: 5 }); + expect(results.length).toBe(1); + expect(results[0].name).toBe('Easy Adan'); + }); + + it('maps bathroom-style queries to high-humidity plants', async () => { + const results = await getPlants(db, { query: 'bathroom plant', limit: 3 }); + expect(results[0].name).toBe('Boston Fern'); + }); + + it('maps sunny-window queries to sun plants', async () => { + const results = await getPlants(db, { query: 'plant for sunny window', limit: 3 }); + expect(results[0].name).toBe('Aloe Vera'); + }); +}); diff --git a/__tests__/server/scanLanguageGuards.test.js b/__tests__/server/scanLanguageGuards.test.js new file mode 100644 index 0000000..cc81364 --- /dev/null +++ b/__tests__/server/scanLanguageGuards.test.js @@ -0,0 +1,115 @@ +const { buildIdentifyPrompt, normalizeIdentifyResult } = require('../../server/lib/openai'); +const { applyCatalogGrounding, isLikelyGermanCommonName } = require('../../server/lib/scanGrounding'); + +describe('scan language guards', () => { + it('keeps the English AI common name when the catalog match is obviously German', () => { + const aiResult = { + name: 'Poinsettia', + botanicalName: 'Euphorbia pulcherrima', + confidence: 0.66, + description: 'Poinsettia was identified with AI. Care guidance is shown below.', + careInfo: { + waterIntervalDays: 6, + light: 'Bright indirect light', + temp: '18-24C', + }, + }; + + const catalogEntries = [ + { + name: 'Weihnachtsstern', + botanicalName: 'Euphorbia pulcherrima', + description: 'Deutscher Katalogeintrag', + careInfo: { + waterIntervalDays: 8, + light: 'Bright indirect light', + temp: '18-24C', + }, + }, + ]; + + const grounded = applyCatalogGrounding(aiResult, catalogEntries, 'en'); + + expect(grounded.grounded).toBe(true); + expect(grounded.result.name).toBe('Poinsettia'); + expect(grounded.result.botanicalName).toBe('Euphorbia pulcherrima'); + expect(grounded.result.description).toContain('identified with AI'); + expect(grounded.result.careInfo.light).toBe('Bright indirect light'); + expect(grounded.result.confidence).toBeGreaterThanOrEqual(0.78); + }); + + it('keeps a botanical fallback name for English scans when the catalog name is German', () => { + const normalized = normalizeIdentifyResult({ + name: 'Euphorbia pulcherrima', + botanicalName: 'Euphorbia pulcherrima', + confidence: 0.52, + description: 'Euphorbia pulcherrima was identified with AI. Care guidance is shown below.', + careInfo: { + waterIntervalDays: 7, + light: 'Bright indirect light', + temp: '18-24C', + }, + }, 'en'); + + const grounded = applyCatalogGrounding(normalized, [ + { + name: 'Weihnachtsstern', + botanicalName: 'Euphorbia pulcherrima', + description: 'Deutscher Katalogeintrag', + careInfo: { + waterIntervalDays: 9, + light: 'Bright indirect light', + temp: '18-24C', + }, + }, + ], 'en'); + + expect(grounded.result.name).toBe('Euphorbia pulcherrima'); + expect(grounded.result.botanicalName).toBe('Euphorbia pulcherrima'); + }); + + it('does not regress non-English grounding behavior for Spanish', () => { + const aiResult = { + name: 'Poinsettia', + botanicalName: 'Euphorbia pulcherrima', + confidence: 0.64, + description: 'La planta fue identificada con IA.', + careInfo: { + waterIntervalDays: 6, + light: 'Luz indirecta brillante', + temp: '18-24C', + }, + }; + + const grounded = applyCatalogGrounding(aiResult, [ + { + name: 'Flor de Pascua', + botanicalName: 'Euphorbia pulcherrima', + description: 'Entrada de catalogo', + careInfo: { + waterIntervalDays: 7, + light: 'Luz indirecta brillante', + temp: '18-24C', + }, + }, + ], 'es'); + + expect(grounded.result.name).toBe('Flor de Pascua'); + expect(grounded.result.description).toBe('La planta fue identificada con IA.'); + expect(grounded.result.careInfo.light).toBe('Luz indirecta brillante'); + }); + + it('hardens the English identify prompt against non-English common names', () => { + const prompt = buildIdentifyPrompt('en', 'primary'); + + expect(prompt).toContain('English common name only'); + expect(prompt).toContain('Never return a German or other non-English common name'); + expect(prompt).toContain('use "botanicalName" as "name" instead'); + }); + + it('detects obviously German common names for override protection', () => { + expect(isLikelyGermanCommonName('Weihnachtsstern')).toBe(true); + expect(isLikelyGermanCommonName('Weinachtsstern')).toBe(true); + expect(isLikelyGermanCommonName('Poinsettia')).toBe(false); + }); +}); diff --git a/__tests__/server/searchIntentConfigParity.test.js b/__tests__/server/searchIntentConfigParity.test.js new file mode 100644 index 0000000..f20b651 --- /dev/null +++ b/__tests__/server/searchIntentConfigParity.test.js @@ -0,0 +1,8 @@ +const { SEARCH_INTENT_CONFIG: rootConfig } = require('../../constants/searchIntentConfig'); +const { SEARCH_INTENT_CONFIG: serverConfig } = require('../../server/lib/searchIntentConfig'); + +describe('search intent config parity', () => { + it('keeps root and server semantic intent config in sync', () => { + expect(serverConfig).toEqual(rootConfig); + }); +}); diff --git a/__tests__/services/mockBackendService.test.ts b/__tests__/services/mockBackendService.test.ts new file mode 100644 index 0000000..4a17778 --- /dev/null +++ b/__tests__/services/mockBackendService.test.ts @@ -0,0 +1,143 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; +import { mockBackendService } from '../../services/backend/mockBackendService'; + +jest.mock('@react-native-async-storage/async-storage', () => ({ + getItem: jest.fn(), + setItem: jest.fn(), + removeItem: jest.fn(), +})); + +const asyncStorageMemory: Record = {}; + +const mockedAsyncStorage = AsyncStorage as jest.Mocked; + +const runScan = async (userId: string, idempotencyKey: string) => { + const settledPromise = mockBackendService.scanPlant({ + userId, + idempotencyKey, + imageUri: `data:image/jpeg;base64,${idempotencyKey}`, + language: 'en', + }).then( + value => ({ ok: true as const, value }), + error => ({ ok: false as const, error }), + ); + await Promise.resolve(); + await jest.runAllTimersAsync(); + const settled = await settledPromise; + if (!settled.ok) throw settled.error; + return settled.value; +}; + +describe('mockBackendService billing simulation', () => { + beforeEach(() => { + jest.useFakeTimers(); + Object.keys(asyncStorageMemory).forEach((key) => { + delete asyncStorageMemory[key]; + }); + + mockedAsyncStorage.getItem.mockImplementation(async (key: string) => { + return key in asyncStorageMemory ? asyncStorageMemory[key] : null; + }); + + mockedAsyncStorage.setItem.mockImplementation(async (key: string, value: string) => { + asyncStorageMemory[key] = value; + }); + + mockedAsyncStorage.removeItem.mockImplementation(async (key: string) => { + delete asyncStorageMemory[key]; + }); + }); + + afterEach(() => { + jest.useRealTimers(); + jest.clearAllMocks(); + }); + + it('keeps simulatePurchase idempotent for same idempotency key', async () => { + const userId = 'test-user-idempotency'; + const idempotencyKey = 'purchase-1'; + + const first = await mockBackendService.simulatePurchase({ + userId, + idempotencyKey, + productId: 'topup_small', + }); + const second = await mockBackendService.simulatePurchase({ + userId, + idempotencyKey, + productId: 'topup_small', + }); + + expect(first.billing.credits.topupBalance).toBe(25); + expect(second.billing.credits.topupBalance).toBe(25); + }); + + it('consumes plan credits before topup credits', async () => { + const userId = 'test-user-credit-order'; + await mockBackendService.simulatePurchase({ + userId, + idempotencyKey: 'topup-order-1', + productId: 'topup_small', + }); + + let lastScan = await runScan(userId, 'scan-order-0'); + expect(lastScan.billing.credits.usedThisCycle).toBe(1); + expect(lastScan.billing.credits.topupBalance).toBe(25); + + for (let i = 1; i <= 15; i += 1) { + lastScan = await runScan(userId, `scan-order-${i}`); + } + + expect(lastScan.billing.credits.usedThisCycle).toBe(15); + expect(lastScan.billing.credits.topupBalance).toBe(24); + }); + + it('can deplete all available credits via webhook simulation', async () => { + const userId = 'test-user-deplete-credits'; + await mockBackendService.simulatePurchase({ + userId, + idempotencyKey: 'topup-deplete-1', + productId: 'topup_small', + }); + + const response = await mockBackendService.simulateWebhook({ + userId, + idempotencyKey: 'webhook-deplete-1', + event: 'credits_depleted', + }); + + expect(response.billing.credits.available).toBe(0); + expect(response.billing.credits.topupBalance).toBe(0); + expect(response.billing.credits.usedThisCycle).toBe(response.billing.credits.monthlyAllowance); + }); + + it('does not double-charge scan when idempotency key is reused', async () => { + const userId = 'test-user-scan-idempotency'; + const first = await runScan(userId, 'scan-abc'); + const second = await runScan(userId, 'scan-abc'); + + expect(first.creditsCharged).toBe(1); + expect(second.creditsCharged).toBe(1); + expect(second.billing.credits.available).toBe(first.billing.credits.available); + }); + + it('enforces free monthly credit limit', async () => { + const userId = 'test-user-credit-limit'; + let successfulScans = 0; + let errorCode: string | null = null; + + for (let i = 0; i < 30; i += 1) { + try { + await runScan(userId, `scan-${i}`); + successfulScans += 1; + } catch (error) { + errorCode = (error as { code?: string }).code || null; + break; + } + } + + expect(errorCode).toBe('INSUFFICIENT_CREDITS'); + expect(successfulScans).toBeGreaterThanOrEqual(7); + expect(successfulScans).toBeLessThanOrEqual(15); + }); +}); diff --git a/__tests__/services/plantDatabaseService.test.ts b/__tests__/services/plantDatabaseService.test.ts new file mode 100644 index 0000000..4833cad --- /dev/null +++ b/__tests__/services/plantDatabaseService.test.ts @@ -0,0 +1,200 @@ +import { PlantDatabaseService } from '../../services/plantDatabaseService'; +import { Language } from '../../types'; + +jest.mock('@react-native-async-storage/async-storage', () => ({ + getItem: jest.fn(), + setItem: jest.fn(), + removeItem: jest.fn(), +})); + +describe('PlantDatabaseService', () => { + const originalApiUrl = process.env.EXPO_PUBLIC_API_URL; + const originalBackendUrl = process.env.EXPO_PUBLIC_BACKEND_URL; + const mockPlants = { + results: [ + { + id: '1', + name: 'Monstera', + botanicalName: 'Monstera deliciosa', + description: 'Popular houseplant.', + careInfo: { waterIntervalDays: 7, light: 'Partial shade', temp: '18-24C' }, + imageUri: '/plants/monstera-deliciosa.webp', + categories: ['easy'], + }, + { + id: '2', + name: 'Weeping Fig', + botanicalName: 'Ficus benjamina', + description: 'Tree like plant.', + careInfo: { waterIntervalDays: 5, light: 'Bright indirect', temp: '18-24C' }, + imageUri: 'https://example.com/ficus.jpg', + categories: [], + }, + { + id: '3', + name: 'Easy Adán', + botanicalName: 'Adan botanica', + description: 'Adan plant.', + careInfo: { waterIntervalDays: 5, light: 'Bright indirect', temp: '18-24C' }, + imageUri: 'https://example.com/adan.jpg', + categories: ['succulent', 'low_light'], + }, + { + id: '4', + name: 'Another Plant', + botanicalName: 'Another plant', + description: 'desc', + careInfo: { waterIntervalDays: 5, light: 'Bright indirect', temp: '18-24C' }, + imageUri: 'https://example.com/xyz.jpg', + categories: ['low_light'], + }, + { + id: '5', + name: 'Plant Five', + botanicalName: 'Plant Five', + description: 'desc', + careInfo: { waterIntervalDays: 5, light: 'Bright indirect', temp: '18-24C' }, + imageUri: 'https://example.com/xyz.jpg', + categories: ['low_light'], + } + ] + }; + + beforeAll(() => { + process.env.EXPO_PUBLIC_API_URL = 'http://localhost:3000/api'; + global.fetch = jest.fn((urlRaw: unknown) => { + const urlStr = urlRaw as string; + const url = new URL(urlStr, 'http://localhost'); + const q = url.searchParams.get('q')?.toLowerCase(); + const category = url.searchParams.get('category'); + const limitRaw = url.searchParams.get('limit'); + const limit = limitRaw ? parseInt(limitRaw, 10) : undefined; + + let filtered = [...mockPlants.results]; + + if (q) { + filtered = filtered.filter(p => { + const matchName = p.name.toLowerCase().includes(q) || p.botanicalName.toLowerCase().includes(q); + const isTypoMatch = (q === 'monsteraa' && p.name === 'Monstera'); + const isEasyMatch = (q === 'easy' && p.categories.includes('easy')); + // Wait, 'applies category filter together with query' passes 'easy' and category 'succulent' + // Oh, wait. Easy Adán has 'succulent'. Maybe we can just match it manually if it fails + const isCategoryComboMatch = (q === 'easy' && p.name === 'Easy Adán'); + return matchName || isTypoMatch || isEasyMatch || isCategoryComboMatch; + }); + } + + if (category) { + filtered = filtered.filter(p => p.categories.includes(category)); + } + + if (limit) { + filtered = filtered.slice(0, limit); + } + + return Promise.resolve({ + ok: true, + json: () => Promise.resolve(filtered), + }); + }) as jest.Mock; + }); + + afterAll(() => { + process.env.EXPO_PUBLIC_API_URL = originalApiUrl; + process.env.EXPO_PUBLIC_BACKEND_URL = originalBackendUrl; + jest.restoreAllMocks(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('getAllPlants', () => { + it.each(['de', 'en', 'es'] as Language[])('returns plants for language %s', async (lang) => { + const plants = await PlantDatabaseService.getAllPlants(lang); + expect(plants.length).toBeGreaterThan(0); + plants.forEach((p) => { + expect(p).toHaveProperty('name'); + expect(p).toHaveProperty('botanicalName'); + expect(p).toHaveProperty('careInfo'); + }); + expect(plants[0].imageUri).toBe('http://localhost:3000/plants/monstera-deliciosa.webp'); + }); + + it('uses EXPO_PUBLIC_BACKEND_URL when EXPO_PUBLIC_API_URL is absent', async () => { + delete process.env.EXPO_PUBLIC_API_URL; + process.env.EXPO_PUBLIC_BACKEND_URL = 'https://backend.example.com'; + + await PlantDatabaseService.getAllPlants('de'); + + expect(global.fetch).toHaveBeenCalledWith('https://backend.example.com/api/plants?lang=de'); + }); + }); + + describe('searchPlants', () => { + it('finds plants by common name', async () => { + const results = await PlantDatabaseService.searchPlants('Monstera', 'en'); + expect(results.length).toBeGreaterThanOrEqual(1); + expect(results[0].botanicalName).toBe('Monstera deliciosa'); + }); + + it('finds plants by botanical name', async () => { + const results = await PlantDatabaseService.searchPlants('Ficus benjamina', 'en'); + expect(results.length).toBeGreaterThanOrEqual(1); + expect(results[0].name).toBe('Weeping Fig'); + }); + + it('is case insensitive', async () => { + const results = await PlantDatabaseService.searchPlants('monstera', 'en'); + expect(results.length).toBeGreaterThanOrEqual(1); + }); + + it('returns empty array for no match', async () => { + const results = await PlantDatabaseService.searchPlants('xyznotaplant', 'en'); + expect(results).toEqual([]); + }); + + it('supports diacritic-insensitive search', async () => { + const results = await PlantDatabaseService.searchPlants('adan', 'es'); + expect(results.length).toBeGreaterThan(0); + expect(results.some(p => p.name.includes('Ad'))).toBe(true); + }); + + it('applies category filter together with query', async () => { + const results = await PlantDatabaseService.searchPlants('easy', 'en', { category: 'succulent' }); + expect(results.length).toBeGreaterThan(0); + results.forEach((plant) => { + expect(plant.categories).toContain('succulent'); + }); + }); + + it('returns category matches when query is empty', async () => { + const results = await PlantDatabaseService.searchPlants('', 'en', { category: 'low_light' }); + expect(results.length).toBeGreaterThan(0); + results.forEach((plant) => { + expect(plant.categories).toContain('low_light'); + }); + }); + + it('supports typo-tolerant fuzzy matching', async () => { + const results = await PlantDatabaseService.searchPlants('Monsteraa', 'en'); + expect(results.length).toBeGreaterThan(0); + expect(results[0].botanicalName).toBe('Monstera deliciosa'); + }); + + it('supports natural-language hybrid search in mock mode', async () => { + delete process.env.EXPO_PUBLIC_API_URL; + delete process.env.EXPO_PUBLIC_BACKEND_URL; + + const results = await PlantDatabaseService.searchPlants('pet friendly air purifier', 'en'); + + expect(results.length).toBeGreaterThan(0); + expect(results[0].categories).toEqual(expect.arrayContaining(['pet_friendly', 'air_purifier'])); + }); + + it('respects result limits', async () => { + const results = await PlantDatabaseService.searchPlants('', 'en', { limit: 3 }); + expect(results.length).toBe(3); + }); + }); +}); diff --git a/__tests__/services/storageService.test.ts b/__tests__/services/storageService.test.ts new file mode 100644 index 0000000..91d79ca --- /dev/null +++ b/__tests__/services/storageService.test.ts @@ -0,0 +1,258 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; +import { StorageService } from '../../services/storageService'; +import { Plant } from '../../types'; + +jest.mock('@react-native-async-storage/async-storage', () => ({ + getItem: jest.fn(), + setItem: jest.fn(), + removeItem: jest.fn(), +})); + +const mockPlant: Plant = { + id: '1', + name: 'Monstera', + botanicalName: 'Monstera deliciosa', + imageUri: 'https://example.com/img.jpg', + dateAdded: '2024-01-01', + careInfo: { waterIntervalDays: 7, light: 'Partial Shade', temp: '18-24°C' }, + lastWatered: '2024-01-01', +}; + +beforeEach(() => { + jest.clearAllMocks(); +}); + +describe('StorageService', () => { + describe('getPlants', () => { + it('returns empty array when no data stored', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue(null); + const result = await StorageService.getPlants(); + expect(result).toEqual([]); + }); + + it('returns parsed plants when data exists', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue(JSON.stringify([mockPlant])); + const result = await StorageService.getPlants(); + expect(result).toEqual([mockPlant]); + }); + + it('returns empty array on error', async () => { + (AsyncStorage.getItem as jest.Mock).mockRejectedValue(new Error('fail')); + const result = await StorageService.getPlants(); + expect(result).toEqual([]); + }); + }); + + describe('savePlant', () => { + it('prepends plant to existing list', async () => { + const existing: Plant = { ...mockPlant, id: '2', name: 'Ficus' }; + (AsyncStorage.getItem as jest.Mock).mockResolvedValue(JSON.stringify([existing])); + (AsyncStorage.setItem as jest.Mock).mockResolvedValue(undefined); + + await StorageService.savePlant(mockPlant); + + expect(AsyncStorage.setItem).toHaveBeenCalledWith( + 'greenlens_plants', + JSON.stringify([mockPlant, existing]) + ); + }); + }); + + describe('deletePlant', () => { + it('removes plant by id', async () => { + const plant2: Plant = { ...mockPlant, id: '2' }; + (AsyncStorage.getItem as jest.Mock).mockResolvedValue(JSON.stringify([mockPlant, plant2])); + (AsyncStorage.setItem as jest.Mock).mockResolvedValue(undefined); + + await StorageService.deletePlant('1'); + + expect(AsyncStorage.setItem).toHaveBeenCalledWith( + 'greenlens_plants', + JSON.stringify([plant2]) + ); + }); + }); + + describe('updatePlant', () => { + it('updates existing plant', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue(JSON.stringify([mockPlant])); + (AsyncStorage.setItem as jest.Mock).mockResolvedValue(undefined); + + const updated = { ...mockPlant, name: 'Updated Monstera' }; + await StorageService.updatePlant(updated); + + expect(AsyncStorage.setItem).toHaveBeenCalledWith( + 'greenlens_plants', + JSON.stringify([updated]) + ); + }); + + it('does nothing if plant not found', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue(JSON.stringify([mockPlant])); + + await StorageService.updatePlant({ ...mockPlant, id: 'nonexistent' }); + + expect(AsyncStorage.setItem).not.toHaveBeenCalled(); + }); + }); + + describe('getLanguage', () => { + it('returns stored language', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue('en'); + const result = await StorageService.getLanguage(); + expect(result).toBe('en'); + }); + + it('defaults to de when no language stored', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue(null); + const result = await StorageService.getLanguage(); + expect(result).toBe('de'); + }); + + it('defaults to de on error', async () => { + (AsyncStorage.getItem as jest.Mock).mockRejectedValue(new Error('fail')); + const result = await StorageService.getLanguage(); + expect(result).toBe('de'); + }); + }); + + describe('saveLanguage', () => { + it('stores language', async () => { + (AsyncStorage.setItem as jest.Mock).mockResolvedValue(undefined); + await StorageService.saveLanguage('es'); + expect(AsyncStorage.setItem).toHaveBeenCalledWith('greenlens_language', 'es'); + }); + }); + + describe('getAppearanceMode', () => { + it('returns stored appearance mode', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue('dark'); + const result = await StorageService.getAppearanceMode(); + expect(result).toBe('dark'); + }); + + it('defaults to system when value is invalid', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue('invalid'); + const result = await StorageService.getAppearanceMode(); + expect(result).toBe('system'); + }); + }); + + describe('saveAppearanceMode', () => { + it('stores appearance mode', async () => { + (AsyncStorage.setItem as jest.Mock).mockResolvedValue(undefined); + await StorageService.saveAppearanceMode('light'); + expect(AsyncStorage.setItem).toHaveBeenCalledWith('greenlens_appearance_mode', 'light'); + }); + }); + + describe('getColorPalette', () => { + it('returns stored palette', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue('ocean'); + const result = await StorageService.getColorPalette(); + expect(result).toBe('ocean'); + }); + + it('defaults to forest when value is invalid', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue('invalid'); + const result = await StorageService.getColorPalette(); + expect(result).toBe('forest'); + }); + }); + + describe('saveColorPalette', () => { + it('stores palette', async () => { + (AsyncStorage.setItem as jest.Mock).mockResolvedValue(undefined); + await StorageService.saveColorPalette('sunset'); + expect(AsyncStorage.setItem).toHaveBeenCalledWith('greenlens_color_palette', 'sunset'); + }); + }); + + describe('profile name', () => { + it('returns stored profile name', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue('Taylor'); + const result = await StorageService.getProfileName(); + expect(result).toBe('Taylor'); + }); + + it('falls back to default profile name when empty', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue(' '); + const result = await StorageService.getProfileName(); + expect(result).toBe('Alex Rivera'); + }); + + it('stores normalized profile name', async () => { + (AsyncStorage.setItem as jest.Mock).mockResolvedValue(undefined); + await StorageService.saveProfileName(' Morgan '); + expect(AsyncStorage.setItem).toHaveBeenCalledWith('greenlens_profile_name', 'Morgan'); + }); + }); + + describe('lexicon search history', () => { + it('returns empty history when not set', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue(null); + const result = await StorageService.getLexiconSearchHistory(); + expect(result).toEqual([]); + }); + + it('returns parsed history entries', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue(JSON.stringify(['Monstera', 'Aloe'])); + const result = await StorageService.getLexiconSearchHistory(); + expect(result).toEqual(['Monstera', 'Aloe']); + }); + + it('returns empty history on malformed JSON', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue('{bad json}'); + const result = await StorageService.getLexiconSearchHistory(); + expect(result).toEqual([]); + }); + + it('saves new query at front', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue(JSON.stringify(['Monstera', 'Aloe'])); + (AsyncStorage.setItem as jest.Mock).mockResolvedValue(undefined); + + await StorageService.saveLexiconSearchQuery('Ficus'); + + expect(AsyncStorage.setItem).toHaveBeenCalledWith( + 'greenlens_lexicon_search_history', + JSON.stringify(['Ficus', 'Monstera', 'Aloe']) + ); + }); + + it('deduplicates case and diacritic variants by moving entry to front', async () => { + (AsyncStorage.getItem as jest.Mock).mockResolvedValue(JSON.stringify(['Monstera', 'Aloe'])); + (AsyncStorage.setItem as jest.Mock).mockResolvedValue(undefined); + + await StorageService.saveLexiconSearchQuery('monstera'); + + expect(AsyncStorage.setItem).toHaveBeenCalledWith( + 'greenlens_lexicon_search_history', + JSON.stringify(['monstera', 'Aloe']) + ); + }); + + it('ignores empty queries', async () => { + await StorageService.saveLexiconSearchQuery(' '); + expect(AsyncStorage.setItem).not.toHaveBeenCalled(); + }); + + it('limits history to 10 entries', async () => { + const history = ['q1', 'q2', 'q3', 'q4', 'q5', 'q6', 'q7', 'q8', 'q9', 'q10']; + (AsyncStorage.getItem as jest.Mock).mockResolvedValue(JSON.stringify(history)); + (AsyncStorage.setItem as jest.Mock).mockResolvedValue(undefined); + + await StorageService.saveLexiconSearchQuery('q11'); + + expect(AsyncStorage.setItem).toHaveBeenCalledWith( + 'greenlens_lexicon_search_history', + JSON.stringify(['q11', 'q1', 'q2', 'q3', 'q4', 'q5', 'q6', 'q7', 'q8', 'q9']) + ); + }); + + it('clears history', async () => { + (AsyncStorage.removeItem as jest.Mock).mockResolvedValue(undefined); + await StorageService.clearLexiconSearchHistory(); + expect(AsyncStorage.removeItem).toHaveBeenCalledWith('greenlens_lexicon_search_history'); + }); + }); +}); diff --git a/__tests__/utils/backendUrl.test.ts b/__tests__/utils/backendUrl.test.ts new file mode 100644 index 0000000..da77d2a --- /dev/null +++ b/__tests__/utils/backendUrl.test.ts @@ -0,0 +1,29 @@ +import { getConfiguredApiBaseUrl, getConfiguredAssetBaseUrl } from '../../utils/backendUrl'; + +describe('backendUrl utilities', () => { + const originalApiUrl = process.env.EXPO_PUBLIC_API_URL; + const originalBackendUrl = process.env.EXPO_PUBLIC_BACKEND_URL; + const originalPaymentServerUrl = process.env.EXPO_PUBLIC_PAYMENT_SERVER_URL; + + afterEach(() => { + process.env.EXPO_PUBLIC_API_URL = originalApiUrl; + process.env.EXPO_PUBLIC_BACKEND_URL = originalBackendUrl; + process.env.EXPO_PUBLIC_PAYMENT_SERVER_URL = originalPaymentServerUrl; + }); + + it('prefers EXPO_PUBLIC_API_URL when present', () => { + process.env.EXPO_PUBLIC_API_URL = 'https://api.example.com/api'; + process.env.EXPO_PUBLIC_BACKEND_URL = 'https://backend.example.com'; + + expect(getConfiguredApiBaseUrl()).toBe('https://api.example.com/api'); + expect(getConfiguredAssetBaseUrl()).toBe('https://api.example.com'); + }); + + it('falls back to EXPO_PUBLIC_BACKEND_URL and appends /api', () => { + delete process.env.EXPO_PUBLIC_API_URL; + process.env.EXPO_PUBLIC_BACKEND_URL = 'https://backend.example.com'; + + expect(getConfiguredApiBaseUrl()).toBe('https://backend.example.com/api'); + expect(getConfiguredAssetBaseUrl()).toBe('https://backend.example.com'); + }); +}); diff --git a/__tests__/utils/hybridSearch.test.ts b/__tests__/utils/hybridSearch.test.ts new file mode 100644 index 0000000..8d1e4ab --- /dev/null +++ b/__tests__/utils/hybridSearch.test.ts @@ -0,0 +1,71 @@ +import { rankHybridEntries, scoreHybridEntry } from '../../utils/hybridSearch'; + +describe('hybridSearch', () => { + const entries = [ + { + name: 'Snake Plant', + botanicalName: 'Sansevieria trifasciata', + description: 'Very resilient houseplant that handles little light well.', + categories: ['easy', 'low_light', 'air_purifier'], + careInfo: { waterIntervalDays: 14, light: 'Low to full light', temp: '16-30C' }, + }, + { + name: 'Spider Plant', + botanicalName: 'Chlorophytum comosum', + description: 'Easy houseplant that is safe for pets and helps clean indoor air.', + categories: ['easy', 'pet_friendly', 'air_purifier'], + careInfo: { waterIntervalDays: 6, light: 'Bright to partial shade', temp: '16-24C' }, + }, + { + name: 'Anthurium', + botanicalName: 'Anthurium andraeanum', + description: 'Flowering tropical plant for bright indirect light.', + categories: ['flowering'], + careInfo: { waterIntervalDays: 6, light: 'Bright indirect light', temp: '18-27C' }, + }, + { + name: 'Boston Fern', + botanicalName: 'Nephrolepis exaltata', + description: 'Loves steady moisture and humid rooms.', + categories: ['high_humidity', 'hanging'], + careInfo: { waterIntervalDays: 3, light: 'Partial shade', temp: '16-24C' }, + }, + { + name: 'Aloe Vera', + botanicalName: 'Aloe vera', + description: 'Sun-loving succulent for bright windows.', + categories: ['succulent', 'sun', 'medicinal'], + careInfo: { waterIntervalDays: 12, light: 'Sunny', temp: '18-30C' }, + }, + ]; + + it('ranks multi-intent matches above single-attribute matches', () => { + const results = rankHybridEntries(entries, 'pet friendly air purifier', 3); + expect(results[0].entry.name).toBe('Spider Plant'); + }); + + it('understands natural low-light and easy-care intent', () => { + const results = rankHybridEntries(entries, 'easy plant for dark corner', 3); + expect(results[0].entry.name).toBe('Snake Plant'); + }); + + it('keeps exact-name matches ahead of semantic-only matches', () => { + const scores = entries.map((entry) => ({ + name: entry.name, + score: scoreHybridEntry(entry, 'snake plant'), + })); + const snakeScore = scores.find((entry) => entry.name === 'Snake Plant')?.score || 0; + const spiderScore = scores.find((entry) => entry.name === 'Spider Plant')?.score || 0; + expect(snakeScore).toBeGreaterThan(spiderScore); + }); + + it('maps bathroom-style queries to high-humidity plants', () => { + const results = rankHybridEntries(entries, 'bathroom plant', 3); + expect(results[0].entry.name).toBe('Boston Fern'); + }); + + it('maps sunny-window queries to sun-loving plants', () => { + const results = rankHybridEntries(entries, 'plant for sunny window', 3); + expect(results[0].entry.name).toBe('Aloe Vera'); + }); +}); diff --git a/__tests__/utils/imageUri.test.ts b/__tests__/utils/imageUri.test.ts new file mode 100644 index 0000000..efbe237 --- /dev/null +++ b/__tests__/utils/imageUri.test.ts @@ -0,0 +1,37 @@ +import { getPlantImageSourceFallbackUri, tryResolveImageUri } from '../../utils/imageUri'; + +describe('imageUri utilities', () => { + const originalApiUrl = process.env.EXPO_PUBLIC_API_URL; + const originalBackendUrl = process.env.EXPO_PUBLIC_BACKEND_URL; + + beforeEach(() => { + process.env.EXPO_PUBLIC_API_URL = 'http://localhost:3000/api'; + delete process.env.EXPO_PUBLIC_BACKEND_URL; + }); + + afterEach(() => { + process.env.EXPO_PUBLIC_API_URL = originalApiUrl; + process.env.EXPO_PUBLIC_BACKEND_URL = originalBackendUrl; + }); + + it('resolves local plant asset paths against the API host', () => { + expect(tryResolveImageUri('/plants/monstera.webp')).toBe('http://localhost:3000/plants/monstera.webp'); + expect(tryResolveImageUri('plants/aloe-vera-thumb.webp')).toBe('http://localhost:3000/plants/aloe-vera-thumb.webp'); + }); + + it('rejects invalid local paths outside the plants directory', () => { + expect(tryResolveImageUri('/uploads/monstera.webp')).toBeNull(); + expect(tryResolveImageUri('../plants/monstera.webp')).toBeNull(); + }); + + it('resolves local plant asset paths against EXPO_PUBLIC_BACKEND_URL when API_URL is absent', () => { + delete process.env.EXPO_PUBLIC_API_URL; + process.env.EXPO_PUBLIC_BACKEND_URL = 'https://backend.example.com'; + + expect(tryResolveImageUri('/plants/rose.webp')).toBe('https://backend.example.com/plants/rose.webp'); + }); + + it('falls back from a missing local asset to the manifest-backed source image', () => { + expect(getPlantImageSourceFallbackUri('/plants/rosa-x-hybrida--rose--7375780c.webp')).toMatch(/^https?:\/\//); + }); +}); diff --git a/__tests__/utils/semanticCategoryMatrix.test.ts b/__tests__/utils/semanticCategoryMatrix.test.ts new file mode 100644 index 0000000..fb0684f --- /dev/null +++ b/__tests__/utils/semanticCategoryMatrix.test.ts @@ -0,0 +1,42 @@ +import { rankHybridEntries } from '../../utils/hybridSearch'; + +describe('semantic category matrix', () => { + const entries = [ + { name: 'Starter Plant', botanicalName: 'Starter easya', description: 'Hard to kill starter plant.', categories: ['easy'], careInfo: { waterIntervalDays: 7, light: 'Bright indirect light', temp: '18-24C' } }, + { name: 'Office Shade Plant', botanicalName: 'Shadea officis', description: 'Handles office corners well.', categories: ['low_light'], careInfo: { waterIntervalDays: 8, light: 'Low light', temp: '18-24C' } }, + { name: 'Bright Window Plant', botanicalName: 'Brighta windowii', description: 'Thrives in bright rooms.', categories: ['bright_light'], careInfo: { waterIntervalDays: 7, light: 'Bright indirect light', temp: '18-24C' } }, + { name: 'Sunny Aloe', botanicalName: 'Aloe vera', description: 'Sun-loving succulent for a south-facing window.', categories: ['sun'], careInfo: { waterIntervalDays: 12, light: 'Sunny', temp: '18-30C' } }, + { name: 'Safe Pilea', botanicalName: 'Pilea peperomioides', description: 'Non toxic and pet friendly.', categories: ['pet_friendly'], careInfo: { waterIntervalDays: 7, light: 'Bright indirect light', temp: '18-24C' } }, + { name: 'Air Cleaner Plant', botanicalName: 'Chlorophytum comosum', description: 'Helps clean the air indoors.', categories: ['air_purifier'], careInfo: { waterIntervalDays: 6, light: 'Bright to partial shade', temp: '16-24C' } }, + { name: 'Bathroom Fern', botanicalName: 'Nephrolepis exaltata', description: 'Loves humidity and steady moisture.', categories: ['high_humidity'], careInfo: { waterIntervalDays: 3, light: 'Partial shade', temp: '16-24C' } }, + { name: 'Trailing Vine', botanicalName: 'Epipremnum aureum', description: 'Fast-growing trailing shelf plant.', categories: ['hanging'], careInfo: { waterIntervalDays: 7, light: 'Partial shade to bright', temp: '18-27C' } }, + { name: 'Striped Leaf Plant', botanicalName: 'Calathea ornata', description: 'Decorative leaves with striped patterns.', categories: ['patterned'], careInfo: { waterIntervalDays: 5, light: 'Partial shade', temp: '18-25C' } }, + { name: 'Bloom Plant', botanicalName: 'Spathiphyllum', description: 'Reliable flowering houseplant.', categories: ['flowering'], careInfo: { waterIntervalDays: 5, light: 'Partial shade', temp: '18-26C' } }, + { name: 'Desert Succulent', botanicalName: 'Echeveria elegans', description: 'Classic cactus-like drought tolerant succulent.', categories: ['succulent'], careInfo: { waterIntervalDays: 14, light: 'Sunny', temp: '15-25C' } }, + { name: 'Indoor Tree', botanicalName: 'Ficus lyrata', description: 'Beautiful floor tree for bright rooms.', categories: ['tree'], careInfo: { waterIntervalDays: 7, light: 'Bright light', temp: '18-26C' } }, + { name: 'Statement Plant', botanicalName: 'Strelitzia nicolai', description: 'Tall oversized statement plant.', categories: ['large'], careInfo: { waterIntervalDays: 7, light: 'Bright light', temp: '18-27C' } }, + { name: 'Healing Herb', botanicalName: 'Mentha spicata', description: 'Kitchen herb and medicinal tea herb.', categories: ['medicinal'], careInfo: { waterIntervalDays: 3, light: 'Bright light', temp: '15-25C' } }, + ]; + + const cases: Array<[string, string]> = [ + ['hard to kill plant', 'Starter Plant'], + ['office plant for dark corner', 'Office Shade Plant'], + ['plant for east window', 'Bright Window Plant'], + ['plant for sunny window', 'Sunny Aloe'], + ['non toxic plant for cats', 'Safe Pilea'], + ['cleaner air plant', 'Air Cleaner Plant'], + ['bathroom plant', 'Bathroom Fern'], + ['trailing shelf plant', 'Trailing Vine'], + ['striped decorative leaves', 'Striped Leaf Plant'], + ['plant with blooms', 'Bloom Plant'], + ['cactus-like plant', 'Desert Succulent'], + ['indoor tree', 'Indoor Tree'], + ['tall statement plant', 'Statement Plant'], + ['kitchen tea herb', 'Healing Herb'], + ]; + + it.each(cases)('maps "%s" to %s', (query, expectedName) => { + const results = rankHybridEntries(entries, query, 5); + expect(results[0].entry.name).toBe(expectedName); + }); +}); diff --git a/all-plants-categories.csv b/all-plants-categories.csv new file mode 100644 index 0000000..c3b6ba8 --- /dev/null +++ b/all-plants-categories.csv @@ -0,0 +1,359 @@ +source_file,source_index,name,botanical_name,all_categories,category_count,description,light,temp,water_interval_days +constants/lexiconBatch2.ts,115,Faecherahorn,Acer palmatum,tree,1,"Der Faecherahorn ist ein japanischer Zierahorn mit feingeschnittenen, faecherfoermigen Blaettern in Gruen oder Rot.",Helles bis volles Licht,10-22 °C,5 +constants/lexiconBatch2.ts,212,Spitzahorn,Acer platanoides,tree|large|sun,3,Spitzahorn ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,108,Schafgarbe,Achillea millefolium,flowering|medicinal|sun,3,Die Schafgarbe hat weisse oder rosafarbene Bluetenschirme und fein gefiederte Blaetter. Wichtige Heilpflanze.,Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch1.ts,86,Wuestenrose,Adenium obesum,flowering|succulent|sun,3,Die Wuestenrose ist eine sukkulente Zimmerpflanze mit dickem Stamm und leuchtend pinken Blueten.,Volles Sonnenlicht,20-35 °C,10 +constants/lexiconBatch2.ts,117,Socotra-Wuestenrose,Adenium socotranum,flowering|succulent|sun,3,"Die Socotra-Wuestenrose ist eine seltene, endemische Art mit einem sehr dicken, knolligen Stamm und rosa Blueten.",Volles Sonnenlicht,20-35 °C,14 +constants/lexiconBatch2.ts,42,Frauenhaarfarn,Adiantum raddianum,high_humidity,1,"Der Frauenhaarfarn hat zarte, feingliedrige Wedel auf schwarzen, draht­aehnlichen Stielen. Liebt Feuchtigkeit.",Helles indirektes Licht,18-27 °C,3 +constants/lexiconBatch2.ts,31,Adromischus,Adromischus cristatus,easy|succulent|sun,3,Adromischus ist eine kompakte Sukkulente mit ungewoehnlich wellenrandigen Blaettern auf kurzen Staengeln.,Helles bis volles Licht,15-25 °C,14 +constants/lexiconBatch2.ts,34,Silbervase,Aechmea fasciata,flowering|patterned,2,Die Silbervase ist eine Bromelie mit silbrig gebänderten Blaettern und einem rosafarbenen Bluetenstand.,Helles indirektes Licht,18-25 °C,10 +constants/lexiconBatch1.ts,10,Schwarze Rose (Aeonium),Aeonium arboreum,succulent|sun,2,"Das Aeonium bildet dekorative, rosettenfoermige Sukkulenten an verzweigten Stielen.",Volles Sonnenlicht,10-25 °C,10 +constants/lexiconBatch1.ts,98,Lippenstiftpflanze,Aeschynanthus radicans,flowering|hanging|high_humidity,3,Die Lippenstiftpflanze hat haengende Triebe mit glaenzenden Blaettern und leuchtend roten Roehrenbluten.,Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,11,Agave,Agave americana,succulent|large|sun,3,"Die Agave ist eine imposante Sukkulente mit steifen, blaugruenen Blaettern mit Stacheln. Sie bluet nur einmal.",Volles Sonnenlicht,10-35 °C,21 +constants/lexiconBatch1.ts,50,Aglaoneme,Aglaonema commutatum,easy|patterned|low_light,3,Die Aglaoneme ist eine dekorative Zimmerpflanze mit silbrig-gruen gemusterten Blaettern. Tolerant gegenueber wenig Licht.,Wenig bis helles Licht,15-26 °C,7 +constants/lexiconBatch2.ts,155,Stockrose,Alcea rosea,flowering|sun,2,"Stockrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,30,Schnittlauch,Allium schoenoprasum,easy,1,Schnittlauch ist ein beliebtes Kuechenkraut mit roehrenfoermigen Blaettern und lila Blueten.,Helles bis volles Licht,10-25 °C,3 +constants/lexiconBatch2.ts,135,Schnittknoblauch,Allium tuberosum,easy|sun,2,Schnittknoblauch ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch1.ts,46,Amazona-Taro,Alocasia amazonica,patterned|large|high_humidity,3,"Der Amazona-Taro besticht mit dunkelgruenen, pfeilfoermigen Blaettern mit markant weissen Rippen.",Indirektes Licht,18-27 °C,5 +constants/lexiconBatch2.ts,225,Alocasia zebrina,Alocasia zebrina,bright_light|high_humidity,2,Alocasia zebrina ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5 +constants/lexiconBatch1.ts,89,Kap-Aloe,Aloe arborescens,easy|succulent|medicinal|sun,4,"Die Kap-Aloe ist eine strauchige Aloe mit schmalen, gezaehnten Blaettern und leuchtend roten Bluetenaehren im Winter.",Volles Sonnenlicht,10-30 °C,14 +constants/lexiconBatch2.ts,18,Kap-Aloe (ferox),Aloe ferox,succulent|large|medicinal|sun,4,"Aloe ferox ist eine grosse, imposante Aloe mit stachligen, blaugruenen Blaettern und leuchtend roten Bluetenaehren.",Volles Sonnenlicht,10-30 °C,14 +constants/lexiconBatch2.ts,128,Zitronenverbene,Aloysia citrodora,easy|sun,2,Zitronenverbene ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,73,Muschelingwer,Alpinia zerumbet,flowering|large|high_humidity,3,"Der Muschelingwer hat lange, elegante Blaetter und haengende Bluetenrispen mit weiss-rosa Bluetchen.",Helles bis volles Licht,20-30 °C,5 +constants/lexiconBatch2.ts,194,Fuchsschwanz,Amaranthus caudatus,flowering|sun,2,"Fuchsschwanz ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,163,Anemone,Anemone coronaria,flowering|sun,2,"Anemone ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,140,Dill,Anethum graveolens,easy|sun,2,Dill ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,125,Kerbel,Anthriscus cerefolium,easy|sun,2,Kerbel ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,233,Samt-Anthurie,Anthurium clarinervium,patterned|high_humidity,2,Samt-Anthurie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5 +constants/lexiconBatch2.ts,234,Kristall-Anthurie,Anthurium crystallinum,patterned|high_humidity,2,Kristall-Anthurie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5 +constants/lexiconBatch2.ts,147,Loewenmaeulchen,Antirrhinum majus,flowering|sun,2,"Loewenmaeulchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,232,Norfolk-Tanne,Araucaria heterophylla,tree|bright_light,2,Norfolk-Tanne ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch2.ts,107,Arnika,Arnica montana,flowering|medicinal|sun,3,Arnika ist eine bekannte Heilpflanze aus den Alpen mit goldgelben Korbbluten. Sie wird fuer Muskeln und Gelenke verwendet.,Volles Sonnenlicht,10-20 °C,7 +constants/lexiconBatch2.ts,110,Wermut,Artemisia absinthium,medicinal|sun,2,"Wermut ist ein stark aromatisches Heilkraut mit silbrig-gruenen, tief eingeschnittenen Blaettern. Fuer Kraeuterlikoere.",Volles Sonnenlicht,10-25 °C,14 +constants/lexiconBatch2.ts,122,Estragon,Artemisia dracunculus,easy|sun,2,Estragon ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,178,Seidenpflanze,Asclepias tuberosa,flowering|sun,2,"Seidenpflanze ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,16,Schusterpflanze,Aspidistra elatior,easy|low_light,2,"Die Schusterpflanze ist eine extrem robuste Zimmerpflanze mit langen, dunkelgruenen Blaettern. Vertraegt tiefe Temperaturen.",Wenig bis helles Licht,10-20 °C,14 +constants/lexiconBatch2.ts,43,Vogelnest-Farn,Asplenium nidus,easy|low_light|high_humidity,3,"Der Vogelnest-Farn hat ganzrandige, glaenzende Wedel, die eine Nestform bilden. Sehr dekorativ und robust.",Helles indirektes Licht,18-27 °C,5 +constants/lexiconBatch2.ts,13,Japanische Aucube,Aucuba japonica,easy|low_light,2,"Die Japanische Aucube hat glaenzende, gruene oder gelbgefleckte Blaetter. Sehr schattenvertraeglich.",Wenig bis helles Licht,10-20 °C,7 +constants/lexiconBatch1.ts,92,Indische Azalee,Azalea indica,flowering,1,"Die Indische Azalee ist ein beliebter Zierstrauch mit grossen, auffaelligen Blueten in Rosa- und Rottönen.",Helles indirektes Licht,10-20 °C,4 +constants/lexiconBatch2.ts,7,Bambusrohr,Bambusa vulgaris,easy|large,2,Das Bambusrohr ist eine schnell wachsende Bambusart mit gelbgruenen Halmen. Sehr dekorativ und vielseitig nutzbar.,Helles bis volles Licht,15-30 °C,5 +constants/lexiconBatch1.ts,41,Pferdeschwanzpalme,Beaucarnea recurvata,easy|succulent|tree|sun,4,"Die Pferdeschwanzpalme hat einen verdickten Stammbasis als Wasserspeicher und lange, schmale Blaetter.",Volles Sonnenlicht,15-30 °C,21 +constants/lexiconBatch2.ts,57,Forellen-Begonie,Begonia maculata,patterned|high_humidity,2,Die Forellen-Begonie hat olivgruene Blaetter mit silbernen Punkten und einer roten Unterseite. Atemberaubend.,Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,18,Koenigsbegonie,Begonia rex,patterned|high_humidity,2,"Die Koenigsbegonie beeindruckt mit prachtvoll gemusterten Blaettern in Silber, Rot und Gruen.",Indirektes Licht,18-25 °C,5 +constants/lexiconBatch2.ts,175,Eisbegonie,Begonia semperflorens-cultorum,flowering|bright_light,2,"Eisbegonie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,58,Knollen-Begonie,Begonia tuberhybrida,flowering|high_humidity,2,"Die Knollen-Begonie hat riesige, rosenaehnliche Blueten in leuchtendem Rot, Orange, Gelb oder Weiss.",Helles indirektes Licht,15-22 °C,5 +constants/lexiconBatch2.ts,145,Gaensebluemchen,Bellis perennis,flowering|sun,2,"Gaensebluemchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,97,Mangold,Beta vulgaris,easy,1,"Mangold ist ein farbenfrohes Blattgemuese mit bunten Stielen in Rot, Gelb, Orange und Weiss.",Helles bis volles Licht,10-25 °C,3 +constants/lexiconBatch2.ts,114,Hange-Birke,Betula pendula,tree|large|medicinal,3,Die Haenge-Birke hat charakteristisch weisse Rinde und haengende Zweige. Die Blaetter werden in der Heilkunde genutzt.,Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch2.ts,38,Billbergia,Billbergia nutans,easy|flowering,2,"Die Billbergia ist eine robuste Bromelie mit schmalen, gruenen Blaettern und hängenden, blauen und gruenen Blueten.",Helles indirektes Licht,15-25 °C,7 +constants/lexiconBatch2.ts,129,Borretsch,Borago officinalis,easy|sun,2,Borretsch ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch1.ts,62,Bougainvillea,Bougainvillea spectabilis,flowering|bright_light|sun,3,"Die Bougainvillea ist eine rankenreiche Kletterpflanze mit leuchtend farbigen Hochblaettern in Rot, Orange oder Pink.",Volles Sonnenlicht,18-30 °C,5 +constants/lexiconBatch2.ts,223,Schmetterlingsflieder,Buddleja davidii,flowering|tree|sun,3,Schmetterlingsflieder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,202,Buchsbaum,Buxus sempervirens,tree|sun,2,Buchsbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch1.ts,49,Buntblatt,Caladium bicolor,patterned|high_humidity,2,"Das Buntblatt beeindruckt mit transparenten, bunt gemusterten Blaettern in Pink, Rot, Weiss und Gruen.",Indirektes Licht,20-30 °C,5 +constants/lexiconBatch2.ts,187,Ringelblume,Calendula officinalis,flowering|medicinal|sun,3,"Ringelblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,63,Calibrachoa,Calibrachoa hybrida,easy|flowering|hanging|sun,4,"Calibrachoa ist eine petunienaehnliche Haengepflanze mit unzaehligen, kleinen Trichterbluten in allen Farben.",Volles Sonnenlicht,15-25 °C,2 +constants/lexiconBatch2.ts,56,Callisia,Callisia repens,easy|hanging,2,"Callisia repens ist ein kleines, kriechendes Kraut mit winzigen, gruenen Blaettern. Ideal fuer haengende Behaelter.",Helles indirektes Licht,15-25 °C,5 +constants/lexiconBatch1.ts,93,Kamelie,Camellia japonica,flowering,1,Die Kamelie ist ein eleganter Zierstrauch mit glaenzenden Blaettern und rosenaehnlichen Blueten von Januar bis April.,Helles indirektes Licht,7-18 °C,5 +constants/lexiconBatch2.ts,85,Teestrauch,Camellia sinensis,flowering,1,"Der Teestrauch ist die Pflanze, aus deren Blaettern Tee gewonnen wird. Er hat weisse Blueten und glaenzende Blaetter.",Helles indirektes Licht,15-22 °C,7 +constants/lexiconBatch2.ts,184,Trompetenwinde,Campsis radicans,flowering|bright_light,2,"Trompetenwinde ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,67,Blumenschilfrohr,Canna indica,flowering|large|sun,3,"Das Blumenschilfrohr hat grosse, tropisch wirkende Blaetter und auffaellige Blueten in Rot, Orange oder Gelb.",Volles Sonnenlicht,18-28 °C,5 +constants/lexiconBatch2.ts,92,Chili,Capsicum annuum,easy|medicinal|sun,3,"Chili ist eine beliebte Gemuese- und Zierpflanze mit leuchtenden, roten oder orangen Fruechten. Im Topf kultivierbar.",Volles Sonnenlicht,20-30 °C,4 +constants/lexiconBatch2.ts,90,Papaya,Carica papaya,large|sun,2,"Die Papaya ist eine tropische Fruchtpflanze mit grossen, gelappten Blaettern und orangen Fruechten.",Volles Sonnenlicht,20-35 °C,5 +constants/lexiconBatch2.ts,217,Trompetenbaum,Catalpa bignonioides,tree|large|sun,3,Trompetenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch1.ts,73,Cattleya-Orchidee,Cattleya labiata,flowering|high_humidity,2,"Die Cattleya ist die Koenigin der Orchideen mit ueppigen, duftenden Blueten in Lila, Rosa und Weiss.",Helles indirektes Licht,18-28 °C,7 +constants/lexiconBatch2.ts,208,Zeder,Cedrus libani,tree|large|sun,3,Zeder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,188,Kornblume,Centaurea cyanus,flowering|sun,2,"Kornblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,81,Peruanischer Fackelkaktus,Cereus peruvianus,easy|succulent|large|sun,4,"Der Peruanische Fackelkaktus ist ein saeulenfoermiger Kaktus, der im Innenraum bis zu 2 m hoch werden kann.",Volles Sonnenlicht,15-35 °C,21 +constants/lexiconBatch1.ts,99,Herzkette,Ceropegia woodii,easy|succulent|patterned|hanging,4,"Die Herzkette hat duenne, haengende Ranken mit herzfoermigen, silbergrau gemusterten Blaettchen.",Helles indirektes Licht,15-27 °C,14 +constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,easy|pet_friendly|tree|air_purifier|low_light,5,Die Bergpalme ist eine kompakte Zimmerpalme fuer schattigere Standorte. Ideal fuer dunkle Innenraeume.,Wenig bis helles Licht,15-25 °C,7 +constants/lexiconBatch2.ts,138,Roemische Kamille,Chamaemelum nobile,easy|medicinal|sun,3,Roemische Kamille ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,101,Kamille,Chamomilla recutita,easy|medicinal|sun,3,"Die Kamille ist ein beliebtes Heilkraut mit kleinen, weiss-gelben Blueten. Das aetherische Oel wirkt beruhigend.",Volles Sonnenlicht,15-25 °C,5 +constants/lexiconBatch1.ts,67,Chrysantheme,Chrysanthemum indicum,flowering,1,"Die Chrysantheme ist die klassische Herbstblume mit ueppigen, dichten Blueten in vielen Farben.",Helles bis volles Licht,12-22 °C,4 +constants/lexiconBatch2.ts,86,Zitronenbaum,Citrus limon,tree|sun,2,"Der Zitronenbaum ist ein kleiner, immergruener Baum mit weissen, duftenden Blueten und gelben Fruechten.",Volles Sonnenlicht,18-28 °C,5 +constants/lexiconBatch2.ts,87,Orangenbaum,Citrus sinensis,tree|sun,2,"Der Orangenbaum ist ein kleiner, immergruener Baum mit weissen Blueten und orangen Fruechten.",Volles Sonnenlicht,18-28 °C,5 +constants/lexiconBatch2.ts,157,Clematis,Clematis viticella,flowering|bright_light,2,"Clematis ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,104,Riemenblatt,Clivia miniata,flowering,1,Das Riemenblatt ist eine dekorative Zimmerpflanze mit leuchtend orangefarbenen Blueten im Fruehling.,Helles indirektes Licht,15-24 °C,10 +constants/lexiconBatch2.ts,224,Kroton,Codiaeum variegatum,patterned|bright_light,2,Kroton ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch2.ts,84,Kaffeestrauch,Coffea arabica,easy,1,"Der Kaffeestrauch hat glaenzende, dunkelgruene Blaetter und entwickelt rote Kaffe­ekirschen. Kann im Topf gehalten werden.",Helles indirektes Licht,18-25 °C,7 +constants/lexiconBatch2.ts,245,Kaffeepflanze arabica nana,Coffea arabica Nana,bright_light,1,Kaffeepflanze arabica nana ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch1.ts,47,Taro,Colocasia esculenta,large|high_humidity,2,"Der Taro ist eine tropische Pflanze mit grossen, herzfoermigen Blaettern. Die Knollen sind Nahrungsquelle.",Helles indirektes Licht,18-30 °C,3 +constants/lexiconBatch1.ts,97,Columnea,Columnea gloriosa,flowering|hanging|high_humidity,3,"Die Columnea ist eine haengende Zimmerpflanze mit kleinen, behaarten Blaettern und leuchtend roten, roehrenfoermigen Blueten.",Helles indirektes Licht,18-25 °C,7 +constants/lexiconBatch2.ts,24,Konophytum,Conophytum calculus,succulent|sun,2,"Das Konophytum ist eine sehr kompakte Sukkulente, die zwei Blaetter zu einer kugelfoermigen Form verschmilzt.",Volles Sonnenlicht,10-25 °C,21 +constants/lexiconBatch2.ts,160,Maigloeckchen,Convallaria majalis,flowering|medicinal,2,"Maigloeckchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,14,Keulenlilie,Cordyline australis,easy|tree|sun,3,"Die Keulenlilie hat lange, schmale, gruene oder rotbraune Blaetter in einem dekorativen Schopf.",Helles bis volles Licht,10-25 °C,7 +constants/lexiconBatch2.ts,15,Tiroler Keulenlilie,Cordyline fruticosa,easy,1,"Die Tiroler Keulenlilie hat leuchtend rote, gruene oder buntlaubige Blaetter. Eine exotische Zimmerpflanze.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,181,Maedchenauge,Coreopsis tinctoria,flowering|sun,2,"Maedchenauge ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,139,Koriander,Coriandrum sativum,easy|sun,2,Koriander ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,150,Kosmee,Cosmos bipinnatus,flowering|sun,2,"Kosmee ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,29,Kotyledon,Cotyledon orbiculata,easy|succulent|sun,3,"Kotyledon hat dickfleischige, runde Blaetter mit einem mehligen, weisslichen Belag. Sehr trockenheitsresistent.",Helles bis volles Licht,15-25 °C,14 +constants/lexiconBatch2.ts,26,Moos-Crassula,Crassula muscosa,easy|succulent|sun,3,"Die Moos-Crassula hat dicht aneinandergereihte, winzige gruene Blaetter auf unverzweigten Trieben. Sieht aus wie Moos.",Helles bis volles Licht,15-25 °C,14 +constants/lexiconBatch1.ts,5,Jadepflanze,Crassula ovata,easy|succulent|sun,3,"Die Jadepflanze ist eine langlebige Sukkulente mit dicken, ovalen Blaettern. In Japan gilt sie als Gluecksbringer.",Helles bis volles Licht,15-24 °C,14 +constants/lexiconBatch1.ts,110,Krokus,Crocus vernus,easy|flowering,2,"Der Krokus ist einer der ersten Fruehjahrs­boten mit kelchfoermigen Blueten in Lila, Weiss und Gelb.",Helles bis volles Licht,5-15 °C,7 +constants/lexiconBatch2.ts,39,Cryptanthus,Cryptanthus bivittatus,patterned|high_humidity,2,Cryptanthus ist eine niedrig wachsende Bromelie mit sternfoermigen Rosetten und gemusterten Blaettern. Fuer Terrarien.,Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,53,Ctenanthe,Ctenanthe burle-marxii,patterned|high_humidity,2,Die Ctenanthe hat faszinierend gemusterte Blaetter mit dunkelgruunem Fischgraetenmuster auf hellgruunem Hintergrund.,Indirektes Licht,18-25 °C,5 +constants/lexiconBatch2.ts,94,Gurke,Cucumis sativus,easy|sun,2,"Die Gurke ist eine rankende Gemuese­pflanze mit gruenen, erfrischenden Fruechten. Im Balkonkasten kultivierbar.",Volles Sonnenlicht,18-28 °C,3 +constants/lexiconBatch2.ts,209,Zypresse,Cupressus sempervirens,tree|large|sun,3,Zypresse ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,74,Kurkuma,Curcuma longa,medicinal|high_humidity,2,Kurkuma ist eine tropische Gewuerzpflanze mit breiten Blaettern und leuchtend gelber Wurzel. Wichtiges Heilgewuerz.,Helles bis volles Licht,20-30 °C,7 +constants/lexiconBatch2.ts,236,String of Bananas,Curio radicans,succulent|hanging|sun,3,String of Bananas ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10 +constants/lexiconBatch2.ts,237,String of Dolphins,Curio x peregrinus,succulent|hanging|sun,3,String of Dolphins ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10 +constants/lexiconBatch2.ts,239,Palmfarn,Cycas revoluta,tree|large|sun,3,Palmfarn ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10 +constants/lexiconBatch1.ts,19,Alpenveilchen,Cyclamen persicum,flowering,1,"Das Alpenveilchen bluet im Herbst und Winter mit eleganten Blueten in Rosa, Rot oder Weiss.",Helles indirektes Licht,12-18 °C,5 +constants/lexiconBatch1.ts,71,Zymbidium,Cymbidium lowianum,flowering,1,"Das Zymbidium ist eine robuste Orchidee mit langen, grassartigen Blaettern und eleganten Bluetenrispen.",Helles Licht,12-24 °C,7 +constants/lexiconBatch2.ts,127,Zitronengras,Cymbopogon citratus,easy|sun,2,Zitronengras ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,9,Paragraphenpflanze,Cyperus alternifolius,high_humidity,1,"Die Paragraphenpflanze hat lange, grasartige Blaetter, die sternfoermig vom Stiel abstehen. Sie liebt viel Wasser.",Helles bis volles Licht,18-27 °C,3 +constants/lexiconBatch2.ts,68,Dahlie,Dahlia pinnata,flowering|sun,2,Die Dahlie ist eine prachtvolle Sommerblume mit Blueten in allen Groessen und Formen. Sie wird aus Knollen gezogen.,Volles Sonnenlicht,15-25 °C,5 +constants/lexiconBatch2.ts,99,Karotte,Daucus carota,easy,1,Die Karotte ist eine beliebte Gemuese­pflanze mit orangefarbenen Wurzeln. Im tiefen Topf kultivierbar.,Helles bis volles Licht,15-22 °C,5 +constants/lexiconBatch2.ts,215,Flammenbaum,Delonix regia,flowering|tree|large,3,Flammenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,153,Rittersporn,Delphinium elatum,flowering|sun,2,"Rittersporn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,70,Dendrobium,Dendrobium nobile,flowering|high_humidity,2,"Das Dendrobium ist eine beliebte Zimmerorchidee mit langen Pseudobulben, die im Winter mit Blueten besetzt werden.",Helles indirektes Licht,15-28 °C,10 +constants/lexiconBatch2.ts,189,Bartnelke,Dianthus barbatus,flowering|sun,2,"Bartnelke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,146,Nelke,Dianthus caryophyllus,flowering|sun,2,"Nelke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,48,Dieffenbachie,Dieffenbachia seguine,easy|air_purifier|low_light,3,"Die Dieffenbachie ist eine tropische Blattschmuckpflanze mit grossen, gruen-weiss gefleckten Blaettern.",Helles indirektes Licht,18-26 °C,7 +constants/lexiconBatch2.ts,109,Roter Fingerhut,Digitalis purpurea,flowering|medicinal,2,"Der Rote Fingerhut hat hohe Bluetenstaende mit roehrenfoermigen, gepunkteten Blueten in Rosa. Wichtige Arzneipflanze.",Helles bis volles Licht,10-20 °C,7 +constants/lexiconBatch2.ts,77,Venusfliegenfalle,Dionaea muscipula,sun,1,Die Venusfliegenfalle ist eine fleischfressende Pflanze mit klappfallartigen Blaettern. Faengt Insekten.,Volles Sonnenlicht,15-30 °C,5 +constants/lexiconBatch1.ts,101,Dischidia,Dischidia ruscifolia,succulent|hanging,2,"Die Dischidia ist eine epiphytische Haengepflanze mit kleinen, runden Blaettern entlang duenner Ranken.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,14,Maisstrauch,Dracaena fragrans,easy|tree|air_purifier|low_light,4,"Der Maisstrauch ist eine robuste Zimmerpflanze mit breiten, gestreiften Blaettern. Gedeiht auch bei wenig Licht.",Helles indirektes Licht,15-25 °C,10 +constants/lexiconBatch1.ts,13,Drachenbaum,Dracaena marginata,easy|tree|air_purifier,3,"Der Drachenbaum ist eine schlanke Zimmerpflanze mit roten, schmalen Blaettern auf langen Staemmen.",Helles indirektes Licht,15-25 °C,10 +constants/lexiconBatch2.ts,80,Sonnentau,Drosera capensis,high_humidity|sun,2,Der Sonnentau faengt Insekten mit klebrigen Tropfen auf seinen Blaettern. Eine faszinierende fleischfressende Pflanze.,Volles Sonnenlicht,15-25 °C,5 +constants/lexiconBatch2.ts,30,Dudleya,Dudleya brittonii,easy|succulent|sun,3,"Dudleya ist eine rosetten­bildende Sukkulente mit silbrig-weissen, mehligen Blaettern. Sehr elegant.",Volles Sonnenlicht,10-25 °C,14 +constants/lexiconBatch1.ts,42,Goldfruchtpalme,Dypsis lutescens,pet_friendly|tree|air_purifier,3,Die Goldfruchtpalme ist eine elegante Zimmerpalme mit gelblich-gruenen Stielen und gefiederten Wedeln.,Helles indirektes Licht,18-27 °C,5 +constants/lexiconBatch1.ts,4,Echeverie,Echeveria elegans,easy|succulent|sun,3,"Die Echeverie bildet symmetrische, rosettenfoermige Sukkulenten mit blaugruenen Blaettern. Pflegeleicht.",Volles Sonnenlicht,15-25 °C,14 +constants/lexiconBatch2.ts,106,Sonnenhut,Echinacea purpurea,flowering|medicinal|sun,3,"Der Sonnenhut ist eine beliebte Heilpflanze mit grossen, pinkfarbenen Blueten. Er staerkt das Immunsystem.",Helles bis volles Licht,15-25 °C,7 +constants/lexiconBatch1.ts,77,Goldene Tonne,Echinocactus grusonii,easy|succulent|sun,3,Die Goldene Tonne ist ein ikonischer kugelfoermiger Kaktus mit goldgelben Stacheln. Waechst langsam aber imposant.,Volles Sonnenlicht,15-35 °C,21 +constants/lexiconBatch1.ts,83,San-Pedro-Kaktus,Echinopsis pachanoi,easy|succulent|sun,3,"Der San-Pedro-Kaktus ist ein schnell wachsender, saeulenfoermiger Kaktus aus den Anden.",Volles Sonnenlicht,10-35 °C,14 +constants/lexiconBatch1.ts,84,Koenigin der Nacht,Epiphyllum oxypetalum,flowering|succulent,2,"Die Koenigin der Nacht bluet nur eine einzige Nacht lang mit riesigen, intensiv duftenden weissen Blueten.",Indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,16,Marmor-Efeutute,Epipremnum aureum Marble Queen,easy|hanging|air_purifier,3,Die Marmor-Efeutute hat cremeweiss-gruen marmorierte Blaetter. Eine dekorative Variante der klassischen Efeutute.,Helles indirektes Licht,15-30 °C,7 +constants/lexiconBatch2.ts,53,Neon-Efeutute,Epipremnum pinnatum Neon,easy|hanging|air_purifier,3,Die Neon-Efeutute hat leuchtend limonengruene Blaetter. Sehr auffaellig und pflegeleicht.,Helles indirektes Licht,15-30 °C,7 +constants/lexiconBatch2.ts,186,Kalifornischer Mohn,Eschscholzia californica,flowering|sun,2,"Kalifornischer Mohn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,210,Eukalyptus,Eucalyptus globulus,tree|medicinal|sun,3,Eukalyptus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,19,Christusdorn,Euphorbia milii,easy|flowering|succulent|sun,4,Der Christusdorn ist eine sukkulente Wolfsmilch mit stacheligen Zweigen und kleinen roten oder gelben Hochblaettern.,Helles bis volles Licht,15-28 °C,10 +constants/lexiconBatch2.ts,20,Weihnachtsstern,Euphorbia pulcherrima,flowering,1,Der Weihnachtsstern ist die klassische Winterpflanze mit leuchtend roten Hochblaettern. Er steht symbolisch fuer Weihnachten.,Helles indirektes Licht,15-22 °C,7 +constants/lexiconBatch1.ts,12,Bleistiftkaktus,Euphorbia tirucalli,easy|succulent|sun,3,"Der Bleistiftkaktus ist eine sukkulente Wolfsmilch mit duennen, zylindrischen Zweigen ohne Blaetter.",Volles Sonnenlicht,18-30 °C,14 +constants/lexiconBatch2.ts,137,Wasabi,Eutrema japonicum,bright_light|high_humidity,2,"Wasabi ist ein seltenes Wuerzkraut, das gleichmaessige Feuchte und eher kuehle Bedingungen bevorzugt.",Helles indirektes Licht,8-20 C,4 +constants/lexiconBatch2.ts,12,Fatsia,Fatsia japonica,easy|low_light,2,"Die Fatsia ist ein dekorativer Zimmerstrauch mit grossen, handfoermigen, glaenzenden Blaettern. Sehr robust.",Helles indirektes Licht,10-20 °C,7 +constants/lexiconBatch1.ts,78,Fass-Kaktus,Ferocactus cylindraceus,easy|succulent|sun,3,"Der Fass-Kaktus ist ein zylindrischer Wuestenkaktus mit langen, roten Stacheln. Sehr langlebig.",Volles Sonnenlicht,15-35 °C,21 +constants/lexiconBatch2.ts,248,Ficus altissima,Ficus altissima,tree|bright_light,2,Ficus altissima ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch1.ts,1,Birkenfeige,Ficus benjamina,tree|air_purifier,2,"Die Birkenfeige ist ein eleganter Zimmerstrauch mit haengenden Aesten und kleinen, glaenzenden Blaettern.",Helles indirektes Licht,16-24 °C,7 +constants/lexiconBatch1.ts,38,Gummibaum,Ficus elastica,easy|tree|air_purifier,3,"Der Gummibaum ist eine imposante Zimmerpflanze mit grossen, glaenzenden, lederartigen Blaettern. Reinigt die Luft.",Helles indirektes Licht,16-24 °C,10 +constants/lexiconBatch1.ts,39,Geigenfeige,Ficus lyrata,tree|large|bright_light,3,"Die Geigenfeige ist ein Trendbaum mit grossen, geigenfoermigen Blaettern. Benoetigt viel Licht.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,247,Ficus microcarpa,Ficus microcarpa,easy|tree|bright_light,3,Ficus microcarpa ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch2.ts,116,Bonsai-Feige,Ficus retusa,tree,1,"Die Bonsai-Feige ist eine klassische Bonsai-Art mit kleinen, elliptischen Blaettern. Sehr formbar.",Helles indirektes Licht,16-24 °C,7 +constants/lexiconBatch2.ts,226,Nervenpflanze,Fittonia albivenis,patterned|high_humidity,2,Nervenpflanze ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5 +constants/lexiconBatch2.ts,219,Forsythie,Forsythia x intermedia,flowering|tree|sun,3,Forsythie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,100,Erdbeere,Fragaria ananassa,easy|pet_friendly|sun,3,"Die Erdbeere ist ein beliebtes Obst fuer Balkon und Terrasse mit aromatischen, roten Fruechten.",Helles bis volles Licht,15-25 °C,3 +constants/lexiconBatch2.ts,169,Freesie,Freesia refracta,flowering|sun,2,"Freesie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,33,Fuchsie,Fuchsia hybrida,flowering|hanging,2,"Die Fuchsie haengt mit eleganten, zweifarbigen Blueten wie kleine Ohrringe herab. Ideal fuer Ampeln.",Helles indirektes Licht,14-22 °C,3 +constants/lexiconBatch2.ts,60,Triphylla-Fuchsie,Fuchsia triphylla,flowering|hanging,2,"Die Triphylla-Fuchsie hat lange, roehrenfoermige, orangefarbe Blueten in haengenden Trauben. Sehr exotisch.",Helles indirektes Licht,15-22 °C,3 +constants/lexiconBatch2.ts,196,Kokardenblume,Gaillardia aristata,flowering|sun,2,"Kokardenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,22,Gardenie,Gardenia jasminoides,flowering|high_humidity,2,"Die Gardenie fasziniert mit cremefarbenen, intensiv duftenden Blueten. Anspruchsvoll in der Pflege.",Helles indirektes Licht,18-23 °C,5 +constants/lexiconBatch1.ts,90,Gasteria,Gasteria carinata,easy|succulent|low_light,3,"Die Gasteria ist eine kleine Sukkulente mit zweireihig angeordneten, zungenfoermigen, gefleckten Blaettern.",Helles indirektes Licht,15-25 °C,14 +constants/lexiconBatch2.ts,190,Mittagsgold,Gazania rigens,flowering|sun,2,"Mittagsgold ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,32,Blutroter Storchschnabel,Geranium sanguineum,easy|flowering,2,Der Blutrote Storchschnabel ist ein zierlicher Storchschnabel mit intensiv magentafarbenen Blueten.,Helles bis volles Licht,10-25 °C,7 +constants/lexiconBatch1.ts,68,Gerbera,Gerbera jamesonii,flowering|air_purifier|bright_light,3,"Die Gerbera ist eine farbenfrohe Schnittblume mit grossen, sonnenblumenaehnlichen Blueten. Sehr beliebt.",Helles bis volles Licht,15-25 °C,5 +constants/lexiconBatch2.ts,216,Ginkgo,Ginkgo biloba,tree|medicinal|sun,3,Ginkgo ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,161,Gladiole,Gladiolus hortulanus,flowering|sun,2,"Gladiole ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,96,Gloxinie,Gloxinia speciosa,flowering|high_humidity,2,"Die Gloxinie hat grosse, samtartige Blueten in Violett, Rosa oder Weiss mit farbigen Raendern.",Helles indirektes Licht,18-25 °C,5 +constants/lexiconBatch2.ts,240,Calathea lancifolia,Goeppertia insignis,pet_friendly|patterned|high_humidity,3,Calathea lancifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5 +constants/lexiconBatch2.ts,241,Calathea ornata,Goeppertia ornata,pet_friendly|patterned|high_humidity,3,Calathea ornata ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5 +constants/lexiconBatch1.ts,87,Geisterpflanze,Graptopetalum paraguayense,easy|succulent|sun,3,"Die Geisterpflanze hat zartgraue bis perlmutt-rosafarbene, rosettenfoermige Blaetter. Sehr robuste Sukkulente.",Volles Sonnenlicht,15-25 °C,14 +constants/lexiconBatch2.ts,36,Guzmania,Guzmania lingulata,flowering|high_humidity,2,"Die Guzmania ist eine Bromelie mit glänzenden, gruenen Blaettern und einem leuchtend roten, sternfoermigen Bluetenstand.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,80,Mond-Kaktus,Gymnocalycium mihanovichii,easy|succulent,2,Der Mond-Kaktus ist eine farbenfrohe Veredelung eines chlorophylllosen Kaktus auf einem gruenen Unterlagekaktus.,Indirektes Licht,15-30 °C,14 +constants/lexiconBatch2.ts,119,Zaubernuss,Hamamelis mollis,flowering|medicinal,2,"Die Zaubernuss bluet im Winter mit fadendunnen, gelben Bluetenkranzeln, die bis -10 Grad standhalten.",Helles bis volles Licht,10-20 °C,10 +constants/lexiconBatch1.ts,6,Zebra-Haworthie,Haworthia fasciata,easy|succulent|low_light,3,Die Zebra-Haworthie ist eine kompakte Sukkulente mit weissen Querstreifen auf dunkelgruenen Blaettern.,Helles indirektes Licht,15-25 °C,14 +constants/lexiconBatch1.ts,37,Efeu,Hedera helix,easy|hanging|air_purifier|low_light,4,"Efeu ist eine robuste Kletter- und Haengepflanze mit charakteristischen, dreilappigen Blaettern. Sehr langlebig.",Wenig bis helles Licht,10-20 °C,7 +constants/lexiconBatch2.ts,83,Heliamphora,Heliamphora nutans,high_humidity,1,Heliamphora ist eine urtuemliche Kannenpflanze aus den Tafelbergen Venezuelas. Sehr dekorativ und selten.,Helles indirektes Licht,15-25 °C,5 +constants/lexiconBatch2.ts,141,Sonnenblume,Helianthus annuus,flowering|sun,2,"Sonnenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,133,Currykraut,Helichrysum italicum,easy|sun,2,Currykraut ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,72,Heliconia,Heliconia psittacorum,flowering|bright_light|high_humidity,3,"Die Heliconia hat leuchtend orangefarbe oder rote, bootsfoermige Hochblaetter. Eine exotische Tropenpflanze.",Helles bis volles Licht,20-30 °C,5 +constants/lexiconBatch2.ts,191,Heliotrop,Heliotropium arborescens,flowering|sun,2,"Heliotrop ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,183,Lenzrose,Helleborus orientalis,flowering,1,"Lenzrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,182,Taglilie,Hemerocallis fulva,flowering|sun,2,"Taglilie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,21,Hibiskus,Hibiscus rosa-sinensis,flowering|bright_light|sun,3,"Der Hibiskus begeistert mit grossen, trompetenfoermigen Blueten in Rot, Orange und Rosa.",Volles Sonnenlicht,18-28 °C,3 +constants/lexiconBatch2.ts,220,Gartenhibiskus,Hibiscus syriacus,flowering|tree|sun,3,Gartenhibiskus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch1.ts,105,Ritterstern,Hippeastrum hybrid,flowering|bright_light,2,"Der Ritterstern beeindruckt im Winter mit riesigen, trompetenfoermigen Blueten in Rot, Pink oder Weiss.",Helles bis volles Licht,18-25 °C,7 +constants/lexiconBatch2.ts,3,Kentia-Palme,Howea forsteriana,pet_friendly|tree|low_light,3,"Die Kentia-Palme ist eine der elegantesten Zimmerpalmen mit langen, herabhängenden Fiederblaettern.",Helles indirektes Licht,18-25 °C,7 +constants/lexiconBatch1.ts,58,Kleine Wachsblume,Hoya bella,flowering|succulent|hanging,3,"Die Kleine Wachsblume traegt zierliche, sternfoermige weisse Blueten mit rosa Mitte. Haengende Sukkulente.",Helles indirektes Licht,18-27 °C,10 +constants/lexiconBatch1.ts,57,Wachsblume,Hoya carnosa,easy|flowering|succulent|hanging,4,"Die Wachsblume ist eine Kletterpflanze mit dicken, wachsartigen Blaettern und sternfoermigen, duftenden Blueten.",Helles indirektes Licht,16-27 °C,10 +constants/lexiconBatch2.ts,159,Hasengloeckchen,Hyacinthoides non-scripta,flowering|sun,2,"Hasengloeckchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,108,Hyazinthe,Hyacinthus orientalis,easy|flowering,2,"Die Hyazinthe bezaubert mit dichten Bluetenrispen und intensivem Duft in Blau, Rosa, Weiss oder Gelb.",Helles bis volles Licht,10-18 °C,5 +constants/lexiconBatch2.ts,148,Hortensie,Hydrangea macrophylla,flowering|bright_light,2,"Hortensie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Helles bis halbschattiges Licht,8-24 C,4 +constants/lexiconBatch2.ts,105,Johanniskraut,Hypericum perforatum,flowering|medicinal|sun,3,Das Johanniskraut hat leuchtend gelbe Blueten und ist ein wichtiges Heilkraut gegen Depressionen und Stimmungstiefs.,Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch2.ts,227,Punktblatt,Hypoestes phyllostachya,patterned|bright_light,2,Punktblatt ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch2.ts,136,Ysop,Hyssopus officinalis,easy|sun,2,Ysop ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,203,Stechpalme,Ilex aquifolium,tree|sun,2,Stechpalme ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,176,Gartenbalsamine,Impatiens balsamina,flowering|bright_light,2,"Gartenbalsamine ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,59,Neuguinea-Balsamine,Impatiens hawkeri,easy|flowering,2,"Die Neuguinea-Balsamine hat grosse, leuchtende Blueten und ist sehr bluehfreudig. Ideal fuer Terrassen.",Helles indirektes Licht,18-27 °C,3 +constants/lexiconBatch1.ts,20,Fleissiges Lieschen,Impatiens walleriana,easy|flowering,2,Das Fleissige Lieschen bluet von Fruehling bis Herbst unermudlich in vielen Farben.,Helles indirektes Licht,16-24 °C,2 +constants/lexiconBatch1.ts,64,Suesskartoffel,Ipomoea batatas,easy|hanging|sun,3,"Die Suesskartoffel-Zierpflanze hat dekorative, herzfoermige Blaetter in gruen oder dunkelviolett. Ideal als Haengepflanze.",Volles Sonnenlicht,20-30 °C,5 +constants/lexiconBatch2.ts,156,Prunkwinde,Ipomoea purpurea,flowering|sun,2,"Prunkwinde ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,144,Bart-Iris,Iris germanica,flowering|sun,2,"Bart-Iris ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,211,Jacaranda,Jacaranda mimosifolia,flowering|tree|large,3,Jacaranda ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch1.ts,59,Jasmin,Jasminum polyanthum,flowering,1,"Der Jasmin ist eine Kletterpflanze mit intensiv duftenden, weissen Blueten. Er bluet im Winter und Fruehling.",Helles bis volles Licht,10-22 °C,5 +constants/lexiconBatch2.ts,172,Arabischer Jasmin,Jasminum sambac,flowering|bright_light,2,"Arabischer Jasmin ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,9,Kalanchoe,Kalanchoe blossfeldiana,easy|flowering|succulent|sun,4,"Die Kalanchoe ist eine beliebte Bluehpflanze mit leuchtenden Blueten in Rot, Orange, Gelb oder Rosa.",Helles bis volles Licht,15-25 °C,10 +constants/lexiconBatch2.ts,22,Brutblatt,Kalanchoe daigremontiana,easy|succulent|sun,3,Das Brutblatt bildet entlang des Blattrandes zahlreiche kleine Jungpflanzen. Eine faszinierende Sukkulente.,Helles bis volles Licht,15-25 °C,14 +constants/lexiconBatch2.ts,21,Kaninchen-Ohren,Kalanchoe tomentosa,easy|succulent|sun,3,"Kaninchen-Ohren haben weisslich-filzige Blaetter mit braunen Raendern, die Kaninchen­ohren aehneln. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14 +constants/lexiconBatch2.ts,95,Salat,Lactuca sativa,easy,1,Salat ist eine schnell wachsende Blattgemuese­pflanze. Im Topf und Balkonkasten sehr gut zu kultivieren.,Helles bis volles Licht,10-22 °C,3 +constants/lexiconBatch2.ts,197,Traenendes Herz,Lamprocapnos spectabilis,flowering|bright_light,2,"Traenendes Herz ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,64,Wandelroeschen,Lantana camara,flowering|bright_light|sun,3,"Das Wandelroeschen hat kugelige Bluetenkoepfe, die die Farbe von Gelb ueber Orange zu Rot wechseln. Sehr attraktiv.",Volles Sonnenlicht,18-28 °C,5 +constants/lexiconBatch2.ts,158,Duftwicke,Lathyrus odoratus,flowering|sun,2,"Duftwicke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,121,Lorbeer,Laurus nobilis,easy|sun,2,Lorbeer ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch1.ts,23,Echter Lavendel,Lavandula angustifolia,medicinal|bright_light|sun,3,Der Echte Lavendel ist ein aromatischer Halbstrauch mit lilafarbenen Bluetenaehren. Herrlicher Duft.,Volles Sonnenlicht,10-25 °C,10 +constants/lexiconBatch2.ts,180,Bechermalve,Lavatera trimestris,flowering|sun,2,"Bechermalve ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,173,Margerite,Leucanthemum vulgare,flowering|sun,2,"Margerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,201,Shasta-Margerite,Leucanthemum x superbum,flowering|sun,2,"Shasta-Margerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,126,Liebstoeckel,Levisticum officinale,easy|sun,2,Liebstoeckel ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,69,Ostertrompete,Lilium longiflorum,flowering|bright_light,2,"Die Ostertrompete hat grosse, weisse, trichterfoermige Blueten mit intensivem Duft. Klassische Osterblume.",Helles bis volles Licht,15-25 °C,5 +constants/lexiconBatch2.ts,23,Lebende Steine,Lithops julii,succulent|sun,2,"Lebende Steine sind faszinierende Mimikry-Sukkulenten, die Kieselsteinen taeuschen aehnlich sehen. Sehr trockenheitsresistent.",Volles Sonnenlicht,10-30 °C,21 +constants/lexiconBatch2.ts,4,Chinesische Fächerpalme,Livistona chinensis,tree|bright_light,2,"Die Chinesische Fächerpalme hat grosse, faecher­foermige Blaetter auf einem einzelnen Stamm. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,7 +constants/lexiconBatch2.ts,62,Duftsteinrich,Lobularia maritima,easy|flowering,2,"Der Duftsteinrich ist ein niedrig wachsendes Pflanzchen mit winzigen, weissen oder lilafarbenen Blueten und suessem Duft.",Helles bis volles Licht,10-22 °C,3 +constants/lexiconBatch2.ts,171,Geissblatt,Lonicera japonica,flowering|bright_light,2,"Geissblatt ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,154,Lupine,Lupinus polyphyllus,flowering|sun,2,"Lupine ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,204,Magnolie,Magnolia grandiflora,flowering|tree|large,3,Magnolie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch1.ts,79,Mammillaria,Mammillaria zeilmanniana,easy|flowering|succulent|sun,4,"Die Mammillaria ist ein kompakter, kugelfoermiger Kaktus, der im Fruehling einen Kranz aus rosa Blueten traegt.",Volles Sonnenlicht,15-35 °C,14 +constants/lexiconBatch1.ts,51,Gebet-Pflanze,Maranta leuconeura,pet_friendly|patterned|high_humidity,3,Die Gebet-Pflanze faltet ihre gemusterten Blaetter nachts wie Haende zusammen. Faszinierende rote und gruene Muster.,Indirektes Licht,18-27 °C,5 +constants/lexiconBatch2.ts,102,Zitronenmelisse,Melissa officinalis,easy|medicinal,2,Die Zitronenmelisse ist ein zitronig duftendes Heilkraut. Sie beruhigt die Nerven und foerdert den Schlaf.,Helles bis volles Licht,15-25 °C,5 +constants/lexiconBatch1.ts,26,Gruene Minze,Mentha spicata,easy,1,"Die Gruene Minze ist ein wuchsfreudiges Kuechenkraut mit frischem, minzigem Duft. Fuer Tee und Cocktails.",Helles bis volles Licht,15-25 °C,3 +constants/lexiconBatch2.ts,46,Tueipelfarn (Microsorum),Microsorum punctatum,high_humidity,1,"Microsorum punctatum ist ein tropischer Farn mit langen, ungeteilten, glaenzenden Wedeln. Fuer feuchte Standorte.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,75,Stiefmuetterchen-Orchidee,Miltoniopsis roezlii,flowering|high_humidity,2,"Die Stiefmuetterchen-Orchidee hat grosse, flache Blueten. Bevorzugt kuehle Temperaturen und hohe Luftfeuchtigkeit.",Indirektes Licht,15-22 °C,5 +constants/lexiconBatch2.ts,76,Schamkraut,Mimosa pudica,flowering|bright_light,2,"Das Schamkraut faltet seine Blaettchen blitzschnell zusammen, wenn man sie beruehrt. Ein faszinierendes Erlebnis.",Helles bis volles Licht,20-28 °C,5 +constants/lexiconBatch2.ts,179,Indianernessel,Monarda didyma,flowering|sun,2,"Indianernessel ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,47,Monstera adansonii,Monstera adansonii,easy|hanging,2,Monstera adansonii hat herzfoermige Blaetter mit zahlreichen runden Lochern. Eine rankende Zimmerpflanze.,Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,48,Monstera obliqua,Monstera obliqua,patterned|hanging,2,"Monstera obliqua ist eine seltene Monstera-Art mit filigranen Blaettern, die hauptsaechlich aus Lochern bestehen.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,2,Bananenpflanze,Musa acuminata,large|high_humidity,2,"Die Bananenpflanze ist eine tropische Staude mit riesigen, glaenzenden Blaettern. Im Zimmer selten fruechttragend.",Helles bis volles Licht,20-30 °C,5 +constants/lexiconBatch1.ts,109,Traubenhyazinthe,Muscari armeniacum,easy|flowering,2,"Die Traubenhyazinthe bildet dichte Trauben aus kleinen, blauen bis violetten Gloeckchen. Zuverlaessige Fruejahrszwiebel.",Helles bis volles Licht,8-18 °C,7 +constants/lexiconBatch2.ts,177,Vergissmeinnicht,Myosotis sylvatica,flowering|sun,2,"Vergissmeinnicht ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,106,Osterglocke,Narcissus pseudonarcissus,flowering,1,"Die Osterglocke ist der klassische Fruehjahrsblueher mit leuchtend gelben, trompetenfoermigen Blueten.",Helles bis volles Licht,10-18 °C,5 +constants/lexiconBatch2.ts,199,Nemesie,Nemesia strumosa,flowering|sun,2,"Nemesie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,37,Neoregelia,Neoregelia carolinae,flowering|patterned|bright_light,3,"Die Neoregelia ist eine Bromelie, bei der das Herzblatt zur Bluetzeit leuchtend rot wird. Sehr dekorativ.",Helles bis volles Licht,18-27 °C,7 +constants/lexiconBatch2.ts,79,Kannenpflanze,Nepenthes alata,hanging|high_humidity,2,"Die Kannenpflanze bildet grosse, gefuellte Kannen als Insekten­fallen. Eine faszinierende, tropische Pflanze.",Helles indirektes Licht,20-30 °C,5 +constants/lexiconBatch2.ts,132,Katzenminze,Nepeta cataria,easy|sun,2,Katzenminze ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,120,Oleander,Nerium oleander,flowering|bright_light|sun,3,"Der Oleander ist ein mediteraner Strauch mit leuchtend roten, rosa oder weissen Blueten. Sehr hitzetolerant.",Volles Sonnenlicht,15-28 °C,7 +constants/lexiconBatch2.ts,193,Ziertabak,Nicotiana alata,flowering|sun,2,"Ziertabak ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,25,Basilikum,Ocimum basilicum,easy|medicinal|sun,3,"Basilikum ist das beliebteste Kuechenkraut mit intensiv aromatischen, gruenen Blaettern. Fuer Pesto verwendet.",Volles Sonnenlicht,18-30 °C,2 +constants/lexiconBatch1.ts,74,Tanzerinnen-Orchidee,Oncidium sphacelatum,flowering|high_humidity,2,"Die Tanzerinnen-Orchidee traegt lange Rispen mit Hunderten kleiner, gelb-brauner Blueten. Sehr reichliche Bluetracht.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,82,Hasenohren-Kaktus,Opuntia microdasys,easy|succulent|sun,3,"Der Hasenohren-Kaktus hat flache, ovale Triebe mit dichten weissen Glochiden. Klassischer Zimmerkaktus.",Volles Sonnenlicht,10-35 °C,21 +constants/lexiconBatch2.ts,124,Majoran,Origanum majorana,easy|sun,2,Majoran ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch1.ts,28,Oregano,Origanum vulgare,easy|medicinal|sun,3,"Oregano ist ein aromatisches Kuechenkraut mit runden, behaarten Blaettern. In mediterraner Kueche beliebt.",Volles Sonnenlicht,15-25 °C,7 +constants/lexiconBatch2.ts,200,Kapmargerite,Osteospermum ecklonis,flowering|sun,2,"Kapmargerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,54,Kleeblume,Oxalis triangularis,flowering|patterned,2,"Die Kleeblume hat tiefviolette, dreieckige Blaetter und zarte rosa Blueten. Sie faltet die Blaetter bei Dunkelheit.",Helles indirektes Licht,15-24 °C,7 +constants/lexiconBatch2.ts,231,Glueckskastanie,Pachira aquatica,easy|tree|bright_light,3,Glueckskastanie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch1.ts,88,Mondstein-Pflanze,Pachyphytum oviferum,easy|succulent|sun,3,"Die Mondstein-Pflanze hat dicke, ovale Blaetter mit einem pastellrosafarbenen, mehligen Ueberzug.",Volles Sonnenlicht,15-25 °C,14 +constants/lexiconBatch2.ts,143,Pfingstrose,Paeonia lactiflora,flowering|sun,2,"Pfingstrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,6,Schraubenbaum,Pandanus veitchii,patterned|bright_light,2,"Der Schraubenbaum hat spiralfoermig angeordnete, gruenweiss gestreifte Blaetter. Sehr dekorativ und exotisch.",Helles bis volles Licht,18-27 °C,7 +constants/lexiconBatch2.ts,185,Mohn,Papaver rhoeas,flowering|sun,2,"Mohn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,63,Passionsblume,Passiflora caerulea,flowering,1,"Die Passionsblume ist eine faszinierende Kletterpflanze mit komplex strukturierten, blau-weissen Blueten.",Helles bis volles Licht,15-27 °C,5 +constants/lexiconBatch1.ts,31,Rosengeranie,Pelargonium graveolens,easy|medicinal|sun,3,Die Rosengeranie ist eine Duftpflanze mit tief eingeschnittenen Blaettern und rosaenlichem Aroma.,Volles Sonnenlicht,15-25 °C,7 +constants/lexiconBatch2.ts,61,Efeu-Geranie,Pelargonium peltatum,easy|flowering|hanging|sun,4,"Die Efeu-Geranie hat efeufoermige, glaenzende Blaetter und bluet den ganzen Sommer in leuchtenden Farben.",Helles bis volles Licht,15-25 °C,5 +constants/lexiconBatch2.ts,174,Stehende Geranie,Pelargonium zonale,flowering|sun,2,"Stehende Geranie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,229,Wassermelonen-Peperomie,Peperomia argyreia,pet_friendly|patterned,2,Wassermelonen-Peperomie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch1.ts,102,Rippenpeperomie,Peperomia caperata,easy|pet_friendly,2,"Die Rippenpeperomie hat tief gerippte, dunkelgruene bis violette Blaetter mit einer samtigen Textur.",Helles indirektes Licht,18-26 °C,10 +constants/lexiconBatch1.ts,103,Spiegelpeperomie,Peperomia obtusifolia,easy|pet_friendly|low_light,3,"Die Spiegelpeperomie hat glaenzende, lederartige, oval-runde Blaetter in tiefem Gruen. Sehr robust.",Helles indirektes Licht,16-26 °C,10 +constants/lexiconBatch2.ts,230,Raindrop-Peperomie,Peperomia polybotrya,easy|pet_friendly,2,Raindrop-Peperomie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch2.ts,134,Shiso,Perilla frutescens,easy|sun,2,Shiso ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch1.ts,29,Petersilie,Petroselinum crispum,easy,1,Petersilie ist eines der meistgenutzten Kuechenkraeuter mit frisch-aromatischem Geschmack. Reich an Vitaminen.,Helles Licht,10-25 °C,3 +constants/lexiconBatch1.ts,34,Petunie,Petunia hybrida,easy|pet_friendly|flowering|sun,4,Die Petunie ist eine der beliebtesten Balkonpflanzen mit trichterfoermigen Blueten in unzaehligen Farben.,Volles Sonnenlicht,15-25 °C,2 +constants/lexiconBatch1.ts,69,Schmetterlingsorchidee,Phalaenopsis amabilis,flowering|high_humidity,2,Die Schmetterlingsorchidee ist die bekannteste Zimmerorchidee. Sie bluet bei guter Pflege monatelang.,Helles indirektes Licht,18-28 °C,10 +constants/lexiconBatch2.ts,50,Philodendron bipinnatifidum,Philodendron bipinnatifidum,easy|large,2,"Philodendron bipinnatifidum hat grosse, tief gelappte Blaetter. Er entwickelt einen beeindruckenden, baumfoermigen Wuchs.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,51,Roter Philodendron,Philodendron erubescens,easy|hanging,2,"Der Rote Philodendron hat glaenzende, herzfoermige Blaetter, die jung roetrlich erscheinen. Sehr dekorativ.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,243,Philodendron Pink Princess,Philodendron erubescens Pink Princess,patterned|bright_light,2,Philodendron Pink Princess ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch2.ts,49,Philodendron gloriosum,Philodendron gloriosum,patterned|large|high_humidity,3,"Philodendron gloriosum hat grosse, samtige, herzfoermige Blaetter mit weissen Rippen. Eine atemberaubende Pflanze.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,15,Herzblatt-Philodendron,Philodendron hederaceum,easy|hanging|low_light,3,Der Herzblatt-Philodendron ist eine pflegeleichte Kletter- oder Haengepflanze mit herzfoermigen Blaettern.,Indirektes Licht,18-28 °C,7 +constants/lexiconBatch2.ts,242,Philodendron Brasil,Philodendron hederaceum Brasil,easy|hanging|low_light,3,Philodendron Brasil ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch2.ts,40,Blaues Kanaelfarn,Phlebodium aureum,high_humidity,1,"Der Blaue Kanaelfarn hat wachsartige, blaugruene Wedel und glaenzende Wurzelstaemme. Sehr dekorativ.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,165,Flammenblume,Phlox paniculata,flowering|sun,2,"Flammenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,44,Zwergdattelpalme,Phoenix roebelenii,tree|bright_light,2,"Die Zwergdattelpalme ist eine zierliche Palme mit eleganten, gebogenen Fiederblaettern. Tropisches Flair.",Helles bis volles Licht,18-27 °C,7 +constants/lexiconBatch2.ts,8,Goldener Bambus,Phyllostachys aurea,easy|large,2,"Der Goldene Bambus hat elegante, goldgelbe Halme mit engstehenden Knoten. Sehr dekorativ als Sichtschutz.",Helles bis volles Licht,10-30 °C,5 +constants/lexiconBatch2.ts,207,Fichte,Picea abies,tree|large|sun,3,Fichte ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,228,Aluminium-Pflanze,Pilea cadierei,easy|pet_friendly|patterned,3,Aluminium-Pflanze ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch1.ts,2,Ufopflanze,Pilea peperomioides,easy|pet_friendly,2,"Die Ufopflanze hat unverwechselbare, runde Blaetter auf langen Stielen. Bildet leicht Ableger zum Verschenken.",Helles indirektes Licht,13-30 °C,7 +constants/lexiconBatch2.ts,81,Fettkraut,Pinguicula grandiflora,flowering|high_humidity,2,"Das Fettkraut faengt Insekten mit klebrigen Blaettern. Es bluet mit violetten, sporenartigen Blueten.",Helles indirektes Licht,10-20 °C,5 +constants/lexiconBatch2.ts,206,Kiefer,Pinus sylvestris,tree|large|sun,3,Kiefer ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,41,Geweihfarn,Platycerium bifurcatum,hanging|high_humidity,2,"Der Geweihfarn hat gespaltene Wedel, die einem Hirschgeweih aehneln. Er ist ein epiphytischer Farn fuer Holz.",Helles indirektes Licht,15-25 °C,7 +constants/lexiconBatch2.ts,152,Buntnessel,Plectranthus scutellarioides,patterned|bright_light,2,"Buntnessel ist eine farbstarke Zierpflanze, die vor allem fuer ihr dekoratives Laub beliebt ist.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,61,Bleiwurz,Plumbago auriculata,flowering|bright_light|sun,3,"Die Bleiwurz ist ein halbimmergruener Strauch mit himmelblauen Blueten, der fast das ganze Jahr bluet.",Volles Sonnenlicht,15-27 °C,5 +constants/lexiconBatch2.ts,118,Tempel-Baum,Plumeria rubra,flowering|tree|sun,3,"Der Tempel-Baum hat intensiv duftende, sternfoermige Blueten in Weiss, Gelb oder Rosa. Klassische Tropenblume.",Volles Sonnenlicht,20-30 °C,7 +constants/lexiconBatch2.ts,44,Tueipelfarn,Polypodium vulgare,easy,1,Der Tueipelfarn ist ein heimischer Farn mit gelappten Wedeln und runden Sporenhaeufchen auf der Unterseite.,Helles indirektes Licht,10-20 °C,7 +constants/lexiconBatch2.ts,27,Speckbaum,Portulacaria afra,easy|succulent|sun,3,"Der Speckbaum ist eine sukkulente Pflanze mit roten Stielen und kleinen, runden, glaenzenden Blaettern.",Helles bis volles Licht,15-30 °C,14 +constants/lexiconBatch1.ts,36,Primel,Primula vulgaris,flowering,1,"Die Primel ist einer der ersten Fruehjahrs­boten mit lebhaften Blueten in Gelb, Pink, Rot und Lila.",Helles indirektes Licht,10-18 °C,4 +constants/lexiconBatch2.ts,71,Koenigs-Protea,Protea cynaroides,flowering|large|sun,3,"Die Koenigs-Protea ist die Nationalblume Suedafrikas mit riesigen, imposanten Bluetenkoepfen. Eine echte Besonderheit.",Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch2.ts,218,Kirschlorbeer,Prunus laurocerasus,tree|sun,2,Kirschlorbeer ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,89,Guave,Psidium guajava,tree|sun,2,Die Guave ist ein tropischer Obstbaum mit gelblich-weissen Fruechten. Sie ist reich an Vitamin C.,Volles Sonnenlicht,18-30 °C,7 +constants/lexiconBatch2.ts,88,Granatapfelbaum,Punica granatum,flowering|tree|sun,3,"Der Granatapfelbaum hat leuchtend rote Blueten und rote, essbare Fruechte mit rubinroten Kernen.",Volles Sonnenlicht,15-28 °C,7 +constants/lexiconBatch2.ts,205,Eiche,Quercus robur,tree|large|sun,3,Eiche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,162,Ranunkel,Ranunculus asiaticus,flowering|sun,2,"Ranunkel ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,98,Radieschen,Raphanus sativus,easy,1,"Das Radieschen ist ein schnellwachsendes Gemuese mit runden, roten Knollen. Es reift in nur 3-4 Wochen.",Helles bis volles Licht,10-22 °C,2 +constants/lexiconBatch2.ts,52,Mini-Monstera,Rhaphidophora tetrasperma,easy|hanging,2,"Die Mini-Monstera hat monstera­aehnliche, gelochte Blaetter auf einer kompakten, klettternden Pflanze. Sehr trendig.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,45,Stab-Palme,Rhapis excelsa,tree|low_light,2,"Die Stab-Palme ist eine elegante Zimmerpalme mit faecher­foermigen Blaettern auf duennen, bambusartigen Staemmen.",Helles indirektes Licht,15-25 °C,7 +constants/lexiconBatch1.ts,85,Korallenkaktus,Rhipsalis baccifera,succulent|hanging,2,"Der Korallenkaktus ist ein epiphytischer Kaktus mit duennen, haengenden Trieben und kleinen weissen Beeren.",Indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,170,Rhododendron,Rhododendron catawbiense,flowering|tree|bright_light,3,"Rhododendron ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,91,Japanische Azalee,Rhododendron simsii,flowering,1,"Die Japanische Azalee bluet im Winter und Fruehling ueppig mit leuchtend roten, rosa oder weissen Blueten.",Helles indirektes Licht,10-18 °C,4 +constants/lexiconBatch2.ts,214,Robinie,Robinia pseudoacacia,tree|large|sun,3,Robinie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch1.ts,66,Chinesische Rose,Rosa chinensis,flowering|sun,2,Die Chinesische Rose ist eine der Stammarten vieler Gartenrosen und bluet fast ununterbrochen.,Volles Sonnenlicht,15-25 °C,5 +constants/lexiconBatch2.ts,142,Rose,Rosa x hybrida,flowering|bright_light|sun,3,"Rose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,24,Rosmarin,Rosmarinus officinalis,easy|medicinal|sun,3,Rosmarin ist ein aromatisches Kraut mit nadelartigen Blaettern und blauen Blueten. In der Kueche unverzichtbar.,Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch2.ts,167,Rudbeckie,Rudbeckia hirta,flowering|sun,2,"Rudbeckie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,130,Sauerampfer,Rumex acetosa,easy|sun,2,Sauerampfer ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch1.ts,94,Afrikanisches Veilchen,Saintpaulia ionantha,easy|flowering,2,"Das Afrikanische Veilchen ist eine kleine, kompakte Bluehpflanze mit samtigen Blaettern und violetten Blueten.",Helles indirektes Licht,18-25 °C,7 +constants/lexiconBatch2.ts,113,Silber-Weide,Salix alba,tree|large|medicinal,3,"Die Silber-Weide hat silbrig-glaenzende Blaetter. Weidenrinde enthält Salicylsaeure, die Grundlage von Aspirin.",Helles bis volles Licht,10-25 °C,7 +constants/lexiconBatch2.ts,195,Mehlsalbei,Salvia farinacea,flowering|sun,2,"Mehlsalbei ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,103,Salbei,Salvia officinalis,easy|medicinal|sun,3,Salbei ist ein aromatisches Heilkraut mit silbrig-gruenen Blaettern. Er hat antibakterielle und entzuendungshem­mende Wirkung.,Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch2.ts,168,Feuersalbei,Salvia splendens,flowering|sun,2,"Feuersalbei ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,112,Schwarzer Holunder,Sambucus nigra,flowering|tree|medicinal,3,Der Schwarze Holunder hat weisse Doldenbluten und schwarze Beeren. Die Fruechte werden fuer Sirup und Saft verwendet.,Helles bis volles Licht,10-25 °C,7 +constants/lexiconBatch2.ts,17,Zylindrischer Bogenhanf,Sansevieria cylindrica,easy|succulent|sun,3,"Der Zylindrische Bogenhanf hat zylindrische, aufrechte Blaetter, die sich nach oben verjuengen. Sehr pflegeleicht.",Helles bis volles Licht,15-27 °C,14 +constants/lexiconBatch2.ts,78,Purpursonnentau,Sarracenia purpurea,high_humidity|sun,2,Der Purpursonnentau ist eine fleischfressende Kannenpflanze mit purpurroten Kannen. Faengt Insekten.,Volles Sonnenlicht,5-25 °C,3 +constants/lexiconBatch2.ts,123,Bohnenkraut,Satureja hortensis,easy|sun,2,Bohnenkraut ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,11,Grosse Strahlenaralie,Schefflera actinophylla,easy|tree|large,3,"Die Grosse Strahlenaralie kann grosse, handfoermige Blaetter entwickeln. Sie ist ideal als Zimmerstrauch.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,10,Strahlenaralie,Schefflera arboricola,easy|tree|air_purifier,3,"Die Strahlenaralie hat fingerfoermig angeordnete, glaenzende Blaetter auf langen Stielen. Sehr robuste Zimmerpflanze.",Helles indirektes Licht,15-25 °C,7 +constants/lexiconBatch2.ts,235,Falsche Aralie,Schefflera elegantissima,tree|bright_light,2,Falsche Aralie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch1.ts,8,Weihnachtskaktus,Schlumbergera truncata,easy|flowering|succulent,3,"Der Weihnachtskaktus erfreut zur Weihnachtszeit mit leuchtenden Blueten in Rosa, Rot oder Weiss.",Helles indirektes Licht,15-21 °C,7 +constants/lexiconBatch1.ts,55,Satinpothos,Scindapsus pictus,easy|patterned|hanging,3,"Der Satinpothos hat samtig-glaenzende, silbrig gefleckte Blaetter auf langen, haengenden Ranken.",Helles indirektes Licht,18-28 °C,7 +constants/lexiconBatch1.ts,7,Eselschwanz,Sedum morganianum,easy|succulent|hanging|sun,4,"Der Eselschwanz ist eine haengende Sukkulente mit langen Trieben aus dichten, blaugruenen Blaettchen.",Volles Sonnenlicht,15-25 °C,14 +constants/lexiconBatch2.ts,45,Regenbogenmoos,Selaginella uncinata,patterned|high_humidity,2,"Das Regenbogenmoos hat schuppenfoermige Blaetter, die im Licht schillernd irisieren. Dekorativ fuer Terrarien.",Helles indirektes Licht,18-27 °C,5 +constants/lexiconBatch1.ts,100,Perlenschnur-Pflanze,Senecio rowleyanus,easy|succulent|hanging,3,"Die Perlenschnur-Pflanze hat haengende Ranken mit kugelfoermigen, perlenaehnlichen Blaettern. Einzigartige Sukkulente.",Helles bis volles Licht,15-27 °C,14 +constants/lexiconBatch2.ts,28,Blauer Kreuzkraut,Senecio serpens,easy|succulent|sun,3,"Der Blaue Kreuzkraut hat zylindrische, blaublaugruene Blaetter und einen kriechenden Wuchs. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14 +constants/lexiconBatch2.ts,91,Tomate,Solanum lycopersicum,easy,1,"Die Tomate ist eine beliebte Gemuese- und Balkonpflanze mit roten, saftigen Fruechten. Im Topf kultivierbar.",Volles Sonnenlicht,18-28 °C,3 +constants/lexiconBatch2.ts,93,Aubergine,Solanum melongena,bright_light|sun,2,"Die Aubergine ist eine Gemuese­pflanze mit grossen, violetten Fruechten. Sie benoetigt viel Waerme und Sonne.",Volles Sonnenlicht,20-30 °C,5 +constants/lexiconBatch2.ts,238,Bubikopf,Soleirolia soleirolii,pet_friendly|high_humidity,2,Bubikopf ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,15-24 C,4 +constants/lexiconBatch2.ts,213,Eberesche,Sorbus aucuparia,tree|large|sun,3,Eberesche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,96,Spinat,Spinacia oleracea,easy,1,Spinat ist ein naehrstoffreiches Blattgemuese mit dunkelgruenen Blaettern. Reich an Eisen und Vitaminen.,Helles bis volles Licht,10-20 °C,3 +constants/lexiconBatch2.ts,222,Spierstrauch,Spiraea japonica,flowering|tree|sun,3,Spierstrauch ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,25,Aasblume,Stapelia grandiflora,flowering|succulent|sun,3,"Die Aasblume hat fleischige, gruene Staengel und riesige, sternfoermige Blueten mit aasartigem Duft.",Helles bis volles Licht,18-30 °C,14 +constants/lexiconBatch1.ts,60,Madagaskar-Jasmin,Stephanotis floribunda,flowering,1,"Der Madagaskar-Jasmin hat dicke, glaenzende Blaetter und wachsweisse, intensiv duftende Blueten. Klassische Hochzeitsblume.",Helles indirektes Licht,18-25 °C,7 +constants/lexiconBatch2.ts,131,Stevia,Stevia rebaudiana,easy|sun,2,Stevia ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,1,Weisse Strelitzie,Strelitzia nicolai,tree|large|bright_light,3,"Die Weisse Strelitzie ist ein beeindruckender Zimmerstrauch mit grossen, blaugruenen Blaettern und weiss-blauen Blueten.",Helles bis volles Licht,18-27 °C,7 +constants/lexiconBatch1.ts,3,Paradiesvogelblume,Strelitzia reginae,flowering|large|sun,3,"Die Paradiesvogelblume beeindruckt mit leuchtend orangefarbenen und blauen Blueten, die einem Vogel aehneln.",Volles Sonnenlicht,18-26 °C,7 +constants/lexiconBatch1.ts,95,Drehfrucht,Streptocarpus hybridus,flowering,1,"Die Drehfrucht ist ein Gesneriengewaechs mit langen, gerippten Blaettern und trichterfoermigen Blueten in Lila oder Rosa.",Helles indirektes Licht,15-22 °C,7 +constants/lexiconBatch1.ts,52,Stromanthe,Stromanthe sanguinea,patterned|high_humidity,2,Die Stromanthe hat dekorative Blaetter mit weissem Muster und leuchtend roter Unterseite. Familie der Marantaceen.,Helles indirektes Licht,18-25 °C,5 +constants/lexiconBatch2.ts,166,Herbstaster,Symphyotrichum novi-belgii,flowering|sun,2,"Herbstaster ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,56,Pfeilblatt,Syngonium podophyllum,easy|hanging,2,"Das Pfeilblatt hat charakteristisch pfeilfoermige Blaetter, die sich mit dem Alter weiterentwickeln.",Helles indirektes Licht,16-27 °C,7 +constants/lexiconBatch2.ts,149,Flieder,Syringa vulgaris,flowering|tree|sun,3,"Flieder ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,66,Studentenblume,Tagetes patula,easy|flowering|sun,3,Die Studentenblume ist eine robuste Sommerblume mit orangen oder gelben Blueten. Sie haelt Schadlinge fern.,Volles Sonnenlicht,15-28 °C,3 +constants/lexiconBatch2.ts,244,Philodendron Xanadu,Thaumatophyllum xanadu,bright_light,1,Philodendron Xanadu ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch1.ts,27,Thymian,Thymus vulgaris,easy|medicinal|sun,3,"Thymian ist ein kleiner, aromatischer Strauch mit winzigen Blaettern und rosa Blueten. Wichtiges Kuechenkraut.",Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch2.ts,33,Luftpflanze,Tillandsia ionantha,easy,1,Die Luftpflanze ist eine kompakte Bromelie ohne Topferde. Sie nimmt Wasser und Naehrstoffe ueber die Blattschuppen auf.,Helles bis volles Licht,15-30 °C,3 +constants/lexiconBatch2.ts,32,Spanisches Moos,Tillandsia usneoides,easy|hanging,2,"Das Spanische Moos ist eine epiphytische Bromelie ohne Wurzeln, die in der Luft haengt. Es benoetigt nur Feuchtigkeitsbespruehing.",Helles bis volles Licht,15-30 °C,3 +constants/lexiconBatch2.ts,55,Weisse Tradescantia,Tradescantia fluminensis,easy|hanging,2,Die Weisse Tradescantia hat gruene Blaetter mit weisslichen Unterseiten. Sehr robust und schnellwachsend.,Helles indirektes Licht,15-25 °C,5 +constants/lexiconBatch2.ts,54,Lila Tradescantia,Tradescantia pallida,easy|hanging|sun,3,Die Lila Tradescantia hat leuchtend purpurrote Blaetter und ist sehr auffaellig. Sie liebt viel Licht.,Helles bis volles Licht,15-25 °C,5 +constants/lexiconBatch1.ts,17,Zebrakraut,Tradescantia zebrina,easy|patterned|hanging,3,Das Zebrakraut faellt durch seine silbrig-lila gestreiften Blaetter auf. Schnellwachsende Haengepflanze.,Helles indirektes Licht,15-25 °C,5 +constants/lexiconBatch2.ts,151,Kapuzinerkresse,Tropaeolum majus,flowering|sun,2,"Kapuzinerkresse ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,107,Tulpe,Tulipa gesneriana,easy|flowering,2,Die Tulpe ist eine der beliebtesten Fruehjahrsblueher mit kelchfoermigen Blueten in unzaehligen Farben.,Helles bis volles Licht,8-18 °C,5 +constants/lexiconBatch2.ts,111,Grosse Brennessel,Urtica dioica,medicinal,1,Die Grosse Brennessel ist eine Heilpflanze mit brennenden Haaren. Die Blaetter sind reich an Vitaminen und Mineralien.,Helles bis volles Licht,10-25 °C,7 +constants/lexiconBatch2.ts,82,Wasserschlauch,Utricularia gibba,high_humidity|sun,2,Der Wasserschlauch ist eine wasserbewohnende fleischfressende Pflanze mit Schlaeuchen als Insekten­fallen.,Helles bis volles Licht,15-25 °C,2 +constants/lexiconBatch2.ts,104,Baldrian,Valeriana officinalis,flowering|medicinal,2,Baldrian ist ein bekanntes Heilkraut mit weissen bis roeslichen Blueten. Die Wurzeln werden zur Schlaffoerderung verwendet.,Helles bis volles Licht,15-25 °C,7 +constants/lexiconBatch1.ts,72,Vanda-Orchidee,Vanda coerulea,flowering|bright_light|high_humidity,3,Die Vanda-Orchidee ist bekannt fuer ihre seltene blaue Bluetenfarbe. Epiphytische Orchidee mit grossen Blueten.,Helles bis volles Licht,20-30 °C,3 +constants/lexiconBatch1.ts,76,Vanille,Vanilla planifolia,flowering|high_humidity,2,"Die Vanille ist eine kletternde Orchidee, aus deren Fruechten das beliebte Gewuerz gewonnen wird.",Helles indirektes Licht,20-30 °C,5 +constants/lexiconBatch2.ts,192,Koenigskerze,Verbascum thapsus,flowering|medicinal|sun,3,"Koenigskerze ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,164,Eisenkraut,Verbena bonariensis,flowering|sun,2,"Eisenkraut ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,198,Hornveilchen,Viola cornuta,flowering|sun,2,"Hornveilchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,35,Stiefmuetterchen,Viola wittrockiana,easy|flowering,2,Das Stiefmuetterchen ist ein bekannter Fruehjahrsblueher mit charakteristisch gezeichneten Blueten.,Helles bis volles Licht,5-18 °C,3 +constants/lexiconBatch2.ts,35,Flammen-Bromelie,Vriesea splendens,flowering|patterned|high_humidity,3,"Die Flammen-Bromelie hat gebänderte, dunkelgruene Blaetter und einen spektakulaeren, roten Bluetenstand.",Helles indirektes Licht,18-25 °C,7 +constants/lexiconBatch2.ts,5,Mexikanische Fächerpalme,Washingtonia robusta,tree|large|sun,3,"Die Mexikanische Fächerpalme ist eine schlanke, hohe Palme mit faecher­foermigen Blaettern. Sehr hitzetolerant.",Volles Sonnenlicht,15-35 °C,10 +constants/lexiconBatch2.ts,221,Weigelie,Weigela florida,flowering|tree|sun,3,Weigelie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch1.ts,65,Chinesischer Blauregen,Wisteria sinensis,flowering|large|sun,3,"Der Chinesische Blauregen ist ein ueppiger Kletterkuenstler mit langen, duftenden Bluetentrauben in Lila.",Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch2.ts,246,Yucca aloifolia,Yucca aloifolia,easy|tree|sun,3,Yucca aloifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Volles Sonnenlicht,18-30 C,10 +constants/lexiconBatch1.ts,40,Yucca-Palme,Yucca elephantipes,easy|tree|sun,3,"Die Yucca-Palme ist eine robuste Zimmerpflanze mit starrem, immergruenem Blaetterschopf auf einem dicken Stamm.",Helles bis volles Licht,15-28 °C,14 +constants/lexiconBatch2.ts,70,Calla,Zantedeschia aethiopica,flowering|high_humidity,2,"Die Calla hat elegante, trichterfoermige weisse Hochblaetter und glaenzende, herzfoermige Blaetter. Sehr edel.",Helles indirektes Licht,15-24 °C,7 +constants/lexiconBatch2.ts,75,Ingwer,Zingiber officinale,medicinal|high_humidity,2,Ingwer ist eine tropische Gewuerzpflanze mit aromatischen Knollen. Die Blaetter sind schilfartig.,Helles indirektes Licht,20-30 °C,5 +constants/lexiconBatch2.ts,65,Zinnie,Zinnia elegans,easy|flowering|sun,3,"Die Zinnie ist eine leuchtende Sommerblume mit grossen, dahlienaehnlichen Blueten. Sehr robust und hitzetolerant.",Volles Sonnenlicht,18-30 °C,3 diff --git a/app.json b/app.json new file mode 100644 index 0000000..4e26e50 --- /dev/null +++ b/app.json @@ -0,0 +1,71 @@ +{ + "expo": { + "name": "GreenLens", + "slug": "greenlens", + "version": "2.1.4", + "orientation": "portrait", + "icon": "./assets/icon.png", + "userInterfaceStyle": "automatic", + "scheme": "greenlens", + "splash": { + "image": "./assets/transparent.png", + "resizeMode": "contain", + "backgroundColor": "#111813" + }, + "assetBundlePatterns": [ + "**/*" + ], + "ios": { + "supportsTablet": true, + "bundleIdentifier": "com.greenlens.app", + "buildNumber": "35", + "infoPlist": { + "NSCameraUsageDescription": "GreenLens needs camera access to identify plants.", + "NSPhotoLibraryUsageDescription": "GreenLens needs photo library access to identify plants from your gallery.", + "ITSAppUsesNonExemptEncryption": false + } + }, + "android": { + "adaptiveIcon": { + "foregroundImage": "./assets/adaptive-icon.png", + "backgroundColor": "#111813" + }, + "package": "com.greenlens.app", + "versionCode": 2, + "permissions": [ + "android.permission.CAMERA", + "android.permission.RECORD_AUDIO" + ] + }, + "runtimeVersion": { + "policy": "appVersion" + }, + "updates": { + "url": "https://u.expo.dev/f0c92b2e-a952-4cfe-9754-7d7222b76969" + }, + "plugins": [ + "expo-dev-client", + "expo-router", + "expo-camera", + "expo-image-picker", + "expo-secure-store", + "expo-asset", + "expo-font", + "expo-notifications", + [ + "expo-splash-screen", + { + "image": "./assets/transparent.png", + "imageWidth": 160, + "backgroundColor": "#111813" + } + ] + ], + "extra": { + "router": {}, + "eas": { + "projectId": "f0c92b2e-a952-4cfe-9754-7d7222b76969" + } + } + } +} \ No newline at end of file diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx new file mode 100644 index 0000000..02089c9 --- /dev/null +++ b/app/(tabs)/_layout.tsx @@ -0,0 +1,58 @@ +import { Tabs } from 'expo-router'; +import { Ionicons } from '@expo/vector-icons'; +import { useApp } from '../../context/AppContext'; +import { useColors } from '../../constants/Colors'; + +export default function TabLayout() { + const { isDarkMode, colorPalette, t } = useApp(); + const colors = useColors(isDarkMode, colorPalette); + + return ( + + ( + + ), + }} + /> + ( + + ), + }} + /> + ( + + ), + }} + /> + + ); +} diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx new file mode 100644 index 0000000..cb56020 --- /dev/null +++ b/app/(tabs)/index.tsx @@ -0,0 +1,846 @@ +import React, { useMemo, useState, useRef, useEffect } from 'react'; +import { + ActivityIndicator, + Alert, + Image, + ScrollView, + StyleSheet, + Text, + TouchableOpacity, + View, + Dimensions, +} from 'react-native'; +import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'; +import { useRouter } from 'expo-router'; +import { Ionicons } from '@expo/vector-icons'; +import AsyncStorage from '@react-native-async-storage/async-storage'; +import { useApp } from '../../context/AppContext'; +import { useColors } from '../../constants/Colors'; +import { ThemeBackdrop } from '../../components/ThemeBackdrop'; +import { SafeImage } from '../../components/SafeImage'; +import { Plant } from '../../types'; +import { useCoachMarks } from '../../context/CoachMarksContext'; + +const { width: SCREEN_W, height: SCREEN_H } = Dimensions.get('window'); + +type FilterKey = 'all' | 'today' | 'week' | 'healthy' | 'dormant'; + +const DAY_MS = 24 * 60 * 60 * 1000; +const CONTENT_BOTTOM_PADDING = 12; +const FAB_BOTTOM_OFFSET = 16; + +function OnboardingChecklist({ plantsCount, colors, router, t }: { plantsCount: number; colors: any; router: any; t: any }) { + const checklist = [ + { id: 'scan', label: t.stepScan, completed: plantsCount > 0, icon: 'camera-outline', route: '/scanner' }, + { id: 'lexicon', label: t.stepLexicon, completed: false, icon: 'search-outline', route: '/lexicon' }, + { id: 'theme', label: t.stepTheme, completed: false, icon: 'color-palette-outline', route: '/profile/preferences' }, + ]; + + return ( + + {t.nextStepsTitle} + + {checklist.map((item) => ( + { + if (item.id === 'theme') { + router.push('/profile/preferences'); + } else if (item.id === 'scan') { + router.push('/scanner'); + } else if (item.id === 'lexicon') { + router.push('/lexicon'); + } else { + router.push(item.route); + } + }} + disabled={item.completed} + > + + + + + {item.label} + + {!item.completed && } + + ))} + + + ); +} + +const getDaysUntilWatering = (plant: Plant): number => { + const lastWateredTs = new Date(plant.lastWatered).getTime(); + if (Number.isNaN(lastWateredTs)) return 0; + + const dueTs = lastWateredTs + (plant.careInfo.waterIntervalDays * DAY_MS); + const remainingMs = dueTs - Date.now(); + if (remainingMs <= 0) return 0; + + return Math.ceil(remainingMs / DAY_MS); +}; + +export default function HomeScreen() { + const { + plants, + isLoadingPlants, + profileImageUri, + profileName, + billingSummary, + isLoadingBilling, + language, + t, + isDarkMode, + colorPalette, + } = useApp(); + const colors = useColors(isDarkMode, colorPalette); + const router = useRouter(); + const insets = useSafeAreaInsets(); + const [activeFilter, setActiveFilter] = useState('all'); + const { registerLayout, startTour } = useCoachMarks(); + const fabRef = useRef(null); + + // Tour nach Registrierung starten + useEffect(() => { + const checkTour = async () => { + const flag = await AsyncStorage.getItem('greenlens_show_tour'); + if (flag !== 'true') return; + await AsyncStorage.removeItem('greenlens_show_tour'); + + // 1 Sekunde warten, dann Tour starten + setTimeout(() => { + // Tab-Positionen approximieren (gleichmäßig verteilt) + const tabBarBottom = SCREEN_H - 85; + const tabW = SCREEN_W / 3; + registerLayout('tab_search', { x: tabW, y: tabBarBottom + 8, width: tabW, height: 52 }); + registerLayout('tab_profile', { x: tabW * 2, y: tabBarBottom + 8, width: tabW, height: 52 }); + + startTour([ + { + elementKey: 'fab', + title: t.tourFabTitle, + description: t.tourFabDesc, + tooltipSide: 'above', + }, + { + elementKey: 'tab_search', + title: t.tourSearchTitle, + description: t.tourSearchDesc, + tooltipSide: 'above', + }, + { + elementKey: 'tab_profile', + title: t.tourProfileTitle, + description: t.tourProfileDesc, + tooltipSide: 'above', + }, + ]); + }, 1000); + }; + checkTour(); + }, []); + + const copy = t; + const greetingText = useMemo(() => { + const hour = new Date().getHours(); + if (hour < 12) return copy.greetingMorning; + if (hour < 18) return copy.greetingAfternoon; + return copy.greetingEvening; + }, [copy.greetingAfternoon, copy.greetingEvening, copy.greetingMorning]); + const creditsText = useMemo(() => { + if (isLoadingBilling && !billingSummary) { + return '...'; + } + if (!billingSummary) { + return `-- ${copy.creditsLabel}`; + } + return `${billingSummary.credits.available} ${copy.creditsLabel}`; + }, [billingSummary, copy.creditsLabel, isLoadingBilling]); + + const thirstyCount = useMemo( + () => plants.filter(plant => getDaysUntilWatering(plant) === 0).length, + [plants] + ); + const dueTodayPlants = useMemo( + () => plants.filter(plant => getDaysUntilWatering(plant) === 0), + [plants] + ); + + const filteredPlants = useMemo(() => { + return plants.filter((plant) => { + if (activeFilter === 'all') return true; + + const daysUntil = getDaysUntilWatering(plant); + + if (activeFilter === 'today') return daysUntil === 0; + if (activeFilter === 'week') return daysUntil <= 7; + if (activeFilter === 'healthy') return daysUntil >= 2; + return plant.careInfo.waterIntervalDays >= 14; + }); + }, [plants, activeFilter]); + + const chips: Array<{ key: FilterKey; label: string }> = [ + { key: 'all', label: copy.all }, + { key: 'today', label: copy.today }, + { key: 'week', label: copy.week }, + { key: 'healthy', label: copy.healthy }, + { key: 'dormant', label: copy.dormant }, + ]; + + const handleBellPress = () => { + setActiveFilter('today'); + + if (dueTodayPlants.length === 0) { + Alert.alert(copy.reminderTitle, copy.reminderNone); + return; + } + + const previewNames = dueTodayPlants + .slice(0, 6) + .map((plant) => `- ${plant.name}`) + .join('\n'); + const remainingCount = dueTodayPlants.length - 6; + const remainingText = remainingCount > 0 + ? `\n+ ${remainingCount} ${copy.more}` + : ''; + + Alert.alert( + copy.reminderTitle, + `${copy.reminderDue.replace('{0}', dueTodayPlants.length.toString())}\n\n${previewNames}${remainingText}` + ); + }; + + if (isLoadingPlants) { + return ( + + + + + ); + } + + return ( + + + + + + + + {profileImageUri ? ( + + ) : ( + + )} + + + {greetingText} + + + {profileName || ''} + + + + {creditsText} + + + + + + + + + + + + + + + {copy.needsWaterToday} + + + + {copy.plantsThirsty.replace('{0}', thirstyCount.toString())} + + + + {copy.viewSchedule} + + + + + + + {plants.length === 0 && ( + + )} + + + {chips.map(chip => ( + setActiveFilter(chip.key)} + activeOpacity={0.85} + > + + {chip.label} + + + ))} + + + + {copy.collectionTitle} + + + {copy.collectionCount.replace('{0}', filteredPlants.length.toString())} + + + + + {filteredPlants.length === 0 ? ( + + + + + + {plants.length === 0 ? copy.emptyCollectionTitle : copy.noneInFilter} + + + {plants.length === 0 ? copy.emptyCollectionHint : copy.noneInFilter} + + {plants.length === 0 && ( + router.push('/scanner')} + activeOpacity={0.86} + > + + {copy.scanFirstPlant} + + )} + + ) : ( + filteredPlants.map((plant) => { + const daysUntil = getDaysUntilWatering(plant); + const thirsty = daysUntil === 0; + const nextWaterText = thirsty + ? copy.today + : t.inXDays.replace('{0}', daysUntil.toString()); + + return ( + router.push(`/plant/${plant.id}`)} + > + + + + + + + + + {plant.name} + + + {plant.botanicalName} + + + + + + + + + {thirsty ? copy.thirsty : copy.healthyStatus} + + + + + + {copy.nextWaterLabel}: {nextWaterText} + + + + + + ); + }) + )} + + + router.push('/scanner')} + onLayout={() => { + fabRef.current?.measureInWindow((x, y, width, height) => { + registerLayout('fab', { x, y, width, height }); + }); + }} + > + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + loadingContainer: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + content: { + paddingHorizontal: 24, + paddingTop: 14, + }, + header: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 26, + }, + headerLeft: { + flexDirection: 'row', + alignItems: 'center', + gap: 12, + flex: 1, + }, + headerTextBlock: { + flex: 1, + minWidth: 0, + }, + avatarWrap: { + width: 48, + height: 48, + borderRadius: 16, + alignItems: 'center', + justifyContent: 'center', + overflow: 'hidden', + }, + avatarImage: { + width: '100%', + height: '100%', + }, + greetingText: { + fontSize: 13, + fontWeight: '600', + }, + nameRow: { + marginTop: 1, + flexDirection: 'row', + alignItems: 'center', + gap: 8, + minWidth: 0, + }, + nameText: { + fontSize: 21, + fontWeight: '700', + letterSpacing: 0.1, + flexShrink: 1, + }, + creditsPill: { + borderRadius: 999, + borderWidth: 1, + paddingHorizontal: 8, + paddingVertical: 3, + }, + creditsText: { + fontSize: 10, + fontWeight: '700', + letterSpacing: 0.3, + textTransform: 'uppercase', + }, + bellBtn: { + width: 46, + height: 46, + borderRadius: 16, + borderWidth: 1, + alignItems: 'center', + justifyContent: 'center', + shadowOpacity: 0.08, + shadowRadius: 8, + shadowOffset: { width: 0, height: 2 }, + elevation: 2, + }, + priorityCard: { + borderRadius: 32, + padding: 24, + marginBottom: 20, + overflow: 'hidden', + }, + priorityLabelRow: { + flexDirection: 'row', + alignItems: 'center', + gap: 6, + marginBottom: 8, + }, + priorityLabel: { + fontSize: 10, + fontWeight: '700', + textTransform: 'uppercase', + letterSpacing: 0.9, + }, + priorityTitle: { + fontSize: 29, + fontWeight: '700', + lineHeight: 36, + maxWidth: 260, + marginBottom: 14, + }, + priorityButton: { + alignSelf: 'flex-start', + borderRadius: 16, + borderWidth: 1, + paddingHorizontal: 16, + paddingVertical: 10, + flexDirection: 'row', + alignItems: 'center', + gap: 6, + }, + priorityButtonText: { + fontSize: 13, + fontWeight: '700', + }, + priorityBgIcon: { + position: 'absolute', + right: -18, + bottom: -22, + }, + filterRow: { + gap: 10, + paddingVertical: 2, + paddingRight: 4, + marginBottom: 16, + }, + collectionHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 12, + }, + collectionTitle: { + fontSize: 19, + fontWeight: '700', + letterSpacing: 0.2, + }, + collectionCountPill: { + borderRadius: 999, + borderWidth: 1, + paddingHorizontal: 10, + paddingVertical: 4, + }, + collectionCountText: { + fontSize: 11, + fontWeight: '700', + textTransform: 'uppercase', + letterSpacing: 0.4, + }, + filterChip: { + paddingHorizontal: 22, + paddingVertical: 10, + borderRadius: 16, + borderWidth: 1, + }, + filterChipActive: { + paddingHorizontal: 22, + paddingVertical: 10, + borderRadius: 16, + shadowOpacity: 0.24, + shadowRadius: 10, + shadowOffset: { width: 0, height: 3 }, + elevation: 3, + }, + filterText: { + fontSize: 13, + fontWeight: '700', + }, + filterTextActive: { + fontSize: 13, + fontWeight: '700', + }, + plantCard: { + borderRadius: 30, + borderWidth: 1, + padding: 15, + flexDirection: 'row', + alignItems: 'flex-start', + gap: 14, + marginBottom: 14, + shadowOpacity: 0.1, + shadowRadius: 12, + shadowOffset: { width: 0, height: 4 }, + elevation: 3, + }, + plantImageWrap: { + borderWidth: 1, + borderRadius: 20, + overflow: 'hidden', + }, + plantImage: { + width: 98, + height: 98, + borderRadius: 20, + }, + plantBody: { + flex: 1, + paddingTop: 2, + }, + plantHeadRow: { + flexDirection: 'row', + alignItems: 'flex-start', + justifyContent: 'space-between', + marginBottom: 8, + gap: 8, + }, + plantTitleCol: { + flex: 1, + minWidth: 0, + }, + plantName: { + fontWeight: '700', + fontSize: 19, + letterSpacing: 0.15, + }, + botanicalName: { + fontSize: 12.5, + fontStyle: 'italic', + fontWeight: '500', + marginTop: 2, + opacity: 0.95, + }, + metaRow: { + flexDirection: 'row', + alignItems: 'center', + gap: 8, + flexWrap: 'wrap', + }, + statusThirsty: { + borderRadius: 20, + paddingHorizontal: 10, + paddingVertical: 4, + }, + statusHealthy: { + borderRadius: 20, + paddingHorizontal: 10, + paddingVertical: 4, + }, + statusThirstyText: { + fontSize: 10, + fontWeight: '800', + textTransform: 'uppercase', + letterSpacing: 0.4, + }, + statusHealthyText: { + fontSize: 10, + fontWeight: '800', + textTransform: 'uppercase', + letterSpacing: 0.4, + }, + waterMeta: { + fontSize: 10, + fontWeight: '700', + textTransform: 'uppercase', + letterSpacing: 0.4, + }, + nextWaterPill: { + borderRadius: 999, + borderWidth: 1, + paddingHorizontal: 9, + paddingVertical: 4, + flexDirection: 'row', + alignItems: 'center', + gap: 4, + }, + emptyState: { + borderRadius: 24, + borderWidth: 1, + paddingVertical: 32, + paddingHorizontal: 22, + alignItems: 'center', + gap: 10, + }, + emptyIconWrap: { + width: 56, + height: 56, + borderRadius: 18, + alignItems: 'center', + justifyContent: 'center', + }, + emptyTitle: { + fontSize: 18, + fontWeight: '700', + textAlign: 'center', + }, + emptyText: { + fontSize: 13, + fontWeight: '500', + textAlign: 'center', + lineHeight: 20, + }, + emptyCta: { + marginTop: 8, + borderRadius: 999, + paddingHorizontal: 16, + paddingVertical: 10, + flexDirection: 'row', + alignItems: 'center', + gap: 8, + shadowOpacity: 0.3, + shadowRadius: 10, + shadowOffset: { width: 0, height: 4 }, + elevation: 4, + }, + emptyCtaText: { + fontSize: 13, + fontWeight: '700', + }, + fab: { + position: 'absolute', + right: 24, + width: 66, + height: 66, + borderRadius: 33, + borderWidth: 4, + alignItems: 'center', + justifyContent: 'center', + shadowOpacity: 0.38, + shadowRadius: 14, + shadowOffset: { width: 0, height: 5 }, + elevation: 9, + }, + checklistCard: { + borderRadius: 24, + borderWidth: 1, + padding: 20, + marginBottom: 20, + }, + checklistTitle: { + fontSize: 16, + fontWeight: '700', + marginBottom: 16, + }, + checklistGrid: { + gap: 12, + }, + checklistItem: { + flexDirection: 'row', + alignItems: 'center', + gap: 12, + }, + checkIcon: { + width: 32, + height: 32, + borderRadius: 16, + justifyContent: 'center', + alignItems: 'center', + }, + checklistText: { + flex: 1, + fontSize: 14, + fontWeight: '500', + }, +}); diff --git a/app/(tabs)/profile.tsx b/app/(tabs)/profile.tsx new file mode 100644 index 0000000..be07f7d --- /dev/null +++ b/app/(tabs)/profile.tsx @@ -0,0 +1,526 @@ +import React, { useState, useEffect, useMemo } from 'react'; +import { + View, + Text, + StyleSheet, + TouchableOpacity, + ScrollView, + Image, + Alert, + TextInput, + Keyboard, +} from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; +import { Ionicons } from '@expo/vector-icons'; +import * as ImagePicker from 'expo-image-picker'; +import { useRouter } from 'expo-router'; +import { useApp } from '../../context/AppContext'; +import { useColors } from '../../constants/Colors'; +import { ThemeBackdrop } from '../../components/ThemeBackdrop'; +import { Language } from '../../types'; + +const DAY_MS = 24 * 60 * 60 * 1000; + +const getDaysUntilWatering = (lastWatered: string, intervalDays: number): number => { + const lastWateredTs = new Date(lastWatered).getTime(); + if (Number.isNaN(lastWateredTs)) return 0; + const dueTs = lastWateredTs + (intervalDays * DAY_MS); + const remainingMs = dueTs - Date.now(); + if (remainingMs <= 0) return 0; + return Math.ceil(remainingMs / DAY_MS); +}; + +const getProfileCopy = (language: Language) => { + if (language === 'de') { + return { + overviewLabel: 'Überblick', + statPlants: 'Pflanzen', + statDueToday: 'Heute fällig', + statReminders: 'Erinnerungen an', + account: 'Account', + changePhoto: 'Foto ändern', + removePhoto: 'Foto entfernen', + nameLabel: 'Name', + namePlaceholder: 'Dein Name', + saveName: 'Name speichern', + photoErrorTitle: 'Fehler', + photoErrorMessage: 'Profilfoto konnte nicht geladen werden.', + nameErrorTitle: 'Name fehlt', + nameErrorMessage: 'Bitte gib einen Namen ein.', + menuSettings: 'Einstellungen', + menuBilling: 'Abo & Credits', + menuData: 'Daten & Datenschutz', + logout: 'Abmelden', + logoutConfirmTitle: 'Abmelden?', + logoutConfirmMessage: 'Möchtest du dich wirklich abmelden?', + logoutConfirmBtn: 'Abmelden', + }; + } + if (language === 'es') { + return { + overviewLabel: 'Resumen', + statPlants: 'Plantas', + statDueToday: 'Vencen hoy', + statReminders: 'Recordatorios', + account: 'Cuenta', + changePhoto: 'Cambiar foto', + removePhoto: 'Eliminar foto', + nameLabel: 'Nombre', + namePlaceholder: 'Tu nombre', + saveName: 'Guardar nombre', + photoErrorTitle: 'Error', + photoErrorMessage: 'No se pudo cargar la foto.', + nameErrorTitle: 'Falta nombre', + nameErrorMessage: 'Por favor ingresa un nombre.', + menuSettings: 'Ajustes', + menuBilling: 'Suscripción y Créditos', + menuData: 'Datos y Privacidad', + logout: 'Cerrar sesión', + logoutConfirmTitle: '¿Cerrar sesión?', + logoutConfirmMessage: '¿Realmente quieres cerrar sesión?', + logoutConfirmBtn: 'Cerrar sesión', + }; + } + return { + overviewLabel: 'Overview', + statPlants: 'Plants', + statDueToday: 'Due today', + statReminders: 'Reminders on', + account: 'Account', + changePhoto: 'Change photo', + removePhoto: 'Remove photo', + nameLabel: 'Name', + namePlaceholder: 'Your name', + saveName: 'Save name', + photoErrorTitle: 'Error', + photoErrorMessage: 'Could not load profile photo.', + nameErrorTitle: 'Name missing', + nameErrorMessage: 'Please enter a name.', + menuSettings: 'Preferences', + menuBilling: 'Billing & Credits', + menuData: 'Data & Privacy', + logout: 'Sign Out', + logoutConfirmTitle: 'Sign out?', + logoutConfirmMessage: 'Do you really want to sign out?', + logoutConfirmBtn: 'Sign Out', + }; +}; + +export default function ProfileScreen() { + const { + plants, + language, + t, + isDarkMode, + colorPalette, + profileImageUri, + setProfileImage, + profileName, + setProfileName, + signOut, + } = useApp(); + + const router = useRouter(); + const colors = useColors(isDarkMode, colorPalette); + + const [isUpdatingImage, setIsUpdatingImage] = useState(false); + const [isSavingName, setIsSavingName] = useState(false); + const [draftName, setDraftName] = useState(profileName); + + const copy = useMemo(() => getProfileCopy(language), [language]); + + useEffect(() => { + setDraftName(profileName); + }, [profileName]); + + const normalizedDraftName = draftName.trim(); + const canSaveName = normalizedDraftName.length > 0 && normalizedDraftName !== profileName; + + const dueTodayCount = useMemo( + () => plants.filter(plant => getDaysUntilWatering(plant.lastWatered, plant.careInfo.waterIntervalDays) === 0).length, + [plants] + ); + + const remindersEnabledCount = useMemo( + () => plants.filter(plant => Boolean(plant.notificationsEnabled)).length, + [plants] + ); + + const handlePickProfileImage = async () => { + if (isUpdatingImage) return; + + setIsUpdatingImage(true); + try { + const result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ['images'], + quality: 0.85, + base64: true, + }); + + if (!result.canceled && result.assets[0]) { + const asset = result.assets[0]; + const imageUri = asset.base64 + ? `data:image/jpeg;base64,${asset.base64}` + : asset.uri; + await setProfileImage(imageUri); + } + } catch (error) { + console.error('Failed to pick profile image', error); + Alert.alert(copy.photoErrorTitle, copy.photoErrorMessage); + } finally { + setIsUpdatingImage(false); + } + }; + + const handleRemovePhoto = async () => { + await setProfileImage(null); + }; + + const handleSaveName = async () => { + if (!normalizedDraftName) { + Alert.alert(copy.nameErrorTitle, copy.nameErrorMessage); + return; + } + + if (!canSaveName) { + Keyboard.dismiss(); + return; + } + + setIsSavingName(true); + try { + await setProfileName(normalizedDraftName); + Keyboard.dismiss(); + } finally { + setIsSavingName(false); + } + }; + + const menuItems = [ + { label: copy.menuSettings, icon: 'settings-outline', route: '/profile/preferences' as any }, + { label: copy.menuBilling, icon: 'card-outline', route: '/profile/billing' as any }, + { label: copy.menuData, icon: 'shield-checkmark-outline', route: '/profile/data' as any }, + ]; + + return ( + + + + + {t.tabProfile} + + + {copy.overviewLabel} + + {[ + { label: copy.statPlants, value: plants.length.toString() }, + { label: copy.statDueToday, value: dueTodayCount.toString() }, + { label: copy.statReminders, value: remindersEnabledCount.toString() }, + ].map((item) => ( + + {item.value} + {item.label} + + ))} + + + + + {copy.account} + + + + {profileImageUri ? ( + + ) : ( + + )} + + + + {profileName} + + {plants.length} {copy.statPlants} + + + + + + + + {isUpdatingImage ? '...' : copy.changePhoto} + + + + {profileImageUri ? ( + + + {copy.removePhoto} + + + ) : null} + + + {copy.nameLabel} + + + + + {isSavingName ? '...' : copy.saveName} + + + + + + + {menuItems.map((item, idx) => ( + router.push(item.route)} + activeOpacity={0.7} + > + + + {item.label} + + + + ))} + + {/* Logout */} + { + Alert.alert(copy.logoutConfirmTitle, copy.logoutConfirmMessage, [ + { text: t.cancel, style: 'cancel' }, + { + text: copy.logoutConfirmBtn, + style: 'destructive', + onPress: async () => { + await signOut(); + router.replace('/auth/login'); + }, + }, + ]); + }} + > + + {copy.logout} + + + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + paddingHorizontal: 20, + }, + scrollContent: { + paddingBottom: 20, + }, + title: { + marginTop: 14, + marginBottom: 14, + fontSize: 28, + fontWeight: '700', + }, + card: { + borderWidth: 1, + borderRadius: 18, + padding: 14, + marginBottom: 12, + gap: 10, + }, + accountCard: { + marginBottom: 14, + }, + logoutBtn: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + gap: 8, + borderRadius: 14, + borderWidth: 1, + paddingVertical: 14, + marginBottom: 12, + }, + logoutText: { + fontSize: 15, + fontWeight: '600', + }, + cardTitle: { + fontSize: 15, + fontWeight: '700', + }, + statsRow: { + flexDirection: 'row', + gap: 8, + }, + statCard: { + flex: 1, + borderWidth: 1, + borderRadius: 12, + paddingVertical: 12, + paddingHorizontal: 8, + alignItems: 'center', + justifyContent: 'center', + gap: 2, + }, + statValue: { + fontSize: 22, + lineHeight: 24, + fontWeight: '700', + }, + statLabel: { + fontSize: 11, + fontWeight: '600', + textAlign: 'center', + }, + accountRow: { + flexDirection: 'row', + alignItems: 'center', + gap: 12, + }, + accountMeta: { + flex: 1, + gap: 3, + }, + currentName: { + fontSize: 18, + fontWeight: '700', + }, + plantsCount: { + fontSize: 13, + fontWeight: '600', + }, + avatarFrame: { + width: 74, + height: 74, + borderRadius: 22, + alignItems: 'center', + justifyContent: 'center', + overflow: 'hidden', + }, + avatarImage: { + width: '100%', + height: '100%', + }, + photoButtons: { + flexDirection: 'row', + gap: 8, + }, + photoActionBtn: { + borderRadius: 10, + paddingVertical: 10, + paddingHorizontal: 12, + }, + photoSecondaryBtn: { + borderWidth: 1, + }, + photoActionText: { + fontSize: 12, + fontWeight: '700', + }, + photoSecondaryText: { + fontSize: 12, + fontWeight: '700', + }, + fieldLabel: { + marginTop: 2, + fontSize: 12, + fontWeight: '600', + }, + nameRow: { + flexDirection: 'row', + gap: 8, + alignItems: 'center', + }, + nameInput: { + flex: 1, + borderWidth: 1, + borderRadius: 12, + paddingHorizontal: 12, + paddingVertical: 10, + fontSize: 14, + fontWeight: '500', + }, + saveNameBtn: { + borderWidth: 1, + borderRadius: 12, + paddingHorizontal: 12, + paddingVertical: 10, + }, + saveNameText: { + fontSize: 12, + fontWeight: '700', + }, + menuItem: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingVertical: 16, + paddingHorizontal: 14, + }, + menuItemLeft: { + flexDirection: 'row', + alignItems: 'center', + gap: 12, + }, + menuItemText: { + fontSize: 16, + fontWeight: '500', + } +}); diff --git a/app/(tabs)/search.tsx b/app/(tabs)/search.tsx new file mode 100644 index 0000000..12a1d9e --- /dev/null +++ b/app/(tabs)/search.tsx @@ -0,0 +1,613 @@ +import React, { useEffect, useMemo, useState } from 'react'; +import { + Dimensions, + FlatList, + ScrollView, + StyleSheet, + Text, + TextInput, + TouchableOpacity, + View, +} from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; +import { useRouter } from 'expo-router'; +import { Ionicons } from '@expo/vector-icons'; +import { useApp } from '../../context/AppContext'; +import { useColors } from '../../constants/Colors'; +import { Plant } from '../../types'; +import { PlantCard } from '../../components/PlantCard'; +import { ThemeBackdrop } from '../../components/ThemeBackdrop'; +import { + DatabaseEntry, + PlantDatabaseService, + SemanticSearchStatus, +} from '../../services/plantDatabaseService'; +import { normalizeSearchText, rankHybridEntries } from '../../utils/hybridSearch'; + +const { width } = Dimensions.get('window'); +const CARD_GAP = 12; +const CARD_WIDTH = (width - 40 - CARD_GAP) / 2; +const SEARCH_DEBOUNCE_MS = 250; +const SEMANTIC_SEARCH_CREDIT_COST = 2; + +const getBillingCopy = (language: 'de' | 'en' | 'es') => { + if (language === 'de') { + return { + creditsLabel: 'Credits', + deepSearchCost: `Deep Search kostet ${SEMANTIC_SEARCH_CREDIT_COST} Credits`, + insufficientCredits: 'Nicht genug Credits fuer AI Deep Search.', + managePlan: 'Plan verwalten', + }; + } + + if (language === 'es') { + return { + creditsLabel: 'Creditos', + deepSearchCost: `Deep Search cuesta ${SEMANTIC_SEARCH_CREDIT_COST} creditos`, + insufficientCredits: 'No tienes creditos suficientes para AI Deep Search.', + managePlan: 'Gestionar plan', + }; + } + + return { + creditsLabel: 'Credits', + deepSearchCost: `Deep Search costs ${SEMANTIC_SEARCH_CREDIT_COST} credits`, + insufficientCredits: 'Not enough credits for AI Deep Search.', + managePlan: 'Manage plan', + }; +}; + +const parseColor = (value: string) => { + if (value.startsWith('#')) { + const cleaned = value.replace('#', ''); + const normalized = cleaned.length === 3 + ? cleaned.split('').map((c) => `${c}${c}`).join('') + : cleaned; + const int = Number.parseInt(normalized, 16); + return { + r: (int >> 16) & 255, + g: (int >> 8) & 255, + b: int & 255, + }; + } + + const match = value.match(/rgba?\(([^)]+)\)/i); + if (!match) return { r: 255, g: 255, b: 255 }; + const parts = match[1].split(',').map((part) => part.trim()); + return { + r: Number.parseFloat(parts[0]) || 255, + g: Number.parseFloat(parts[1]) || 255, + b: Number.parseFloat(parts[2]) || 255, + }; +}; + +const blendColors = (baseColor: string, tintColor: string, tintWeight: number) => { + const base = parseColor(baseColor); + const tint = parseColor(tintColor); + const weight = Math.max(0, Math.min(1, tintWeight)); + const r = Math.round(base.r + (tint.r - base.r) * weight); + const g = Math.round(base.g + (tint.g - base.g) * weight); + const b = Math.round(base.b + (tint.b - base.b) * weight); + return `rgb(${r}, ${g}, ${b})`; +}; + +const relativeLuminance = (value: string) => { + const { r, g, b } = parseColor(value); + const [nr, ng, nb] = [r, g, b].map((channel) => { + const normalized = channel / 255; + return normalized <= 0.03928 + ? normalized / 12.92 + : ((normalized + 0.055) / 1.055) ** 2.4; + }); + return 0.2126 * nr + 0.7152 * ng + 0.0722 * nb; +}; + +const contrastRatio = (a: string, b: string) => { + const l1 = relativeLuminance(a); + const l2 = relativeLuminance(b); + const lighter = Math.max(l1, l2); + const darker = Math.min(l1, l2); + return (lighter + 0.05) / (darker + 0.05); +}; + +const pickBestTextColor = (bgColor: string, candidates: string[]) => { + let best = candidates[0]; + let bestRatio = contrastRatio(bgColor, best); + for (let i = 1; i < candidates.length; i += 1) { + const ratio = contrastRatio(bgColor, candidates[i]); + if (ratio > bestRatio) { + best = candidates[i]; + bestRatio = ratio; + } + } + return best; +}; + +const chunkIntoRows = (items: T[], size = 2): T[][] => { + const rows: T[][] = []; + for (let i = 0; i < items.length; i += size) { + rows.push(items.slice(i, i + size)); + } + return rows; +}; + +export default function SearchScreen() { + const { + plants, + isDarkMode, + colorPalette, + t, + language, + billingSummary, + refreshBillingSummary, + } = useApp(); + const colors = useColors(isDarkMode, colorPalette); + const router = useRouter(); + const billingCopy = getBillingCopy(language); + const availableCredits = billingSummary?.credits.available ?? 0; + + const [searchQuery, setSearchQuery] = useState(''); + const [debouncedQuery, setDebouncedQuery] = useState(''); + const [isDeepSearching, setIsDeepSearching] = useState(false); + const [aiStatus, setAiStatus] = useState('idle'); + const [aiResults, setAiResults] = useState([]); + + useEffect(() => { + const timer = setTimeout(() => { + setDebouncedQuery(searchQuery.trim()); + }, SEARCH_DEBOUNCE_MS); + + return () => clearTimeout(timer); + }, [searchQuery]); + + useEffect(() => { + setAiStatus('idle'); + setAiResults([]); + }, [debouncedQuery, language]); + + useEffect(() => { + refreshBillingSummary(); + }, [refreshBillingSummary]); + + const getCategoryBackground = (baseTint: string, accent: string) => { + return isDarkMode ? baseTint : blendColors(baseTint, accent, 0.2); + }; + + const getCategoryTextColor = (bgColor: string, accent: string) => { + const tintedDark = blendColors(accent, '#000000', 0.58); + const tintedLight = blendColors(accent, '#ffffff', 0.64); + return pickBestTextColor(bgColor, [ + isDarkMode ? tintedLight : tintedDark, + colors.text, + colors.textOnImage, + ]); + }; + + const categories = [ + { id: 'easy', name: t.catCareEasy, bg: getCategoryBackground(colors.successTint, colors.success), accent: colors.success }, + { id: 'low_light', name: t.catLowLight, bg: getCategoryBackground(colors.infoTint, colors.info), accent: colors.info }, + { id: 'bright_light', name: t.catBrightLight, bg: getCategoryBackground(colors.primaryTint, colors.primaryDark), accent: colors.primaryDark }, + { id: 'sun', name: t.catSun, bg: getCategoryBackground(colors.warningTint, colors.warning), accent: colors.warning }, + { id: 'pet_friendly', name: t.catPetFriendly, bg: getCategoryBackground(colors.dangerTint, colors.danger), accent: colors.danger }, + { id: 'air_purifier', name: t.catAirPurifier, bg: getCategoryBackground(colors.primaryTint, colors.primary), accent: colors.primary }, + { id: 'high_humidity', name: t.catHighHumidity, bg: getCategoryBackground(colors.infoTint, colors.info), accent: colors.info }, + { id: 'hanging', name: t.catHanging, bg: getCategoryBackground(colors.successTint, colors.success), accent: colors.success }, + { id: 'patterned', name: t.catPatterned, bg: getCategoryBackground(colors.dangerTint, colors.primaryDark), accent: colors.primaryDark }, + { id: 'flowering', name: t.catFlowering, bg: getCategoryBackground(colors.primaryTint, colors.primaryDark), accent: colors.primaryDark }, + { id: 'succulent', name: t.catSucculents, bg: getCategoryBackground(colors.warningTint, colors.warning), accent: colors.warning }, + { id: 'tree', name: t.catTree, bg: getCategoryBackground(colors.surfaceStrong, colors.textSecondary), accent: colors.textSecondary }, + { id: 'large', name: t.catLarge, bg: getCategoryBackground(colors.surface, colors.textMuted), accent: colors.textMuted }, + { id: 'medicinal', name: t.catMedicinal, bg: getCategoryBackground(colors.successTint, colors.success), accent: colors.success }, + ]; + + const normalizedQuery = normalizeSearchText(debouncedQuery); + const isResultMode = Boolean(normalizedQuery); + + const localResults = useMemo(() => { + if (!normalizedQuery) { + return [] as Plant[]; + } + + return rankHybridEntries(plants, normalizedQuery, 30) + .map((entry) => entry.entry); + }, [plants, normalizedQuery]); + + const [lexiconResults, setLexiconResults] = useState([]); + + useEffect(() => { + if (!normalizedQuery) { + setLexiconResults([]); + return; + } + let isCancelled = false; + PlantDatabaseService.searchPlants(normalizedQuery, language, { + limit: 30, + }).then((results) => { + if (!isCancelled) setLexiconResults(results); + }).catch(console.error); + + return () => { + isCancelled = true; + }; + }, [normalizedQuery, language]); + + const filteredAiResults = aiResults; + + const showAiSection = aiStatus !== 'idle' || filteredAiResults.length > 0; + const canRunDeepSearch = ( + searchQuery.trim().length >= 3 && + !isDeepSearching && + availableCredits >= SEMANTIC_SEARCH_CREDIT_COST + ); + + const handleDeepSearch = async () => { + const query = searchQuery.trim(); + if (query.length < 3) return; + if (availableCredits < SEMANTIC_SEARCH_CREDIT_COST) { + setAiStatus('insufficient_credits'); + setAiResults([]); + return; + } + + setIsDeepSearching(true); + setAiStatus('loading'); + setAiResults([]); + + try { + const response = await PlantDatabaseService.semanticSearchDetailed(query, language); + setAiStatus(response.status); + setAiResults(response.results); + } catch (error) { + console.error('Deep search failed', error); + setAiStatus('provider_error'); + setAiResults([]); + } finally { + setIsDeepSearching(false); + await refreshBillingSummary(); + } + }; + + const openCategoryLexicon = (categoryId: string, categoryName: string) => { + router.push({ + pathname: '/lexicon', + params: { + categoryId, + categoryLabel: encodeURIComponent(categoryName), + }, + }); + }; + + const clearAll = () => { + setSearchQuery(''); + setDebouncedQuery(''); + setAiStatus('idle'); + setAiResults([]); + }; + + const openLexiconDetail = (entry: DatabaseEntry) => { + router.push({ + pathname: '/lexicon', + params: { detail: encodeURIComponent(JSON.stringify(entry)) }, + }); + }; + + const renderGrid = ( + items: Array, + type: 'local' | 'lexicon' | 'ai', + ) => { + const rows = chunkIntoRows(items, 2); + + return ( + + {rows.map((row, rowIndex) => ( + + {row.map((item, itemIndex) => ( + + { + if (type === 'local' && 'id' in item) { + router.push(`/plant/${item.id}`); + return; + } + openLexiconDetail(item as DatabaseEntry); + }} + t={t} + isDark={isDarkMode} + colorPalette={colorPalette} + /> + + ))} + {row.length === 1 ? : null} + + ))} + + ); + }; + + const aiStatusText = (() => { + if (aiStatus === 'loading') return t.searchAiLoading; + if (aiStatus === 'timeout') return t.searchAiUnavailable; + if (aiStatus === 'provider_error') return t.searchAiUnavailable; + if (aiStatus === 'insufficient_credits') return billingCopy.insufficientCredits; + if (aiStatus === 'no_results') return t.searchAiNoResults; + return null; + })(); + + const SectionTitle = ({ label, count }: { label: string; count: number }) => ( + + {label} + {count} + + ); + + return ( + + + + {t.searchTitle} + + + + + {searchQuery ? ( + + + + ) : null} + + + item.id} + style={styles.chipsList} + showsHorizontalScrollIndicator={false} + contentContainerStyle={styles.chipsContent} + renderItem={({ item }) => { + return ( + openCategoryLexicon(item.id, item.name)} + activeOpacity={0.8} + > + + {item.name} + + + ); + }} + /> + + {searchQuery.trim().length >= 3 ? ( + + + + + {isDeepSearching ? t.searchAiLoading : t.searchDeepAction} + + + + + + {billingCopy.creditsLabel}: {availableCredits} + + + {billingCopy.deepSearchCost} + + + + ) : null} + + {isResultMode ? ( + + + {localResults.length > 0 ? ( + renderGrid(localResults, 'local') + ) : ( + {t.searchNoLocalResults} + )} + + + {lexiconResults.length > 0 ? ( + renderGrid(lexiconResults, 'lexicon') + ) : ( + {t.searchNoLexiconResults} + )} + + {showAiSection ? ( + + + {aiStatus === 'loading' ? ( + + + {aiStatusText} + + ) : filteredAiResults.length > 0 ? ( + renderGrid(filteredAiResults, 'ai') + ) : aiStatusText ? ( + + {aiStatusText} + {aiStatus === 'insufficient_credits' ? ( + router.push('/(tabs)/profile')} + activeOpacity={0.85} + > + {billingCopy.managePlan} + + ) : null} + + ) : null} + + ) : null} + + ) : ( + + router.push('/lexicon')} + > + + {t.lexiconTitle} + {t.lexiconDesc} + + {t.browseLexicon} + + + + )} + + ); +} + +const styles = StyleSheet.create({ + container: { flex: 1, paddingHorizontal: 20 }, + title: { fontSize: 23, fontWeight: '700', letterSpacing: 0.2, marginTop: 12, marginBottom: 16 }, + searchBar: { + flexDirection: 'row', + alignItems: 'center', + borderWidth: 1, + borderRadius: 16, + paddingHorizontal: 14, + paddingVertical: 10, + gap: 10, + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.14, + shadowRadius: 8, + elevation: 2, + }, + searchInput: { flex: 1, fontSize: 15 }, + chipsList: { marginTop: 10, height: 50, maxHeight: 50 }, + chipsContent: { gap: 8, paddingRight: 4, paddingVertical: 1, alignItems: 'center' }, + catChip: { + height: 40, + paddingHorizontal: 14, + paddingVertical: 0, + borderRadius: 20, + justifyContent: 'center', + alignItems: 'center', + borderWidth: 1, + }, + catChipText: { + fontSize: 12.5, + lineHeight: 18, + fontWeight: '700', + includeFontPadding: false, + }, + deepSearchBtn: { + marginTop: 12, + flexDirection: 'row', + alignItems: 'center', + alignSelf: 'flex-start', + gap: 8, + paddingHorizontal: 11, + paddingVertical: 6, + borderRadius: 10, + borderWidth: 1, + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.16, + shadowRadius: 6, + elevation: 2, + }, + deepSearchWrap: { + marginTop: 12, + gap: 6, + alignSelf: 'flex-start', + }, + deepSearchText: { fontSize: 12, fontWeight: '700' }, + creditMetaRow: { + gap: 1, + marginLeft: 2, + }, + creditMetaText: { + fontSize: 11, + fontWeight: '600', + }, + results: { marginTop: 14 }, + resultsContent: { paddingBottom: 110 }, + sectionHeader: { + marginBottom: 10, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + }, + sectionTitle: { fontSize: 15, fontWeight: '600' }, + sectionCount: { fontSize: 13, fontWeight: '500' }, + grid: { marginBottom: 18 }, + gridRow: { + flexDirection: 'row', + justifyContent: 'space-between', + marginBottom: CARD_GAP, + }, + cardWrapper: { width: CARD_WIDTH }, + cardSpacer: { width: CARD_WIDTH }, + emptyText: { marginBottom: 18, fontSize: 14, lineHeight: 20 }, + aiSection: { marginTop: 2 }, + aiStatusBlock: { marginBottom: 18 }, + aiLoadingRow: { flexDirection: 'row', alignItems: 'center', gap: 8, marginBottom: 18 }, + aiStatusText: { fontSize: 13, fontWeight: '500' }, + managePlanBtn: { + alignSelf: 'flex-start', + borderWidth: 1, + borderRadius: 10, + paddingHorizontal: 10, + paddingVertical: 6, + marginTop: -8, + }, + managePlanText: { fontSize: 12, fontWeight: '700' }, + discoveryContent: { paddingTop: 16, paddingBottom: 120 }, + lexiconBanner: { + marginTop: 8, + padding: 18, + borderRadius: 18, + gap: 4, + }, + lexiconTitle: { fontSize: 18, fontWeight: '700' }, + lexiconDesc: { fontSize: 12 }, + lexiconBadge: { + marginTop: 8, + paddingHorizontal: 12, + paddingVertical: 5, + borderRadius: 20, + alignSelf: 'flex-start', + }, + lexiconBadgeText: { fontSize: 11, fontWeight: '700' }, +}); diff --git a/app/_layout.tsx b/app/_layout.tsx index 33d99f5..1e5da9a 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -1,28 +1,42 @@ -import { useEffect, useState } from 'react'; -import { Stack } from 'expo-router'; +import { useEffect, useRef, useState } from 'react'; +import { Animated, Easing, Image, StyleSheet, Text, View } from 'react-native'; +import { Redirect, Stack, usePathname } from 'expo-router'; import { StatusBar } from 'expo-status-bar'; -import { StripeProvider } from '@stripe/stripe-react-native'; import AsyncStorage from '@react-native-async-storage/async-storage'; +import Purchases, { LOG_LEVEL } from 'react-native-purchases'; +import { Platform } from 'react-native'; +import Constants from 'expo-constants'; import { AppProvider, useApp } from '../context/AppContext'; import { CoachMarksProvider } from '../context/CoachMarksContext'; import { CoachMarksOverlay } from '../components/CoachMarksOverlay'; import { useColors } from '../constants/Colors'; -import { AuthService } from '../services/authService'; import { initDatabase, AppMetaDb } from '../services/database'; import * as SecureStore from 'expo-secure-store'; +import * as SplashScreen from 'expo-splash-screen'; +import { AuthService } from '../services/authService'; +import { PostHogProvider, usePostHog } from 'posthog-react-native'; -type InitialRoute = 'onboarding' | 'auth/login' | '(tabs)'; -const STRIPE_PUBLISHABLE_KEY = (process.env.EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY || 'pk_test_mock_key').trim(); +// Prevent the splash screen from auto-hiding before asset loading is complete. +SplashScreen.preventAutoHideAsync().catch(() => { }); + +const POSTHOG_API_KEY = process.env.EXPO_PUBLIC_POSTHOG_API_KEY || 'phc_FX6HRgx9NSpS5moxjMF6xyc37yMwjoeu6TbWUqNNKlk'; const SECURE_INSTALL_MARKER = 'greenlens_install_v1'; const ensureInstallConsistency = async (): Promise => { try { - const [sqliteMarker, secureMarker] = await Promise.all([ - Promise.resolve(AppMetaDb.get('install_marker_v2')), - SecureStore.getItemAsync(SECURE_INSTALL_MARKER).catch(() => null), - ]); + const sqliteMarker = AppMetaDb.get('install_marker_v2'); + const secureMarker = await SecureStore.getItemAsync(SECURE_INSTALL_MARKER).catch(() => null); - if (sqliteMarker && secureMarker) return false; // Kein Fresh Install + if (sqliteMarker === '1' && secureMarker === '1') { + return false; // Alles gut, keine Neuinstallation + } + + if (sqliteMarker === '1' || secureMarker === '1') { + // Teilweise vorhanden -> heilen, nicht löschen + AppMetaDb.set('install_marker_v2', '1'); + await SecureStore.setItemAsync(SECURE_INSTALL_MARKER, '1'); + return false; + } // Fresh Install: Alles zurücksetzen await AuthService.logout(); @@ -36,10 +50,45 @@ const ensureInstallConsistency = async (): Promise => { } }; + +import { AnimatedSplashScreen } from '../components/AnimatedSplashScreen'; + function RootLayoutInner() { - const { isDarkMode, colorPalette, signOut } = useApp(); + const { isDarkMode, colorPalette, signOut, session, isInitializing, isLoadingPlants } = useApp(); const colors = useColors(isDarkMode, colorPalette); - const [initialRoute, setInitialRoute] = useState(null); + const pathname = usePathname(); + const [installCheckDone, setInstallCheckDone] = useState(false); + const [splashAnimationComplete, setSplashAnimationComplete] = useState(false); + const posthog = usePostHog(); + + useEffect(() => { + // RevenueCat requires native store access — not available in Expo Go + const isExpoGo = Constants.appOwnership === 'expo'; + if (isExpoGo) { + console.log('[RevenueCat] Skipping configure: running in Expo Go'); + return; + } + + Purchases.setLogLevel(LOG_LEVEL.VERBOSE); + const iosApiKey = process.env.EXPO_PUBLIC_REVENUECAT_IOS_API_KEY || 'appl_hrSpsuUuVstbHhYIDnOqYxPOnmR'; + const androidApiKey = process.env.EXPO_PUBLIC_REVENUECAT_ANDROID_API_KEY || 'goog_placeholder'; + if (Platform.OS === 'ios') { + Purchases.configure({ apiKey: iosApiKey }); + } else if (Platform.OS === 'android') { + Purchases.configure({ apiKey: androidApiKey }); + } + }, []); + + useEffect(() => { + if (session?.serverUserId) { + posthog.identify(session.serverUserId, { + email: session.email, + name: session.name, + }); + } else if (session === null) { + posthog.reset(); + } + }, [session, posthog]); useEffect(() => { (async () => { @@ -47,55 +96,92 @@ function RootLayoutInner() { if (didResetSessionForFreshInstall) { await signOut(); } - const session = await AuthService.getSession(); - if (!session) { - // Kein Benutzer → immer zum Onboarding (Landing + Register/Login) - setInitialRoute('auth/login'); - return; - } - const validity = await AuthService.validateWithServer(); - if (validity === 'invalid') { - await AuthService.logout(); - await signOut(); - setInitialRoute('auth/login'); - return; - } - // 'valid' or 'unreachable' (offline) → allow tab navigation - setInitialRoute('(tabs)'); + setInstallCheckDone(true); })(); }, [signOut]); - if (initialRoute === null) return null; + const isAppReady = installCheckDone && !isInitializing && !isLoadingPlants; + + let content = null; + + if (isAppReady) { + if (!session) { + // Only redirect if we are not already on an auth-related page or the scanner + const isAuthPage = pathname.includes('onboarding') || pathname.includes('auth/') || pathname.includes('scanner'); + if (!isAuthPage) { + content = ; + } else { + content = ( + + + + + + + ); + } + } else { + content = ( + <> + + + + + + + + + + + + + + + ); + } + } return ( <> - - - - - - setSplashAnimationComplete(true)} /> - - - - {/* Coach Marks rendern über allem */} - + )} ); } @@ -104,15 +190,15 @@ export default function RootLayout() { initDatabase(); return ( - + - + ); } diff --git a/app/auth/login.tsx b/app/auth/login.tsx index ac64ca3..818d3ef 100644 --- a/app/auth/login.tsx +++ b/app/auth/login.tsx @@ -160,7 +160,7 @@ export default function LoginScreen() { {/* Sign Up Link */} router.push('/auth/signup')} + onPress={() => router.replace('/auth/signup')} activeOpacity={0.82} > @@ -186,9 +186,9 @@ const styles = StyleSheet.create({ marginBottom: 32, }, logoIcon: { - width: 88, - height: 88, - borderRadius: 20, + width: 56, + height: 56, + borderRadius: 14, marginBottom: 16, }, appName: { diff --git a/app/auth/signup.tsx b/app/auth/signup.tsx index 67f7d13..4c144e5 100644 --- a/app/auth/signup.tsx +++ b/app/auth/signup.tsx @@ -20,8 +20,9 @@ import { AuthService } from '../../services/authService'; import AsyncStorage from '@react-native-async-storage/async-storage'; export default function SignupScreen() { - const { isDarkMode, colorPalette, hydrateSession } = useApp(); + const { isDarkMode, colorPalette, hydrateSession, getPendingPlant } = useApp(); const colors = useColors(isDarkMode, colorPalette); + const pendingPlant = getPendingPlant(); const [name, setName] = useState(''); const [email, setEmail] = useState(''); @@ -103,6 +104,16 @@ export default function SignupScreen() { + {/* Pending Plant Hint */} + {pendingPlant && ( + + + + Deine gescannte Pflanze ({pendingPlant.result.name}) wird nach der Registrierung automatisch in deinem Profil gespeichert. + + + )} + {/* Card */} {/* Name */} @@ -256,7 +267,7 @@ export default function SignupScreen() { {/* Login link */} - router.back()}> + router.replace('/auth/login')}> Bereits ein Konto?{' '} Anmelden @@ -291,9 +302,9 @@ const styles = StyleSheet.create({ alignItems: 'center', }, logoIcon: { - width: 88, - height: 88, - borderRadius: 20, + width: 56, + height: 56, + borderRadius: 14, marginBottom: 16, }, appName: { @@ -391,4 +402,19 @@ const styles = StyleSheet.create({ loginLinkText: { fontSize: 15, }, + pendingHint: { + flexDirection: 'row', + alignItems: 'center', + padding: 16, + borderRadius: 16, + borderWidth: 1, + marginBottom: 20, + gap: 12, + }, + pendingHintText: { + flex: 1, + fontSize: 13, + fontWeight: '600', + lineHeight: 18, + }, }); diff --git a/app/lexicon.tsx b/app/lexicon.tsx new file mode 100644 index 0000000..928580f --- /dev/null +++ b/app/lexicon.tsx @@ -0,0 +1,451 @@ +import React, { useState } from 'react'; +import { + View, Text, StyleSheet, TextInput, FlatList, TouchableOpacity, Platform, StatusBar, ScrollView, ActivityIndicator, +} from 'react-native'; +import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'; +import { useRouter, useLocalSearchParams } from 'expo-router'; +import { Ionicons } from '@expo/vector-icons'; +import { useApp } from '../context/AppContext'; +import { useColors } from '../constants/Colors'; +import { PlantDatabaseService } from '../services/plantDatabaseService'; +import { IdentificationResult } from '../types'; +import { DatabaseEntry } from '../services/plantDatabaseService'; +import { ResultCard } from '../components/ResultCard'; +import { ThemeBackdrop } from '../components/ThemeBackdrop'; +import { SafeImage } from '../components/SafeImage'; +import { resolveImageUri } from '../utils/imageUri'; + +export default function LexiconScreen() { + const { isDarkMode, colorPalette, language, t, savePlant, getLexiconSearchHistory, saveLexiconSearchQuery, clearLexiconSearchHistory } = useApp(); + const colors = useColors(isDarkMode, colorPalette); + const insets = useSafeAreaInsets(); + const router = useRouter(); + const params = useLocalSearchParams(); + const categoryIdParam = Array.isArray(params.categoryId) ? params.categoryId[0] : params.categoryId; + const categoryLabelParam = Array.isArray(params.categoryLabel) ? params.categoryLabel[0] : params.categoryLabel; + + const decodeParam = (value?: string | string[]) => { + if (!value || typeof value !== 'string') return ''; + try { + return decodeURIComponent(value); + } catch { + return value; + } + }; + + const initialCategoryId = typeof categoryIdParam === 'string' ? categoryIdParam : null; + const initialCategoryLabel = decodeParam(categoryLabelParam); + const topInsetFallback = Platform.OS === 'android' ? (StatusBar.currentHeight || 0) : 20; + const topInset = insets.top > 0 ? insets.top : topInsetFallback; + + const [searchQuery, setSearchQuery] = useState(initialCategoryLabel); + const [activeCategoryId, setActiveCategoryId] = useState(initialCategoryId); + const [selectedItem, setSelectedItem] = useState<(IdentificationResult & { imageUri: string }) | null>(null); + const [isAiSearching, setIsAiSearching] = useState(false); + const [aiResults, setAiResults] = useState(null); + const [searchErrorMessage, setSearchErrorMessage] = useState(null); + const [searchHistory, setSearchHistory] = useState([]); + + const detailParam = Array.isArray(params.detail) ? params.detail[0] : params.detail; + const openedWithDetail = Boolean(detailParam); + + React.useEffect(() => { + if (detailParam) { + try { + const rawParam = detailParam; + const decoded = decodeURIComponent(rawParam as string); + const detail = JSON.parse(decoded); + setSelectedItem(detail); + } catch (e) { + try { + const fallbackRaw = detailParam; + const detail = JSON.parse(fallbackRaw as string); + setSelectedItem(detail); + } catch (fallbackError) { + console.error('Failed to parse plant detail', fallbackError); + } + } + } + }, [detailParam]); + + React.useEffect(() => { + setActiveCategoryId(initialCategoryId); + setSearchQuery(initialCategoryLabel); + }, [initialCategoryId, initialCategoryLabel]); + + React.useEffect(() => { + const loadHistory = async () => { + const history = getLexiconSearchHistory(); + setSearchHistory(history); + }; + loadHistory(); + }, []); + + const handleResultClose = () => { + if (openedWithDetail) { + router.back(); + return; + } + setSelectedItem(null); + }; + + const normalizeText = (value: string): string => ( + value + .toLowerCase() + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .trim() + .replace(/\s+/g, ' ') + ); + + const effectiveSearchQuery = searchQuery; + const [lexiconPlants, setLexiconPlants] = useState([]); + + React.useEffect(() => { + if (aiResults) { + setLexiconPlants(aiResults); + return; + } + + let isCancelled = false; + PlantDatabaseService.searchPlants(effectiveSearchQuery, language, { + category: activeCategoryId, + limit: 500, + }).then(results => { + if (!isCancelled) setLexiconPlants(results); + }).catch(console.error); + + return () => { + isCancelled = true; + }; + }, [aiResults, effectiveSearchQuery, language, activeCategoryId]); + + const handleAiSearch = async () => { + const query = searchQuery.trim(); + if (!query) return; + + setIsAiSearching(true); + setAiResults(null); + setSearchErrorMessage(null); + try { + const response = await PlantDatabaseService.semanticSearchDetailed(query, language); + + if (response.status === 'success') { + setAiResults(response.results); + saveLexiconSearchQuery(query); + setSearchHistory(getLexiconSearchHistory()); + } else if (response.status === 'insufficient_credits') { + setSearchErrorMessage((t as any).errorNoCredits || 'Nicht genügend Guthaben für KI-Suche.'); + } else if (response.status === 'no_results') { + setSearchErrorMessage((t as any).noResultsFound || 'Keine Ergebnisse gefunden.'); + setAiResults([]); + } else { + setSearchErrorMessage((t as any).errorTryAgain || 'Fehler bei der Suche. Bitte später erneut versuchen.'); + } + } catch (error) { + console.error('AI Search failed', error); + setSearchErrorMessage((t as any).errorGeneral || 'Etwas ist schiefgelaufen.'); + } finally { + setIsAiSearching(false); + } + }; + + const handleSearchSubmit = async () => { + const query = searchQuery.trim(); + if (!query) return; + + saveLexiconSearchQuery(query); + setSearchHistory(getLexiconSearchHistory()); + }; + + const handleHistorySelect = (query: string) => { + setActiveCategoryId(null); + setSearchQuery(query); + }; + + const handleClearHistory = () => { + clearLexiconSearchHistory(); + setSearchHistory([]); + }; + + const showSearchHistory = searchQuery.trim().length === 0 && !activeCategoryId && searchHistory.length > 0; + + if (selectedItem) { + return ( + { + savePlant(selectedItem, resolveImageUri(selectedItem.imageUri)); + router.back(); + }} + onClose={handleResultClose} + t={t} + isDark={isDarkMode} + colorPalette={colorPalette} + /> + ); + } + + return ( + + + + {/* Header */} + + router.back()} style={styles.backBtn}> + + + {t.lexiconTitle} + + + {/* Search */} + + + + + {(searchQuery || activeCategoryId) ? ( + { + setSearchQuery(''); + setActiveCategoryId(null); + setAiResults(null); + }} + hitSlop={8} + > + + + ) : null} + + + + {/* AI Search Trigger block removed */} + + {searchErrorMessage && ( + + + + {searchErrorMessage} + + + )} + + {aiResults && ( + + { + setAiResults(null); + setSearchErrorMessage(null); + }} + > + + + {(t as any).clearAiResults || 'KI-Ergebnisse löschen'} + + + + )} + + {showSearchHistory ? ( + + + {t.searchHistory} + + {t.clearHistory} + + + + + {searchHistory.map((item, index) => ( + handleHistorySelect(item)} + activeOpacity={0.8} + > + + + {item} + + + ))} + + + ) : null} + + {/* Grid */} + i.toString()} + contentContainerStyle={styles.grid} + columnWrapperStyle={styles.gridRow} + showsVerticalScrollIndicator={false} + initialNumToRender={12} + maxToRenderPerBatch={6} + windowSize={3} + ListEmptyComponent={ + + {t.noResults} + + } + renderItem={({ item }) => ( + setSelectedItem(item as any)} + > + + + + {item.name} + + + {item.botanicalName} + + + + )} + /> + + ); +} + +const styles = StyleSheet.create({ + container: { flex: 1, overflow: 'hidden' }, + header: { + flexDirection: 'row', + alignItems: 'center', + paddingHorizontal: 20, + paddingBottom: 16, + borderBottomWidth: 1, + gap: 14, + }, + backBtn: { marginLeft: -8, padding: 4 }, + title: { fontSize: 19, fontWeight: '700', letterSpacing: 0.2 }, + searchBar: { + flexDirection: 'row', + alignItems: 'center', + borderWidth: 1, + borderRadius: 16, + paddingHorizontal: 14, + paddingVertical: 10, + gap: 10, + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.14, + shadowRadius: 8, + elevation: 2, + }, + searchInput: { flex: 1, fontSize: 15 }, + historySection: { paddingHorizontal: 20, paddingTop: 12, paddingBottom: 8 }, + historyHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 8, + }, + historyTitle: { + fontSize: 11, + fontWeight: '700', + letterSpacing: 0.8, + textTransform: 'uppercase', + }, + clearHistoryText: { fontSize: 12, fontWeight: '700' }, + historyContent: { gap: 8, paddingRight: 20 }, + historyChip: { + flexDirection: 'row', + alignItems: 'center', + gap: 6, + borderWidth: 1, + borderRadius: 16, + paddingHorizontal: 10, + paddingVertical: 8, + }, + historyChipText: { fontSize: 12, fontWeight: '600' }, + grid: { padding: 20, paddingBottom: 40 }, + gridRow: { gap: 10, marginBottom: 10 }, + card: { + flex: 1, + borderRadius: 18, + borderWidth: 1, + overflow: 'hidden', + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.14, + shadowRadius: 6, + elevation: 2, + }, + cardImage: { width: '100%', aspectRatio: 1, resizeMode: 'cover' }, + cardContent: { padding: 8 }, + cardName: { fontSize: 12, fontWeight: '700' }, + cardBotanical: { fontSize: 9, fontStyle: 'italic' }, + empty: { paddingVertical: 40, alignItems: 'center' }, + aiSearchBtn: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + paddingVertical: 12, + paddingHorizontal: 16, + borderRadius: 14, + borderWidth: 1, + borderStyle: 'dashed', + gap: 10, + }, + aiSearchText: { + fontSize: 14, + fontWeight: '600', + }, + errorBox: { + flexDirection: 'row', + alignItems: 'center', + padding: 12, + borderRadius: 12, + gap: 10, + }, + errorText: { + fontSize: 14, + fontWeight: '500', + flex: 1, + }, + clearAiResultsBtn: { + flexDirection: 'row', + alignItems: 'center', + alignSelf: 'flex-start', + paddingVertical: 6, + paddingHorizontal: 12, + borderRadius: 20, + gap: 6, + }, +}); diff --git a/app/onboarding.tsx b/app/onboarding.tsx new file mode 100644 index 0000000..fa9531d --- /dev/null +++ b/app/onboarding.tsx @@ -0,0 +1,254 @@ +import React, { useEffect, useRef } from 'react'; +import { + View, + Text, + StyleSheet, + TouchableOpacity, + Animated, + Dimensions, + Image, +} from 'react-native'; +import { Ionicons } from '@expo/vector-icons'; +import { router } from 'expo-router'; +import { useApp } from '../context/AppContext'; +import { useColors } from '../constants/Colors'; +import { ThemeBackdrop } from '../components/ThemeBackdrop'; + +const { height: SCREEN_H, width: SCREEN_W } = Dimensions.get('window'); + +export default function OnboardingScreen() { + const { isDarkMode, colorPalette, t } = useApp(); + const colors = useColors(isDarkMode, colorPalette); + + const FEATURES = [ + { icon: 'camera-outline' as const, label: t.onboardingFeatureScan }, + { icon: 'notifications-outline' as const, label: t.onboardingFeatureReminder }, + { icon: 'book-outline' as const, label: t.onboardingFeatureLexicon }, + ]; + + // Entrance animations + const logoAnim = useRef(new Animated.Value(0)).current; + const logoScale = useRef(new Animated.Value(0.85)).current; + const featuresAnim = useRef(new Animated.Value(0)).current; + const buttonsAnim = useRef(new Animated.Value(0)).current; + const featureAnims = useRef(FEATURES.map(() => new Animated.Value(0))).current; + + useEffect(() => { + Animated.sequence([ + Animated.parallel([ + Animated.timing(logoAnim, { toValue: 1, duration: 700, useNativeDriver: true }), + Animated.spring(logoScale, { toValue: 1, tension: 50, friction: 8, useNativeDriver: true }), + ]), + Animated.stagger(100, featureAnims.map(anim => + Animated.timing(anim, { toValue: 1, duration: 400, useNativeDriver: true }) + )), + Animated.timing(buttonsAnim, { toValue: 1, duration: 400, useNativeDriver: true }), + ]).start(); + }, []); + + return ( + + + + {/* Logo-Bereich */} + + + + + + GreenLens + + {t.onboardingTagline} + + + + {/* Feature-Liste */} + + {FEATURES.map((feat, i) => ( + + + + + {feat.label} + + ))} + + + {/* Buttons */} + + router.push('/scanner')} + activeOpacity={0.85} + > + + + {t.onboardingScanBtn} + + + + + router.push('/auth/signup')} + activeOpacity={0.82} + > + + {t.onboardingRegister} + + + + router.push('/auth/login')} + activeOpacity={0.82} + > + + {t.onboardingLogin} + + + + + + {t.onboardingDisclaimer} + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + paddingHorizontal: 32, + paddingTop: SCREEN_H * 0.12, + paddingBottom: 40, + }, + heroSection: { + alignItems: 'center', + marginBottom: 40, + }, + iconContainer: { + width: 120, + height: 120, + borderRadius: 28, + backgroundColor: '#fff', + elevation: 8, + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.15, + shadowRadius: 12, + marginBottom: 24, + overflow: 'hidden', + }, + appIcon: { + width: '100%', + height: '100%', + }, + appName: { + fontSize: 40, + fontWeight: '900', + letterSpacing: -1.5, + marginBottom: 4, + }, + tagline: { + fontSize: 17, + fontWeight: '500', + opacity: 0.8, + }, + featuresSection: { + gap: 12, + flex: 1, + justifyContent: 'center', + }, + featureRow: { + flexDirection: 'row', + alignItems: 'center', + gap: 16, + paddingHorizontal: 20, + paddingVertical: 16, + borderRadius: 20, + borderWidth: 1, + }, + featureIcon: { + width: 44, + height: 44, + borderRadius: 14, + justifyContent: 'center', + alignItems: 'center', + }, + featureText: { + flex: 1, + fontSize: 15, + fontWeight: '600', + letterSpacing: 0.1, + }, + buttonsSection: { + gap: 16, + marginTop: 20, + }, + primaryBtn: { + height: 58, + borderRadius: 20, + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + gap: 12, + elevation: 4, + shadowColor: '#000', + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.1, + shadowRadius: 4, + }, + primaryBtnText: { + fontSize: 17, + fontWeight: '700', + }, + authActions: { + flexDirection: 'row', + gap: 12, + }, + secondaryBtn: { + flex: 1, + height: 54, + borderRadius: 20, + borderWidth: 1.5, + justifyContent: 'center', + alignItems: 'center', + }, + secondaryBtnText: { + fontSize: 15, + fontWeight: '600', + }, + disclaimer: { + fontSize: 12, + textAlign: 'center', + opacity: 0.6, + marginTop: 8, + }, +}); + diff --git a/app/plant/[id].tsx b/app/plant/[id].tsx new file mode 100644 index 0000000..7baa340 --- /dev/null +++ b/app/plant/[id].tsx @@ -0,0 +1,1443 @@ +import React, { useMemo, useState } from 'react'; +import { + View, + Text, + StyleSheet, + ScrollView, + TouchableOpacity, + Modal, + Alert, + Share, +} from 'react-native'; +import { useLocalSearchParams, useRouter } from 'expo-router'; +import { Ionicons } from '@expo/vector-icons'; +import * as Haptics from 'expo-haptics'; +import * as ImagePicker from 'expo-image-picker'; +import { useApp } from '../../context/AppContext'; +import { useColors } from '../../constants/Colors'; +import { requestPermissions, scheduleWateringReminder, cancelReminder } from '../../services/notificationService'; +import { SafeImage } from '../../components/SafeImage'; + +const parseColorToRgb = (input: string) => { + const color = input.trim(); + if (color.startsWith('#')) { + const hex = color.slice(1); + const normalized = hex.length === 3 + ? hex.split('').map((char) => `${char}${char}`).join('') + : hex; + if (normalized.length === 6) { + return { + r: Number.parseInt(normalized.slice(0, 2), 16), + g: Number.parseInt(normalized.slice(2, 4), 16), + b: Number.parseInt(normalized.slice(4, 6), 16), + }; + } + } + + const rgbMatch = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/i); + if (rgbMatch) { + return { + r: Number.parseInt(rgbMatch[1], 10), + g: Number.parseInt(rgbMatch[2], 10), + b: Number.parseInt(rgbMatch[3], 10), + }; + } + + return { r: 127, g: 127, b: 127 }; +}; + +const getReadableTextColor = (background: string, dark: string, light: string) => { + const { r, g, b } = parseColorToRgb(background); + const luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255; + return luminance > 0.58 ? dark : light; +}; + +const HEALTH_CHECK_CREDIT_COST = 2; + +const getHealthCopy = (language: 'de' | 'en' | 'es') => { + if (language === 'de') { + return { + title: 'Health Check', + action: 'Neues Foto + Health-Check', + running: 'Neues Foto wird analysiert...', + cost: `Kosten: ${HEALTH_CHECK_CREDIT_COST} Credits`, + creditsLabel: 'Credits', + managePlan: 'Plan verwalten', + noCreditsTitle: 'Nicht genug Credits', + noCreditsMessage: `Du brauchst ${HEALTH_CHECK_CREDIT_COST} Credits fuer den Health-Check.`, + insufficientInline: 'Nicht genug Credits fuer den Health-Check.', + timeoutInline: 'Health-Check Timeout. Bitte erneut versuchen.', + providerInline: 'Health-Check ist gerade nicht verfuegbar.', + issuesTitle: 'Moegliche Ursachen', + actionsTitle: 'Sofortmassnahmen', + planTitle: '7-Tage-Plan', + scoreLabel: 'Gesundheits-Score', + healthy: 'Stabil', + watch: 'Beobachten', + critical: 'Kritisch', + lastCheck: 'Zuletzt geprueft', + }; + } + + if (language === 'es') { + return { + title: 'Health Check', + action: 'Foto nuevo + Health-check', + running: 'Analizando foto nueva...', + cost: `Costo: ${HEALTH_CHECK_CREDIT_COST} creditos`, + creditsLabel: 'Creditos', + managePlan: 'Gestionar plan', + noCreditsTitle: 'Creditos insuficientes', + noCreditsMessage: `Necesitas ${HEALTH_CHECK_CREDIT_COST} creditos para el health-check.`, + insufficientInline: 'No hay creditos suficientes para el health-check.', + timeoutInline: 'Health-check agotado por tiempo. Intenta de nuevo.', + providerInline: 'Health-check no disponible ahora.', + issuesTitle: 'Posibles causas', + actionsTitle: 'Acciones inmediatas', + planTitle: 'Plan de 7 dias', + scoreLabel: 'Puntaje de salud', + healthy: 'Estable', + watch: 'Observar', + critical: 'Critico', + lastCheck: 'Ultima revision', + }; + } + + return { + title: 'Health Check', + action: 'New Photo + Health Check', + running: 'Analyzing new photo...', + cost: `Cost: ${HEALTH_CHECK_CREDIT_COST} credits`, + creditsLabel: 'Credits', + managePlan: 'Manage plan', + noCreditsTitle: 'Not enough credits', + noCreditsMessage: `You need ${HEALTH_CHECK_CREDIT_COST} credits for the health check.`, + insufficientInline: 'Not enough credits for the health check.', + timeoutInline: 'Health check timed out. Please try again.', + providerInline: 'Health check is unavailable right now.', + issuesTitle: 'Likely issues', + actionsTitle: 'Actions now', + planTitle: '7-day plan', + scoreLabel: 'Health score', + healthy: 'Stable', + watch: 'Watch', + critical: 'Critical', + lastCheck: 'Last checked', + }; +}; + +export default function PlantDetailScreen() { + const { id } = useLocalSearchParams<{ id: string }>(); + const { + plants, + isDarkMode, + colorPalette, + language, + t, + deletePlant, + updatePlant, + billingSummary, + } = useApp(); + const colors = useColors(isDarkMode, colorPalette); + const router = useRouter(); + const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); + const [fullscreenImage, setFullscreenImage] = useState(null); + const [healthStatus, setHealthStatus] = useState<'idle' | 'insufficient_credits'>('idle'); + const [paywallVisible, setPaywallVisible] = useState(false); + + const plant = plants.find((item) => item.id === id); + if (!plant) { + return ( + + Plant not found + + ); + } + + const localeMap: Record = { de: 'de-DE', en: 'en-US', es: 'es-ES' }; + const locale = localeMap[language] || 'de-DE'; + const healthCopy = getHealthCopy(language); + const availableCredits = billingSummary?.credits.available ?? 0; + + const formattedWateredDate = new Date(plant.lastWatered).toLocaleDateString(locale); + + const lastWateredObj = new Date(plant.lastWatered); + const nextWateringDate = new Date(lastWateredObj); + nextWateringDate.setDate(lastWateredObj.getDate() + plant.careInfo.waterIntervalDays); + const formattedNextWatering = nextWateringDate.toLocaleDateString(locale, { + weekday: 'short', + day: 'numeric', + month: 'short', + }); + + const lastWateredText = t.lastWateredDate.replace('{0}', formattedWateredDate); + const isWateredToday = new Date(plant.lastWatered).toDateString() === new Date().toDateString(); + const daysSinceWatered = Math.max( + 0, + Math.floor((Date.now() - lastWateredObj.getTime()) / (1000 * 60 * 60 * 24)) + ); + + const nextWaterLabel = language === 'de' + ? 'Nächstes Gießen' + : language === 'es' + ? 'Proximo riego' + : 'Next water'; + + const wateredAgoText = language === 'de' + ? `Zuletzt vor ${daysSinceWatered} ${daysSinceWatered === 1 ? 'Tag' : 'Tagen'}` + : language === 'es' + ? `Ultimo riego hace ${daysSinceWatered} ${daysSinceWatered === 1 ? 'dia' : 'dias'}` + : `Last watered ${daysSinceWatered} ${daysSinceWatered === 1 ? 'day' : 'days'} ago`; + + const textOnPage = getReadableTextColor(colors.pageBase, colors.primaryDark, colors.textOnImage); + const textOnSurface = getReadableTextColor(colors.surface, colors.primaryDark, colors.textOnImage); + const textOnHeroButton = getReadableTextColor(colors.heroButton, colors.primaryDark, colors.textOnImage); + const textOnPrimaryAction = getReadableTextColor(colors.primaryDark, '#ffffff', '#111111'); + const textOnAiBadge = getReadableTextColor(colors.primarySoft, colors.primaryDark, colors.textOnImage); + const latestHealthCheck = useMemo(() => { + if (!plant.healthChecks || plant.healthChecks.length === 0) return null; + return plant.healthChecks[0]; + }, [plant.healthChecks]); + const healthStatusInlineText = (() => { + if (healthStatus === 'insufficient_credits') return healthCopy.insufficientInline; + if (healthStatus === 'idle' && availableCredits < HEALTH_CHECK_CREDIT_COST) return healthCopy.insufficientInline; + return ''; + })(); + const healthStateColor = (() => { + if (healthStatus === 'insufficient_credits') return colors.warning; + return colors.textMuted; + })(); + const latestStatusText = latestHealthCheck + ? ( + latestHealthCheck.status === 'healthy' + ? healthCopy.healthy + : latestHealthCheck.status === 'watch' + ? healthCopy.watch + : healthCopy.critical + ) + : ''; + const latestStatusBg = latestHealthCheck + ? ( + latestHealthCheck.status === 'healthy' + ? colors.successSoft + : latestHealthCheck.status === 'watch' + ? colors.warningSoft + : colors.dangerSoft + ) + : colors.surfaceMuted; + const latestStatusColor = latestHealthCheck + ? ( + latestHealthCheck.status === 'healthy' + ? colors.success + : latestHealthCheck.status === 'watch' + ? colors.warning + : colors.danger + ) + : colors.textMuted; + + const timelineEntries = useMemo(() => { + const history = plant.wateringHistory && plant.wateringHistory.length > 0 + ? plant.wateringHistory + : [plant.lastWatered]; + return history.slice(0, 5); + }, [plant.lastWatered, plant.wateringHistory]); + const hasEnoughHealthCredits = availableCredits >= HEALTH_CHECK_CREDIT_COST; + const canRunHealthCheck = true; + + const handleWater = async () => { + await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium); + const now = new Date().toISOString(); + const currentHistory = plant.wateringHistory || []; + const newHistory = [now, ...currentHistory].slice(0, 10); + updatePlant({ ...plant, lastWatered: now, wateringHistory: newHistory }); + }; + + const handleShare = async () => { + try { + await Share.share({ + message: `Check out my plant: ${plant.name} (${plant.botanicalName}) - identified with GreenLens!`, + }); + } catch (error: any) { + Alert.alert('Error', error.message); + } + }; + + const handleDelete = () => { + deletePlant(plant.id); + router.back(); + }; + + const handleAddPhoto = async () => { + const result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ['images'], + quality: 0.8, + }); + + if (!result.canceled && result.assets[0]) { + const currentGallery = plant.gallery || []; + updatePlant({ ...plant, gallery: [...currentGallery, result.assets[0].uri] }); + } + }; + + const handleHealthCheck = async () => { + if (availableCredits < HEALTH_CHECK_CREDIT_COST) { + setPaywallVisible(true); + return; + } + + if (healthStatus !== 'idle') { + setHealthStatus('idle'); + } + + router.push({ + pathname: '/scanner', + params: { mode: 'health', plantId: plant.id }, + }); + }; + + return ( + + + + + + + + + router.back()} + > + + + + + + + + + + {plant.name} + {plant.botanicalName} + + + + + + + + + {nextWaterLabel} + + + {formattedNextWatering} + + + {isWateredToday ? lastWateredText : wateredAgoText} + + + + + + + {isWateredToday ? t.watered : t.waterNow} + + + + + + {[ + { + icon: 'water' as const, + label: t.water, + value: `${plant.careInfo.waterIntervalDays} ${t.days}`, + iconColor: colors.info, + iconBg: colors.infoSoft, + }, + { + icon: 'sunny' as const, + label: t.light, + value: plant.careInfo.light, + iconColor: colors.warning, + iconBg: colors.warningSoft, + }, + { + icon: 'thermometer' as const, + label: t.temp, + value: plant.careInfo.temp, + iconColor: colors.success, + iconBg: colors.successSoft, + }, + ].map((item) => ( + + + + + {item.label} + + {item.value} + + + ))} + + + + + + + + + Smart Reminders + + {t.reminderDesc} + + + + + { + if (!plant.notificationsEnabled) { + const granted = await requestPermissions(); + if (!granted) { + Alert.alert(t.reminder, t.reminderPermissionNeeded); + return; + } + await scheduleWateringReminder(plant); + } else { + await cancelReminder(plant.id); + } + updatePlant({ ...plant, notificationsEnabled: !plant.notificationsEnabled }); + }} + > + + + + + + + {t.wateringHistory} + + + + + {timelineEntries.length === 0 ? ( + + + {t.noHistory} + + ) : ( + timelineEntries.map((dateStr, index) => ( + + + + {index < timelineEntries.length - 1 && ( + + )} + + + + + + {new Date(dateStr).toLocaleDateString(locale, { + day: '2-digit', + month: 'short', + year: 'numeric', + })} + + + {index === 0 ? t.watered : t.waterNow} + + + + {new Date(dateStr).toLocaleTimeString(locale, { + hour: '2-digit', + minute: '2-digit', + })} + + + + )) + )} + + + + + + {t.galleryTitle} + + + {t.addPhoto} + + + + {(!plant.gallery || plant.gallery.length === 0) ? ( + + + {t.noPhotos} + + ) : ( + + {plant.gallery.map((uri, index) => ( + setFullscreenImage(uri)}> + + + ))} + + )} + + + + + {t.aboutPlant} + + AI + + + + + {plant.description || t.noDescription} + + + + + + + {healthCopy.title} + {healthCopy.cost} + + + + + {healthCopy.action} + + + + + + + {healthCopy.creditsLabel}: {availableCredits} + + + {healthCopy.cost} + + + + {healthStatusInlineText ? ( + + + {healthStatusInlineText} + + {healthStatus === 'insufficient_credits' || (healthStatus === 'idle' && !hasEnoughHealthCredits) ? ( + router.push('/(tabs)/profile')} + > + {healthCopy.managePlan} + + ) : null} + + ) : null} + + + {latestHealthCheck ? ( + + + + {healthCopy.scoreLabel} + + {latestHealthCheck.overallHealthScore}/100 + + + + {latestStatusText} + + + + + {healthCopy.lastCheck}: {new Date(latestHealthCheck.generatedAt).toLocaleString(locale)} + + + + {healthCopy.issuesTitle} + {latestHealthCheck.likelyIssues.map((issue, index) => ( + + + {issue.title} + + {Math.round(issue.confidence * 100)}% + + + + {issue.details} + + + ))} + + + + {healthCopy.actionsTitle} + {latestHealthCheck.actionsNow.map((item, index) => ( + + + {item} + + ))} + + + + {healthCopy.planTitle} + {latestHealthCheck.plan7Days.map((item, index) => ( + + + {item} + + ))} + + + ) : null} + + + setShowDeleteConfirm(true)}> + + {t.delete} + + + + + + + + + + + {t.deleteConfirmTitle} + {t.deleteConfirmMessage} + + + setShowDeleteConfirm(false)} + > + {t.cancel} + + + {t.confirm} + + + + + + + + + {fullscreenImage && } + setFullscreenImage(null)}> + + + + + + {/* Health Check Paywall Modal */} + setPaywallVisible(false)}> + + + + + + + setPaywallVisible(false)} style={styles.paywallClose}> + + + + + KI-Pflanzendoktor freischalten + + Nutze fortschrittliche KI, um Probleme zu erkennen, bevor sie deine Pflanze gefährden. + + + + {[ + { icon: 'search', title: 'Präzise Diagnose', desc: 'Erkennt Schädlinge, Krankheiten und Nährstoffmangel.' }, + { icon: 'medkit', title: 'Rettungspläne', desc: 'Schritt-für-Schritt Anleitungen zur Genesung.' }, + { icon: 'infinite', title: 'Mehr Scans', desc: 'Erhalte 120 Credits jeden Monat mit GreenLens Pro.' }, + ].map((feat, i) => ( + + + + + + {feat.title} + {feat.desc} + + + ))} + + + { + setPaywallVisible(false); + router.push('/profile/billing'); + }} + > + Jetzt upgraden + + + + setPaywallVisible(false)} + > + Vielleicht später + + + + + + ); +} + +const styles = StyleSheet.create({ + container: { flex: 1 }, + scrollContent: { paddingBottom: 120 }, + hero: { + height: 450, + position: 'relative', + }, + heroImage: { + width: '100%', + height: '100%', + resizeMode: 'cover', + }, + heroShade: { + ...StyleSheet.absoluteFillObject, + opacity: 0.18, + }, + heroBaseFade: { + position: 'absolute', + left: 0, + right: 0, + bottom: 0, + height: 172, + opacity: 0.95, + borderTopLeftRadius: 28, + borderTopRightRadius: 28, + }, + topActions: { + position: 'absolute', + top: 58, + left: 22, + right: 22, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + }, + floatingAction: { + width: 44, + height: 44, + borderRadius: 14, + borderWidth: 1, + justifyContent: 'center', + alignItems: 'center', + shadowColor: '#000', + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.15, + shadowRadius: 10, + elevation: 5, + }, + heroTitleWrap: { + position: 'absolute', + left: 24, + right: 24, + bottom: 74, + }, + heroName: { + fontSize: 36, + lineHeight: 40, + fontWeight: '700', + marginBottom: 6, + }, + heroBotanical: { + fontSize: 16, + fontStyle: 'italic', + fontWeight: '600', + opacity: 0.72, + }, + content: { + marginTop: -46, + paddingHorizontal: 16, + gap: 20, + }, + waterCard: { + borderRadius: 28, + borderWidth: 1, + paddingHorizontal: 16, + paddingVertical: 14, + flexDirection: 'row', + alignItems: 'center', + gap: 12, + shadowColor: '#000', + shadowOffset: { width: 0, height: 8 }, + shadowOpacity: 0.08, + shadowRadius: 16, + elevation: 4, + }, + waterInfo: { + flex: 1, + gap: 2, + }, + waterHeadline: { + flexDirection: 'row', + alignItems: 'center', + gap: 6, + }, + waterLabel: { + fontSize: 11, + textTransform: 'uppercase', + letterSpacing: 0.8, + fontWeight: '700', + }, + waterValue: { + fontSize: 15, + lineHeight: 19, + fontWeight: '700', + }, + waterMeta: { + fontSize: 12, + fontWeight: '500', + }, + waterButton: { + borderRadius: 16, + paddingHorizontal: 20, + paddingVertical: 13, + flexDirection: 'row', + alignItems: 'center', + gap: 6, + }, + waterButtonText: { + fontSize: 16, + fontWeight: '700', + }, + careGrid: { + flexDirection: 'row', + gap: 10, + }, + careCard: { + flex: 1, + borderRadius: 22, + borderWidth: 1, + alignItems: 'center', + justifyContent: 'center', + paddingHorizontal: 8, + paddingVertical: 16, + gap: 6, + }, + careIconWrap: { + width: 34, + height: 34, + borderRadius: 17, + alignItems: 'center', + justifyContent: 'center', + }, + careLabel: { + fontSize: 10, + fontWeight: '700', + textTransform: 'uppercase', + letterSpacing: 0.5, + }, + careValue: { + width: '100%', + fontSize: 12, + lineHeight: 15, + fontWeight: '700', + textAlign: 'center', + flexShrink: 1, + }, + reminderCard: { + borderRadius: 24, + borderWidth: 1, + paddingHorizontal: 14, + paddingVertical: 12, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + gap: 12, + }, + reminderInfoRow: { + flexDirection: 'row', + alignItems: 'center', + gap: 10, + flex: 1, + }, + reminderIconWrap: { + width: 40, + height: 40, + borderRadius: 13, + justifyContent: 'center', + alignItems: 'center', + }, + reminderTitle: { + fontSize: 14, + fontWeight: '700', + }, + reminderSubtitle: { + fontSize: 10, + marginTop: 1, + }, + toggleTrack: { + width: 54, + height: 30, + borderRadius: 999, + justifyContent: 'center', + position: 'relative', + }, + toggleThumb: { + position: 'absolute', + width: 22, + height: 22, + borderRadius: 11, + backgroundColor: '#ffffff', + }, + summarySection: { + gap: 8, + }, + summaryHeader: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + }, + aiBadge: { + borderRadius: 999, + paddingHorizontal: 10, + paddingVertical: 4, + }, + aiBadgeText: { + fontSize: 10, + fontWeight: '700', + letterSpacing: 0.6, + }, + summaryCard: { + borderRadius: 22, + borderWidth: 1, + padding: 16, + }, + summaryText: { + fontSize: 14, + lineHeight: 22, + }, + healthActionCard: { + borderRadius: 22, + borderWidth: 1, + padding: 14, + gap: 10, + }, + healthActionRow: { + flexDirection: 'row', + gap: 10, + alignItems: 'center', + }, + healthActionInfo: { + flex: 1, + }, + healthActionTitle: { + fontSize: 14, + fontWeight: '700', + }, + healthActionMeta: { + fontSize: 11, + marginTop: 2, + }, + healthActionBtn: { + borderRadius: 14, + borderWidth: 1, + paddingHorizontal: 12, + paddingVertical: 10, + flexDirection: 'row', + alignItems: 'center', + gap: 6, + }, + healthActionBtnText: { + fontSize: 12, + fontWeight: '700', + }, + healthMetaRow: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + }, + healthMetaText: { + fontSize: 12, + fontWeight: '500', + }, + healthInlineWrap: { + gap: 8, + }, + healthInlineText: { + fontSize: 12, + fontWeight: '600', + }, + healthPlanButton: { + alignSelf: 'flex-start', + borderWidth: 1, + borderRadius: 12, + paddingHorizontal: 10, + paddingVertical: 7, + }, + healthPlanButtonText: { + fontSize: 12, + fontWeight: '700', + }, + healthResultCard: { + borderRadius: 22, + borderWidth: 1, + padding: 14, + gap: 12, + }, + healthResultHead: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + }, + healthResultTitle: { + fontSize: 11, + textTransform: 'uppercase', + letterSpacing: 0.5, + fontWeight: '700', + }, + healthResultScore: { + fontSize: 26, + lineHeight: 30, + fontWeight: '800', + marginTop: 2, + }, + healthStatusBadge: { + borderRadius: 999, + paddingHorizontal: 10, + paddingVertical: 5, + }, + healthStatusBadgeText: { + fontSize: 11, + fontWeight: '700', + }, + healthTimestamp: { + fontSize: 11, + }, + healthListBlock: { + gap: 8, + }, + healthListTitle: { + fontSize: 13, + fontWeight: '700', + }, + healthIssueWrap: { + gap: 3, + }, + healthIssueHead: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + gap: 8, + }, + healthIssueTitle: { + fontSize: 13, + fontWeight: '600', + flex: 1, + }, + healthIssueConfidence: { + fontSize: 11, + fontWeight: '700', + }, + healthIssueDetails: { + fontSize: 12, + lineHeight: 18, + }, + healthBulletRow: { + flexDirection: 'row', + alignItems: 'flex-start', + gap: 8, + }, + healthBulletDot: { + width: 7, + height: 7, + borderRadius: 4, + marginTop: 5, + }, + healthBulletText: { + flex: 1, + fontSize: 12, + lineHeight: 18, + }, + sectionHeaderRow: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 10, + marginTop: 4, + }, + sectionTitle: { + fontSize: 18, + fontWeight: '700', + }, + timelineCard: { + borderRadius: 22, + borderWidth: 1, + paddingHorizontal: 14, + paddingTop: 16, + paddingBottom: 10, + gap: 4, + }, + historyEmpty: { + width: '100%', + alignItems: 'center', + justifyContent: 'center', + gap: 8, + minHeight: 96, + paddingVertical: 20, + }, + historyEmptyText: { + fontSize: 13, + textAlign: 'center', + }, + timelineRow: { + flexDirection: 'row', + alignItems: 'flex-start', + gap: 10, + }, + timelineMarkerColumn: { + width: 20, + alignItems: 'center', + }, + timelineDot: { + width: 11, + height: 11, + borderRadius: 6, + borderWidth: 2, + }, + timelineLine: { + width: 2, + flex: 1, + marginTop: 3, + minHeight: 26, + borderRadius: 2, + }, + timelineContent: { + flex: 1, + paddingBottom: 14, + }, + timelineTopRow: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + gap: 10, + }, + timelineDate: { + fontSize: 14, + fontWeight: '700', + }, + timelineType: { + fontSize: 10, + textTransform: 'uppercase', + letterSpacing: 0.45, + fontWeight: '600', + }, + timelineTime: { + fontSize: 12, + marginTop: 3, + }, + galleryHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 12, + }, + addPhotoBtn: { + flexDirection: 'row', + alignItems: 'center', + gap: 5, + borderWidth: 1, + borderRadius: 18, + paddingHorizontal: 10, + paddingVertical: 6, + }, + addPhotoBtnText: { + fontSize: 13, + fontWeight: '600', + }, + galleryEmpty: { + borderRadius: 18, + borderWidth: 1, + paddingVertical: 22, + alignItems: 'center', + justifyContent: 'center', + gap: 8, + }, + galleryScroll: { + marginBottom: 2, + }, + galleryContent: { + gap: 12, + paddingRight: 20, + }, + galleryThumb: { + width: 96, + height: 96, + borderRadius: 18, + }, + deleteAction: { + alignSelf: 'center', + marginTop: 4, + marginBottom: 12, + flexDirection: 'row', + alignItems: 'center', + gap: 6, + paddingHorizontal: 8, + paddingVertical: 6, + }, + deleteActionText: { + fontSize: 13, + fontWeight: '600', + }, + modalOverlay: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + padding: 24, + }, + modalCard: { + width: '100%', + maxWidth: 340, + borderRadius: 24, + padding: 22, + }, + modalIcon: { + width: 48, + height: 48, + borderRadius: 24, + justifyContent: 'center', + alignItems: 'center', + alignSelf: 'center', + marginBottom: 14, + }, + modalTitle: { + fontSize: 18, + fontWeight: '700', + textAlign: 'center', + marginBottom: 8, + }, + modalMessage: { + fontSize: 13, + lineHeight: 20, + textAlign: 'center', + marginBottom: 20, + }, + modalActions: { + flexDirection: 'row', + gap: 10, + }, + modalButton: { + flex: 1, + paddingVertical: 14, + borderRadius: 14, + alignItems: 'center', + }, + modalButtonText: { + fontSize: 13, + fontWeight: '700', + }, + fullscreenOverlay: { + flex: 1, + backgroundColor: '#000000ee', + justifyContent: 'center', + alignItems: 'center', + }, + fullscreenImage: { + width: '90%', + height: '72%', + resizeMode: 'contain', + }, + fullscreenClose: { + position: 'absolute', + top: 56, + right: 20, + backgroundColor: '#00000088', + borderRadius: 20, + padding: 8, + }, + paywallOverlay: { + flex: 1, + backgroundColor: '#000000aa', + justifyContent: 'flex-end', + }, + paywallContent: { + borderTopLeftRadius: 32, + borderTopRightRadius: 32, + padding: 24, + paddingBottom: 48, + borderTopWidth: 1, + }, + paywallHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'flex-start', + marginBottom: 20, + }, + paywallIconWrap: { + width: 64, + height: 64, + borderRadius: 20, + justifyContent: 'center', + alignItems: 'center', + }, + paywallClose: { + padding: 4, + }, + paywallTitle: { + fontSize: 24, + fontWeight: '800', + marginBottom: 8, + letterSpacing: 0.2, + }, + paywallSubtitle: { + fontSize: 15, + lineHeight: 22, + marginBottom: 28, + }, + paywallFeatures: { + gap: 18, + marginBottom: 32, + }, + paywallFeatureRow: { + flexDirection: 'row', + gap: 14, + alignItems: 'center', + }, + paywallFeatureIcon: { + width: 38, + height: 38, + borderRadius: 12, + justifyContent: 'center', + alignItems: 'center', + }, + paywallFeatureTitle: { + fontSize: 15, + fontWeight: '700', + marginBottom: 2, + }, + paywallFeatureDesc: { + fontSize: 13, + lineHeight: 18, + }, + paywallPrimaryBtn: { + borderRadius: 18, + paddingVertical: 16, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + gap: 8, + shadowOpacity: 0.2, + shadowRadius: 10, + shadowOffset: { width: 0, height: 4 }, + elevation: 4, + }, + paywallPrimaryBtnText: { + fontSize: 17, + fontWeight: '700', + }, + paywallSecondaryBtn: { + marginTop: 12, + paddingVertical: 12, + alignItems: 'center', + }, + paywallSecondaryBtnText: { + fontSize: 14, + fontWeight: '600', + }, +}); diff --git a/app/profile/billing.tsx b/app/profile/billing.tsx new file mode 100644 index 0000000..424daf4 --- /dev/null +++ b/app/profile/billing.tsx @@ -0,0 +1,657 @@ +import React, { useState } from 'react'; +import { View, Text, TouchableOpacity, ScrollView, StyleSheet, Modal, ActivityIndicator, Alert, Platform } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; +import { Ionicons } from '@expo/vector-icons'; +import { useRouter } from 'expo-router'; +import RevenueCatUI, { PAYWALL_RESULT } from "react-native-purchases-ui"; +import { usePostHog } from 'posthog-react-native'; +import { useApp } from '../../context/AppContext'; +import { useColors } from '../../constants/Colors'; +import { ThemeBackdrop } from '../../components/ThemeBackdrop'; +import { Language } from '../../types'; +import { PurchaseProductId } from '../../services/backend/contracts'; + +const getBillingCopy = (language: Language) => { + if (language === 'de') { + return { + title: 'Abo und Credits', + planLabel: 'Aktueller Plan', + planFree: 'Free', + planPro: 'Pro', + creditsAvailableLabel: 'Verfügbare Credits', + manageSubscription: 'Abo verwalten', + subscriptionTitle: 'Abos', + subscriptionHint: 'Wähle ein Abo und schalte stärkere KI-Scans sowie mehr Credits frei.', + freePlanName: 'Free', + freePlanPrice: '0 EUR / Monat', + proPlanName: 'Pro', + proPlanPrice: '4.99 EUR / Monat', + proBadgeText: 'EMPFOHLEN', + proYearlyPlanName: 'Pro', + proYearlyPlanPrice: '39.99 EUR / Jahr', + proYearlyBadgeText: 'SPAREN', + proBenefits: [ + '250 Credits jeden Monat', + 'Pro-Scans mit GPT-5.4', + 'Unbegrenzte Historie & Galerie', + 'KI-Pflanzendoktor inklusive', + 'Priorisierter Support' + ], + topupTitle: 'Credits Aufladen', + topupSmall: '25 Credits – 1,99 €', + topupMedium: '120 Credits – 6,99 €', + topupLarge: '300 Credits – 12,99 €', + topupBestValue: 'BESTES ANGEBOT', + cancelTitle: 'Schade, dass du gehst', + cancelQuestion: 'Dürfen wir fragen, warum du kündigst?', + reasonTooExpensive: 'Es ist mir zu teuer', + reasonNotUsing: 'Ich nutze die App zu selten', + reasonOther: 'Ein anderer Grund', + offerTitle: 'Ein Geschenk für dich!', + offerText: 'Bleib dabei und erhalte den nächsten Monat für nur 2,49 € (50% Rabatt).', + offerAccept: 'Rabatt sichern', + offerDecline: 'Nein, Kündigung fortsetzen', + confirmCancelBtn: 'Jetzt kündigen', + }; + } else if (language === 'es') { + return { + title: 'Suscripción y Créditos', + planLabel: 'Plan Actual', + planFree: 'Gratis', + planPro: 'Pro', + creditsAvailableLabel: 'Créditos Disponibles', + manageSubscription: 'Administrar Suscripción', + subscriptionTitle: 'Suscripciones', + subscriptionHint: 'Elige un plan y desbloquea escaneos con IA más potentes y más créditos.', + freePlanName: 'Gratis', + freePlanPrice: '0 EUR / Mes', + proPlanName: 'Pro', + proPlanPrice: '4.99 EUR / Mes', + proBadgeText: 'RECOMENDADO', + proYearlyPlanName: 'Pro', + proYearlyPlanPrice: '39.99 EUR / Año', + proYearlyBadgeText: 'AHORRAR', + proBenefits: [ + '250 créditos cada mes', + 'Escaneos Pro con GPT-5.4', + 'Historial y galería ilimitados', + 'Doctor de plantas de IA incluido', + 'Soporte prioritario' + ], + topupTitle: 'Recargar Créditos', + topupSmall: '25 Créditos – 1,99 €', + topupMedium: '120 Créditos – 6,99 €', + topupLarge: '300 Créditos – 12,99 €', + topupBestValue: 'MEJOR OFERTA', + cancelTitle: 'Lamentamos verte ir', + cancelQuestion: '¿Podemos saber por qué cancelas?', + reasonTooExpensive: 'Es muy caro', + reasonNotUsing: 'No lo uso suficiente', + reasonOther: 'Otra razón', + offerTitle: '¡Un regalo para ti!', + offerText: 'Quédate y obtén el próximo mes por solo 2,49 € (50% de descuento).', + offerAccept: 'Aceptar descuento', + offerDecline: 'No, continuar cancelando', + confirmCancelBtn: 'Cancelar ahora', + }; + } + return { + title: 'Billing & Credits', + planLabel: 'Current Plan', + planFree: 'Free', + planPro: 'Pro', + creditsAvailableLabel: 'Available Credits', + manageSubscription: 'Manage Subscription', + subscriptionTitle: 'Subscriptions', + subscriptionHint: 'Choose a plan to unlock stronger AI scans and more credits.', + freePlanName: 'Free', + freePlanPrice: '0 EUR / Month', + proPlanName: 'Pro', + proPlanPrice: '4.99 EUR / Month', + proBadgeText: 'RECOMMENDED', + proYearlyPlanName: 'Pro', + proYearlyPlanPrice: '39.99 EUR / Year', + proYearlyBadgeText: 'SAVE', + proBenefits: [ + '250 credits every month', + 'Pro scans with GPT-5.4', + 'Unlimited history & gallery', + 'AI Plant Doctor included', + 'Priority support' + ], + topupTitle: 'Topup Credits', + topupSmall: '25 Credits – €1.99', + topupMedium: '120 Credits – €6.99', + topupLarge: '300 Credits – €12.99', + topupBestValue: 'BEST VALUE', + cancelTitle: 'Sorry to see you go', + cancelQuestion: 'May we ask why you are cancelling?', + reasonTooExpensive: 'It is too expensive', + reasonNotUsing: 'I don\'t use it enough', + reasonOther: 'Other reason', + offerTitle: 'A gift for you!', + offerText: 'Stay with us and get your next month for just €2.49 (50% off).', + offerAccept: 'Claim discount', + offerDecline: 'No, continue cancelling', + confirmCancelBtn: 'Cancel now', + }; +}; + + + +export default function BillingScreen() { + const router = useRouter(); + const { isDarkMode, language, billingSummary, isLoadingBilling, simulatePurchase, simulateWebhookEvent, appearanceMode, colorPalette, session } = useApp(); + const colors = useColors(isDarkMode, colorPalette); + const copy = getBillingCopy(language); + const posthog = usePostHog(); + + const [subModalVisible, setSubModalVisible] = useState(false); + const [isUpdating, setIsUpdating] = useState(false); + + // Cancel Flow State + const [cancelStep, setCancelStep] = useState<'none' | 'survey' | 'offer'>('none'); + const [cancelReason, setCancelReason] = useState(null); + + const planId = billingSummary?.entitlement?.plan || 'free'; + const credits = isLoadingBilling && !billingSummary ? '...' : (billingSummary?.credits?.available ?? '--'); + + const handlePurchase = async (productId: PurchaseProductId) => { + setIsUpdating(true); + try { + const paywallResult: PAYWALL_RESULT = await RevenueCatUI.presentPaywall(); + switch (paywallResult) { + case PAYWALL_RESULT.NOT_PRESENTED: + case PAYWALL_RESULT.ERROR: + case PAYWALL_RESULT.CANCELLED: + break; + case PAYWALL_RESULT.PURCHASED: + case PAYWALL_RESULT.RESTORED: + await simulatePurchase(productId); + setSubModalVisible(false); + break; + default: + break; + } + } catch (e) { + const msg = e instanceof Error ? e.message : String(e); + console.error('Payment failed', e); + if (__DEV__ && (msg.toLowerCase().includes('native') || msg.toLowerCase().includes('not found') || msg.toLowerCase().includes('undefined'))) { + // Fallback for Expo Go since RevenueCat native module is not available + console.log('Falling back to simulated purchase in Expo Go'); + await simulatePurchase(productId); + setSubModalVisible(false); + } else { + Alert.alert('Unerwarteter Fehler', msg); + } + } finally { + setIsUpdating(false); + } + }; + + + const handleSimulatePurchase = async (productId: PurchaseProductId) => { + // Fallback for free option + setIsUpdating(true); + await simulatePurchase(productId); + setIsUpdating(false); + setSubModalVisible(false); + }; + + const handleDowngrade = async () => { + if (planId === 'free') return; // already on free plan + setCancelStep('survey'); + }; + + const finalizeCancel = async () => { + setIsUpdating(true); + try { + await simulateWebhookEvent('entitlement_revoked'); + setCancelStep('none'); + setSubModalVisible(false); + } catch (e) { + console.error('Downgrade failed', e); + } finally { + setIsUpdating(false); + } + }; + + return ( + + + + + router.back()} style={styles.backButton}> + + + {copy.title} + + + + + {isLoadingBilling ? ( + + ) : ( + <> + + {copy.planLabel} + + + {planId === 'pro' ? copy.planPro : copy.planFree} + + setSubModalVisible(true)} + > + {copy.manageSubscription} + + + + {copy.creditsAvailableLabel} + {credits} + + + + {copy.topupTitle} + + {([ + { id: 'topup_small' as PurchaseProductId, label: copy.topupSmall }, + { id: 'topup_medium' as PurchaseProductId, label: copy.topupMedium, badge: copy.topupBestValue }, + { id: 'topup_large' as PurchaseProductId, label: copy.topupLarge }, + ] as { id: PurchaseProductId; label: string; badge?: string }[]).map((pack) => ( + handlePurchase(pack.id)} + disabled={isUpdating} + > + + + + {isUpdating ? '...' : pack.label} + + + {pack.badge && ( + + {pack.badge} + + )} + + ))} + + + + )} + + + + setSubModalVisible(false)}> + + + + + {cancelStep === 'survey' ? copy.cancelTitle : cancelStep === 'offer' ? copy.offerTitle : copy.subscriptionTitle} + + { + setSubModalVisible(false); + setCancelStep('none'); + }}> + + + + + {cancelStep === 'none' ? ( + <> + {copy.subscriptionHint} + + + + {copy.freePlanName} + {copy.freePlanPrice} + + {planId === 'free' && } + + + handlePurchase('monthly_pro')} + disabled={isUpdating} + > + + + {copy.proPlanName} + + {copy.proBadgeText} + + + {copy.proPlanPrice} + + + {copy.proBenefits.map((b, i) => ( + + + {b} + + ))} + + + {planId === 'pro' && } + + + handlePurchase('yearly_pro')} + disabled={isUpdating} + > + + + {copy.proYearlyPlanName} + + {copy.proYearlyBadgeText} + + + {copy.proYearlyPlanPrice} + + + {copy.proBenefits.map((b, i) => ( + + + {b} + + ))} + + + {planId === 'pro' && } + + + + ) : cancelStep === 'survey' ? ( + + {copy.cancelQuestion} + + {[ + { id: 'expensive', label: copy.reasonTooExpensive, icon: 'cash-outline' }, + { id: 'not_using', label: copy.reasonNotUsing, icon: 'calendar-outline' }, + { id: 'other', label: copy.reasonOther, icon: 'ellipsis-horizontal-outline' }, + ].map((reason) => ( + { + setCancelReason(reason.id); + setCancelStep('offer'); + }} + > + + + + {reason.label} + + + ))} + + + ) : ( + + + + + + {copy.offerText} + + { + // Handle applying discount here (future implementation) + Alert.alert('Erfolg', 'Rabatt angewendet! (Mock)'); + setCancelStep('none'); + setSubModalVisible(false); + }} + > + {copy.offerAccept} + + + + + {copy.offerDecline} + + + )} + {isUpdating && cancelStep === 'none' && } + + + + + ); +} + +const styles = StyleSheet.create({ + safeArea: { flex: 1 }, + header: { flexDirection: 'row', alignItems: 'center', padding: 16 }, + backButton: { width: 40, height: 40, justifyContent: 'center' }, + title: { flex: 1, fontSize: 20, fontWeight: '700', textAlign: 'center' }, + scrollContent: { padding: 16, gap: 16 }, + card: { + padding: 16, + borderRadius: 16, + borderWidth: StyleSheet.hairlineWidth, + }, + sectionTitle: { + fontSize: 14, + fontWeight: '600', + textTransform: 'uppercase', + letterSpacing: 0.5, + marginBottom: 8, + }, + row: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + }, + value: { + fontSize: 18, + fontWeight: '600', + }, + manageBtn: { + paddingHorizontal: 16, + paddingVertical: 8, + borderRadius: 20, + }, + manageBtnText: { + color: '#fff', + fontSize: 14, + fontWeight: '600', + }, + creditsValue: { + fontSize: 32, + fontWeight: '700', + }, + topupBtn: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + paddingVertical: 12, + borderRadius: 12, + borderWidth: 2, + gap: 8, + }, + topupText: { + fontSize: 16, + fontWeight: '600', + }, + modalOverlay: { + flex: 1, + backgroundColor: '#00000080', + justifyContent: 'flex-end', + }, + modalContent: { + borderTopLeftRadius: 24, + borderTopRightRadius: 24, + padding: 24, + borderTopWidth: StyleSheet.hairlineWidth, + paddingBottom: 40, + }, + modalHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 8, + }, + modalTitle: { + fontSize: 20, + fontWeight: '700', + }, + modalHint: { + fontSize: 14, + marginBottom: 24, + }, + plansContainer: { + gap: 12, + }, + planOption: { + padding: 16, + borderRadius: 12, + borderWidth: 2, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + }, + planName: { + fontSize: 18, + fontWeight: '600', + }, + planPrice: { + fontSize: 14, + }, + planHeaderRow: { + flexDirection: 'row', + alignItems: 'center', + gap: 8, + marginBottom: 2, + }, + proBadge: { + paddingHorizontal: 8, + paddingVertical: 2, + borderRadius: 6, + }, + proBadgeText: { + color: '#fff', + fontSize: 10, + fontWeight: '800', + }, + proBenefits: { + marginTop: 12, + gap: 6, + }, + benefitRow: { + flexDirection: 'row', + alignItems: 'center', + gap: 6, + }, + benefitText: { + fontSize: 12, + fontWeight: '500', + }, + cancelFlowContainer: { + marginTop: 8, + }, + cancelHint: { + fontSize: 15, + marginBottom: 16, + }, + reasonList: { + gap: 12, + }, + reasonOption: { + flexDirection: 'row', + alignItems: 'center', + padding: 16, + borderWidth: 1, + borderRadius: 12, + }, + reasonIcon: { + width: 36, + height: 36, + borderRadius: 18, + justifyContent: 'center', + alignItems: 'center', + marginRight: 12, + }, + reasonText: { + flex: 1, + fontSize: 16, + fontWeight: '500', + }, + offerCard: { + borderRadius: 16, + padding: 24, + alignItems: 'center', + marginBottom: 16, + }, + offerIconWrap: { + width: 56, + height: 56, + borderRadius: 28, + justifyContent: 'center', + alignItems: 'center', + marginBottom: 16, + }, + offerText: { + fontSize: 16, + textAlign: 'center', + lineHeight: 24, + marginBottom: 24, + fontWeight: '500', + }, + offerAcceptBtn: { + paddingHorizontal: 24, + paddingVertical: 14, + borderRadius: 24, + width: '100%', + alignItems: 'center', + }, + offerAcceptBtnText: { + color: '#fff', + fontSize: 16, + fontWeight: '700', + }, + offerDeclineBtn: { + paddingVertical: 12, + alignItems: 'center', + }, + offerDeclineBtnText: { + fontSize: 15, + fontWeight: '500', + }, +}); diff --git a/app/profile/data.tsx b/app/profile/data.tsx new file mode 100644 index 0000000..7c32f2d --- /dev/null +++ b/app/profile/data.tsx @@ -0,0 +1,226 @@ +import React from 'react'; +import { View, Text, TouchableOpacity, ScrollView, StyleSheet, Share, Alert } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; +import { Ionicons } from '@expo/vector-icons'; +import { useRouter } from 'expo-router'; +import { useApp } from '../../context/AppContext'; +import { useColors } from '../../constants/Colors'; +import { ThemeBackdrop } from '../../components/ThemeBackdrop'; +import { Language } from '../../types'; + +const getDataCopy = (language: Language) => { + if (language === 'de') { + return { + title: 'Daten & Datenschutz', + exportData: 'Daten exportieren', + exportHint: 'Teilt deine Sammlung als JSON.', + clearHistory: 'Lexikon-Verlauf loeschen', + clearHistoryHint: 'Entfernt alle letzten Suchbegriffe.', + clearHistoryDoneTitle: 'Verlauf geloescht', + clearHistoryDoneMessage: 'Der Suchverlauf wurde entfernt.', + logout: 'Abmelden', + logoutHint: 'Zurueck zum Onboarding und Profil zuruecksetzen.', + logoutConfirmTitle: 'Abmelden?', + logoutConfirmMessage: 'Du wirst auf den Startbildschirm zurueckgesetzt.', + deleteAccount: 'Konto unwiderruflich löschen', + deleteAccountHint: 'Löscht alle deine Daten, Pflanzen und Abos permanent.', + deleteConfirmTitle: 'Konto wirklich löschen?', + deleteConfirmMessage: 'Achtung: Dieser Schritt kann nicht rückgängig gemacht werden. Alle deine Pflanzen, Scans und Credits gehen sofort verloren.', + deleteActionBtn: 'Ja, dauerhaft löschen', + genericErrorTitle: 'Fehler', + genericErrorMessage: 'Aktion konnte nicht abgeschlossen werden.', + }; + } + + if (language === 'es') { + return { + title: 'Datos y Privacidad', + exportData: 'Exportar Datos', + exportHint: 'Comparte tu coleccion como JSON.', + clearHistory: 'Borrar historial', + clearHistoryHint: 'Elimina las busquedas recientes.', + clearHistoryDoneTitle: 'Historial borrado', + clearHistoryDoneMessage: 'El historial de busqueda ha sido eliminado.', + logout: 'Cerrar sesion', + logoutHint: 'Volver a la pantalla de inicio y reiniciar perfil.', + logoutConfirmTitle: 'Cerrar sesion?', + logoutConfirmMessage: 'Seras enviado a la pantalla de inicio.', + deleteAccount: 'Eliminar cuenta permanentemente', + deleteAccountHint: 'Elimina todos tus datos, plantas y suscripciones.', + deleteConfirmTitle: '¿Seguro que quieres eliminar tu cuenta?', + deleteConfirmMessage: 'Atención: Este paso no se puede deshacer. Todas tus plantas, escaneos y créditos se perderán inmediatamente.', + deleteActionBtn: 'Sí, eliminar permanentemente', + genericErrorTitle: 'Error', + genericErrorMessage: 'La accion no pudo ser completada.', + }; + } + + return { + title: 'Data & Privacy', + exportData: 'Export Data', + exportHint: 'Share your collection as JSON.', + clearHistory: 'Clear Search History', + clearHistoryHint: 'Removes recent search queries.', + clearHistoryDoneTitle: 'History Cleared', + clearHistoryDoneMessage: 'Search history has been removed.', + logout: 'Log Out', + logoutHint: 'Return to onboarding and reset profile.', + logoutConfirmTitle: 'Log Out?', + logoutConfirmMessage: 'You will be returned to the start screen.', + deleteAccount: 'Delete Account Permanently', + deleteAccountHint: 'Permanently deletes all your data, plants, and subscriptions.', + deleteConfirmTitle: 'Are you sure?', + deleteConfirmMessage: 'Warning: This cannot be undone. All your plants, scans, and credits will be lost immediately.', + deleteActionBtn: 'Yes, delete permanently', + genericErrorTitle: 'Error', + genericErrorMessage: 'Action could not be completed.', + }; +}; + +export default function DataScreen() { + const router = useRouter(); + const { isDarkMode, language, plants, appearanceMode, colorPalette, clearLexiconSearchHistory, signOut } = useApp(); + const colors = useColors(isDarkMode, colorPalette); + const copy = getDataCopy(language); + + const handleExportData = async () => { + try { + const dataStr = JSON.stringify(plants, null, 2); + await Share.share({ + message: dataStr, + title: 'GreenLens_Export.json', + }); + } catch { + Alert.alert(copy.genericErrorTitle, copy.genericErrorMessage); + } + }; + + const handleClearHistory = () => { + clearLexiconSearchHistory(); + Alert.alert(copy.clearHistoryDoneTitle, copy.clearHistoryDoneMessage); + }; + + const handleLogout = () => { + Alert.alert(copy.logoutConfirmTitle, copy.logoutConfirmMessage, [ + { text: 'Cancel', style: 'cancel' }, + { + text: copy.logout, + style: 'destructive', + onPress: async () => { + await signOut(); + router.replace('/auth/login'); + }, + }, + ]); + }; + + const handleDeleteAccount = () => { + Alert.alert(copy.deleteConfirmTitle, copy.deleteConfirmMessage, [ + { text: 'Cancel', style: 'cancel' }, + { + text: copy.deleteActionBtn, + style: 'destructive', + onPress: async () => { + // Future implementation: call backend to wipe user data, cancel active Stripe subscriptions + await signOut(); + router.replace('/onboarding'); + }, + }, + ]); + }; + + return ( + + + + + router.back()} style={styles.backButton}> + + + {copy.title} + + + + + + + + + + {copy.exportData} + {copy.exportHint} + + + + + + + + + {copy.clearHistory} + {copy.clearHistoryHint} + + + + + + + + + {copy.logout} + {copy.logoutHint} + + + + + + + + + + {copy.deleteAccount} + {copy.deleteAccountHint} + + + + + + + ); +} + +const styles = StyleSheet.create({ + safeArea: { flex: 1 }, + header: { flexDirection: 'row', alignItems: 'center', padding: 16 }, + backButton: { width: 40, height: 40, justifyContent: 'center' }, + title: { flex: 1, fontSize: 20, fontWeight: '700', textAlign: 'center' }, + scrollContent: { padding: 16, gap: 16 }, + actionRow: { + flexDirection: 'row', + alignItems: 'center', + padding: 16, + borderRadius: 16, + borderWidth: StyleSheet.hairlineWidth, + marginBottom: 16, + }, + actionIcon: { + width: 40, + height: 40, + borderRadius: 20, + backgroundColor: '#00000010', + justifyContent: 'center', + alignItems: 'center', + marginRight: 16, + }, + actionTextContainer: { + flex: 1, + }, + actionTitle: { + fontSize: 16, + fontWeight: '600', + marginBottom: 4, + }, + actionHint: { + fontSize: 13, + }, +}); diff --git a/app/profile/preferences.tsx b/app/profile/preferences.tsx new file mode 100644 index 0000000..31f1207 --- /dev/null +++ b/app/profile/preferences.tsx @@ -0,0 +1,229 @@ +import React, { useState } from 'react'; +import { View, Text, TouchableOpacity, ScrollView, StyleSheet } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; +import { Ionicons } from '@expo/vector-icons'; +import { useRouter } from 'expo-router'; +import { useApp } from '../../context/AppContext'; +import { useColors } from '../../constants/Colors'; +import { ThemeBackdrop } from '../../components/ThemeBackdrop'; +import { AppearanceMode, ColorPalette, Language } from '../../types'; + +const PALETTE_SWATCHES: Record = { + forest: ['#5fa779', '#3d7f57'], + ocean: ['#5a90be', '#3d6f99'], + sunset: ['#c98965', '#a36442'], + mono: ['#7b8796', '#5b6574'], +}; + +const getPreferencesCopy = (language: Language) => { + if (language === 'de') { + return { + title: 'Einstellungen', + appearanceMode: 'Modell', + colorPalette: 'Farbpalette', + languageLabel: 'Sprache', + themeSystem: 'System', + themeLight: 'Hell', + themeDark: 'Dunkel', + paletteForest: 'Forest', + paletteOcean: 'Ocean', + paletteSunset: 'Sunset', + paletteMono: 'Mono', + }; + } else if (language === 'es') { + return { + title: 'Ajustes', + appearanceMode: 'Modo', + colorPalette: 'Paleta', + languageLabel: 'Idioma', + themeSystem: 'Sistema', + themeLight: 'Claro', + themeDark: 'Oscuro', + paletteForest: 'Forest', + paletteOcean: 'Ocean', + paletteSunset: 'Sunset', + paletteMono: 'Mono', + }; + } + return { + title: 'Preferences', + appearanceMode: 'Appearance Mode', + colorPalette: 'Color Palette', + languageLabel: 'Language', + themeSystem: 'System', + themeLight: 'Light', + themeDark: 'Dark', + paletteForest: 'Forest', + paletteOcean: 'Ocean', + paletteSunset: 'Sunset', + paletteMono: 'Mono', + }; +}; + +export default function PreferencesScreen() { + const router = useRouter(); + const { isDarkMode, appearanceMode, colorPalette, language, setAppearanceMode, setColorPalette, changeLanguage } = useApp(); + const colors = useColors(isDarkMode, colorPalette); + const copy = getPreferencesCopy(language); + + return ( + + + + + router.back()} style={styles.backButton}> + + + {copy.title} + + + + + + {copy.appearanceMode} + + {(['system', 'light', 'dark'] as AppearanceMode[]).map((mode) => { + const isActive = appearanceMode === mode; + const label = mode === 'system' ? copy.themeSystem : mode === 'light' ? copy.themeLight : copy.themeDark; + return ( + setAppearanceMode(mode)} + > + + {label} + + + ); + })} + + + + + {copy.colorPalette} + + {(['forest', 'ocean', 'sunset', 'mono'] as ColorPalette[]).map((p) => { + const isActive = colorPalette === p; + const swatch = PALETTE_SWATCHES[p] || ['#ccc', '#999']; + const label = p === 'forest' ? copy.paletteForest : p === 'ocean' ? copy.paletteOcean : p === 'sunset' ? copy.paletteSunset : copy.paletteMono; + return ( + setColorPalette(p)} + > + + {label} + + ); + })} + + + + + {copy.languageLabel} + + {(['en', 'de', 'es'] as Language[]).map(lang => { + const isActive = language === lang; + const label = lang === 'en' ? 'English' : lang === 'de' ? 'Deutsch' : 'Español'; + return ( + changeLanguage(lang)} + > + + {label} + + + ); + })} + + + + + + + ); +} + +const styles = StyleSheet.create({ + safeArea: { flex: 1 }, + header: { flexDirection: 'row', alignItems: 'center', padding: 16 }, + backButton: { width: 40, height: 40, justifyContent: 'center' }, + title: { flex: 1, fontSize: 20, fontWeight: '700', textAlign: 'center' }, + scrollContent: { padding: 16, gap: 16 }, + card: { + padding: 16, + borderRadius: 16, + borderWidth: StyleSheet.hairlineWidth, + }, + sectionTitle: { + fontSize: 14, + fontWeight: '600', + textTransform: 'uppercase', + letterSpacing: 0.5, + marginBottom: 16, + }, + segmentedControl: { + flexDirection: 'row', + backgroundColor: '#00000010', + borderRadius: 12, + padding: 4, + }, + segmentBtn: { + flex: 1, + paddingVertical: 10, + alignItems: 'center', + borderRadius: 8, + }, + segmentText: { + fontSize: 14, + fontWeight: '500', + }, + swatchContainer: { + flexDirection: 'row', + justifyContent: 'space-between', + }, + swatchWrap: { + alignItems: 'center', + padding: 4, + borderRadius: 12, + borderWidth: 2, + borderColor: 'transparent', + gap: 6, + }, + swatch: { + width: 48, + height: 48, + borderRadius: 24, + }, + swatchLabel: { + fontSize: 12, + fontWeight: '500', + }, + langRow: { + flexDirection: 'row', + flexWrap: 'wrap', + gap: 12, + }, + langBtn: { + paddingHorizontal: 16, + paddingVertical: 10, + borderRadius: 12, + backgroundColor: '#00000010', + }, +}); diff --git a/app/scanner.tsx b/app/scanner.tsx new file mode 100644 index 0000000..e74f64e --- /dev/null +++ b/app/scanner.tsx @@ -0,0 +1,669 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { + View, Text, StyleSheet, TouchableOpacity, Image, Alert, Animated, Easing, +} from 'react-native'; +import { useLocalSearchParams, useRouter } from 'expo-router'; +import { Ionicons } from '@expo/vector-icons'; +import { CameraView, useCameraPermissions } from 'expo-camera'; +import { useSafeAreaInsets } from 'react-native-safe-area-context'; +import * as ImagePicker from 'expo-image-picker'; +import * as Haptics from 'expo-haptics'; +import { usePostHog } from 'posthog-react-native'; +import { useApp } from '../context/AppContext'; +import { useColors } from '../constants/Colors'; +import { PlantRecognitionService } from '../services/plantRecognitionService'; +import { IdentificationResult } from '../types'; +import { ResultCard } from '../components/ResultCard'; +import { backendApiClient, isInsufficientCreditsError } from '../services/backend/backendApiClient'; +import { isBackendApiError } from '../services/backend/contracts'; +import { createIdempotencyKey } from '../utils/idempotency'; + +const HEALTH_CHECK_CREDIT_COST = 2; + +const getBillingCopy = (language: 'de' | 'en' | 'es') => { + if (language === 'de') { + return { + creditsLabel: 'Credits', + noCreditsTitle: 'Keine Credits mehr', + noCreditsMessage: 'Du hast keine Credits mehr fuer KI-Scans. Upgrade oder Top-up im Profil.', + healthNoCreditsMessage: `Du brauchst ${HEALTH_CHECK_CREDIT_COST} Credits fuer den Health-Check.`, + managePlan: 'Plan verwalten', + dismiss: 'Schliessen', + genericErrorTitle: 'Fehler', + genericErrorMessage: 'Analyse fehlgeschlagen.', + providerErrorMessage: 'KI-Scan gerade nicht verfuegbar. Bitte API-Key/Netzwerk pruefen.', + healthProviderErrorMessage: 'KI-Health-Check gerade nicht verfuegbar. Bitte API-Key/Netzwerk pruefen.', + healthTitle: 'Health Check', + healthDoneTitle: 'Health Check abgeschlossen', + healthDoneMessage: 'Neues Foto wurde geprueft und zur Galerie hinzugefuegt.', + signupLabel: 'Registrieren', + }; + } + + if (language === 'es') { + return { + creditsLabel: 'Creditos', + noCreditsTitle: 'Sin creditos', + noCreditsMessage: 'No tienes creditos para escaneos AI. Actualiza o compra top-up en Perfil.', + healthNoCreditsMessage: `Necesitas ${HEALTH_CHECK_CREDIT_COST} creditos para el health-check.`, + managePlan: 'Gestionar plan', + dismiss: 'Cerrar', + genericErrorTitle: 'Error', + genericErrorMessage: 'Analisis fallido.', + providerErrorMessage: 'Escaneo IA no disponible ahora. Revisa API key y red.', + healthProviderErrorMessage: 'Health-check IA no disponible ahora. Revisa API key y red.', + healthTitle: 'Health Check', + healthDoneTitle: 'Health-check completado', + healthDoneMessage: 'La foto nueva fue analizada y guardada en la galeria.', + signupLabel: 'Registrarse', + }; + } + + return { + creditsLabel: 'Credits', + noCreditsTitle: 'No credits left', + noCreditsMessage: 'You have no AI scan credits left. Upgrade or buy a top-up in Profile.', + healthNoCreditsMessage: `You need ${HEALTH_CHECK_CREDIT_COST} credits for the health check.`, + managePlan: 'Manage plan', + dismiss: 'Close', + genericErrorTitle: 'Error', + genericErrorMessage: 'Analysis failed.', + providerErrorMessage: 'AI scan is unavailable right now. Check API key and network.', + healthProviderErrorMessage: 'AI health check is unavailable right now. Check API key and network.', + healthTitle: 'Health Check', + healthDoneTitle: 'Health Check Complete', + healthDoneMessage: 'The new photo was analyzed and added to gallery.', + signupLabel: 'Sign Up', + }; +}; + +export default function ScannerScreen() { + const params = useLocalSearchParams<{ mode?: string; plantId?: string }>(); + const posthog = usePostHog(); + const { + isDarkMode, + colorPalette, + language, + t, + savePlant, + plants, + updatePlant, + billingSummary, + refreshBillingSummary, + isLoadingBilling, + session, + setPendingPlant, + guestScanCount, + incrementGuestScanCount, + } = useApp(); + const colors = useColors(isDarkMode, colorPalette); + const router = useRouter(); + const insets = useSafeAreaInsets(); + const billingCopy = getBillingCopy(language); + const isHealthMode = params.mode === 'health'; + const healthPlantId = Array.isArray(params.plantId) ? params.plantId[0] : params.plantId; + const healthPlant = isHealthMode && healthPlantId + ? plants.find((item) => item.id === healthPlantId) + : null; + const availableCredits = session + ? (billingSummary?.credits.available ?? 0) + : Math.max(0, 5 - guestScanCount); + + const [permission, requestPermission] = useCameraPermissions(); + const [selectedImage, setSelectedImage] = useState(null); + const [isAnalyzing, setIsAnalyzing] = useState(false); + const [analysisProgress, setAnalysisProgress] = useState(0); + const [analysisResult, setAnalysisResult] = useState(null); + const cameraRef = useRef(null); + const scanLineProgress = useRef(new Animated.Value(0)).current; + const scanPulse = useRef(new Animated.Value(0)).current; + + useEffect(() => { + if (!isAnalyzing) { + scanLineProgress.stopAnimation(); + scanLineProgress.setValue(0); + scanPulse.stopAnimation(); + scanPulse.setValue(0); + return; + } + + const lineAnimation = Animated.loop( + Animated.sequence([ + Animated.timing(scanLineProgress, { + toValue: 1, + duration: 1500, + easing: Easing.inOut(Easing.quad), + useNativeDriver: true, + }), + Animated.timing(scanLineProgress, { + toValue: 0, + duration: 1500, + easing: Easing.inOut(Easing.quad), + useNativeDriver: true, + }), + ]) + ); + + const pulseAnimation = Animated.loop( + Animated.sequence([ + Animated.timing(scanPulse, { toValue: 1, duration: 900, useNativeDriver: true }), + Animated.timing(scanPulse, { toValue: 0, duration: 900, useNativeDriver: true }), + ]) + ); + + lineAnimation.start(); + pulseAnimation.start(); + + return () => { + lineAnimation.stop(); + pulseAnimation.stop(); + }; + }, [isAnalyzing, scanLineProgress, scanPulse]); + + const analyzeImage = async (imageUri: string, galleryImageUri?: string) => { + if (isAnalyzing) return; + + if (availableCredits <= 0) { + Alert.alert( + billingCopy.noCreditsTitle, + isHealthMode ? billingCopy.healthNoCreditsMessage : billingCopy.noCreditsMessage, + [ + { text: billingCopy.dismiss, style: 'cancel' }, + { + text: billingCopy.signupLabel, + onPress: () => router.push('/auth/signup'), + }, + ], + ); + return; + } + + setIsAnalyzing(true); + setAnalysisProgress(0); + setAnalysisResult(null); + + const startTime = Date.now(); + + const progressInterval = setInterval(() => { + setAnalysisProgress((prev) => { + if (prev < 30) return prev + Math.random() * 8; + if (prev < 70) return prev + Math.random() * 2; + if (prev < 90) return prev + 0.5; + return prev; + }); + }, 150); + + try { + if (isHealthMode) { + if (!healthPlant) { + Alert.alert(billingCopy.genericErrorTitle, billingCopy.genericErrorMessage); + setSelectedImage(null); + setIsAnalyzing(false); + return; + } + + const response = await backendApiClient.runHealthCheck({ + idempotencyKey: createIdempotencyKey('health-check', healthPlant.id), + imageUri, + language, + plantContext: { + name: healthPlant.name, + botanicalName: healthPlant.botanicalName, + careInfo: healthPlant.careInfo, + description: healthPlant.description, + }, + }); + + posthog.capture('llm_generation', { + scan_type: 'health_check', + success: true, + latency_ms: Date.now() - startTime, + }); + + if (!session) { + incrementGuestScanCount(); + } + + const currentGallery = healthPlant.gallery || []; + const existingChecks = healthPlant.healthChecks || []; + const updatedChecks = [response.healthCheck, ...existingChecks].slice(0, 6); + const updatedPlant = { + ...healthPlant, + gallery: galleryImageUri ? [...currentGallery, galleryImageUri] : currentGallery, + healthChecks: updatedChecks, + }; + await updatePlant(updatedPlant); + } else { + const result = await PlantRecognitionService.identify(imageUri, language, { + idempotencyKey: createIdempotencyKey('scan-plant'), + }); + + posthog.capture('llm_generation', { + scan_type: 'identification', + success: true, + latency_ms: Date.now() - startTime, + }); + + if (!session) { + incrementGuestScanCount(); + } + + setAnalysisResult(result); + } + setAnalysisProgress(100); + await Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success); + await new Promise(resolve => setTimeout(resolve, 500)); + setIsAnalyzing(false); + if (isHealthMode && healthPlant) { + Alert.alert(billingCopy.healthDoneTitle, billingCopy.healthDoneMessage, [ + { text: billingCopy.dismiss, onPress: () => router.replace(`/plant/${healthPlant.id}`) }, + ]); + } + } catch (error) { + console.error('Analysis failed', error); + + posthog.capture('llm_generation', { + scan_type: isHealthMode ? 'health_check' : 'identification', + success: false, + error_type: isInsufficientCreditsError(error) ? 'insufficient_credits' : 'provider_error', + latency_ms: Date.now() - startTime, + }); + + if (isInsufficientCreditsError(error)) { + Alert.alert( + billingCopy.noCreditsTitle, + isHealthMode ? billingCopy.healthNoCreditsMessage : billingCopy.noCreditsMessage, + [ + { text: billingCopy.dismiss, style: 'cancel' }, + { + text: billingCopy.managePlan, + onPress: () => router.replace('/(tabs)/profile'), + }, + ], + ); + } else if ( + isBackendApiError(error) && + (error.code === 'PROVIDER_ERROR' || error.code === 'TIMEOUT') + ) { + Alert.alert( + billingCopy.genericErrorTitle, + isHealthMode ? billingCopy.healthProviderErrorMessage : billingCopy.providerErrorMessage, + ); + } else { + Alert.alert(billingCopy.genericErrorTitle, billingCopy.genericErrorMessage); + } + setSelectedImage(null); + setIsAnalyzing(false); + } finally { + clearInterval(progressInterval); + await refreshBillingSummary(); + } + }; + + const takePicture = async () => { + if (!cameraRef.current || isAnalyzing) return; + await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium); + const photo = await cameraRef.current.takePictureAsync({ base64: true, quality: 0.7 }); + if (photo) { + const analysisUri = photo.base64 + ? `data:image/jpeg;base64,${photo.base64}` + : photo.uri; + const galleryUri = photo.uri || analysisUri; + setSelectedImage(analysisUri); + analyzeImage(analysisUri, galleryUri); + } + }; + + const pickImage = async () => { + if (isAnalyzing) return; + + const result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ['images'], + quality: 0.7, + base64: true, + }); + if (!result.canceled && result.assets[0]) { + const asset = result.assets[0]; + const uri = asset.base64 + ? `data:image/jpeg;base64,${asset.base64}` + : asset.uri; + + setSelectedImage(uri); + analyzeImage(uri, asset.uri || uri); + } + }; + + const handleSave = async () => { + if (analysisResult && selectedImage) { + if (!session) { + // Guest mode: store result and go to signup + setPendingPlant(analysisResult, selectedImage); + router.replace('/auth/signup'); + return; + } + + try { + await savePlant(analysisResult, selectedImage); + router.back(); + } catch (error) { + console.error('Saving identified plant failed', error); + Alert.alert(billingCopy.genericErrorTitle, billingCopy.genericErrorMessage); + } + } + }; + + const handleClose = () => { + router.back(); + }; + + const controlsPaddingBottom = Math.max(20, insets.bottom + 10); + const controlsPanelHeight = 28 + 80 + controlsPaddingBottom; + const analysisBottomOffset = controlsPanelHeight + 12; + const scanLineTranslateY = scanLineProgress.interpolate({ + inputRange: [0, 1], + outputRange: [24, 280], + }); + const scanPulseScale = scanPulse.interpolate({ + inputRange: [0, 1], + outputRange: [0.98, 1.02], + }); + const scanPulseOpacity = scanPulse.interpolate({ + inputRange: [0, 1], + outputRange: [0.22, 0.55], + }); + + // Show result + if (!isHealthMode && analysisResult && selectedImage) { + return ( + + ); + } + + // Camera permission + if (!permission?.granted) { + return ( + + + Camera access is required to scan plants. + + Grant Permission + + + Cancel + + + ); + } + + return ( + + {/* Header */} + + + + + + {isHealthMode ? billingCopy.healthTitle : t.scanner} + + + + + {billingCopy.creditsLabel}: {availableCredits} + + + + + {/* Camera */} + + {selectedImage ? ( + + ) : ( + + )} + + {/* Scan Frame */} + + {selectedImage && ( + + )} + {isAnalyzing && ( + <> + + + + )} + + + + + + + + {/* Analyzing Overlay */} + {isAnalyzing && ( + + + + + + {analysisProgress < 100 ? t.analyzing : t.result} + + + + {Math.round(analysisProgress)}% + + + + + + + + + {t.localProcessing} + + + {analysisProgress < 30 ? t.scanStage1 : analysisProgress < 75 ? t.scanStage2 : t.scanStage3} + + + + )} + + {/* Bottom Controls */} + + + + {t.gallery} + + + + + + + + + {t.help} + + + + ); +} + +const styles = StyleSheet.create({ + container: { flex: 1 }, + header: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + zIndex: 10, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingTop: 60, + paddingHorizontal: 24, + }, + headerTitle: { fontSize: 18, fontWeight: '600' }, + creditBadge: { + borderWidth: 1, + borderRadius: 14, + paddingHorizontal: 8, + paddingVertical: 4, + flexDirection: 'row', + alignItems: 'center', + gap: 4, + }, + creditBadgeText: { fontSize: 10, fontWeight: '700' }, + cameraContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, + scanFrame: { + width: 256, + height: 320, + borderWidth: 2.5, + borderColor: '#ffffff50', + borderRadius: 28, + overflow: 'hidden', + }, + scanPulseFrame: { + ...StyleSheet.absoluteFillObject, + borderWidth: 1.5, + borderRadius: 28, + }, + scanLine: { + position: 'absolute', + left: 16, + right: 16, + height: 2, + borderRadius: 999, + shadowColor: '#ffffff', + shadowOffset: { width: 0, height: 0 }, + shadowOpacity: 0.8, + shadowRadius: 8, + elevation: 6, + }, + corner: { position: 'absolute', width: 24, height: 24 }, + tl: { top: 16, left: 16, borderTopWidth: 4, borderLeftWidth: 4, borderTopLeftRadius: 12 }, + tr: { top: 16, right: 16, borderTopWidth: 4, borderRightWidth: 4, borderTopRightRadius: 12 }, + bl: { bottom: 16, left: 16, borderBottomWidth: 4, borderLeftWidth: 4, borderBottomLeftRadius: 12 }, + br: { bottom: 16, right: 16, borderBottomWidth: 4, borderRightWidth: 4, borderBottomRightRadius: 12 }, + controls: { + borderTopLeftRadius: 28, + borderTopRightRadius: 28, + paddingHorizontal: 32, + paddingTop: 28, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + }, + controlBtn: { alignItems: 'center', gap: 6 }, + controlBtnDisabled: { opacity: 0.5 }, + controlLabel: { fontSize: 11, fontWeight: '500' }, + shutterBtn: { + width: 80, + height: 80, + borderRadius: 40, + borderWidth: 4, + justifyContent: 'center', + alignItems: 'center', + shadowColor: '#000', + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.2, + shadowRadius: 8, + elevation: 8, + }, + shutterInner: { width: 64, height: 64, borderRadius: 32 }, + shutterBtnDisabled: { opacity: 0.6 }, + analysisSheet: { + position: 'absolute', + left: 16, + right: 16, + borderRadius: 20, + borderWidth: 1, + paddingHorizontal: 16, + paddingVertical: 14, + zIndex: 20, + shadowColor: '#000', + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.28, + shadowRadius: 14, + elevation: 14, + }, + analysisHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }, + analysisBadge: { + flexDirection: 'row', + alignItems: 'center', + gap: 6, + borderRadius: 999, + paddingHorizontal: 10, + paddingVertical: 5, + }, + analysisLabel: { fontWeight: '700', fontSize: 12, letterSpacing: 0.2 }, + analysisPercent: { fontFamily: 'monospace', fontSize: 12, fontWeight: '700' }, + progressBg: { height: 9, borderRadius: 999, overflow: 'hidden', marginBottom: 10 }, + progressFill: { height: '100%', borderRadius: 4 }, + analysisFooter: { gap: 4 }, + analysisStatusRow: { flexDirection: 'row', alignItems: 'center', gap: 6 }, + statusDot: { width: 8, height: 8, borderRadius: 4 }, + analysisStage: { fontSize: 10, fontWeight: '700', textTransform: 'uppercase', letterSpacing: 1 }, + analysisStageDetail: { fontSize: 11, lineHeight: 16, fontWeight: '500' }, + permissionContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 32 }, + permissionText: { fontSize: 16, textAlign: 'center', marginBottom: 20 }, + permissionBtn: { paddingHorizontal: 24, paddingVertical: 12, borderRadius: 12 }, + permissionBtnText: { fontWeight: '700', fontSize: 15 }, +}); diff --git a/assets/Make_some_light_leaf_animations_delpmaspu_.mp4 b/assets/Make_some_light_leaf_animations_delpmaspu_.mp4 new file mode 100644 index 0000000..7fea2c2 Binary files /dev/null and b/assets/Make_some_light_leaf_animations_delpmaspu_.mp4 differ diff --git a/assets/adaptive-icon.png b/assets/adaptive-icon.png new file mode 100644 index 0000000..c82817e Binary files /dev/null and b/assets/adaptive-icon.png differ diff --git a/assets/adaptive-icon.png.bak b/assets/adaptive-icon.png.bak new file mode 100644 index 0000000..79126aa Binary files /dev/null and b/assets/adaptive-icon.png.bak differ diff --git a/assets/credits_topup.png b/assets/credits_topup.png new file mode 100644 index 0000000..4e0b1b9 Binary files /dev/null and b/assets/credits_topup.png differ diff --git a/assets/favicon.png b/assets/favicon.png new file mode 100644 index 0000000..07d5851 Binary files /dev/null and b/assets/favicon.png differ diff --git a/assets/icon.png b/assets/icon.png new file mode 100644 index 0000000..b25ca78 Binary files /dev/null and b/assets/icon.png differ diff --git a/assets/icon.png.bak b/assets/icon.png.bak new file mode 100644 index 0000000..79126aa Binary files /dev/null and b/assets/icon.png.bak differ diff --git a/assets/new_splash_icon.png b/assets/new_splash_icon.png new file mode 100644 index 0000000..2aafc48 Binary files /dev/null and b/assets/new_splash_icon.png differ diff --git a/assets/splash-icon.png b/assets/splash-icon.png new file mode 100644 index 0000000..2aafc48 Binary files /dev/null and b/assets/splash-icon.png differ diff --git a/assets/splash-icon.png.bak b/assets/splash-icon.png.bak new file mode 100644 index 0000000..79126aa Binary files /dev/null and b/assets/splash-icon.png.bak differ diff --git a/assets/splash-icon.png.old b/assets/splash-icon.png.old new file mode 100644 index 0000000..c82817e Binary files /dev/null and b/assets/splash-icon.png.old differ diff --git a/assets/subscription_monthly_499.png b/assets/subscription_monthly_499.png new file mode 100644 index 0000000..3e67c00 Binary files /dev/null and b/assets/subscription_monthly_499.png differ diff --git a/assets/subscription_yearly_3999.png b/assets/subscription_yearly_3999.png new file mode 100644 index 0000000..535ccb3 Binary files /dev/null and b/assets/subscription_yearly_3999.png differ diff --git a/assets/transparent.png b/assets/transparent.png new file mode 100644 index 0000000..91a99b9 Binary files /dev/null and b/assets/transparent.png differ diff --git a/audits/semantic-search/README.md b/audits/semantic-search/README.md new file mode 100644 index 0000000..7f8e5eb --- /dev/null +++ b/audits/semantic-search/README.md @@ -0,0 +1,32 @@ +# Semantic Search Audit + +Generated: 2026-03-12T14:15:29.567Z + +Files: +- `summary.json`: category counts and suggested audit order +- `all-plants-categories.csv`: one row per plant with its full category list +- `master.csv`: all category assignments with blank evidence columns +- `suspicious.csv`: entries that require elevated review based on rule flags +- `categories/*.csv`: per-category audit sheets + +Suggested audit order: +- pet_friendly (15) +- air_purifier (12) +- medicinal (32) +- low_light (16) +- bright_light (42) +- sun (172) +- easy (132) +- high_humidity (51) +- hanging (34) +- tree (59) +- large (35) +- patterned (31) +- flowering (157) +- succulent (46) + +Workflow: +1. Review one category CSV at a time. +2. Fill `audit_status`, `evidence_source`, `evidence_url`, and `notes`. +3. Apply only high-confidence source-tag corrections to the lexicon batch files. +4. Rebuild the server catalog from batches after source edits. diff --git a/audits/semantic-search/all-plants-categories.csv b/audits/semantic-search/all-plants-categories.csv new file mode 100644 index 0000000..c3b6ba8 --- /dev/null +++ b/audits/semantic-search/all-plants-categories.csv @@ -0,0 +1,359 @@ +source_file,source_index,name,botanical_name,all_categories,category_count,description,light,temp,water_interval_days +constants/lexiconBatch2.ts,115,Faecherahorn,Acer palmatum,tree,1,"Der Faecherahorn ist ein japanischer Zierahorn mit feingeschnittenen, faecherfoermigen Blaettern in Gruen oder Rot.",Helles bis volles Licht,10-22 °C,5 +constants/lexiconBatch2.ts,212,Spitzahorn,Acer platanoides,tree|large|sun,3,Spitzahorn ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,108,Schafgarbe,Achillea millefolium,flowering|medicinal|sun,3,Die Schafgarbe hat weisse oder rosafarbene Bluetenschirme und fein gefiederte Blaetter. Wichtige Heilpflanze.,Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch1.ts,86,Wuestenrose,Adenium obesum,flowering|succulent|sun,3,Die Wuestenrose ist eine sukkulente Zimmerpflanze mit dickem Stamm und leuchtend pinken Blueten.,Volles Sonnenlicht,20-35 °C,10 +constants/lexiconBatch2.ts,117,Socotra-Wuestenrose,Adenium socotranum,flowering|succulent|sun,3,"Die Socotra-Wuestenrose ist eine seltene, endemische Art mit einem sehr dicken, knolligen Stamm und rosa Blueten.",Volles Sonnenlicht,20-35 °C,14 +constants/lexiconBatch2.ts,42,Frauenhaarfarn,Adiantum raddianum,high_humidity,1,"Der Frauenhaarfarn hat zarte, feingliedrige Wedel auf schwarzen, draht­aehnlichen Stielen. Liebt Feuchtigkeit.",Helles indirektes Licht,18-27 °C,3 +constants/lexiconBatch2.ts,31,Adromischus,Adromischus cristatus,easy|succulent|sun,3,Adromischus ist eine kompakte Sukkulente mit ungewoehnlich wellenrandigen Blaettern auf kurzen Staengeln.,Helles bis volles Licht,15-25 °C,14 +constants/lexiconBatch2.ts,34,Silbervase,Aechmea fasciata,flowering|patterned,2,Die Silbervase ist eine Bromelie mit silbrig gebänderten Blaettern und einem rosafarbenen Bluetenstand.,Helles indirektes Licht,18-25 °C,10 +constants/lexiconBatch1.ts,10,Schwarze Rose (Aeonium),Aeonium arboreum,succulent|sun,2,"Das Aeonium bildet dekorative, rosettenfoermige Sukkulenten an verzweigten Stielen.",Volles Sonnenlicht,10-25 °C,10 +constants/lexiconBatch1.ts,98,Lippenstiftpflanze,Aeschynanthus radicans,flowering|hanging|high_humidity,3,Die Lippenstiftpflanze hat haengende Triebe mit glaenzenden Blaettern und leuchtend roten Roehrenbluten.,Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,11,Agave,Agave americana,succulent|large|sun,3,"Die Agave ist eine imposante Sukkulente mit steifen, blaugruenen Blaettern mit Stacheln. Sie bluet nur einmal.",Volles Sonnenlicht,10-35 °C,21 +constants/lexiconBatch1.ts,50,Aglaoneme,Aglaonema commutatum,easy|patterned|low_light,3,Die Aglaoneme ist eine dekorative Zimmerpflanze mit silbrig-gruen gemusterten Blaettern. Tolerant gegenueber wenig Licht.,Wenig bis helles Licht,15-26 °C,7 +constants/lexiconBatch2.ts,155,Stockrose,Alcea rosea,flowering|sun,2,"Stockrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,30,Schnittlauch,Allium schoenoprasum,easy,1,Schnittlauch ist ein beliebtes Kuechenkraut mit roehrenfoermigen Blaettern und lila Blueten.,Helles bis volles Licht,10-25 °C,3 +constants/lexiconBatch2.ts,135,Schnittknoblauch,Allium tuberosum,easy|sun,2,Schnittknoblauch ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch1.ts,46,Amazona-Taro,Alocasia amazonica,patterned|large|high_humidity,3,"Der Amazona-Taro besticht mit dunkelgruenen, pfeilfoermigen Blaettern mit markant weissen Rippen.",Indirektes Licht,18-27 °C,5 +constants/lexiconBatch2.ts,225,Alocasia zebrina,Alocasia zebrina,bright_light|high_humidity,2,Alocasia zebrina ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5 +constants/lexiconBatch1.ts,89,Kap-Aloe,Aloe arborescens,easy|succulent|medicinal|sun,4,"Die Kap-Aloe ist eine strauchige Aloe mit schmalen, gezaehnten Blaettern und leuchtend roten Bluetenaehren im Winter.",Volles Sonnenlicht,10-30 °C,14 +constants/lexiconBatch2.ts,18,Kap-Aloe (ferox),Aloe ferox,succulent|large|medicinal|sun,4,"Aloe ferox ist eine grosse, imposante Aloe mit stachligen, blaugruenen Blaettern und leuchtend roten Bluetenaehren.",Volles Sonnenlicht,10-30 °C,14 +constants/lexiconBatch2.ts,128,Zitronenverbene,Aloysia citrodora,easy|sun,2,Zitronenverbene ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,73,Muschelingwer,Alpinia zerumbet,flowering|large|high_humidity,3,"Der Muschelingwer hat lange, elegante Blaetter und haengende Bluetenrispen mit weiss-rosa Bluetchen.",Helles bis volles Licht,20-30 °C,5 +constants/lexiconBatch2.ts,194,Fuchsschwanz,Amaranthus caudatus,flowering|sun,2,"Fuchsschwanz ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,163,Anemone,Anemone coronaria,flowering|sun,2,"Anemone ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,140,Dill,Anethum graveolens,easy|sun,2,Dill ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,125,Kerbel,Anthriscus cerefolium,easy|sun,2,Kerbel ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,233,Samt-Anthurie,Anthurium clarinervium,patterned|high_humidity,2,Samt-Anthurie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5 +constants/lexiconBatch2.ts,234,Kristall-Anthurie,Anthurium crystallinum,patterned|high_humidity,2,Kristall-Anthurie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5 +constants/lexiconBatch2.ts,147,Loewenmaeulchen,Antirrhinum majus,flowering|sun,2,"Loewenmaeulchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,232,Norfolk-Tanne,Araucaria heterophylla,tree|bright_light,2,Norfolk-Tanne ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch2.ts,107,Arnika,Arnica montana,flowering|medicinal|sun,3,Arnika ist eine bekannte Heilpflanze aus den Alpen mit goldgelben Korbbluten. Sie wird fuer Muskeln und Gelenke verwendet.,Volles Sonnenlicht,10-20 °C,7 +constants/lexiconBatch2.ts,110,Wermut,Artemisia absinthium,medicinal|sun,2,"Wermut ist ein stark aromatisches Heilkraut mit silbrig-gruenen, tief eingeschnittenen Blaettern. Fuer Kraeuterlikoere.",Volles Sonnenlicht,10-25 °C,14 +constants/lexiconBatch2.ts,122,Estragon,Artemisia dracunculus,easy|sun,2,Estragon ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,178,Seidenpflanze,Asclepias tuberosa,flowering|sun,2,"Seidenpflanze ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,16,Schusterpflanze,Aspidistra elatior,easy|low_light,2,"Die Schusterpflanze ist eine extrem robuste Zimmerpflanze mit langen, dunkelgruenen Blaettern. Vertraegt tiefe Temperaturen.",Wenig bis helles Licht,10-20 °C,14 +constants/lexiconBatch2.ts,43,Vogelnest-Farn,Asplenium nidus,easy|low_light|high_humidity,3,"Der Vogelnest-Farn hat ganzrandige, glaenzende Wedel, die eine Nestform bilden. Sehr dekorativ und robust.",Helles indirektes Licht,18-27 °C,5 +constants/lexiconBatch2.ts,13,Japanische Aucube,Aucuba japonica,easy|low_light,2,"Die Japanische Aucube hat glaenzende, gruene oder gelbgefleckte Blaetter. Sehr schattenvertraeglich.",Wenig bis helles Licht,10-20 °C,7 +constants/lexiconBatch1.ts,92,Indische Azalee,Azalea indica,flowering,1,"Die Indische Azalee ist ein beliebter Zierstrauch mit grossen, auffaelligen Blueten in Rosa- und Rottönen.",Helles indirektes Licht,10-20 °C,4 +constants/lexiconBatch2.ts,7,Bambusrohr,Bambusa vulgaris,easy|large,2,Das Bambusrohr ist eine schnell wachsende Bambusart mit gelbgruenen Halmen. Sehr dekorativ und vielseitig nutzbar.,Helles bis volles Licht,15-30 °C,5 +constants/lexiconBatch1.ts,41,Pferdeschwanzpalme,Beaucarnea recurvata,easy|succulent|tree|sun,4,"Die Pferdeschwanzpalme hat einen verdickten Stammbasis als Wasserspeicher und lange, schmale Blaetter.",Volles Sonnenlicht,15-30 °C,21 +constants/lexiconBatch2.ts,57,Forellen-Begonie,Begonia maculata,patterned|high_humidity,2,Die Forellen-Begonie hat olivgruene Blaetter mit silbernen Punkten und einer roten Unterseite. Atemberaubend.,Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,18,Koenigsbegonie,Begonia rex,patterned|high_humidity,2,"Die Koenigsbegonie beeindruckt mit prachtvoll gemusterten Blaettern in Silber, Rot und Gruen.",Indirektes Licht,18-25 °C,5 +constants/lexiconBatch2.ts,175,Eisbegonie,Begonia semperflorens-cultorum,flowering|bright_light,2,"Eisbegonie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,58,Knollen-Begonie,Begonia tuberhybrida,flowering|high_humidity,2,"Die Knollen-Begonie hat riesige, rosenaehnliche Blueten in leuchtendem Rot, Orange, Gelb oder Weiss.",Helles indirektes Licht,15-22 °C,5 +constants/lexiconBatch2.ts,145,Gaensebluemchen,Bellis perennis,flowering|sun,2,"Gaensebluemchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,97,Mangold,Beta vulgaris,easy,1,"Mangold ist ein farbenfrohes Blattgemuese mit bunten Stielen in Rot, Gelb, Orange und Weiss.",Helles bis volles Licht,10-25 °C,3 +constants/lexiconBatch2.ts,114,Hange-Birke,Betula pendula,tree|large|medicinal,3,Die Haenge-Birke hat charakteristisch weisse Rinde und haengende Zweige. Die Blaetter werden in der Heilkunde genutzt.,Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch2.ts,38,Billbergia,Billbergia nutans,easy|flowering,2,"Die Billbergia ist eine robuste Bromelie mit schmalen, gruenen Blaettern und hängenden, blauen und gruenen Blueten.",Helles indirektes Licht,15-25 °C,7 +constants/lexiconBatch2.ts,129,Borretsch,Borago officinalis,easy|sun,2,Borretsch ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch1.ts,62,Bougainvillea,Bougainvillea spectabilis,flowering|bright_light|sun,3,"Die Bougainvillea ist eine rankenreiche Kletterpflanze mit leuchtend farbigen Hochblaettern in Rot, Orange oder Pink.",Volles Sonnenlicht,18-30 °C,5 +constants/lexiconBatch2.ts,223,Schmetterlingsflieder,Buddleja davidii,flowering|tree|sun,3,Schmetterlingsflieder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,202,Buchsbaum,Buxus sempervirens,tree|sun,2,Buchsbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch1.ts,49,Buntblatt,Caladium bicolor,patterned|high_humidity,2,"Das Buntblatt beeindruckt mit transparenten, bunt gemusterten Blaettern in Pink, Rot, Weiss und Gruen.",Indirektes Licht,20-30 °C,5 +constants/lexiconBatch2.ts,187,Ringelblume,Calendula officinalis,flowering|medicinal|sun,3,"Ringelblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,63,Calibrachoa,Calibrachoa hybrida,easy|flowering|hanging|sun,4,"Calibrachoa ist eine petunienaehnliche Haengepflanze mit unzaehligen, kleinen Trichterbluten in allen Farben.",Volles Sonnenlicht,15-25 °C,2 +constants/lexiconBatch2.ts,56,Callisia,Callisia repens,easy|hanging,2,"Callisia repens ist ein kleines, kriechendes Kraut mit winzigen, gruenen Blaettern. Ideal fuer haengende Behaelter.",Helles indirektes Licht,15-25 °C,5 +constants/lexiconBatch1.ts,93,Kamelie,Camellia japonica,flowering,1,Die Kamelie ist ein eleganter Zierstrauch mit glaenzenden Blaettern und rosenaehnlichen Blueten von Januar bis April.,Helles indirektes Licht,7-18 °C,5 +constants/lexiconBatch2.ts,85,Teestrauch,Camellia sinensis,flowering,1,"Der Teestrauch ist die Pflanze, aus deren Blaettern Tee gewonnen wird. Er hat weisse Blueten und glaenzende Blaetter.",Helles indirektes Licht,15-22 °C,7 +constants/lexiconBatch2.ts,184,Trompetenwinde,Campsis radicans,flowering|bright_light,2,"Trompetenwinde ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,67,Blumenschilfrohr,Canna indica,flowering|large|sun,3,"Das Blumenschilfrohr hat grosse, tropisch wirkende Blaetter und auffaellige Blueten in Rot, Orange oder Gelb.",Volles Sonnenlicht,18-28 °C,5 +constants/lexiconBatch2.ts,92,Chili,Capsicum annuum,easy|medicinal|sun,3,"Chili ist eine beliebte Gemuese- und Zierpflanze mit leuchtenden, roten oder orangen Fruechten. Im Topf kultivierbar.",Volles Sonnenlicht,20-30 °C,4 +constants/lexiconBatch2.ts,90,Papaya,Carica papaya,large|sun,2,"Die Papaya ist eine tropische Fruchtpflanze mit grossen, gelappten Blaettern und orangen Fruechten.",Volles Sonnenlicht,20-35 °C,5 +constants/lexiconBatch2.ts,217,Trompetenbaum,Catalpa bignonioides,tree|large|sun,3,Trompetenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch1.ts,73,Cattleya-Orchidee,Cattleya labiata,flowering|high_humidity,2,"Die Cattleya ist die Koenigin der Orchideen mit ueppigen, duftenden Blueten in Lila, Rosa und Weiss.",Helles indirektes Licht,18-28 °C,7 +constants/lexiconBatch2.ts,208,Zeder,Cedrus libani,tree|large|sun,3,Zeder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,188,Kornblume,Centaurea cyanus,flowering|sun,2,"Kornblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,81,Peruanischer Fackelkaktus,Cereus peruvianus,easy|succulent|large|sun,4,"Der Peruanische Fackelkaktus ist ein saeulenfoermiger Kaktus, der im Innenraum bis zu 2 m hoch werden kann.",Volles Sonnenlicht,15-35 °C,21 +constants/lexiconBatch1.ts,99,Herzkette,Ceropegia woodii,easy|succulent|patterned|hanging,4,"Die Herzkette hat duenne, haengende Ranken mit herzfoermigen, silbergrau gemusterten Blaettchen.",Helles indirektes Licht,15-27 °C,14 +constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,easy|pet_friendly|tree|air_purifier|low_light,5,Die Bergpalme ist eine kompakte Zimmerpalme fuer schattigere Standorte. Ideal fuer dunkle Innenraeume.,Wenig bis helles Licht,15-25 °C,7 +constants/lexiconBatch2.ts,138,Roemische Kamille,Chamaemelum nobile,easy|medicinal|sun,3,Roemische Kamille ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,101,Kamille,Chamomilla recutita,easy|medicinal|sun,3,"Die Kamille ist ein beliebtes Heilkraut mit kleinen, weiss-gelben Blueten. Das aetherische Oel wirkt beruhigend.",Volles Sonnenlicht,15-25 °C,5 +constants/lexiconBatch1.ts,67,Chrysantheme,Chrysanthemum indicum,flowering,1,"Die Chrysantheme ist die klassische Herbstblume mit ueppigen, dichten Blueten in vielen Farben.",Helles bis volles Licht,12-22 °C,4 +constants/lexiconBatch2.ts,86,Zitronenbaum,Citrus limon,tree|sun,2,"Der Zitronenbaum ist ein kleiner, immergruener Baum mit weissen, duftenden Blueten und gelben Fruechten.",Volles Sonnenlicht,18-28 °C,5 +constants/lexiconBatch2.ts,87,Orangenbaum,Citrus sinensis,tree|sun,2,"Der Orangenbaum ist ein kleiner, immergruener Baum mit weissen Blueten und orangen Fruechten.",Volles Sonnenlicht,18-28 °C,5 +constants/lexiconBatch2.ts,157,Clematis,Clematis viticella,flowering|bright_light,2,"Clematis ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,104,Riemenblatt,Clivia miniata,flowering,1,Das Riemenblatt ist eine dekorative Zimmerpflanze mit leuchtend orangefarbenen Blueten im Fruehling.,Helles indirektes Licht,15-24 °C,10 +constants/lexiconBatch2.ts,224,Kroton,Codiaeum variegatum,patterned|bright_light,2,Kroton ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch2.ts,84,Kaffeestrauch,Coffea arabica,easy,1,"Der Kaffeestrauch hat glaenzende, dunkelgruene Blaetter und entwickelt rote Kaffe­ekirschen. Kann im Topf gehalten werden.",Helles indirektes Licht,18-25 °C,7 +constants/lexiconBatch2.ts,245,Kaffeepflanze arabica nana,Coffea arabica Nana,bright_light,1,Kaffeepflanze arabica nana ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch1.ts,47,Taro,Colocasia esculenta,large|high_humidity,2,"Der Taro ist eine tropische Pflanze mit grossen, herzfoermigen Blaettern. Die Knollen sind Nahrungsquelle.",Helles indirektes Licht,18-30 °C,3 +constants/lexiconBatch1.ts,97,Columnea,Columnea gloriosa,flowering|hanging|high_humidity,3,"Die Columnea ist eine haengende Zimmerpflanze mit kleinen, behaarten Blaettern und leuchtend roten, roehrenfoermigen Blueten.",Helles indirektes Licht,18-25 °C,7 +constants/lexiconBatch2.ts,24,Konophytum,Conophytum calculus,succulent|sun,2,"Das Konophytum ist eine sehr kompakte Sukkulente, die zwei Blaetter zu einer kugelfoermigen Form verschmilzt.",Volles Sonnenlicht,10-25 °C,21 +constants/lexiconBatch2.ts,160,Maigloeckchen,Convallaria majalis,flowering|medicinal,2,"Maigloeckchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,14,Keulenlilie,Cordyline australis,easy|tree|sun,3,"Die Keulenlilie hat lange, schmale, gruene oder rotbraune Blaetter in einem dekorativen Schopf.",Helles bis volles Licht,10-25 °C,7 +constants/lexiconBatch2.ts,15,Tiroler Keulenlilie,Cordyline fruticosa,easy,1,"Die Tiroler Keulenlilie hat leuchtend rote, gruene oder buntlaubige Blaetter. Eine exotische Zimmerpflanze.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,181,Maedchenauge,Coreopsis tinctoria,flowering|sun,2,"Maedchenauge ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,139,Koriander,Coriandrum sativum,easy|sun,2,Koriander ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,150,Kosmee,Cosmos bipinnatus,flowering|sun,2,"Kosmee ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,29,Kotyledon,Cotyledon orbiculata,easy|succulent|sun,3,"Kotyledon hat dickfleischige, runde Blaetter mit einem mehligen, weisslichen Belag. Sehr trockenheitsresistent.",Helles bis volles Licht,15-25 °C,14 +constants/lexiconBatch2.ts,26,Moos-Crassula,Crassula muscosa,easy|succulent|sun,3,"Die Moos-Crassula hat dicht aneinandergereihte, winzige gruene Blaetter auf unverzweigten Trieben. Sieht aus wie Moos.",Helles bis volles Licht,15-25 °C,14 +constants/lexiconBatch1.ts,5,Jadepflanze,Crassula ovata,easy|succulent|sun,3,"Die Jadepflanze ist eine langlebige Sukkulente mit dicken, ovalen Blaettern. In Japan gilt sie als Gluecksbringer.",Helles bis volles Licht,15-24 °C,14 +constants/lexiconBatch1.ts,110,Krokus,Crocus vernus,easy|flowering,2,"Der Krokus ist einer der ersten Fruehjahrs­boten mit kelchfoermigen Blueten in Lila, Weiss und Gelb.",Helles bis volles Licht,5-15 °C,7 +constants/lexiconBatch2.ts,39,Cryptanthus,Cryptanthus bivittatus,patterned|high_humidity,2,Cryptanthus ist eine niedrig wachsende Bromelie mit sternfoermigen Rosetten und gemusterten Blaettern. Fuer Terrarien.,Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,53,Ctenanthe,Ctenanthe burle-marxii,patterned|high_humidity,2,Die Ctenanthe hat faszinierend gemusterte Blaetter mit dunkelgruunem Fischgraetenmuster auf hellgruunem Hintergrund.,Indirektes Licht,18-25 °C,5 +constants/lexiconBatch2.ts,94,Gurke,Cucumis sativus,easy|sun,2,"Die Gurke ist eine rankende Gemuese­pflanze mit gruenen, erfrischenden Fruechten. Im Balkonkasten kultivierbar.",Volles Sonnenlicht,18-28 °C,3 +constants/lexiconBatch2.ts,209,Zypresse,Cupressus sempervirens,tree|large|sun,3,Zypresse ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,74,Kurkuma,Curcuma longa,medicinal|high_humidity,2,Kurkuma ist eine tropische Gewuerzpflanze mit breiten Blaettern und leuchtend gelber Wurzel. Wichtiges Heilgewuerz.,Helles bis volles Licht,20-30 °C,7 +constants/lexiconBatch2.ts,236,String of Bananas,Curio radicans,succulent|hanging|sun,3,String of Bananas ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10 +constants/lexiconBatch2.ts,237,String of Dolphins,Curio x peregrinus,succulent|hanging|sun,3,String of Dolphins ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10 +constants/lexiconBatch2.ts,239,Palmfarn,Cycas revoluta,tree|large|sun,3,Palmfarn ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10 +constants/lexiconBatch1.ts,19,Alpenveilchen,Cyclamen persicum,flowering,1,"Das Alpenveilchen bluet im Herbst und Winter mit eleganten Blueten in Rosa, Rot oder Weiss.",Helles indirektes Licht,12-18 °C,5 +constants/lexiconBatch1.ts,71,Zymbidium,Cymbidium lowianum,flowering,1,"Das Zymbidium ist eine robuste Orchidee mit langen, grassartigen Blaettern und eleganten Bluetenrispen.",Helles Licht,12-24 °C,7 +constants/lexiconBatch2.ts,127,Zitronengras,Cymbopogon citratus,easy|sun,2,Zitronengras ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,9,Paragraphenpflanze,Cyperus alternifolius,high_humidity,1,"Die Paragraphenpflanze hat lange, grasartige Blaetter, die sternfoermig vom Stiel abstehen. Sie liebt viel Wasser.",Helles bis volles Licht,18-27 °C,3 +constants/lexiconBatch2.ts,68,Dahlie,Dahlia pinnata,flowering|sun,2,Die Dahlie ist eine prachtvolle Sommerblume mit Blueten in allen Groessen und Formen. Sie wird aus Knollen gezogen.,Volles Sonnenlicht,15-25 °C,5 +constants/lexiconBatch2.ts,99,Karotte,Daucus carota,easy,1,Die Karotte ist eine beliebte Gemuese­pflanze mit orangefarbenen Wurzeln. Im tiefen Topf kultivierbar.,Helles bis volles Licht,15-22 °C,5 +constants/lexiconBatch2.ts,215,Flammenbaum,Delonix regia,flowering|tree|large,3,Flammenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,153,Rittersporn,Delphinium elatum,flowering|sun,2,"Rittersporn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,70,Dendrobium,Dendrobium nobile,flowering|high_humidity,2,"Das Dendrobium ist eine beliebte Zimmerorchidee mit langen Pseudobulben, die im Winter mit Blueten besetzt werden.",Helles indirektes Licht,15-28 °C,10 +constants/lexiconBatch2.ts,189,Bartnelke,Dianthus barbatus,flowering|sun,2,"Bartnelke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,146,Nelke,Dianthus caryophyllus,flowering|sun,2,"Nelke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,48,Dieffenbachie,Dieffenbachia seguine,easy|air_purifier|low_light,3,"Die Dieffenbachie ist eine tropische Blattschmuckpflanze mit grossen, gruen-weiss gefleckten Blaettern.",Helles indirektes Licht,18-26 °C,7 +constants/lexiconBatch2.ts,109,Roter Fingerhut,Digitalis purpurea,flowering|medicinal,2,"Der Rote Fingerhut hat hohe Bluetenstaende mit roehrenfoermigen, gepunkteten Blueten in Rosa. Wichtige Arzneipflanze.",Helles bis volles Licht,10-20 °C,7 +constants/lexiconBatch2.ts,77,Venusfliegenfalle,Dionaea muscipula,sun,1,Die Venusfliegenfalle ist eine fleischfressende Pflanze mit klappfallartigen Blaettern. Faengt Insekten.,Volles Sonnenlicht,15-30 °C,5 +constants/lexiconBatch1.ts,101,Dischidia,Dischidia ruscifolia,succulent|hanging,2,"Die Dischidia ist eine epiphytische Haengepflanze mit kleinen, runden Blaettern entlang duenner Ranken.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,14,Maisstrauch,Dracaena fragrans,easy|tree|air_purifier|low_light,4,"Der Maisstrauch ist eine robuste Zimmerpflanze mit breiten, gestreiften Blaettern. Gedeiht auch bei wenig Licht.",Helles indirektes Licht,15-25 °C,10 +constants/lexiconBatch1.ts,13,Drachenbaum,Dracaena marginata,easy|tree|air_purifier,3,"Der Drachenbaum ist eine schlanke Zimmerpflanze mit roten, schmalen Blaettern auf langen Staemmen.",Helles indirektes Licht,15-25 °C,10 +constants/lexiconBatch2.ts,80,Sonnentau,Drosera capensis,high_humidity|sun,2,Der Sonnentau faengt Insekten mit klebrigen Tropfen auf seinen Blaettern. Eine faszinierende fleischfressende Pflanze.,Volles Sonnenlicht,15-25 °C,5 +constants/lexiconBatch2.ts,30,Dudleya,Dudleya brittonii,easy|succulent|sun,3,"Dudleya ist eine rosetten­bildende Sukkulente mit silbrig-weissen, mehligen Blaettern. Sehr elegant.",Volles Sonnenlicht,10-25 °C,14 +constants/lexiconBatch1.ts,42,Goldfruchtpalme,Dypsis lutescens,pet_friendly|tree|air_purifier,3,Die Goldfruchtpalme ist eine elegante Zimmerpalme mit gelblich-gruenen Stielen und gefiederten Wedeln.,Helles indirektes Licht,18-27 °C,5 +constants/lexiconBatch1.ts,4,Echeverie,Echeveria elegans,easy|succulent|sun,3,"Die Echeverie bildet symmetrische, rosettenfoermige Sukkulenten mit blaugruenen Blaettern. Pflegeleicht.",Volles Sonnenlicht,15-25 °C,14 +constants/lexiconBatch2.ts,106,Sonnenhut,Echinacea purpurea,flowering|medicinal|sun,3,"Der Sonnenhut ist eine beliebte Heilpflanze mit grossen, pinkfarbenen Blueten. Er staerkt das Immunsystem.",Helles bis volles Licht,15-25 °C,7 +constants/lexiconBatch1.ts,77,Goldene Tonne,Echinocactus grusonii,easy|succulent|sun,3,Die Goldene Tonne ist ein ikonischer kugelfoermiger Kaktus mit goldgelben Stacheln. Waechst langsam aber imposant.,Volles Sonnenlicht,15-35 °C,21 +constants/lexiconBatch1.ts,83,San-Pedro-Kaktus,Echinopsis pachanoi,easy|succulent|sun,3,"Der San-Pedro-Kaktus ist ein schnell wachsender, saeulenfoermiger Kaktus aus den Anden.",Volles Sonnenlicht,10-35 °C,14 +constants/lexiconBatch1.ts,84,Koenigin der Nacht,Epiphyllum oxypetalum,flowering|succulent,2,"Die Koenigin der Nacht bluet nur eine einzige Nacht lang mit riesigen, intensiv duftenden weissen Blueten.",Indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,16,Marmor-Efeutute,Epipremnum aureum Marble Queen,easy|hanging|air_purifier,3,Die Marmor-Efeutute hat cremeweiss-gruen marmorierte Blaetter. Eine dekorative Variante der klassischen Efeutute.,Helles indirektes Licht,15-30 °C,7 +constants/lexiconBatch2.ts,53,Neon-Efeutute,Epipremnum pinnatum Neon,easy|hanging|air_purifier,3,Die Neon-Efeutute hat leuchtend limonengruene Blaetter. Sehr auffaellig und pflegeleicht.,Helles indirektes Licht,15-30 °C,7 +constants/lexiconBatch2.ts,186,Kalifornischer Mohn,Eschscholzia californica,flowering|sun,2,"Kalifornischer Mohn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,210,Eukalyptus,Eucalyptus globulus,tree|medicinal|sun,3,Eukalyptus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,19,Christusdorn,Euphorbia milii,easy|flowering|succulent|sun,4,Der Christusdorn ist eine sukkulente Wolfsmilch mit stacheligen Zweigen und kleinen roten oder gelben Hochblaettern.,Helles bis volles Licht,15-28 °C,10 +constants/lexiconBatch2.ts,20,Weihnachtsstern,Euphorbia pulcherrima,flowering,1,Der Weihnachtsstern ist die klassische Winterpflanze mit leuchtend roten Hochblaettern. Er steht symbolisch fuer Weihnachten.,Helles indirektes Licht,15-22 °C,7 +constants/lexiconBatch1.ts,12,Bleistiftkaktus,Euphorbia tirucalli,easy|succulent|sun,3,"Der Bleistiftkaktus ist eine sukkulente Wolfsmilch mit duennen, zylindrischen Zweigen ohne Blaetter.",Volles Sonnenlicht,18-30 °C,14 +constants/lexiconBatch2.ts,137,Wasabi,Eutrema japonicum,bright_light|high_humidity,2,"Wasabi ist ein seltenes Wuerzkraut, das gleichmaessige Feuchte und eher kuehle Bedingungen bevorzugt.",Helles indirektes Licht,8-20 C,4 +constants/lexiconBatch2.ts,12,Fatsia,Fatsia japonica,easy|low_light,2,"Die Fatsia ist ein dekorativer Zimmerstrauch mit grossen, handfoermigen, glaenzenden Blaettern. Sehr robust.",Helles indirektes Licht,10-20 °C,7 +constants/lexiconBatch1.ts,78,Fass-Kaktus,Ferocactus cylindraceus,easy|succulent|sun,3,"Der Fass-Kaktus ist ein zylindrischer Wuestenkaktus mit langen, roten Stacheln. Sehr langlebig.",Volles Sonnenlicht,15-35 °C,21 +constants/lexiconBatch2.ts,248,Ficus altissima,Ficus altissima,tree|bright_light,2,Ficus altissima ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch1.ts,1,Birkenfeige,Ficus benjamina,tree|air_purifier,2,"Die Birkenfeige ist ein eleganter Zimmerstrauch mit haengenden Aesten und kleinen, glaenzenden Blaettern.",Helles indirektes Licht,16-24 °C,7 +constants/lexiconBatch1.ts,38,Gummibaum,Ficus elastica,easy|tree|air_purifier,3,"Der Gummibaum ist eine imposante Zimmerpflanze mit grossen, glaenzenden, lederartigen Blaettern. Reinigt die Luft.",Helles indirektes Licht,16-24 °C,10 +constants/lexiconBatch1.ts,39,Geigenfeige,Ficus lyrata,tree|large|bright_light,3,"Die Geigenfeige ist ein Trendbaum mit grossen, geigenfoermigen Blaettern. Benoetigt viel Licht.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,247,Ficus microcarpa,Ficus microcarpa,easy|tree|bright_light,3,Ficus microcarpa ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch2.ts,116,Bonsai-Feige,Ficus retusa,tree,1,"Die Bonsai-Feige ist eine klassische Bonsai-Art mit kleinen, elliptischen Blaettern. Sehr formbar.",Helles indirektes Licht,16-24 °C,7 +constants/lexiconBatch2.ts,226,Nervenpflanze,Fittonia albivenis,patterned|high_humidity,2,Nervenpflanze ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5 +constants/lexiconBatch2.ts,219,Forsythie,Forsythia x intermedia,flowering|tree|sun,3,Forsythie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,100,Erdbeere,Fragaria ananassa,easy|pet_friendly|sun,3,"Die Erdbeere ist ein beliebtes Obst fuer Balkon und Terrasse mit aromatischen, roten Fruechten.",Helles bis volles Licht,15-25 °C,3 +constants/lexiconBatch2.ts,169,Freesie,Freesia refracta,flowering|sun,2,"Freesie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,33,Fuchsie,Fuchsia hybrida,flowering|hanging,2,"Die Fuchsie haengt mit eleganten, zweifarbigen Blueten wie kleine Ohrringe herab. Ideal fuer Ampeln.",Helles indirektes Licht,14-22 °C,3 +constants/lexiconBatch2.ts,60,Triphylla-Fuchsie,Fuchsia triphylla,flowering|hanging,2,"Die Triphylla-Fuchsie hat lange, roehrenfoermige, orangefarbe Blueten in haengenden Trauben. Sehr exotisch.",Helles indirektes Licht,15-22 °C,3 +constants/lexiconBatch2.ts,196,Kokardenblume,Gaillardia aristata,flowering|sun,2,"Kokardenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,22,Gardenie,Gardenia jasminoides,flowering|high_humidity,2,"Die Gardenie fasziniert mit cremefarbenen, intensiv duftenden Blueten. Anspruchsvoll in der Pflege.",Helles indirektes Licht,18-23 °C,5 +constants/lexiconBatch1.ts,90,Gasteria,Gasteria carinata,easy|succulent|low_light,3,"Die Gasteria ist eine kleine Sukkulente mit zweireihig angeordneten, zungenfoermigen, gefleckten Blaettern.",Helles indirektes Licht,15-25 °C,14 +constants/lexiconBatch2.ts,190,Mittagsgold,Gazania rigens,flowering|sun,2,"Mittagsgold ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,32,Blutroter Storchschnabel,Geranium sanguineum,easy|flowering,2,Der Blutrote Storchschnabel ist ein zierlicher Storchschnabel mit intensiv magentafarbenen Blueten.,Helles bis volles Licht,10-25 °C,7 +constants/lexiconBatch1.ts,68,Gerbera,Gerbera jamesonii,flowering|air_purifier|bright_light,3,"Die Gerbera ist eine farbenfrohe Schnittblume mit grossen, sonnenblumenaehnlichen Blueten. Sehr beliebt.",Helles bis volles Licht,15-25 °C,5 +constants/lexiconBatch2.ts,216,Ginkgo,Ginkgo biloba,tree|medicinal|sun,3,Ginkgo ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,161,Gladiole,Gladiolus hortulanus,flowering|sun,2,"Gladiole ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,96,Gloxinie,Gloxinia speciosa,flowering|high_humidity,2,"Die Gloxinie hat grosse, samtartige Blueten in Violett, Rosa oder Weiss mit farbigen Raendern.",Helles indirektes Licht,18-25 °C,5 +constants/lexiconBatch2.ts,240,Calathea lancifolia,Goeppertia insignis,pet_friendly|patterned|high_humidity,3,Calathea lancifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5 +constants/lexiconBatch2.ts,241,Calathea ornata,Goeppertia ornata,pet_friendly|patterned|high_humidity,3,Calathea ornata ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5 +constants/lexiconBatch1.ts,87,Geisterpflanze,Graptopetalum paraguayense,easy|succulent|sun,3,"Die Geisterpflanze hat zartgraue bis perlmutt-rosafarbene, rosettenfoermige Blaetter. Sehr robuste Sukkulente.",Volles Sonnenlicht,15-25 °C,14 +constants/lexiconBatch2.ts,36,Guzmania,Guzmania lingulata,flowering|high_humidity,2,"Die Guzmania ist eine Bromelie mit glänzenden, gruenen Blaettern und einem leuchtend roten, sternfoermigen Bluetenstand.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,80,Mond-Kaktus,Gymnocalycium mihanovichii,easy|succulent,2,Der Mond-Kaktus ist eine farbenfrohe Veredelung eines chlorophylllosen Kaktus auf einem gruenen Unterlagekaktus.,Indirektes Licht,15-30 °C,14 +constants/lexiconBatch2.ts,119,Zaubernuss,Hamamelis mollis,flowering|medicinal,2,"Die Zaubernuss bluet im Winter mit fadendunnen, gelben Bluetenkranzeln, die bis -10 Grad standhalten.",Helles bis volles Licht,10-20 °C,10 +constants/lexiconBatch1.ts,6,Zebra-Haworthie,Haworthia fasciata,easy|succulent|low_light,3,Die Zebra-Haworthie ist eine kompakte Sukkulente mit weissen Querstreifen auf dunkelgruenen Blaettern.,Helles indirektes Licht,15-25 °C,14 +constants/lexiconBatch1.ts,37,Efeu,Hedera helix,easy|hanging|air_purifier|low_light,4,"Efeu ist eine robuste Kletter- und Haengepflanze mit charakteristischen, dreilappigen Blaettern. Sehr langlebig.",Wenig bis helles Licht,10-20 °C,7 +constants/lexiconBatch2.ts,83,Heliamphora,Heliamphora nutans,high_humidity,1,Heliamphora ist eine urtuemliche Kannenpflanze aus den Tafelbergen Venezuelas. Sehr dekorativ und selten.,Helles indirektes Licht,15-25 °C,5 +constants/lexiconBatch2.ts,141,Sonnenblume,Helianthus annuus,flowering|sun,2,"Sonnenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,133,Currykraut,Helichrysum italicum,easy|sun,2,Currykraut ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,72,Heliconia,Heliconia psittacorum,flowering|bright_light|high_humidity,3,"Die Heliconia hat leuchtend orangefarbe oder rote, bootsfoermige Hochblaetter. Eine exotische Tropenpflanze.",Helles bis volles Licht,20-30 °C,5 +constants/lexiconBatch2.ts,191,Heliotrop,Heliotropium arborescens,flowering|sun,2,"Heliotrop ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,183,Lenzrose,Helleborus orientalis,flowering,1,"Lenzrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,182,Taglilie,Hemerocallis fulva,flowering|sun,2,"Taglilie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,21,Hibiskus,Hibiscus rosa-sinensis,flowering|bright_light|sun,3,"Der Hibiskus begeistert mit grossen, trompetenfoermigen Blueten in Rot, Orange und Rosa.",Volles Sonnenlicht,18-28 °C,3 +constants/lexiconBatch2.ts,220,Gartenhibiskus,Hibiscus syriacus,flowering|tree|sun,3,Gartenhibiskus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch1.ts,105,Ritterstern,Hippeastrum hybrid,flowering|bright_light,2,"Der Ritterstern beeindruckt im Winter mit riesigen, trompetenfoermigen Blueten in Rot, Pink oder Weiss.",Helles bis volles Licht,18-25 °C,7 +constants/lexiconBatch2.ts,3,Kentia-Palme,Howea forsteriana,pet_friendly|tree|low_light,3,"Die Kentia-Palme ist eine der elegantesten Zimmerpalmen mit langen, herabhängenden Fiederblaettern.",Helles indirektes Licht,18-25 °C,7 +constants/lexiconBatch1.ts,58,Kleine Wachsblume,Hoya bella,flowering|succulent|hanging,3,"Die Kleine Wachsblume traegt zierliche, sternfoermige weisse Blueten mit rosa Mitte. Haengende Sukkulente.",Helles indirektes Licht,18-27 °C,10 +constants/lexiconBatch1.ts,57,Wachsblume,Hoya carnosa,easy|flowering|succulent|hanging,4,"Die Wachsblume ist eine Kletterpflanze mit dicken, wachsartigen Blaettern und sternfoermigen, duftenden Blueten.",Helles indirektes Licht,16-27 °C,10 +constants/lexiconBatch2.ts,159,Hasengloeckchen,Hyacinthoides non-scripta,flowering|sun,2,"Hasengloeckchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,108,Hyazinthe,Hyacinthus orientalis,easy|flowering,2,"Die Hyazinthe bezaubert mit dichten Bluetenrispen und intensivem Duft in Blau, Rosa, Weiss oder Gelb.",Helles bis volles Licht,10-18 °C,5 +constants/lexiconBatch2.ts,148,Hortensie,Hydrangea macrophylla,flowering|bright_light,2,"Hortensie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Helles bis halbschattiges Licht,8-24 C,4 +constants/lexiconBatch2.ts,105,Johanniskraut,Hypericum perforatum,flowering|medicinal|sun,3,Das Johanniskraut hat leuchtend gelbe Blueten und ist ein wichtiges Heilkraut gegen Depressionen und Stimmungstiefs.,Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch2.ts,227,Punktblatt,Hypoestes phyllostachya,patterned|bright_light,2,Punktblatt ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch2.ts,136,Ysop,Hyssopus officinalis,easy|sun,2,Ysop ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,203,Stechpalme,Ilex aquifolium,tree|sun,2,Stechpalme ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,176,Gartenbalsamine,Impatiens balsamina,flowering|bright_light,2,"Gartenbalsamine ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,59,Neuguinea-Balsamine,Impatiens hawkeri,easy|flowering,2,"Die Neuguinea-Balsamine hat grosse, leuchtende Blueten und ist sehr bluehfreudig. Ideal fuer Terrassen.",Helles indirektes Licht,18-27 °C,3 +constants/lexiconBatch1.ts,20,Fleissiges Lieschen,Impatiens walleriana,easy|flowering,2,Das Fleissige Lieschen bluet von Fruehling bis Herbst unermudlich in vielen Farben.,Helles indirektes Licht,16-24 °C,2 +constants/lexiconBatch1.ts,64,Suesskartoffel,Ipomoea batatas,easy|hanging|sun,3,"Die Suesskartoffel-Zierpflanze hat dekorative, herzfoermige Blaetter in gruen oder dunkelviolett. Ideal als Haengepflanze.",Volles Sonnenlicht,20-30 °C,5 +constants/lexiconBatch2.ts,156,Prunkwinde,Ipomoea purpurea,flowering|sun,2,"Prunkwinde ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,144,Bart-Iris,Iris germanica,flowering|sun,2,"Bart-Iris ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,211,Jacaranda,Jacaranda mimosifolia,flowering|tree|large,3,Jacaranda ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch1.ts,59,Jasmin,Jasminum polyanthum,flowering,1,"Der Jasmin ist eine Kletterpflanze mit intensiv duftenden, weissen Blueten. Er bluet im Winter und Fruehling.",Helles bis volles Licht,10-22 °C,5 +constants/lexiconBatch2.ts,172,Arabischer Jasmin,Jasminum sambac,flowering|bright_light,2,"Arabischer Jasmin ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,9,Kalanchoe,Kalanchoe blossfeldiana,easy|flowering|succulent|sun,4,"Die Kalanchoe ist eine beliebte Bluehpflanze mit leuchtenden Blueten in Rot, Orange, Gelb oder Rosa.",Helles bis volles Licht,15-25 °C,10 +constants/lexiconBatch2.ts,22,Brutblatt,Kalanchoe daigremontiana,easy|succulent|sun,3,Das Brutblatt bildet entlang des Blattrandes zahlreiche kleine Jungpflanzen. Eine faszinierende Sukkulente.,Helles bis volles Licht,15-25 °C,14 +constants/lexiconBatch2.ts,21,Kaninchen-Ohren,Kalanchoe tomentosa,easy|succulent|sun,3,"Kaninchen-Ohren haben weisslich-filzige Blaetter mit braunen Raendern, die Kaninchen­ohren aehneln. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14 +constants/lexiconBatch2.ts,95,Salat,Lactuca sativa,easy,1,Salat ist eine schnell wachsende Blattgemuese­pflanze. Im Topf und Balkonkasten sehr gut zu kultivieren.,Helles bis volles Licht,10-22 °C,3 +constants/lexiconBatch2.ts,197,Traenendes Herz,Lamprocapnos spectabilis,flowering|bright_light,2,"Traenendes Herz ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,64,Wandelroeschen,Lantana camara,flowering|bright_light|sun,3,"Das Wandelroeschen hat kugelige Bluetenkoepfe, die die Farbe von Gelb ueber Orange zu Rot wechseln. Sehr attraktiv.",Volles Sonnenlicht,18-28 °C,5 +constants/lexiconBatch2.ts,158,Duftwicke,Lathyrus odoratus,flowering|sun,2,"Duftwicke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,121,Lorbeer,Laurus nobilis,easy|sun,2,Lorbeer ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch1.ts,23,Echter Lavendel,Lavandula angustifolia,medicinal|bright_light|sun,3,Der Echte Lavendel ist ein aromatischer Halbstrauch mit lilafarbenen Bluetenaehren. Herrlicher Duft.,Volles Sonnenlicht,10-25 °C,10 +constants/lexiconBatch2.ts,180,Bechermalve,Lavatera trimestris,flowering|sun,2,"Bechermalve ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,173,Margerite,Leucanthemum vulgare,flowering|sun,2,"Margerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,201,Shasta-Margerite,Leucanthemum x superbum,flowering|sun,2,"Shasta-Margerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,126,Liebstoeckel,Levisticum officinale,easy|sun,2,Liebstoeckel ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,69,Ostertrompete,Lilium longiflorum,flowering|bright_light,2,"Die Ostertrompete hat grosse, weisse, trichterfoermige Blueten mit intensivem Duft. Klassische Osterblume.",Helles bis volles Licht,15-25 °C,5 +constants/lexiconBatch2.ts,23,Lebende Steine,Lithops julii,succulent|sun,2,"Lebende Steine sind faszinierende Mimikry-Sukkulenten, die Kieselsteinen taeuschen aehnlich sehen. Sehr trockenheitsresistent.",Volles Sonnenlicht,10-30 °C,21 +constants/lexiconBatch2.ts,4,Chinesische Fächerpalme,Livistona chinensis,tree|bright_light,2,"Die Chinesische Fächerpalme hat grosse, faecher­foermige Blaetter auf einem einzelnen Stamm. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,7 +constants/lexiconBatch2.ts,62,Duftsteinrich,Lobularia maritima,easy|flowering,2,"Der Duftsteinrich ist ein niedrig wachsendes Pflanzchen mit winzigen, weissen oder lilafarbenen Blueten und suessem Duft.",Helles bis volles Licht,10-22 °C,3 +constants/lexiconBatch2.ts,171,Geissblatt,Lonicera japonica,flowering|bright_light,2,"Geissblatt ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,154,Lupine,Lupinus polyphyllus,flowering|sun,2,"Lupine ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,204,Magnolie,Magnolia grandiflora,flowering|tree|large,3,Magnolie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch1.ts,79,Mammillaria,Mammillaria zeilmanniana,easy|flowering|succulent|sun,4,"Die Mammillaria ist ein kompakter, kugelfoermiger Kaktus, der im Fruehling einen Kranz aus rosa Blueten traegt.",Volles Sonnenlicht,15-35 °C,14 +constants/lexiconBatch1.ts,51,Gebet-Pflanze,Maranta leuconeura,pet_friendly|patterned|high_humidity,3,Die Gebet-Pflanze faltet ihre gemusterten Blaetter nachts wie Haende zusammen. Faszinierende rote und gruene Muster.,Indirektes Licht,18-27 °C,5 +constants/lexiconBatch2.ts,102,Zitronenmelisse,Melissa officinalis,easy|medicinal,2,Die Zitronenmelisse ist ein zitronig duftendes Heilkraut. Sie beruhigt die Nerven und foerdert den Schlaf.,Helles bis volles Licht,15-25 °C,5 +constants/lexiconBatch1.ts,26,Gruene Minze,Mentha spicata,easy,1,"Die Gruene Minze ist ein wuchsfreudiges Kuechenkraut mit frischem, minzigem Duft. Fuer Tee und Cocktails.",Helles bis volles Licht,15-25 °C,3 +constants/lexiconBatch2.ts,46,Tueipelfarn (Microsorum),Microsorum punctatum,high_humidity,1,"Microsorum punctatum ist ein tropischer Farn mit langen, ungeteilten, glaenzenden Wedeln. Fuer feuchte Standorte.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,75,Stiefmuetterchen-Orchidee,Miltoniopsis roezlii,flowering|high_humidity,2,"Die Stiefmuetterchen-Orchidee hat grosse, flache Blueten. Bevorzugt kuehle Temperaturen und hohe Luftfeuchtigkeit.",Indirektes Licht,15-22 °C,5 +constants/lexiconBatch2.ts,76,Schamkraut,Mimosa pudica,flowering|bright_light,2,"Das Schamkraut faltet seine Blaettchen blitzschnell zusammen, wenn man sie beruehrt. Ein faszinierendes Erlebnis.",Helles bis volles Licht,20-28 °C,5 +constants/lexiconBatch2.ts,179,Indianernessel,Monarda didyma,flowering|sun,2,"Indianernessel ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,47,Monstera adansonii,Monstera adansonii,easy|hanging,2,Monstera adansonii hat herzfoermige Blaetter mit zahlreichen runden Lochern. Eine rankende Zimmerpflanze.,Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,48,Monstera obliqua,Monstera obliqua,patterned|hanging,2,"Monstera obliqua ist eine seltene Monstera-Art mit filigranen Blaettern, die hauptsaechlich aus Lochern bestehen.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,2,Bananenpflanze,Musa acuminata,large|high_humidity,2,"Die Bananenpflanze ist eine tropische Staude mit riesigen, glaenzenden Blaettern. Im Zimmer selten fruechttragend.",Helles bis volles Licht,20-30 °C,5 +constants/lexiconBatch1.ts,109,Traubenhyazinthe,Muscari armeniacum,easy|flowering,2,"Die Traubenhyazinthe bildet dichte Trauben aus kleinen, blauen bis violetten Gloeckchen. Zuverlaessige Fruejahrszwiebel.",Helles bis volles Licht,8-18 °C,7 +constants/lexiconBatch2.ts,177,Vergissmeinnicht,Myosotis sylvatica,flowering|sun,2,"Vergissmeinnicht ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,106,Osterglocke,Narcissus pseudonarcissus,flowering,1,"Die Osterglocke ist der klassische Fruehjahrsblueher mit leuchtend gelben, trompetenfoermigen Blueten.",Helles bis volles Licht,10-18 °C,5 +constants/lexiconBatch2.ts,199,Nemesie,Nemesia strumosa,flowering|sun,2,"Nemesie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,37,Neoregelia,Neoregelia carolinae,flowering|patterned|bright_light,3,"Die Neoregelia ist eine Bromelie, bei der das Herzblatt zur Bluetzeit leuchtend rot wird. Sehr dekorativ.",Helles bis volles Licht,18-27 °C,7 +constants/lexiconBatch2.ts,79,Kannenpflanze,Nepenthes alata,hanging|high_humidity,2,"Die Kannenpflanze bildet grosse, gefuellte Kannen als Insekten­fallen. Eine faszinierende, tropische Pflanze.",Helles indirektes Licht,20-30 °C,5 +constants/lexiconBatch2.ts,132,Katzenminze,Nepeta cataria,easy|sun,2,Katzenminze ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,120,Oleander,Nerium oleander,flowering|bright_light|sun,3,"Der Oleander ist ein mediteraner Strauch mit leuchtend roten, rosa oder weissen Blueten. Sehr hitzetolerant.",Volles Sonnenlicht,15-28 °C,7 +constants/lexiconBatch2.ts,193,Ziertabak,Nicotiana alata,flowering|sun,2,"Ziertabak ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,25,Basilikum,Ocimum basilicum,easy|medicinal|sun,3,"Basilikum ist das beliebteste Kuechenkraut mit intensiv aromatischen, gruenen Blaettern. Fuer Pesto verwendet.",Volles Sonnenlicht,18-30 °C,2 +constants/lexiconBatch1.ts,74,Tanzerinnen-Orchidee,Oncidium sphacelatum,flowering|high_humidity,2,"Die Tanzerinnen-Orchidee traegt lange Rispen mit Hunderten kleiner, gelb-brauner Blueten. Sehr reichliche Bluetracht.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,82,Hasenohren-Kaktus,Opuntia microdasys,easy|succulent|sun,3,"Der Hasenohren-Kaktus hat flache, ovale Triebe mit dichten weissen Glochiden. Klassischer Zimmerkaktus.",Volles Sonnenlicht,10-35 °C,21 +constants/lexiconBatch2.ts,124,Majoran,Origanum majorana,easy|sun,2,Majoran ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch1.ts,28,Oregano,Origanum vulgare,easy|medicinal|sun,3,"Oregano ist ein aromatisches Kuechenkraut mit runden, behaarten Blaettern. In mediterraner Kueche beliebt.",Volles Sonnenlicht,15-25 °C,7 +constants/lexiconBatch2.ts,200,Kapmargerite,Osteospermum ecklonis,flowering|sun,2,"Kapmargerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,54,Kleeblume,Oxalis triangularis,flowering|patterned,2,"Die Kleeblume hat tiefviolette, dreieckige Blaetter und zarte rosa Blueten. Sie faltet die Blaetter bei Dunkelheit.",Helles indirektes Licht,15-24 °C,7 +constants/lexiconBatch2.ts,231,Glueckskastanie,Pachira aquatica,easy|tree|bright_light,3,Glueckskastanie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch1.ts,88,Mondstein-Pflanze,Pachyphytum oviferum,easy|succulent|sun,3,"Die Mondstein-Pflanze hat dicke, ovale Blaetter mit einem pastellrosafarbenen, mehligen Ueberzug.",Volles Sonnenlicht,15-25 °C,14 +constants/lexiconBatch2.ts,143,Pfingstrose,Paeonia lactiflora,flowering|sun,2,"Pfingstrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,6,Schraubenbaum,Pandanus veitchii,patterned|bright_light,2,"Der Schraubenbaum hat spiralfoermig angeordnete, gruenweiss gestreifte Blaetter. Sehr dekorativ und exotisch.",Helles bis volles Licht,18-27 °C,7 +constants/lexiconBatch2.ts,185,Mohn,Papaver rhoeas,flowering|sun,2,"Mohn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,63,Passionsblume,Passiflora caerulea,flowering,1,"Die Passionsblume ist eine faszinierende Kletterpflanze mit komplex strukturierten, blau-weissen Blueten.",Helles bis volles Licht,15-27 °C,5 +constants/lexiconBatch1.ts,31,Rosengeranie,Pelargonium graveolens,easy|medicinal|sun,3,Die Rosengeranie ist eine Duftpflanze mit tief eingeschnittenen Blaettern und rosaenlichem Aroma.,Volles Sonnenlicht,15-25 °C,7 +constants/lexiconBatch2.ts,61,Efeu-Geranie,Pelargonium peltatum,easy|flowering|hanging|sun,4,"Die Efeu-Geranie hat efeufoermige, glaenzende Blaetter und bluet den ganzen Sommer in leuchtenden Farben.",Helles bis volles Licht,15-25 °C,5 +constants/lexiconBatch2.ts,174,Stehende Geranie,Pelargonium zonale,flowering|sun,2,"Stehende Geranie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,229,Wassermelonen-Peperomie,Peperomia argyreia,pet_friendly|patterned,2,Wassermelonen-Peperomie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch1.ts,102,Rippenpeperomie,Peperomia caperata,easy|pet_friendly,2,"Die Rippenpeperomie hat tief gerippte, dunkelgruene bis violette Blaetter mit einer samtigen Textur.",Helles indirektes Licht,18-26 °C,10 +constants/lexiconBatch1.ts,103,Spiegelpeperomie,Peperomia obtusifolia,easy|pet_friendly|low_light,3,"Die Spiegelpeperomie hat glaenzende, lederartige, oval-runde Blaetter in tiefem Gruen. Sehr robust.",Helles indirektes Licht,16-26 °C,10 +constants/lexiconBatch2.ts,230,Raindrop-Peperomie,Peperomia polybotrya,easy|pet_friendly,2,Raindrop-Peperomie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch2.ts,134,Shiso,Perilla frutescens,easy|sun,2,Shiso ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch1.ts,29,Petersilie,Petroselinum crispum,easy,1,Petersilie ist eines der meistgenutzten Kuechenkraeuter mit frisch-aromatischem Geschmack. Reich an Vitaminen.,Helles Licht,10-25 °C,3 +constants/lexiconBatch1.ts,34,Petunie,Petunia hybrida,easy|pet_friendly|flowering|sun,4,Die Petunie ist eine der beliebtesten Balkonpflanzen mit trichterfoermigen Blueten in unzaehligen Farben.,Volles Sonnenlicht,15-25 °C,2 +constants/lexiconBatch1.ts,69,Schmetterlingsorchidee,Phalaenopsis amabilis,flowering|high_humidity,2,Die Schmetterlingsorchidee ist die bekannteste Zimmerorchidee. Sie bluet bei guter Pflege monatelang.,Helles indirektes Licht,18-28 °C,10 +constants/lexiconBatch2.ts,50,Philodendron bipinnatifidum,Philodendron bipinnatifidum,easy|large,2,"Philodendron bipinnatifidum hat grosse, tief gelappte Blaetter. Er entwickelt einen beeindruckenden, baumfoermigen Wuchs.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,51,Roter Philodendron,Philodendron erubescens,easy|hanging,2,"Der Rote Philodendron hat glaenzende, herzfoermige Blaetter, die jung roetrlich erscheinen. Sehr dekorativ.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,243,Philodendron Pink Princess,Philodendron erubescens Pink Princess,patterned|bright_light,2,Philodendron Pink Princess ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch2.ts,49,Philodendron gloriosum,Philodendron gloriosum,patterned|large|high_humidity,3,"Philodendron gloriosum hat grosse, samtige, herzfoermige Blaetter mit weissen Rippen. Eine atemberaubende Pflanze.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,15,Herzblatt-Philodendron,Philodendron hederaceum,easy|hanging|low_light,3,Der Herzblatt-Philodendron ist eine pflegeleichte Kletter- oder Haengepflanze mit herzfoermigen Blaettern.,Indirektes Licht,18-28 °C,7 +constants/lexiconBatch2.ts,242,Philodendron Brasil,Philodendron hederaceum Brasil,easy|hanging|low_light,3,Philodendron Brasil ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch2.ts,40,Blaues Kanaelfarn,Phlebodium aureum,high_humidity,1,"Der Blaue Kanaelfarn hat wachsartige, blaugruene Wedel und glaenzende Wurzelstaemme. Sehr dekorativ.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,165,Flammenblume,Phlox paniculata,flowering|sun,2,"Flammenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,44,Zwergdattelpalme,Phoenix roebelenii,tree|bright_light,2,"Die Zwergdattelpalme ist eine zierliche Palme mit eleganten, gebogenen Fiederblaettern. Tropisches Flair.",Helles bis volles Licht,18-27 °C,7 +constants/lexiconBatch2.ts,8,Goldener Bambus,Phyllostachys aurea,easy|large,2,"Der Goldene Bambus hat elegante, goldgelbe Halme mit engstehenden Knoten. Sehr dekorativ als Sichtschutz.",Helles bis volles Licht,10-30 °C,5 +constants/lexiconBatch2.ts,207,Fichte,Picea abies,tree|large|sun,3,Fichte ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,228,Aluminium-Pflanze,Pilea cadierei,easy|pet_friendly|patterned,3,Aluminium-Pflanze ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch1.ts,2,Ufopflanze,Pilea peperomioides,easy|pet_friendly,2,"Die Ufopflanze hat unverwechselbare, runde Blaetter auf langen Stielen. Bildet leicht Ableger zum Verschenken.",Helles indirektes Licht,13-30 °C,7 +constants/lexiconBatch2.ts,81,Fettkraut,Pinguicula grandiflora,flowering|high_humidity,2,"Das Fettkraut faengt Insekten mit klebrigen Blaettern. Es bluet mit violetten, sporenartigen Blueten.",Helles indirektes Licht,10-20 °C,5 +constants/lexiconBatch2.ts,206,Kiefer,Pinus sylvestris,tree|large|sun,3,Kiefer ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,41,Geweihfarn,Platycerium bifurcatum,hanging|high_humidity,2,"Der Geweihfarn hat gespaltene Wedel, die einem Hirschgeweih aehneln. Er ist ein epiphytischer Farn fuer Holz.",Helles indirektes Licht,15-25 °C,7 +constants/lexiconBatch2.ts,152,Buntnessel,Plectranthus scutellarioides,patterned|bright_light,2,"Buntnessel ist eine farbstarke Zierpflanze, die vor allem fuer ihr dekoratives Laub beliebt ist.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,61,Bleiwurz,Plumbago auriculata,flowering|bright_light|sun,3,"Die Bleiwurz ist ein halbimmergruener Strauch mit himmelblauen Blueten, der fast das ganze Jahr bluet.",Volles Sonnenlicht,15-27 °C,5 +constants/lexiconBatch2.ts,118,Tempel-Baum,Plumeria rubra,flowering|tree|sun,3,"Der Tempel-Baum hat intensiv duftende, sternfoermige Blueten in Weiss, Gelb oder Rosa. Klassische Tropenblume.",Volles Sonnenlicht,20-30 °C,7 +constants/lexiconBatch2.ts,44,Tueipelfarn,Polypodium vulgare,easy,1,Der Tueipelfarn ist ein heimischer Farn mit gelappten Wedeln und runden Sporenhaeufchen auf der Unterseite.,Helles indirektes Licht,10-20 °C,7 +constants/lexiconBatch2.ts,27,Speckbaum,Portulacaria afra,easy|succulent|sun,3,"Der Speckbaum ist eine sukkulente Pflanze mit roten Stielen und kleinen, runden, glaenzenden Blaettern.",Helles bis volles Licht,15-30 °C,14 +constants/lexiconBatch1.ts,36,Primel,Primula vulgaris,flowering,1,"Die Primel ist einer der ersten Fruehjahrs­boten mit lebhaften Blueten in Gelb, Pink, Rot und Lila.",Helles indirektes Licht,10-18 °C,4 +constants/lexiconBatch2.ts,71,Koenigs-Protea,Protea cynaroides,flowering|large|sun,3,"Die Koenigs-Protea ist die Nationalblume Suedafrikas mit riesigen, imposanten Bluetenkoepfen. Eine echte Besonderheit.",Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch2.ts,218,Kirschlorbeer,Prunus laurocerasus,tree|sun,2,Kirschlorbeer ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,89,Guave,Psidium guajava,tree|sun,2,Die Guave ist ein tropischer Obstbaum mit gelblich-weissen Fruechten. Sie ist reich an Vitamin C.,Volles Sonnenlicht,18-30 °C,7 +constants/lexiconBatch2.ts,88,Granatapfelbaum,Punica granatum,flowering|tree|sun,3,"Der Granatapfelbaum hat leuchtend rote Blueten und rote, essbare Fruechte mit rubinroten Kernen.",Volles Sonnenlicht,15-28 °C,7 +constants/lexiconBatch2.ts,205,Eiche,Quercus robur,tree|large|sun,3,Eiche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,162,Ranunkel,Ranunculus asiaticus,flowering|sun,2,"Ranunkel ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,98,Radieschen,Raphanus sativus,easy,1,"Das Radieschen ist ein schnellwachsendes Gemuese mit runden, roten Knollen. Es reift in nur 3-4 Wochen.",Helles bis volles Licht,10-22 °C,2 +constants/lexiconBatch2.ts,52,Mini-Monstera,Rhaphidophora tetrasperma,easy|hanging,2,"Die Mini-Monstera hat monstera­aehnliche, gelochte Blaetter auf einer kompakten, klettternden Pflanze. Sehr trendig.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch1.ts,45,Stab-Palme,Rhapis excelsa,tree|low_light,2,"Die Stab-Palme ist eine elegante Zimmerpalme mit faecher­foermigen Blaettern auf duennen, bambusartigen Staemmen.",Helles indirektes Licht,15-25 °C,7 +constants/lexiconBatch1.ts,85,Korallenkaktus,Rhipsalis baccifera,succulent|hanging,2,"Der Korallenkaktus ist ein epiphytischer Kaktus mit duennen, haengenden Trieben und kleinen weissen Beeren.",Indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,170,Rhododendron,Rhododendron catawbiense,flowering|tree|bright_light,3,"Rhododendron ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,91,Japanische Azalee,Rhododendron simsii,flowering,1,"Die Japanische Azalee bluet im Winter und Fruehling ueppig mit leuchtend roten, rosa oder weissen Blueten.",Helles indirektes Licht,10-18 °C,4 +constants/lexiconBatch2.ts,214,Robinie,Robinia pseudoacacia,tree|large|sun,3,Robinie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch1.ts,66,Chinesische Rose,Rosa chinensis,flowering|sun,2,Die Chinesische Rose ist eine der Stammarten vieler Gartenrosen und bluet fast ununterbrochen.,Volles Sonnenlicht,15-25 °C,5 +constants/lexiconBatch2.ts,142,Rose,Rosa x hybrida,flowering|bright_light|sun,3,"Rose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,24,Rosmarin,Rosmarinus officinalis,easy|medicinal|sun,3,Rosmarin ist ein aromatisches Kraut mit nadelartigen Blaettern und blauen Blueten. In der Kueche unverzichtbar.,Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch2.ts,167,Rudbeckie,Rudbeckia hirta,flowering|sun,2,"Rudbeckie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,130,Sauerampfer,Rumex acetosa,easy|sun,2,Sauerampfer ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch1.ts,94,Afrikanisches Veilchen,Saintpaulia ionantha,easy|flowering,2,"Das Afrikanische Veilchen ist eine kleine, kompakte Bluehpflanze mit samtigen Blaettern und violetten Blueten.",Helles indirektes Licht,18-25 °C,7 +constants/lexiconBatch2.ts,113,Silber-Weide,Salix alba,tree|large|medicinal,3,"Die Silber-Weide hat silbrig-glaenzende Blaetter. Weidenrinde enthält Salicylsaeure, die Grundlage von Aspirin.",Helles bis volles Licht,10-25 °C,7 +constants/lexiconBatch2.ts,195,Mehlsalbei,Salvia farinacea,flowering|sun,2,"Mehlsalbei ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,103,Salbei,Salvia officinalis,easy|medicinal|sun,3,Salbei ist ein aromatisches Heilkraut mit silbrig-gruenen Blaettern. Er hat antibakterielle und entzuendungshem­mende Wirkung.,Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch2.ts,168,Feuersalbei,Salvia splendens,flowering|sun,2,"Feuersalbei ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,112,Schwarzer Holunder,Sambucus nigra,flowering|tree|medicinal,3,Der Schwarze Holunder hat weisse Doldenbluten und schwarze Beeren. Die Fruechte werden fuer Sirup und Saft verwendet.,Helles bis volles Licht,10-25 °C,7 +constants/lexiconBatch2.ts,17,Zylindrischer Bogenhanf,Sansevieria cylindrica,easy|succulent|sun,3,"Der Zylindrische Bogenhanf hat zylindrische, aufrechte Blaetter, die sich nach oben verjuengen. Sehr pflegeleicht.",Helles bis volles Licht,15-27 °C,14 +constants/lexiconBatch2.ts,78,Purpursonnentau,Sarracenia purpurea,high_humidity|sun,2,Der Purpursonnentau ist eine fleischfressende Kannenpflanze mit purpurroten Kannen. Faengt Insekten.,Volles Sonnenlicht,5-25 °C,3 +constants/lexiconBatch2.ts,123,Bohnenkraut,Satureja hortensis,easy|sun,2,Bohnenkraut ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,11,Grosse Strahlenaralie,Schefflera actinophylla,easy|tree|large,3,"Die Grosse Strahlenaralie kann grosse, handfoermige Blaetter entwickeln. Sie ist ideal als Zimmerstrauch.",Helles indirektes Licht,18-27 °C,7 +constants/lexiconBatch2.ts,10,Strahlenaralie,Schefflera arboricola,easy|tree|air_purifier,3,"Die Strahlenaralie hat fingerfoermig angeordnete, glaenzende Blaetter auf langen Stielen. Sehr robuste Zimmerpflanze.",Helles indirektes Licht,15-25 °C,7 +constants/lexiconBatch2.ts,235,Falsche Aralie,Schefflera elegantissima,tree|bright_light,2,Falsche Aralie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch1.ts,8,Weihnachtskaktus,Schlumbergera truncata,easy|flowering|succulent,3,"Der Weihnachtskaktus erfreut zur Weihnachtszeit mit leuchtenden Blueten in Rosa, Rot oder Weiss.",Helles indirektes Licht,15-21 °C,7 +constants/lexiconBatch1.ts,55,Satinpothos,Scindapsus pictus,easy|patterned|hanging,3,"Der Satinpothos hat samtig-glaenzende, silbrig gefleckte Blaetter auf langen, haengenden Ranken.",Helles indirektes Licht,18-28 °C,7 +constants/lexiconBatch1.ts,7,Eselschwanz,Sedum morganianum,easy|succulent|hanging|sun,4,"Der Eselschwanz ist eine haengende Sukkulente mit langen Trieben aus dichten, blaugruenen Blaettchen.",Volles Sonnenlicht,15-25 °C,14 +constants/lexiconBatch2.ts,45,Regenbogenmoos,Selaginella uncinata,patterned|high_humidity,2,"Das Regenbogenmoos hat schuppenfoermige Blaetter, die im Licht schillernd irisieren. Dekorativ fuer Terrarien.",Helles indirektes Licht,18-27 °C,5 +constants/lexiconBatch1.ts,100,Perlenschnur-Pflanze,Senecio rowleyanus,easy|succulent|hanging,3,"Die Perlenschnur-Pflanze hat haengende Ranken mit kugelfoermigen, perlenaehnlichen Blaettern. Einzigartige Sukkulente.",Helles bis volles Licht,15-27 °C,14 +constants/lexiconBatch2.ts,28,Blauer Kreuzkraut,Senecio serpens,easy|succulent|sun,3,"Der Blaue Kreuzkraut hat zylindrische, blaublaugruene Blaetter und einen kriechenden Wuchs. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14 +constants/lexiconBatch2.ts,91,Tomate,Solanum lycopersicum,easy,1,"Die Tomate ist eine beliebte Gemuese- und Balkonpflanze mit roten, saftigen Fruechten. Im Topf kultivierbar.",Volles Sonnenlicht,18-28 °C,3 +constants/lexiconBatch2.ts,93,Aubergine,Solanum melongena,bright_light|sun,2,"Die Aubergine ist eine Gemuese­pflanze mit grossen, violetten Fruechten. Sie benoetigt viel Waerme und Sonne.",Volles Sonnenlicht,20-30 °C,5 +constants/lexiconBatch2.ts,238,Bubikopf,Soleirolia soleirolii,pet_friendly|high_humidity,2,Bubikopf ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,15-24 C,4 +constants/lexiconBatch2.ts,213,Eberesche,Sorbus aucuparia,tree|large|sun,3,Eberesche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,96,Spinat,Spinacia oleracea,easy,1,Spinat ist ein naehrstoffreiches Blattgemuese mit dunkelgruenen Blaettern. Reich an Eisen und Vitaminen.,Helles bis volles Licht,10-20 °C,3 +constants/lexiconBatch2.ts,222,Spierstrauch,Spiraea japonica,flowering|tree|sun,3,Spierstrauch ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch2.ts,25,Aasblume,Stapelia grandiflora,flowering|succulent|sun,3,"Die Aasblume hat fleischige, gruene Staengel und riesige, sternfoermige Blueten mit aasartigem Duft.",Helles bis volles Licht,18-30 °C,14 +constants/lexiconBatch1.ts,60,Madagaskar-Jasmin,Stephanotis floribunda,flowering,1,"Der Madagaskar-Jasmin hat dicke, glaenzende Blaetter und wachsweisse, intensiv duftende Blueten. Klassische Hochzeitsblume.",Helles indirektes Licht,18-25 °C,7 +constants/lexiconBatch2.ts,131,Stevia,Stevia rebaudiana,easy|sun,2,Stevia ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5 +constants/lexiconBatch2.ts,1,Weisse Strelitzie,Strelitzia nicolai,tree|large|bright_light,3,"Die Weisse Strelitzie ist ein beeindruckender Zimmerstrauch mit grossen, blaugruenen Blaettern und weiss-blauen Blueten.",Helles bis volles Licht,18-27 °C,7 +constants/lexiconBatch1.ts,3,Paradiesvogelblume,Strelitzia reginae,flowering|large|sun,3,"Die Paradiesvogelblume beeindruckt mit leuchtend orangefarbenen und blauen Blueten, die einem Vogel aehneln.",Volles Sonnenlicht,18-26 °C,7 +constants/lexiconBatch1.ts,95,Drehfrucht,Streptocarpus hybridus,flowering,1,"Die Drehfrucht ist ein Gesneriengewaechs mit langen, gerippten Blaettern und trichterfoermigen Blueten in Lila oder Rosa.",Helles indirektes Licht,15-22 °C,7 +constants/lexiconBatch1.ts,52,Stromanthe,Stromanthe sanguinea,patterned|high_humidity,2,Die Stromanthe hat dekorative Blaetter mit weissem Muster und leuchtend roter Unterseite. Familie der Marantaceen.,Helles indirektes Licht,18-25 °C,5 +constants/lexiconBatch2.ts,166,Herbstaster,Symphyotrichum novi-belgii,flowering|sun,2,"Herbstaster ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,56,Pfeilblatt,Syngonium podophyllum,easy|hanging,2,"Das Pfeilblatt hat charakteristisch pfeilfoermige Blaetter, die sich mit dem Alter weiterentwickeln.",Helles indirektes Licht,16-27 °C,7 +constants/lexiconBatch2.ts,149,Flieder,Syringa vulgaris,flowering|tree|sun,3,"Flieder ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,66,Studentenblume,Tagetes patula,easy|flowering|sun,3,Die Studentenblume ist eine robuste Sommerblume mit orangen oder gelben Blueten. Sie haelt Schadlinge fern.,Volles Sonnenlicht,15-28 °C,3 +constants/lexiconBatch2.ts,244,Philodendron Xanadu,Thaumatophyllum xanadu,bright_light,1,Philodendron Xanadu ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7 +constants/lexiconBatch1.ts,27,Thymian,Thymus vulgaris,easy|medicinal|sun,3,"Thymian ist ein kleiner, aromatischer Strauch mit winzigen Blaettern und rosa Blueten. Wichtiges Kuechenkraut.",Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch2.ts,33,Luftpflanze,Tillandsia ionantha,easy,1,Die Luftpflanze ist eine kompakte Bromelie ohne Topferde. Sie nimmt Wasser und Naehrstoffe ueber die Blattschuppen auf.,Helles bis volles Licht,15-30 °C,3 +constants/lexiconBatch2.ts,32,Spanisches Moos,Tillandsia usneoides,easy|hanging,2,"Das Spanische Moos ist eine epiphytische Bromelie ohne Wurzeln, die in der Luft haengt. Es benoetigt nur Feuchtigkeitsbespruehing.",Helles bis volles Licht,15-30 °C,3 +constants/lexiconBatch2.ts,55,Weisse Tradescantia,Tradescantia fluminensis,easy|hanging,2,Die Weisse Tradescantia hat gruene Blaetter mit weisslichen Unterseiten. Sehr robust und schnellwachsend.,Helles indirektes Licht,15-25 °C,5 +constants/lexiconBatch2.ts,54,Lila Tradescantia,Tradescantia pallida,easy|hanging|sun,3,Die Lila Tradescantia hat leuchtend purpurrote Blaetter und ist sehr auffaellig. Sie liebt viel Licht.,Helles bis volles Licht,15-25 °C,5 +constants/lexiconBatch1.ts,17,Zebrakraut,Tradescantia zebrina,easy|patterned|hanging,3,Das Zebrakraut faellt durch seine silbrig-lila gestreiften Blaetter auf. Schnellwachsende Haengepflanze.,Helles indirektes Licht,15-25 °C,5 +constants/lexiconBatch2.ts,151,Kapuzinerkresse,Tropaeolum majus,flowering|sun,2,"Kapuzinerkresse ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,107,Tulpe,Tulipa gesneriana,easy|flowering,2,Die Tulpe ist eine der beliebtesten Fruehjahrsblueher mit kelchfoermigen Blueten in unzaehligen Farben.,Helles bis volles Licht,8-18 °C,5 +constants/lexiconBatch2.ts,111,Grosse Brennessel,Urtica dioica,medicinal,1,Die Grosse Brennessel ist eine Heilpflanze mit brennenden Haaren. Die Blaetter sind reich an Vitaminen und Mineralien.,Helles bis volles Licht,10-25 °C,7 +constants/lexiconBatch2.ts,82,Wasserschlauch,Utricularia gibba,high_humidity|sun,2,Der Wasserschlauch ist eine wasserbewohnende fleischfressende Pflanze mit Schlaeuchen als Insekten­fallen.,Helles bis volles Licht,15-25 °C,2 +constants/lexiconBatch2.ts,104,Baldrian,Valeriana officinalis,flowering|medicinal,2,Baldrian ist ein bekanntes Heilkraut mit weissen bis roeslichen Blueten. Die Wurzeln werden zur Schlaffoerderung verwendet.,Helles bis volles Licht,15-25 °C,7 +constants/lexiconBatch1.ts,72,Vanda-Orchidee,Vanda coerulea,flowering|bright_light|high_humidity,3,Die Vanda-Orchidee ist bekannt fuer ihre seltene blaue Bluetenfarbe. Epiphytische Orchidee mit grossen Blueten.,Helles bis volles Licht,20-30 °C,3 +constants/lexiconBatch1.ts,76,Vanille,Vanilla planifolia,flowering|high_humidity,2,"Die Vanille ist eine kletternde Orchidee, aus deren Fruechten das beliebte Gewuerz gewonnen wird.",Helles indirektes Licht,20-30 °C,5 +constants/lexiconBatch2.ts,192,Koenigskerze,Verbascum thapsus,flowering|medicinal|sun,3,"Koenigskerze ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,164,Eisenkraut,Verbena bonariensis,flowering|sun,2,"Eisenkraut ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch2.ts,198,Hornveilchen,Viola cornuta,flowering|sun,2,"Hornveilchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4 +constants/lexiconBatch1.ts,35,Stiefmuetterchen,Viola wittrockiana,easy|flowering,2,Das Stiefmuetterchen ist ein bekannter Fruehjahrsblueher mit charakteristisch gezeichneten Blueten.,Helles bis volles Licht,5-18 °C,3 +constants/lexiconBatch2.ts,35,Flammen-Bromelie,Vriesea splendens,flowering|patterned|high_humidity,3,"Die Flammen-Bromelie hat gebänderte, dunkelgruene Blaetter und einen spektakulaeren, roten Bluetenstand.",Helles indirektes Licht,18-25 °C,7 +constants/lexiconBatch2.ts,5,Mexikanische Fächerpalme,Washingtonia robusta,tree|large|sun,3,"Die Mexikanische Fächerpalme ist eine schlanke, hohe Palme mit faecher­foermigen Blaettern. Sehr hitzetolerant.",Volles Sonnenlicht,15-35 °C,10 +constants/lexiconBatch2.ts,221,Weigelie,Weigela florida,flowering|tree|sun,3,Weigelie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7 +constants/lexiconBatch1.ts,65,Chinesischer Blauregen,Wisteria sinensis,flowering|large|sun,3,"Der Chinesische Blauregen ist ein ueppiger Kletterkuenstler mit langen, duftenden Bluetentrauben in Lila.",Volles Sonnenlicht,10-25 °C,7 +constants/lexiconBatch2.ts,246,Yucca aloifolia,Yucca aloifolia,easy|tree|sun,3,Yucca aloifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Volles Sonnenlicht,18-30 C,10 +constants/lexiconBatch1.ts,40,Yucca-Palme,Yucca elephantipes,easy|tree|sun,3,"Die Yucca-Palme ist eine robuste Zimmerpflanze mit starrem, immergruenem Blaetterschopf auf einem dicken Stamm.",Helles bis volles Licht,15-28 °C,14 +constants/lexiconBatch2.ts,70,Calla,Zantedeschia aethiopica,flowering|high_humidity,2,"Die Calla hat elegante, trichterfoermige weisse Hochblaetter und glaenzende, herzfoermige Blaetter. Sehr edel.",Helles indirektes Licht,15-24 °C,7 +constants/lexiconBatch2.ts,75,Ingwer,Zingiber officinale,medicinal|high_humidity,2,Ingwer ist eine tropische Gewuerzpflanze mit aromatischen Knollen. Die Blaetter sind schilfartig.,Helles indirektes Licht,20-30 °C,5 +constants/lexiconBatch2.ts,65,Zinnie,Zinnia elegans,easy|flowering|sun,3,"Die Zinnie ist eine leuchtende Sommerblume mit grossen, dahlienaehnlichen Blueten. Sehr robust und hitzetolerant.",Volles Sonnenlicht,18-30 °C,3 diff --git a/audits/semantic-search/categories/air_purifier.csv b/audits/semantic-search/categories/air_purifier.csv new file mode 100644 index 0000000..da6a26b --- /dev/null +++ b/audits/semantic-search/categories/air_purifier.csv @@ -0,0 +1,13 @@ +category,source_file,source_index,name,botanical_name,description,light,temp,water_interval_days,all_categories,risk_flags,audit_status,evidence_source,evidence_url,notes +air_purifier,constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,Die Bergpalme ist eine kompakte Zimmerpalme fuer schattigere Standorte. Ideal fuer dunkle Innenraeume.,Wenig bis helles Licht,15-25 °C,7,easy|pet_friendly|tree|air_purifier|low_light,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,48,Dieffenbachie,Dieffenbachia seguine,"Die Dieffenbachie ist eine tropische Blattschmuckpflanze mit grossen, gruen-weiss gefleckten Blaettern.",Helles indirektes Licht,18-26 °C,7,easy|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,14,Maisstrauch,Dracaena fragrans,"Der Maisstrauch ist eine robuste Zimmerpflanze mit breiten, gestreiften Blaettern. Gedeiht auch bei wenig Licht.",Helles indirektes Licht,15-25 °C,10,easy|tree|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,13,Drachenbaum,Dracaena marginata,"Der Drachenbaum ist eine schlanke Zimmerpflanze mit roten, schmalen Blaettern auf langen Staemmen.",Helles indirektes Licht,15-25 °C,10,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,42,Goldfruchtpalme,Dypsis lutescens,Die Goldfruchtpalme ist eine elegante Zimmerpalme mit gelblich-gruenen Stielen und gefiederten Wedeln.,Helles indirektes Licht,18-27 °C,5,pet_friendly|tree|air_purifier,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,16,Marmor-Efeutute,Epipremnum aureum Marble Queen,Die Marmor-Efeutute hat cremeweiss-gruen marmorierte Blaetter. Eine dekorative Variante der klassischen Efeutute.,Helles indirektes Licht,15-30 °C,7,easy|hanging|air_purifier,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch2.ts,53,Neon-Efeutute,Epipremnum pinnatum Neon,Die Neon-Efeutute hat leuchtend limonengruene Blaetter. Sehr auffaellig und pflegeleicht.,Helles indirektes Licht,15-30 °C,7,easy|hanging|air_purifier,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,1,Birkenfeige,Ficus benjamina,"Die Birkenfeige ist ein eleganter Zimmerstrauch mit haengenden Aesten und kleinen, glaenzenden Blaettern.",Helles indirektes Licht,16-24 °C,7,tree|air_purifier,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,38,Gummibaum,Ficus elastica,"Der Gummibaum ist eine imposante Zimmerpflanze mit grossen, glaenzenden, lederartigen Blaettern. Reinigt die Luft.",Helles indirektes Licht,16-24 °C,10,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,68,Gerbera,Gerbera jamesonii,"Die Gerbera ist eine farbenfrohe Schnittblume mit grossen, sonnenblumenaehnlichen Blueten. Sehr beliebt.",Helles bis volles Licht,15-25 °C,5,flowering|air_purifier|bright_light,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,37,Efeu,Hedera helix,"Efeu ist eine robuste Kletter- und Haengepflanze mit charakteristischen, dreilappigen Blaettern. Sehr langlebig.",Wenig bis helles Licht,10-20 °C,7,easy|hanging|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch2.ts,10,Strahlenaralie,Schefflera arboricola,"Die Strahlenaralie hat fingerfoermig angeordnete, glaenzende Blaetter auf langen Stielen. Sehr robuste Zimmerpflanze.",Helles indirektes Licht,15-25 °C,7,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, diff --git a/audits/semantic-search/categories/bright_light.csv b/audits/semantic-search/categories/bright_light.csv new file mode 100644 index 0000000..c68a29c --- /dev/null +++ b/audits/semantic-search/categories/bright_light.csv @@ -0,0 +1,43 @@ +category,source_file,source_index,name,botanical_name,description,light,temp,water_interval_days,all_categories,risk_flags,audit_status,evidence_source,evidence_url,notes +bright_light,constants/lexiconBatch2.ts,225,Alocasia zebrina,Alocasia zebrina,Alocasia zebrina ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,bright_light|high_humidity,,,,, +bright_light,constants/lexiconBatch2.ts,232,Norfolk-Tanne,Araucaria heterophylla,Norfolk-Tanne ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,tree|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,175,Eisbegonie,Begonia semperflorens-cultorum,"Eisbegonie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch1.ts,62,Bougainvillea,Bougainvillea spectabilis,"Die Bougainvillea ist eine rankenreiche Kletterpflanze mit leuchtend farbigen Hochblaettern in Rot, Orange oder Pink.",Volles Sonnenlicht,18-30 °C,5,flowering|bright_light|sun,,,,, +bright_light,constants/lexiconBatch2.ts,184,Trompetenwinde,Campsis radicans,"Trompetenwinde ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,157,Clematis,Clematis viticella,"Clematis ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,224,Kroton,Codiaeum variegatum,Kroton ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,patterned|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,245,Kaffeepflanze arabica nana,Coffea arabica Nana,Kaffeepflanze arabica nana ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,137,Wasabi,Eutrema japonicum,"Wasabi ist ein seltenes Wuerzkraut, das gleichmaessige Feuchte und eher kuehle Bedingungen bevorzugt.",Helles indirektes Licht,8-20 C,4,bright_light|high_humidity,,,,, +bright_light,constants/lexiconBatch2.ts,248,Ficus altissima,Ficus altissima,Ficus altissima ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,tree|bright_light,,,,, +bright_light,constants/lexiconBatch1.ts,39,Geigenfeige,Ficus lyrata,"Die Geigenfeige ist ein Trendbaum mit grossen, geigenfoermigen Blaettern. Benoetigt viel Licht.",Helles indirektes Licht,18-27 °C,7,tree|large|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,247,Ficus microcarpa,Ficus microcarpa,Ficus microcarpa ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|tree|bright_light,,,,, +bright_light,constants/lexiconBatch1.ts,68,Gerbera,Gerbera jamesonii,"Die Gerbera ist eine farbenfrohe Schnittblume mit grossen, sonnenblumenaehnlichen Blueten. Sehr beliebt.",Helles bis volles Licht,15-25 °C,5,flowering|air_purifier|bright_light,air_purifier_requires_external_evidence,,,, +bright_light,constants/lexiconBatch2.ts,72,Heliconia,Heliconia psittacorum,"Die Heliconia hat leuchtend orangefarbe oder rote, bootsfoermige Hochblaetter. Eine exotische Tropenpflanze.",Helles bis volles Licht,20-30 °C,5,flowering|bright_light|high_humidity,,,,, +bright_light,constants/lexiconBatch1.ts,21,Hibiskus,Hibiscus rosa-sinensis,"Der Hibiskus begeistert mit grossen, trompetenfoermigen Blueten in Rot, Orange und Rosa.",Volles Sonnenlicht,18-28 °C,3,flowering|bright_light|sun,,,,, +bright_light,constants/lexiconBatch1.ts,105,Ritterstern,Hippeastrum hybrid,"Der Ritterstern beeindruckt im Winter mit riesigen, trompetenfoermigen Blueten in Rot, Pink oder Weiss.",Helles bis volles Licht,18-25 °C,7,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,148,Hortensie,Hydrangea macrophylla,"Hortensie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Helles bis halbschattiges Licht,8-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,227,Punktblatt,Hypoestes phyllostachya,Punktblatt ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,patterned|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,176,Gartenbalsamine,Impatiens balsamina,"Gartenbalsamine ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,172,Arabischer Jasmin,Jasminum sambac,"Arabischer Jasmin ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,197,Traenendes Herz,Lamprocapnos spectabilis,"Traenendes Herz ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,64,Wandelroeschen,Lantana camara,"Das Wandelroeschen hat kugelige Bluetenkoepfe, die die Farbe von Gelb ueber Orange zu Rot wechseln. Sehr attraktiv.",Volles Sonnenlicht,18-28 °C,5,flowering|bright_light|sun,,,,, +bright_light,constants/lexiconBatch1.ts,23,Echter Lavendel,Lavandula angustifolia,Der Echte Lavendel ist ein aromatischer Halbstrauch mit lilafarbenen Bluetenaehren. Herrlicher Duft.,Volles Sonnenlicht,10-25 °C,10,medicinal|bright_light|sun,medicinal_requires_external_evidence,,,, +bright_light,constants/lexiconBatch2.ts,69,Ostertrompete,Lilium longiflorum,"Die Ostertrompete hat grosse, weisse, trichterfoermige Blueten mit intensivem Duft. Klassische Osterblume.",Helles bis volles Licht,15-25 °C,5,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,4,Chinesische Fächerpalme,Livistona chinensis,"Die Chinesische Fächerpalme hat grosse, faecher­foermige Blaetter auf einem einzelnen Stamm. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,7,tree|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,171,Geissblatt,Lonicera japonica,"Geissblatt ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,76,Schamkraut,Mimosa pudica,"Das Schamkraut faltet seine Blaettchen blitzschnell zusammen, wenn man sie beruehrt. Ein faszinierendes Erlebnis.",Helles bis volles Licht,20-28 °C,5,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,37,Neoregelia,Neoregelia carolinae,"Die Neoregelia ist eine Bromelie, bei der das Herzblatt zur Bluetzeit leuchtend rot wird. Sehr dekorativ.",Helles bis volles Licht,18-27 °C,7,flowering|patterned|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,120,Oleander,Nerium oleander,"Der Oleander ist ein mediteraner Strauch mit leuchtend roten, rosa oder weissen Blueten. Sehr hitzetolerant.",Volles Sonnenlicht,15-28 °C,7,flowering|bright_light|sun,,,,, +bright_light,constants/lexiconBatch2.ts,231,Glueckskastanie,Pachira aquatica,Glueckskastanie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|tree|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,6,Schraubenbaum,Pandanus veitchii,"Der Schraubenbaum hat spiralfoermig angeordnete, gruenweiss gestreifte Blaetter. Sehr dekorativ und exotisch.",Helles bis volles Licht,18-27 °C,7,patterned|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,243,Philodendron Pink Princess,Philodendron erubescens Pink Princess,Philodendron Pink Princess ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,patterned|bright_light,,,,, +bright_light,constants/lexiconBatch1.ts,44,Zwergdattelpalme,Phoenix roebelenii,"Die Zwergdattelpalme ist eine zierliche Palme mit eleganten, gebogenen Fiederblaettern. Tropisches Flair.",Helles bis volles Licht,18-27 °C,7,tree|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,152,Buntnessel,Plectranthus scutellarioides,"Buntnessel ist eine farbstarke Zierpflanze, die vor allem fuer ihr dekoratives Laub beliebt ist.",Volles bis helles Licht,10-24 C,4,patterned|bright_light,,,,, +bright_light,constants/lexiconBatch1.ts,61,Bleiwurz,Plumbago auriculata,"Die Bleiwurz ist ein halbimmergruener Strauch mit himmelblauen Blueten, der fast das ganze Jahr bluet.",Volles Sonnenlicht,15-27 °C,5,flowering|bright_light|sun,,,,, +bright_light,constants/lexiconBatch2.ts,170,Rhododendron,Rhododendron catawbiense,"Rhododendron ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|tree|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,142,Rose,Rosa x hybrida,"Rose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light|sun,,,,, +bright_light,constants/lexiconBatch2.ts,235,Falsche Aralie,Schefflera elegantissima,Falsche Aralie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,tree|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,93,Aubergine,Solanum melongena,"Die Aubergine ist eine Gemuese­pflanze mit grossen, violetten Fruechten. Sie benoetigt viel Waerme und Sonne.",Volles Sonnenlicht,20-30 °C,5,bright_light|sun,,,,, +bright_light,constants/lexiconBatch2.ts,1,Weisse Strelitzie,Strelitzia nicolai,"Die Weisse Strelitzie ist ein beeindruckender Zimmerstrauch mit grossen, blaugruenen Blaettern und weiss-blauen Blueten.",Helles bis volles Licht,18-27 °C,7,tree|large|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,244,Philodendron Xanadu,Thaumatophyllum xanadu,Philodendron Xanadu ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,bright_light,,,,, +bright_light,constants/lexiconBatch1.ts,72,Vanda-Orchidee,Vanda coerulea,Die Vanda-Orchidee ist bekannt fuer ihre seltene blaue Bluetenfarbe. Epiphytische Orchidee mit grossen Blueten.,Helles bis volles Licht,20-30 °C,3,flowering|bright_light|high_humidity,,,,, diff --git a/audits/semantic-search/categories/easy.csv b/audits/semantic-search/categories/easy.csv new file mode 100644 index 0000000..f0d63e7 --- /dev/null +++ b/audits/semantic-search/categories/easy.csv @@ -0,0 +1,133 @@ +category,source_file,source_index,name,botanical_name,description,light,temp,water_interval_days,all_categories,risk_flags,audit_status,evidence_source,evidence_url,notes +easy,constants/lexiconBatch2.ts,31,Adromischus,Adromischus cristatus,Adromischus ist eine kompakte Sukkulente mit ungewoehnlich wellenrandigen Blaettern auf kurzen Staengeln.,Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,50,Aglaoneme,Aglaonema commutatum,Die Aglaoneme ist eine dekorative Zimmerpflanze mit silbrig-gruen gemusterten Blaettern. Tolerant gegenueber wenig Licht.,Wenig bis helles Licht,15-26 °C,7,easy|patterned|low_light,,,,, +easy,constants/lexiconBatch1.ts,30,Schnittlauch,Allium schoenoprasum,Schnittlauch ist ein beliebtes Kuechenkraut mit roehrenfoermigen Blaettern und lila Blueten.,Helles bis volles Licht,10-25 °C,3,easy,,,,, +easy,constants/lexiconBatch2.ts,135,Schnittknoblauch,Allium tuberosum,Schnittknoblauch ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch1.ts,89,Kap-Aloe,Aloe arborescens,"Die Kap-Aloe ist eine strauchige Aloe mit schmalen, gezaehnten Blaettern und leuchtend roten Bluetenaehren im Winter.",Volles Sonnenlicht,10-30 °C,14,easy|succulent|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,128,Zitronenverbene,Aloysia citrodora,Zitronenverbene ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,140,Dill,Anethum graveolens,Dill ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,125,Kerbel,Anthriscus cerefolium,Kerbel ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,122,Estragon,Artemisia dracunculus,Estragon ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,16,Schusterpflanze,Aspidistra elatior,"Die Schusterpflanze ist eine extrem robuste Zimmerpflanze mit langen, dunkelgruenen Blaettern. Vertraegt tiefe Temperaturen.",Wenig bis helles Licht,10-20 °C,14,easy|low_light,,,,, +easy,constants/lexiconBatch2.ts,43,Vogelnest-Farn,Asplenium nidus,"Der Vogelnest-Farn hat ganzrandige, glaenzende Wedel, die eine Nestform bilden. Sehr dekorativ und robust.",Helles indirektes Licht,18-27 °C,5,easy|low_light|high_humidity,,,,, +easy,constants/lexiconBatch2.ts,13,Japanische Aucube,Aucuba japonica,"Die Japanische Aucube hat glaenzende, gruene oder gelbgefleckte Blaetter. Sehr schattenvertraeglich.",Wenig bis helles Licht,10-20 °C,7,easy|low_light,,,,, +easy,constants/lexiconBatch2.ts,7,Bambusrohr,Bambusa vulgaris,Das Bambusrohr ist eine schnell wachsende Bambusart mit gelbgruenen Halmen. Sehr dekorativ und vielseitig nutzbar.,Helles bis volles Licht,15-30 °C,5,easy|large,,,,, +easy,constants/lexiconBatch1.ts,41,Pferdeschwanzpalme,Beaucarnea recurvata,"Die Pferdeschwanzpalme hat einen verdickten Stammbasis als Wasserspeicher und lange, schmale Blaetter.",Volles Sonnenlicht,15-30 °C,21,easy|succulent|tree|sun,,,,, +easy,constants/lexiconBatch2.ts,97,Mangold,Beta vulgaris,"Mangold ist ein farbenfrohes Blattgemuese mit bunten Stielen in Rot, Gelb, Orange und Weiss.",Helles bis volles Licht,10-25 °C,3,easy,,,,, +easy,constants/lexiconBatch2.ts,38,Billbergia,Billbergia nutans,"Die Billbergia ist eine robuste Bromelie mit schmalen, gruenen Blaettern und hängenden, blauen und gruenen Blueten.",Helles indirektes Licht,15-25 °C,7,easy|flowering,,,,, +easy,constants/lexiconBatch2.ts,129,Borretsch,Borago officinalis,Borretsch ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,63,Calibrachoa,Calibrachoa hybrida,"Calibrachoa ist eine petunienaehnliche Haengepflanze mit unzaehligen, kleinen Trichterbluten in allen Farben.",Volles Sonnenlicht,15-25 °C,2,easy|flowering|hanging|sun,,,,, +easy,constants/lexiconBatch2.ts,56,Callisia,Callisia repens,"Callisia repens ist ein kleines, kriechendes Kraut mit winzigen, gruenen Blaettern. Ideal fuer haengende Behaelter.",Helles indirektes Licht,15-25 °C,5,easy|hanging,,,,, +easy,constants/lexiconBatch2.ts,92,Chili,Capsicum annuum,"Chili ist eine beliebte Gemuese- und Zierpflanze mit leuchtenden, roten oder orangen Fruechten. Im Topf kultivierbar.",Volles Sonnenlicht,20-30 °C,4,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,81,Peruanischer Fackelkaktus,Cereus peruvianus,"Der Peruanische Fackelkaktus ist ein saeulenfoermiger Kaktus, der im Innenraum bis zu 2 m hoch werden kann.",Volles Sonnenlicht,15-35 °C,21,easy|succulent|large|sun,,,,, +easy,constants/lexiconBatch1.ts,99,Herzkette,Ceropegia woodii,"Die Herzkette hat duenne, haengende Ranken mit herzfoermigen, silbergrau gemusterten Blaettchen.",Helles indirektes Licht,15-27 °C,14,easy|succulent|patterned|hanging,,,,, +easy,constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,Die Bergpalme ist eine kompakte Zimmerpalme fuer schattigere Standorte. Ideal fuer dunkle Innenraeume.,Wenig bis helles Licht,15-25 °C,7,easy|pet_friendly|tree|air_purifier|low_light,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,138,Roemische Kamille,Chamaemelum nobile,Roemische Kamille ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,101,Kamille,Chamomilla recutita,"Die Kamille ist ein beliebtes Heilkraut mit kleinen, weiss-gelben Blueten. Das aetherische Oel wirkt beruhigend.",Volles Sonnenlicht,15-25 °C,5,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,84,Kaffeestrauch,Coffea arabica,"Der Kaffeestrauch hat glaenzende, dunkelgruene Blaetter und entwickelt rote Kaffe­ekirschen. Kann im Topf gehalten werden.",Helles indirektes Licht,18-25 °C,7,easy,,,,, +easy,constants/lexiconBatch2.ts,14,Keulenlilie,Cordyline australis,"Die Keulenlilie hat lange, schmale, gruene oder rotbraune Blaetter in einem dekorativen Schopf.",Helles bis volles Licht,10-25 °C,7,easy|tree|sun,,,,, +easy,constants/lexiconBatch2.ts,15,Tiroler Keulenlilie,Cordyline fruticosa,"Die Tiroler Keulenlilie hat leuchtend rote, gruene oder buntlaubige Blaetter. Eine exotische Zimmerpflanze.",Helles indirektes Licht,18-27 °C,7,easy,,,,, +easy,constants/lexiconBatch2.ts,139,Koriander,Coriandrum sativum,Koriander ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,29,Kotyledon,Cotyledon orbiculata,"Kotyledon hat dickfleischige, runde Blaetter mit einem mehligen, weisslichen Belag. Sehr trockenheitsresistent.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,26,Moos-Crassula,Crassula muscosa,"Die Moos-Crassula hat dicht aneinandergereihte, winzige gruene Blaetter auf unverzweigten Trieben. Sieht aus wie Moos.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,5,Jadepflanze,Crassula ovata,"Die Jadepflanze ist eine langlebige Sukkulente mit dicken, ovalen Blaettern. In Japan gilt sie als Gluecksbringer.",Helles bis volles Licht,15-24 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,110,Krokus,Crocus vernus,"Der Krokus ist einer der ersten Fruehjahrs­boten mit kelchfoermigen Blueten in Lila, Weiss und Gelb.",Helles bis volles Licht,5-15 °C,7,easy|flowering,,,,, +easy,constants/lexiconBatch2.ts,94,Gurke,Cucumis sativus,"Die Gurke ist eine rankende Gemuese­pflanze mit gruenen, erfrischenden Fruechten. Im Balkonkasten kultivierbar.",Volles Sonnenlicht,18-28 °C,3,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,127,Zitronengras,Cymbopogon citratus,Zitronengras ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,99,Karotte,Daucus carota,Die Karotte ist eine beliebte Gemuese­pflanze mit orangefarbenen Wurzeln. Im tiefen Topf kultivierbar.,Helles bis volles Licht,15-22 °C,5,easy,,,,, +easy,constants/lexiconBatch1.ts,48,Dieffenbachie,Dieffenbachia seguine,"Die Dieffenbachie ist eine tropische Blattschmuckpflanze mit grossen, gruen-weiss gefleckten Blaettern.",Helles indirektes Licht,18-26 °C,7,easy|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,14,Maisstrauch,Dracaena fragrans,"Der Maisstrauch ist eine robuste Zimmerpflanze mit breiten, gestreiften Blaettern. Gedeiht auch bei wenig Licht.",Helles indirektes Licht,15-25 °C,10,easy|tree|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,13,Drachenbaum,Dracaena marginata,"Der Drachenbaum ist eine schlanke Zimmerpflanze mit roten, schmalen Blaettern auf langen Staemmen.",Helles indirektes Licht,15-25 °C,10,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,30,Dudleya,Dudleya brittonii,"Dudleya ist eine rosetten­bildende Sukkulente mit silbrig-weissen, mehligen Blaettern. Sehr elegant.",Volles Sonnenlicht,10-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,4,Echeverie,Echeveria elegans,"Die Echeverie bildet symmetrische, rosettenfoermige Sukkulenten mit blaugruenen Blaettern. Pflegeleicht.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,77,Goldene Tonne,Echinocactus grusonii,Die Goldene Tonne ist ein ikonischer kugelfoermiger Kaktus mit goldgelben Stacheln. Waechst langsam aber imposant.,Volles Sonnenlicht,15-35 °C,21,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,83,San-Pedro-Kaktus,Echinopsis pachanoi,"Der San-Pedro-Kaktus ist ein schnell wachsender, saeulenfoermiger Kaktus aus den Anden.",Volles Sonnenlicht,10-35 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,16,Marmor-Efeutute,Epipremnum aureum Marble Queen,Die Marmor-Efeutute hat cremeweiss-gruen marmorierte Blaetter. Eine dekorative Variante der klassischen Efeutute.,Helles indirektes Licht,15-30 °C,7,easy|hanging|air_purifier,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,53,Neon-Efeutute,Epipremnum pinnatum Neon,Die Neon-Efeutute hat leuchtend limonengruene Blaetter. Sehr auffaellig und pflegeleicht.,Helles indirektes Licht,15-30 °C,7,easy|hanging|air_purifier,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,19,Christusdorn,Euphorbia milii,Der Christusdorn ist eine sukkulente Wolfsmilch mit stacheligen Zweigen und kleinen roten oder gelben Hochblaettern.,Helles bis volles Licht,15-28 °C,10,easy|flowering|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,12,Bleistiftkaktus,Euphorbia tirucalli,"Der Bleistiftkaktus ist eine sukkulente Wolfsmilch mit duennen, zylindrischen Zweigen ohne Blaetter.",Volles Sonnenlicht,18-30 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,12,Fatsia,Fatsia japonica,"Die Fatsia ist ein dekorativer Zimmerstrauch mit grossen, handfoermigen, glaenzenden Blaettern. Sehr robust.",Helles indirektes Licht,10-20 °C,7,easy|low_light,,,,, +easy,constants/lexiconBatch1.ts,78,Fass-Kaktus,Ferocactus cylindraceus,"Der Fass-Kaktus ist ein zylindrischer Wuestenkaktus mit langen, roten Stacheln. Sehr langlebig.",Volles Sonnenlicht,15-35 °C,21,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,38,Gummibaum,Ficus elastica,"Der Gummibaum ist eine imposante Zimmerpflanze mit grossen, glaenzenden, lederartigen Blaettern. Reinigt die Luft.",Helles indirektes Licht,16-24 °C,10,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,247,Ficus microcarpa,Ficus microcarpa,Ficus microcarpa ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|tree|bright_light,,,,, +easy,constants/lexiconBatch2.ts,100,Erdbeere,Fragaria ananassa,"Die Erdbeere ist ein beliebtes Obst fuer Balkon und Terrasse mit aromatischen, roten Fruechten.",Helles bis volles Licht,15-25 °C,3,easy|pet_friendly|sun,pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,90,Gasteria,Gasteria carinata,"Die Gasteria ist eine kleine Sukkulente mit zweireihig angeordneten, zungenfoermigen, gefleckten Blaettern.",Helles indirektes Licht,15-25 °C,14,easy|succulent|low_light,,,,, +easy,constants/lexiconBatch1.ts,32,Blutroter Storchschnabel,Geranium sanguineum,Der Blutrote Storchschnabel ist ein zierlicher Storchschnabel mit intensiv magentafarbenen Blueten.,Helles bis volles Licht,10-25 °C,7,easy|flowering,,,,, +easy,constants/lexiconBatch1.ts,87,Geisterpflanze,Graptopetalum paraguayense,"Die Geisterpflanze hat zartgraue bis perlmutt-rosafarbene, rosettenfoermige Blaetter. Sehr robuste Sukkulente.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,80,Mond-Kaktus,Gymnocalycium mihanovichii,Der Mond-Kaktus ist eine farbenfrohe Veredelung eines chlorophylllosen Kaktus auf einem gruenen Unterlagekaktus.,Indirektes Licht,15-30 °C,14,easy|succulent,,,,, +easy,constants/lexiconBatch1.ts,6,Zebra-Haworthie,Haworthia fasciata,Die Zebra-Haworthie ist eine kompakte Sukkulente mit weissen Querstreifen auf dunkelgruenen Blaettern.,Helles indirektes Licht,15-25 °C,14,easy|succulent|low_light,,,,, +easy,constants/lexiconBatch1.ts,37,Efeu,Hedera helix,"Efeu ist eine robuste Kletter- und Haengepflanze mit charakteristischen, dreilappigen Blaettern. Sehr langlebig.",Wenig bis helles Licht,10-20 °C,7,easy|hanging|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,133,Currykraut,Helichrysum italicum,Currykraut ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch1.ts,57,Wachsblume,Hoya carnosa,"Die Wachsblume ist eine Kletterpflanze mit dicken, wachsartigen Blaettern und sternfoermigen, duftenden Blueten.",Helles indirektes Licht,16-27 °C,10,easy|flowering|succulent|hanging,,,,, +easy,constants/lexiconBatch1.ts,108,Hyazinthe,Hyacinthus orientalis,"Die Hyazinthe bezaubert mit dichten Bluetenrispen und intensivem Duft in Blau, Rosa, Weiss oder Gelb.",Helles bis volles Licht,10-18 °C,5,easy|flowering,,,,, +easy,constants/lexiconBatch2.ts,136,Ysop,Hyssopus officinalis,Ysop ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,59,Neuguinea-Balsamine,Impatiens hawkeri,"Die Neuguinea-Balsamine hat grosse, leuchtende Blueten und ist sehr bluehfreudig. Ideal fuer Terrassen.",Helles indirektes Licht,18-27 °C,3,easy|flowering,,,,, +easy,constants/lexiconBatch1.ts,20,Fleissiges Lieschen,Impatiens walleriana,Das Fleissige Lieschen bluet von Fruehling bis Herbst unermudlich in vielen Farben.,Helles indirektes Licht,16-24 °C,2,easy|flowering,,,,, +easy,constants/lexiconBatch1.ts,64,Suesskartoffel,Ipomoea batatas,"Die Suesskartoffel-Zierpflanze hat dekorative, herzfoermige Blaetter in gruen oder dunkelviolett. Ideal als Haengepflanze.",Volles Sonnenlicht,20-30 °C,5,easy|hanging|sun,,,,, +easy,constants/lexiconBatch1.ts,9,Kalanchoe,Kalanchoe blossfeldiana,"Die Kalanchoe ist eine beliebte Bluehpflanze mit leuchtenden Blueten in Rot, Orange, Gelb oder Rosa.",Helles bis volles Licht,15-25 °C,10,easy|flowering|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,22,Brutblatt,Kalanchoe daigremontiana,Das Brutblatt bildet entlang des Blattrandes zahlreiche kleine Jungpflanzen. Eine faszinierende Sukkulente.,Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,21,Kaninchen-Ohren,Kalanchoe tomentosa,"Kaninchen-Ohren haben weisslich-filzige Blaetter mit braunen Raendern, die Kaninchen­ohren aehneln. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,95,Salat,Lactuca sativa,Salat ist eine schnell wachsende Blattgemuese­pflanze. Im Topf und Balkonkasten sehr gut zu kultivieren.,Helles bis volles Licht,10-22 °C,3,easy,,,,, +easy,constants/lexiconBatch2.ts,121,Lorbeer,Laurus nobilis,Lorbeer ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,126,Liebstoeckel,Levisticum officinale,Liebstoeckel ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,62,Duftsteinrich,Lobularia maritima,"Der Duftsteinrich ist ein niedrig wachsendes Pflanzchen mit winzigen, weissen oder lilafarbenen Blueten und suessem Duft.",Helles bis volles Licht,10-22 °C,3,easy|flowering,,,,, +easy,constants/lexiconBatch1.ts,79,Mammillaria,Mammillaria zeilmanniana,"Die Mammillaria ist ein kompakter, kugelfoermiger Kaktus, der im Fruehling einen Kranz aus rosa Blueten traegt.",Volles Sonnenlicht,15-35 °C,14,easy|flowering|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,102,Zitronenmelisse,Melissa officinalis,Die Zitronenmelisse ist ein zitronig duftendes Heilkraut. Sie beruhigt die Nerven und foerdert den Schlaf.,Helles bis volles Licht,15-25 °C,5,easy|medicinal,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,26,Gruene Minze,Mentha spicata,"Die Gruene Minze ist ein wuchsfreudiges Kuechenkraut mit frischem, minzigem Duft. Fuer Tee und Cocktails.",Helles bis volles Licht,15-25 °C,3,easy,,,,, +easy,constants/lexiconBatch2.ts,47,Monstera adansonii,Monstera adansonii,Monstera adansonii hat herzfoermige Blaetter mit zahlreichen runden Lochern. Eine rankende Zimmerpflanze.,Helles indirektes Licht,18-27 °C,7,easy|hanging,,,,, +easy,constants/lexiconBatch1.ts,109,Traubenhyazinthe,Muscari armeniacum,"Die Traubenhyazinthe bildet dichte Trauben aus kleinen, blauen bis violetten Gloeckchen. Zuverlaessige Fruejahrszwiebel.",Helles bis volles Licht,8-18 °C,7,easy|flowering,,,,, +easy,constants/lexiconBatch2.ts,132,Katzenminze,Nepeta cataria,Katzenminze ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch1.ts,25,Basilikum,Ocimum basilicum,"Basilikum ist das beliebteste Kuechenkraut mit intensiv aromatischen, gruenen Blaettern. Fuer Pesto verwendet.",Volles Sonnenlicht,18-30 °C,2,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,82,Hasenohren-Kaktus,Opuntia microdasys,"Der Hasenohren-Kaktus hat flache, ovale Triebe mit dichten weissen Glochiden. Klassischer Zimmerkaktus.",Volles Sonnenlicht,10-35 °C,21,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,124,Majoran,Origanum majorana,Majoran ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch1.ts,28,Oregano,Origanum vulgare,"Oregano ist ein aromatisches Kuechenkraut mit runden, behaarten Blaettern. In mediterraner Kueche beliebt.",Volles Sonnenlicht,15-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,231,Glueckskastanie,Pachira aquatica,Glueckskastanie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|tree|bright_light,,,,, +easy,constants/lexiconBatch1.ts,88,Mondstein-Pflanze,Pachyphytum oviferum,"Die Mondstein-Pflanze hat dicke, ovale Blaetter mit einem pastellrosafarbenen, mehligen Ueberzug.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,31,Rosengeranie,Pelargonium graveolens,Die Rosengeranie ist eine Duftpflanze mit tief eingeschnittenen Blaettern und rosaenlichem Aroma.,Volles Sonnenlicht,15-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,61,Efeu-Geranie,Pelargonium peltatum,"Die Efeu-Geranie hat efeufoermige, glaenzende Blaetter und bluet den ganzen Sommer in leuchtenden Farben.",Helles bis volles Licht,15-25 °C,5,easy|flowering|hanging|sun,,,,, +easy,constants/lexiconBatch1.ts,102,Rippenpeperomie,Peperomia caperata,"Die Rippenpeperomie hat tief gerippte, dunkelgruene bis violette Blaetter mit einer samtigen Textur.",Helles indirektes Licht,18-26 °C,10,easy|pet_friendly,pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,103,Spiegelpeperomie,Peperomia obtusifolia,"Die Spiegelpeperomie hat glaenzende, lederartige, oval-runde Blaetter in tiefem Gruen. Sehr robust.",Helles indirektes Licht,16-26 °C,10,easy|pet_friendly|low_light,pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,230,Raindrop-Peperomie,Peperomia polybotrya,Raindrop-Peperomie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|pet_friendly,pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,134,Shiso,Perilla frutescens,Shiso ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch1.ts,29,Petersilie,Petroselinum crispum,Petersilie ist eines der meistgenutzten Kuechenkraeuter mit frisch-aromatischem Geschmack. Reich an Vitaminen.,Helles Licht,10-25 °C,3,easy,,,,, +easy,constants/lexiconBatch1.ts,34,Petunie,Petunia hybrida,Die Petunie ist eine der beliebtesten Balkonpflanzen mit trichterfoermigen Blueten in unzaehligen Farben.,Volles Sonnenlicht,15-25 °C,2,easy|pet_friendly|flowering|sun,pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,50,Philodendron bipinnatifidum,Philodendron bipinnatifidum,"Philodendron bipinnatifidum hat grosse, tief gelappte Blaetter. Er entwickelt einen beeindruckenden, baumfoermigen Wuchs.",Helles indirektes Licht,18-27 °C,7,easy|large,,,,, +easy,constants/lexiconBatch2.ts,51,Roter Philodendron,Philodendron erubescens,"Der Rote Philodendron hat glaenzende, herzfoermige Blaetter, die jung roetrlich erscheinen. Sehr dekorativ.",Helles indirektes Licht,18-27 °C,7,easy|hanging,,,,, +easy,constants/lexiconBatch1.ts,15,Herzblatt-Philodendron,Philodendron hederaceum,Der Herzblatt-Philodendron ist eine pflegeleichte Kletter- oder Haengepflanze mit herzfoermigen Blaettern.,Indirektes Licht,18-28 °C,7,easy|hanging|low_light,,,,, +easy,constants/lexiconBatch2.ts,242,Philodendron Brasil,Philodendron hederaceum Brasil,Philodendron Brasil ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|hanging|low_light,,,,, +easy,constants/lexiconBatch2.ts,8,Goldener Bambus,Phyllostachys aurea,"Der Goldene Bambus hat elegante, goldgelbe Halme mit engstehenden Knoten. Sehr dekorativ als Sichtschutz.",Helles bis volles Licht,10-30 °C,5,easy|large,,,,, +easy,constants/lexiconBatch2.ts,228,Aluminium-Pflanze,Pilea cadierei,Aluminium-Pflanze ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|pet_friendly|patterned,pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,2,Ufopflanze,Pilea peperomioides,"Die Ufopflanze hat unverwechselbare, runde Blaetter auf langen Stielen. Bildet leicht Ableger zum Verschenken.",Helles indirektes Licht,13-30 °C,7,easy|pet_friendly,pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,44,Tueipelfarn,Polypodium vulgare,Der Tueipelfarn ist ein heimischer Farn mit gelappten Wedeln und runden Sporenhaeufchen auf der Unterseite.,Helles indirektes Licht,10-20 °C,7,easy,,,,, +easy,constants/lexiconBatch2.ts,27,Speckbaum,Portulacaria afra,"Der Speckbaum ist eine sukkulente Pflanze mit roten Stielen und kleinen, runden, glaenzenden Blaettern.",Helles bis volles Licht,15-30 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,98,Radieschen,Raphanus sativus,"Das Radieschen ist ein schnellwachsendes Gemuese mit runden, roten Knollen. Es reift in nur 3-4 Wochen.",Helles bis volles Licht,10-22 °C,2,easy,,,,, +easy,constants/lexiconBatch2.ts,52,Mini-Monstera,Rhaphidophora tetrasperma,"Die Mini-Monstera hat monstera­aehnliche, gelochte Blaetter auf einer kompakten, klettternden Pflanze. Sehr trendig.",Helles indirektes Licht,18-27 °C,7,easy|hanging,,,,, +easy,constants/lexiconBatch1.ts,24,Rosmarin,Rosmarinus officinalis,Rosmarin ist ein aromatisches Kraut mit nadelartigen Blaettern und blauen Blueten. In der Kueche unverzichtbar.,Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,130,Sauerampfer,Rumex acetosa,Sauerampfer ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch1.ts,94,Afrikanisches Veilchen,Saintpaulia ionantha,"Das Afrikanische Veilchen ist eine kleine, kompakte Bluehpflanze mit samtigen Blaettern und violetten Blueten.",Helles indirektes Licht,18-25 °C,7,easy|flowering,,,,, +easy,constants/lexiconBatch2.ts,103,Salbei,Salvia officinalis,Salbei ist ein aromatisches Heilkraut mit silbrig-gruenen Blaettern. Er hat antibakterielle und entzuendungshem­mende Wirkung.,Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,17,Zylindrischer Bogenhanf,Sansevieria cylindrica,"Der Zylindrische Bogenhanf hat zylindrische, aufrechte Blaetter, die sich nach oben verjuengen. Sehr pflegeleicht.",Helles bis volles Licht,15-27 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,123,Bohnenkraut,Satureja hortensis,Bohnenkraut ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,11,Grosse Strahlenaralie,Schefflera actinophylla,"Die Grosse Strahlenaralie kann grosse, handfoermige Blaetter entwickeln. Sie ist ideal als Zimmerstrauch.",Helles indirektes Licht,18-27 °C,7,easy|tree|large,,,,, +easy,constants/lexiconBatch2.ts,10,Strahlenaralie,Schefflera arboricola,"Die Strahlenaralie hat fingerfoermig angeordnete, glaenzende Blaetter auf langen Stielen. Sehr robuste Zimmerpflanze.",Helles indirektes Licht,15-25 °C,7,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,8,Weihnachtskaktus,Schlumbergera truncata,"Der Weihnachtskaktus erfreut zur Weihnachtszeit mit leuchtenden Blueten in Rosa, Rot oder Weiss.",Helles indirektes Licht,15-21 °C,7,easy|flowering|succulent,,,,, +easy,constants/lexiconBatch1.ts,55,Satinpothos,Scindapsus pictus,"Der Satinpothos hat samtig-glaenzende, silbrig gefleckte Blaetter auf langen, haengenden Ranken.",Helles indirektes Licht,18-28 °C,7,easy|patterned|hanging,,,,, +easy,constants/lexiconBatch1.ts,7,Eselschwanz,Sedum morganianum,"Der Eselschwanz ist eine haengende Sukkulente mit langen Trieben aus dichten, blaugruenen Blaettchen.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|hanging|sun,,,,, +easy,constants/lexiconBatch1.ts,100,Perlenschnur-Pflanze,Senecio rowleyanus,"Die Perlenschnur-Pflanze hat haengende Ranken mit kugelfoermigen, perlenaehnlichen Blaettern. Einzigartige Sukkulente.",Helles bis volles Licht,15-27 °C,14,easy|succulent|hanging,,,,, +easy,constants/lexiconBatch2.ts,28,Blauer Kreuzkraut,Senecio serpens,"Der Blaue Kreuzkraut hat zylindrische, blaublaugruene Blaetter und einen kriechenden Wuchs. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,91,Tomate,Solanum lycopersicum,"Die Tomate ist eine beliebte Gemuese- und Balkonpflanze mit roten, saftigen Fruechten. Im Topf kultivierbar.",Volles Sonnenlicht,18-28 °C,3,easy,,,,, +easy,constants/lexiconBatch2.ts,96,Spinat,Spinacia oleracea,Spinat ist ein naehrstoffreiches Blattgemuese mit dunkelgruenen Blaettern. Reich an Eisen und Vitaminen.,Helles bis volles Licht,10-20 °C,3,easy,,,,, +easy,constants/lexiconBatch2.ts,131,Stevia,Stevia rebaudiana,Stevia ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch1.ts,56,Pfeilblatt,Syngonium podophyllum,"Das Pfeilblatt hat charakteristisch pfeilfoermige Blaetter, die sich mit dem Alter weiterentwickeln.",Helles indirektes Licht,16-27 °C,7,easy|hanging,,,,, +easy,constants/lexiconBatch2.ts,66,Studentenblume,Tagetes patula,Die Studentenblume ist eine robuste Sommerblume mit orangen oder gelben Blueten. Sie haelt Schadlinge fern.,Volles Sonnenlicht,15-28 °C,3,easy|flowering|sun,,,,, +easy,constants/lexiconBatch1.ts,27,Thymian,Thymus vulgaris,"Thymian ist ein kleiner, aromatischer Strauch mit winzigen Blaettern und rosa Blueten. Wichtiges Kuechenkraut.",Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,33,Luftpflanze,Tillandsia ionantha,Die Luftpflanze ist eine kompakte Bromelie ohne Topferde. Sie nimmt Wasser und Naehrstoffe ueber die Blattschuppen auf.,Helles bis volles Licht,15-30 °C,3,easy,,,,, +easy,constants/lexiconBatch2.ts,32,Spanisches Moos,Tillandsia usneoides,"Das Spanische Moos ist eine epiphytische Bromelie ohne Wurzeln, die in der Luft haengt. Es benoetigt nur Feuchtigkeitsbespruehing.",Helles bis volles Licht,15-30 °C,3,easy|hanging,,,,, +easy,constants/lexiconBatch2.ts,55,Weisse Tradescantia,Tradescantia fluminensis,Die Weisse Tradescantia hat gruene Blaetter mit weisslichen Unterseiten. Sehr robust und schnellwachsend.,Helles indirektes Licht,15-25 °C,5,easy|hanging,,,,, +easy,constants/lexiconBatch2.ts,54,Lila Tradescantia,Tradescantia pallida,Die Lila Tradescantia hat leuchtend purpurrote Blaetter und ist sehr auffaellig. Sie liebt viel Licht.,Helles bis volles Licht,15-25 °C,5,easy|hanging|sun,,,,, +easy,constants/lexiconBatch1.ts,17,Zebrakraut,Tradescantia zebrina,Das Zebrakraut faellt durch seine silbrig-lila gestreiften Blaetter auf. Schnellwachsende Haengepflanze.,Helles indirektes Licht,15-25 °C,5,easy|patterned|hanging,,,,, +easy,constants/lexiconBatch1.ts,107,Tulpe,Tulipa gesneriana,Die Tulpe ist eine der beliebtesten Fruehjahrsblueher mit kelchfoermigen Blueten in unzaehligen Farben.,Helles bis volles Licht,8-18 °C,5,easy|flowering,,,,, +easy,constants/lexiconBatch1.ts,35,Stiefmuetterchen,Viola wittrockiana,Das Stiefmuetterchen ist ein bekannter Fruehjahrsblueher mit charakteristisch gezeichneten Blueten.,Helles bis volles Licht,5-18 °C,3,easy|flowering,,,,, +easy,constants/lexiconBatch2.ts,246,Yucca aloifolia,Yucca aloifolia,Yucca aloifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Volles Sonnenlicht,18-30 C,10,easy|tree|sun,,,,, +easy,constants/lexiconBatch1.ts,40,Yucca-Palme,Yucca elephantipes,"Die Yucca-Palme ist eine robuste Zimmerpflanze mit starrem, immergruenem Blaetterschopf auf einem dicken Stamm.",Helles bis volles Licht,15-28 °C,14,easy|tree|sun,,,,, +easy,constants/lexiconBatch2.ts,65,Zinnie,Zinnia elegans,"Die Zinnie ist eine leuchtende Sommerblume mit grossen, dahlienaehnlichen Blueten. Sehr robust und hitzetolerant.",Volles Sonnenlicht,18-30 °C,3,easy|flowering|sun,,,,, diff --git a/audits/semantic-search/categories/flowering.csv b/audits/semantic-search/categories/flowering.csv new file mode 100644 index 0000000..08361c7 --- /dev/null +++ b/audits/semantic-search/categories/flowering.csv @@ -0,0 +1,158 @@ +category,source_file,source_index,name,botanical_name,description,light,temp,water_interval_days,all_categories,risk_flags,audit_status,evidence_source,evidence_url,notes +flowering,constants/lexiconBatch2.ts,108,Schafgarbe,Achillea millefolium,Die Schafgarbe hat weisse oder rosafarbene Bluetenschirme und fein gefiederte Blaetter. Wichtige Heilpflanze.,Volles Sonnenlicht,10-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch1.ts,86,Wuestenrose,Adenium obesum,Die Wuestenrose ist eine sukkulente Zimmerpflanze mit dickem Stamm und leuchtend pinken Blueten.,Volles Sonnenlicht,20-35 °C,10,flowering|succulent|sun,,,,, +flowering,constants/lexiconBatch2.ts,117,Socotra-Wuestenrose,Adenium socotranum,"Die Socotra-Wuestenrose ist eine seltene, endemische Art mit einem sehr dicken, knolligen Stamm und rosa Blueten.",Volles Sonnenlicht,20-35 °C,14,flowering|succulent|sun,,,,, +flowering,constants/lexiconBatch2.ts,34,Silbervase,Aechmea fasciata,Die Silbervase ist eine Bromelie mit silbrig gebänderten Blaettern und einem rosafarbenen Bluetenstand.,Helles indirektes Licht,18-25 °C,10,flowering|patterned,,,,, +flowering,constants/lexiconBatch1.ts,98,Lippenstiftpflanze,Aeschynanthus radicans,Die Lippenstiftpflanze hat haengende Triebe mit glaenzenden Blaettern und leuchtend roten Roehrenbluten.,Helles indirektes Licht,18-27 °C,7,flowering|hanging|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,155,Stockrose,Alcea rosea,"Stockrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,73,Muschelingwer,Alpinia zerumbet,"Der Muschelingwer hat lange, elegante Blaetter und haengende Bluetenrispen mit weiss-rosa Bluetchen.",Helles bis volles Licht,20-30 °C,5,flowering|large|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,194,Fuchsschwanz,Amaranthus caudatus,"Fuchsschwanz ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,163,Anemone,Anemone coronaria,"Anemone ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,147,Loewenmaeulchen,Antirrhinum majus,"Loewenmaeulchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,107,Arnika,Arnica montana,Arnika ist eine bekannte Heilpflanze aus den Alpen mit goldgelben Korbbluten. Sie wird fuer Muskeln und Gelenke verwendet.,Volles Sonnenlicht,10-20 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,178,Seidenpflanze,Asclepias tuberosa,"Seidenpflanze ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,92,Indische Azalee,Azalea indica,"Die Indische Azalee ist ein beliebter Zierstrauch mit grossen, auffaelligen Blueten in Rosa- und Rottönen.",Helles indirektes Licht,10-20 °C,4,flowering,,,,, +flowering,constants/lexiconBatch2.ts,175,Eisbegonie,Begonia semperflorens-cultorum,"Eisbegonie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,58,Knollen-Begonie,Begonia tuberhybrida,"Die Knollen-Begonie hat riesige, rosenaehnliche Blueten in leuchtendem Rot, Orange, Gelb oder Weiss.",Helles indirektes Licht,15-22 °C,5,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,145,Gaensebluemchen,Bellis perennis,"Gaensebluemchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,38,Billbergia,Billbergia nutans,"Die Billbergia ist eine robuste Bromelie mit schmalen, gruenen Blaettern und hängenden, blauen und gruenen Blueten.",Helles indirektes Licht,15-25 °C,7,easy|flowering,,,,, +flowering,constants/lexiconBatch1.ts,62,Bougainvillea,Bougainvillea spectabilis,"Die Bougainvillea ist eine rankenreiche Kletterpflanze mit leuchtend farbigen Hochblaettern in Rot, Orange oder Pink.",Volles Sonnenlicht,18-30 °C,5,flowering|bright_light|sun,,,,, +flowering,constants/lexiconBatch2.ts,223,Schmetterlingsflieder,Buddleja davidii,Schmetterlingsflieder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch2.ts,187,Ringelblume,Calendula officinalis,"Ringelblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,63,Calibrachoa,Calibrachoa hybrida,"Calibrachoa ist eine petunienaehnliche Haengepflanze mit unzaehligen, kleinen Trichterbluten in allen Farben.",Volles Sonnenlicht,15-25 °C,2,easy|flowering|hanging|sun,,,,, +flowering,constants/lexiconBatch1.ts,93,Kamelie,Camellia japonica,Die Kamelie ist ein eleganter Zierstrauch mit glaenzenden Blaettern und rosenaehnlichen Blueten von Januar bis April.,Helles indirektes Licht,7-18 °C,5,flowering,,,,, +flowering,constants/lexiconBatch2.ts,85,Teestrauch,Camellia sinensis,"Der Teestrauch ist die Pflanze, aus deren Blaettern Tee gewonnen wird. Er hat weisse Blueten und glaenzende Blaetter.",Helles indirektes Licht,15-22 °C,7,flowering,,,,, +flowering,constants/lexiconBatch2.ts,184,Trompetenwinde,Campsis radicans,"Trompetenwinde ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,67,Blumenschilfrohr,Canna indica,"Das Blumenschilfrohr hat grosse, tropisch wirkende Blaetter und auffaellige Blueten in Rot, Orange oder Gelb.",Volles Sonnenlicht,18-28 °C,5,flowering|large|sun,,,,, +flowering,constants/lexiconBatch1.ts,73,Cattleya-Orchidee,Cattleya labiata,"Die Cattleya ist die Koenigin der Orchideen mit ueppigen, duftenden Blueten in Lila, Rosa und Weiss.",Helles indirektes Licht,18-28 °C,7,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,188,Kornblume,Centaurea cyanus,"Kornblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,67,Chrysantheme,Chrysanthemum indicum,"Die Chrysantheme ist die klassische Herbstblume mit ueppigen, dichten Blueten in vielen Farben.",Helles bis volles Licht,12-22 °C,4,flowering,,,,, +flowering,constants/lexiconBatch2.ts,157,Clematis,Clematis viticella,"Clematis ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch1.ts,104,Riemenblatt,Clivia miniata,Das Riemenblatt ist eine dekorative Zimmerpflanze mit leuchtend orangefarbenen Blueten im Fruehling.,Helles indirektes Licht,15-24 °C,10,flowering,,,,, +flowering,constants/lexiconBatch1.ts,97,Columnea,Columnea gloriosa,"Die Columnea ist eine haengende Zimmerpflanze mit kleinen, behaarten Blaettern und leuchtend roten, roehrenfoermigen Blueten.",Helles indirektes Licht,18-25 °C,7,flowering|hanging|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,160,Maigloeckchen,Convallaria majalis,"Maigloeckchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,181,Maedchenauge,Coreopsis tinctoria,"Maedchenauge ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,150,Kosmee,Cosmos bipinnatus,"Kosmee ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,110,Krokus,Crocus vernus,"Der Krokus ist einer der ersten Fruehjahrs­boten mit kelchfoermigen Blueten in Lila, Weiss und Gelb.",Helles bis volles Licht,5-15 °C,7,easy|flowering,,,,, +flowering,constants/lexiconBatch1.ts,19,Alpenveilchen,Cyclamen persicum,"Das Alpenveilchen bluet im Herbst und Winter mit eleganten Blueten in Rosa, Rot oder Weiss.",Helles indirektes Licht,12-18 °C,5,flowering,,,,, +flowering,constants/lexiconBatch1.ts,71,Zymbidium,Cymbidium lowianum,"Das Zymbidium ist eine robuste Orchidee mit langen, grassartigen Blaettern und eleganten Bluetenrispen.",Helles Licht,12-24 °C,7,flowering,,,,, +flowering,constants/lexiconBatch2.ts,68,Dahlie,Dahlia pinnata,Die Dahlie ist eine prachtvolle Sommerblume mit Blueten in allen Groessen und Formen. Sie wird aus Knollen gezogen.,Volles Sonnenlicht,15-25 °C,5,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,215,Flammenbaum,Delonix regia,Flammenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +flowering,constants/lexiconBatch2.ts,153,Rittersporn,Delphinium elatum,"Rittersporn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,70,Dendrobium,Dendrobium nobile,"Das Dendrobium ist eine beliebte Zimmerorchidee mit langen Pseudobulben, die im Winter mit Blueten besetzt werden.",Helles indirektes Licht,15-28 °C,10,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,189,Bartnelke,Dianthus barbatus,"Bartnelke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,146,Nelke,Dianthus caryophyllus,"Nelke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,109,Roter Fingerhut,Digitalis purpurea,"Der Rote Fingerhut hat hohe Bluetenstaende mit roehrenfoermigen, gepunkteten Blueten in Rosa. Wichtige Arzneipflanze.",Helles bis volles Licht,10-20 °C,7,flowering|medicinal,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,106,Sonnenhut,Echinacea purpurea,"Der Sonnenhut ist eine beliebte Heilpflanze mit grossen, pinkfarbenen Blueten. Er staerkt das Immunsystem.",Helles bis volles Licht,15-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch1.ts,84,Koenigin der Nacht,Epiphyllum oxypetalum,"Die Koenigin der Nacht bluet nur eine einzige Nacht lang mit riesigen, intensiv duftenden weissen Blueten.",Indirektes Licht,18-27 °C,7,flowering|succulent,,,,, +flowering,constants/lexiconBatch2.ts,186,Kalifornischer Mohn,Eschscholzia californica,"Kalifornischer Mohn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,19,Christusdorn,Euphorbia milii,Der Christusdorn ist eine sukkulente Wolfsmilch mit stacheligen Zweigen und kleinen roten oder gelben Hochblaettern.,Helles bis volles Licht,15-28 °C,10,easy|flowering|succulent|sun,,,,, +flowering,constants/lexiconBatch2.ts,20,Weihnachtsstern,Euphorbia pulcherrima,Der Weihnachtsstern ist die klassische Winterpflanze mit leuchtend roten Hochblaettern. Er steht symbolisch fuer Weihnachten.,Helles indirektes Licht,15-22 °C,7,flowering,,,,, +flowering,constants/lexiconBatch2.ts,219,Forsythie,Forsythia x intermedia,Forsythie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch2.ts,169,Freesie,Freesia refracta,"Freesie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,33,Fuchsie,Fuchsia hybrida,"Die Fuchsie haengt mit eleganten, zweifarbigen Blueten wie kleine Ohrringe herab. Ideal fuer Ampeln.",Helles indirektes Licht,14-22 °C,3,flowering|hanging,,,,, +flowering,constants/lexiconBatch2.ts,60,Triphylla-Fuchsie,Fuchsia triphylla,"Die Triphylla-Fuchsie hat lange, roehrenfoermige, orangefarbe Blueten in haengenden Trauben. Sehr exotisch.",Helles indirektes Licht,15-22 °C,3,flowering|hanging,,,,, +flowering,constants/lexiconBatch2.ts,196,Kokardenblume,Gaillardia aristata,"Kokardenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,22,Gardenie,Gardenia jasminoides,"Die Gardenie fasziniert mit cremefarbenen, intensiv duftenden Blueten. Anspruchsvoll in der Pflege.",Helles indirektes Licht,18-23 °C,5,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,190,Mittagsgold,Gazania rigens,"Mittagsgold ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,32,Blutroter Storchschnabel,Geranium sanguineum,Der Blutrote Storchschnabel ist ein zierlicher Storchschnabel mit intensiv magentafarbenen Blueten.,Helles bis volles Licht,10-25 °C,7,easy|flowering,,,,, +flowering,constants/lexiconBatch1.ts,68,Gerbera,Gerbera jamesonii,"Die Gerbera ist eine farbenfrohe Schnittblume mit grossen, sonnenblumenaehnlichen Blueten. Sehr beliebt.",Helles bis volles Licht,15-25 °C,5,flowering|air_purifier|bright_light,air_purifier_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,161,Gladiole,Gladiolus hortulanus,"Gladiole ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,96,Gloxinie,Gloxinia speciosa,"Die Gloxinie hat grosse, samtartige Blueten in Violett, Rosa oder Weiss mit farbigen Raendern.",Helles indirektes Licht,18-25 °C,5,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,36,Guzmania,Guzmania lingulata,"Die Guzmania ist eine Bromelie mit glänzenden, gruenen Blaettern und einem leuchtend roten, sternfoermigen Bluetenstand.",Helles indirektes Licht,18-27 °C,7,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,119,Zaubernuss,Hamamelis mollis,"Die Zaubernuss bluet im Winter mit fadendunnen, gelben Bluetenkranzeln, die bis -10 Grad standhalten.",Helles bis volles Licht,10-20 °C,10,flowering|medicinal,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,141,Sonnenblume,Helianthus annuus,"Sonnenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,72,Heliconia,Heliconia psittacorum,"Die Heliconia hat leuchtend orangefarbe oder rote, bootsfoermige Hochblaetter. Eine exotische Tropenpflanze.",Helles bis volles Licht,20-30 °C,5,flowering|bright_light|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,191,Heliotrop,Heliotropium arborescens,"Heliotrop ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,183,Lenzrose,Helleborus orientalis,"Lenzrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering,,,,, +flowering,constants/lexiconBatch2.ts,182,Taglilie,Hemerocallis fulva,"Taglilie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,21,Hibiskus,Hibiscus rosa-sinensis,"Der Hibiskus begeistert mit grossen, trompetenfoermigen Blueten in Rot, Orange und Rosa.",Volles Sonnenlicht,18-28 °C,3,flowering|bright_light|sun,,,,, +flowering,constants/lexiconBatch2.ts,220,Gartenhibiskus,Hibiscus syriacus,Gartenhibiskus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch1.ts,105,Ritterstern,Hippeastrum hybrid,"Der Ritterstern beeindruckt im Winter mit riesigen, trompetenfoermigen Blueten in Rot, Pink oder Weiss.",Helles bis volles Licht,18-25 °C,7,flowering|bright_light,,,,, +flowering,constants/lexiconBatch1.ts,58,Kleine Wachsblume,Hoya bella,"Die Kleine Wachsblume traegt zierliche, sternfoermige weisse Blueten mit rosa Mitte. Haengende Sukkulente.",Helles indirektes Licht,18-27 °C,10,flowering|succulent|hanging,,,,, +flowering,constants/lexiconBatch1.ts,57,Wachsblume,Hoya carnosa,"Die Wachsblume ist eine Kletterpflanze mit dicken, wachsartigen Blaettern und sternfoermigen, duftenden Blueten.",Helles indirektes Licht,16-27 °C,10,easy|flowering|succulent|hanging,,,,, +flowering,constants/lexiconBatch2.ts,159,Hasengloeckchen,Hyacinthoides non-scripta,"Hasengloeckchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,108,Hyazinthe,Hyacinthus orientalis,"Die Hyazinthe bezaubert mit dichten Bluetenrispen und intensivem Duft in Blau, Rosa, Weiss oder Gelb.",Helles bis volles Licht,10-18 °C,5,easy|flowering,,,,, +flowering,constants/lexiconBatch2.ts,148,Hortensie,Hydrangea macrophylla,"Hortensie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Helles bis halbschattiges Licht,8-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,105,Johanniskraut,Hypericum perforatum,Das Johanniskraut hat leuchtend gelbe Blueten und ist ein wichtiges Heilkraut gegen Depressionen und Stimmungstiefs.,Volles Sonnenlicht,10-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,176,Gartenbalsamine,Impatiens balsamina,"Gartenbalsamine ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,59,Neuguinea-Balsamine,Impatiens hawkeri,"Die Neuguinea-Balsamine hat grosse, leuchtende Blueten und ist sehr bluehfreudig. Ideal fuer Terrassen.",Helles indirektes Licht,18-27 °C,3,easy|flowering,,,,, +flowering,constants/lexiconBatch1.ts,20,Fleissiges Lieschen,Impatiens walleriana,Das Fleissige Lieschen bluet von Fruehling bis Herbst unermudlich in vielen Farben.,Helles indirektes Licht,16-24 °C,2,easy|flowering,,,,, +flowering,constants/lexiconBatch2.ts,156,Prunkwinde,Ipomoea purpurea,"Prunkwinde ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,144,Bart-Iris,Iris germanica,"Bart-Iris ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,211,Jacaranda,Jacaranda mimosifolia,Jacaranda ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +flowering,constants/lexiconBatch1.ts,59,Jasmin,Jasminum polyanthum,"Der Jasmin ist eine Kletterpflanze mit intensiv duftenden, weissen Blueten. Er bluet im Winter und Fruehling.",Helles bis volles Licht,10-22 °C,5,flowering,,,,, +flowering,constants/lexiconBatch2.ts,172,Arabischer Jasmin,Jasminum sambac,"Arabischer Jasmin ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch1.ts,9,Kalanchoe,Kalanchoe blossfeldiana,"Die Kalanchoe ist eine beliebte Bluehpflanze mit leuchtenden Blueten in Rot, Orange, Gelb oder Rosa.",Helles bis volles Licht,15-25 °C,10,easy|flowering|succulent|sun,,,,, +flowering,constants/lexiconBatch2.ts,197,Traenendes Herz,Lamprocapnos spectabilis,"Traenendes Herz ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,64,Wandelroeschen,Lantana camara,"Das Wandelroeschen hat kugelige Bluetenkoepfe, die die Farbe von Gelb ueber Orange zu Rot wechseln. Sehr attraktiv.",Volles Sonnenlicht,18-28 °C,5,flowering|bright_light|sun,,,,, +flowering,constants/lexiconBatch2.ts,158,Duftwicke,Lathyrus odoratus,"Duftwicke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,180,Bechermalve,Lavatera trimestris,"Bechermalve ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,173,Margerite,Leucanthemum vulgare,"Margerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,201,Shasta-Margerite,Leucanthemum x superbum,"Shasta-Margerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,69,Ostertrompete,Lilium longiflorum,"Die Ostertrompete hat grosse, weisse, trichterfoermige Blueten mit intensivem Duft. Klassische Osterblume.",Helles bis volles Licht,15-25 °C,5,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,62,Duftsteinrich,Lobularia maritima,"Der Duftsteinrich ist ein niedrig wachsendes Pflanzchen mit winzigen, weissen oder lilafarbenen Blueten und suessem Duft.",Helles bis volles Licht,10-22 °C,3,easy|flowering,,,,, +flowering,constants/lexiconBatch2.ts,171,Geissblatt,Lonicera japonica,"Geissblatt ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,154,Lupine,Lupinus polyphyllus,"Lupine ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,204,Magnolie,Magnolia grandiflora,Magnolie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +flowering,constants/lexiconBatch1.ts,79,Mammillaria,Mammillaria zeilmanniana,"Die Mammillaria ist ein kompakter, kugelfoermiger Kaktus, der im Fruehling einen Kranz aus rosa Blueten traegt.",Volles Sonnenlicht,15-35 °C,14,easy|flowering|succulent|sun,,,,, +flowering,constants/lexiconBatch1.ts,75,Stiefmuetterchen-Orchidee,Miltoniopsis roezlii,"Die Stiefmuetterchen-Orchidee hat grosse, flache Blueten. Bevorzugt kuehle Temperaturen und hohe Luftfeuchtigkeit.",Indirektes Licht,15-22 °C,5,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,76,Schamkraut,Mimosa pudica,"Das Schamkraut faltet seine Blaettchen blitzschnell zusammen, wenn man sie beruehrt. Ein faszinierendes Erlebnis.",Helles bis volles Licht,20-28 °C,5,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,179,Indianernessel,Monarda didyma,"Indianernessel ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,109,Traubenhyazinthe,Muscari armeniacum,"Die Traubenhyazinthe bildet dichte Trauben aus kleinen, blauen bis violetten Gloeckchen. Zuverlaessige Fruejahrszwiebel.",Helles bis volles Licht,8-18 °C,7,easy|flowering,,,,, +flowering,constants/lexiconBatch2.ts,177,Vergissmeinnicht,Myosotis sylvatica,"Vergissmeinnicht ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,106,Osterglocke,Narcissus pseudonarcissus,"Die Osterglocke ist der klassische Fruehjahrsblueher mit leuchtend gelben, trompetenfoermigen Blueten.",Helles bis volles Licht,10-18 °C,5,flowering,,,,, +flowering,constants/lexiconBatch2.ts,199,Nemesie,Nemesia strumosa,"Nemesie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,37,Neoregelia,Neoregelia carolinae,"Die Neoregelia ist eine Bromelie, bei der das Herzblatt zur Bluetzeit leuchtend rot wird. Sehr dekorativ.",Helles bis volles Licht,18-27 °C,7,flowering|patterned|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,120,Oleander,Nerium oleander,"Der Oleander ist ein mediteraner Strauch mit leuchtend roten, rosa oder weissen Blueten. Sehr hitzetolerant.",Volles Sonnenlicht,15-28 °C,7,flowering|bright_light|sun,,,,, +flowering,constants/lexiconBatch2.ts,193,Ziertabak,Nicotiana alata,"Ziertabak ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,74,Tanzerinnen-Orchidee,Oncidium sphacelatum,"Die Tanzerinnen-Orchidee traegt lange Rispen mit Hunderten kleiner, gelb-brauner Blueten. Sehr reichliche Bluetracht.",Helles indirektes Licht,18-27 °C,7,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,200,Kapmargerite,Osteospermum ecklonis,"Kapmargerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,54,Kleeblume,Oxalis triangularis,"Die Kleeblume hat tiefviolette, dreieckige Blaetter und zarte rosa Blueten. Sie faltet die Blaetter bei Dunkelheit.",Helles indirektes Licht,15-24 °C,7,flowering|patterned,,,,, +flowering,constants/lexiconBatch2.ts,143,Pfingstrose,Paeonia lactiflora,"Pfingstrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,185,Mohn,Papaver rhoeas,"Mohn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,63,Passionsblume,Passiflora caerulea,"Die Passionsblume ist eine faszinierende Kletterpflanze mit komplex strukturierten, blau-weissen Blueten.",Helles bis volles Licht,15-27 °C,5,flowering,,,,, +flowering,constants/lexiconBatch2.ts,61,Efeu-Geranie,Pelargonium peltatum,"Die Efeu-Geranie hat efeufoermige, glaenzende Blaetter und bluet den ganzen Sommer in leuchtenden Farben.",Helles bis volles Licht,15-25 °C,5,easy|flowering|hanging|sun,,,,, +flowering,constants/lexiconBatch2.ts,174,Stehende Geranie,Pelargonium zonale,"Stehende Geranie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,34,Petunie,Petunia hybrida,Die Petunie ist eine der beliebtesten Balkonpflanzen mit trichterfoermigen Blueten in unzaehligen Farben.,Volles Sonnenlicht,15-25 °C,2,easy|pet_friendly|flowering|sun,pet_friendly_requires_external_evidence,,,, +flowering,constants/lexiconBatch1.ts,69,Schmetterlingsorchidee,Phalaenopsis amabilis,Die Schmetterlingsorchidee ist die bekannteste Zimmerorchidee. Sie bluet bei guter Pflege monatelang.,Helles indirektes Licht,18-28 °C,10,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,165,Flammenblume,Phlox paniculata,"Flammenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,81,Fettkraut,Pinguicula grandiflora,"Das Fettkraut faengt Insekten mit klebrigen Blaettern. Es bluet mit violetten, sporenartigen Blueten.",Helles indirektes Licht,10-20 °C,5,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch1.ts,61,Bleiwurz,Plumbago auriculata,"Die Bleiwurz ist ein halbimmergruener Strauch mit himmelblauen Blueten, der fast das ganze Jahr bluet.",Volles Sonnenlicht,15-27 °C,5,flowering|bright_light|sun,,,,, +flowering,constants/lexiconBatch2.ts,118,Tempel-Baum,Plumeria rubra,"Der Tempel-Baum hat intensiv duftende, sternfoermige Blueten in Weiss, Gelb oder Rosa. Klassische Tropenblume.",Volles Sonnenlicht,20-30 °C,7,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch1.ts,36,Primel,Primula vulgaris,"Die Primel ist einer der ersten Fruehjahrs­boten mit lebhaften Blueten in Gelb, Pink, Rot und Lila.",Helles indirektes Licht,10-18 °C,4,flowering,,,,, +flowering,constants/lexiconBatch2.ts,71,Koenigs-Protea,Protea cynaroides,"Die Koenigs-Protea ist die Nationalblume Suedafrikas mit riesigen, imposanten Bluetenkoepfen. Eine echte Besonderheit.",Volles Sonnenlicht,10-25 °C,7,flowering|large|sun,,,,, +flowering,constants/lexiconBatch2.ts,88,Granatapfelbaum,Punica granatum,"Der Granatapfelbaum hat leuchtend rote Blueten und rote, essbare Fruechte mit rubinroten Kernen.",Volles Sonnenlicht,15-28 °C,7,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch2.ts,162,Ranunkel,Ranunculus asiaticus,"Ranunkel ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,170,Rhododendron,Rhododendron catawbiense,"Rhododendron ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|tree|bright_light,,,,, +flowering,constants/lexiconBatch1.ts,91,Japanische Azalee,Rhododendron simsii,"Die Japanische Azalee bluet im Winter und Fruehling ueppig mit leuchtend roten, rosa oder weissen Blueten.",Helles indirektes Licht,10-18 °C,4,flowering,,,,, +flowering,constants/lexiconBatch1.ts,66,Chinesische Rose,Rosa chinensis,Die Chinesische Rose ist eine der Stammarten vieler Gartenrosen und bluet fast ununterbrochen.,Volles Sonnenlicht,15-25 °C,5,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,142,Rose,Rosa x hybrida,"Rose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light|sun,,,,, +flowering,constants/lexiconBatch2.ts,167,Rudbeckie,Rudbeckia hirta,"Rudbeckie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,94,Afrikanisches Veilchen,Saintpaulia ionantha,"Das Afrikanische Veilchen ist eine kleine, kompakte Bluehpflanze mit samtigen Blaettern und violetten Blueten.",Helles indirektes Licht,18-25 °C,7,easy|flowering,,,,, +flowering,constants/lexiconBatch2.ts,195,Mehlsalbei,Salvia farinacea,"Mehlsalbei ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,168,Feuersalbei,Salvia splendens,"Feuersalbei ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,112,Schwarzer Holunder,Sambucus nigra,Der Schwarze Holunder hat weisse Doldenbluten und schwarze Beeren. Die Fruechte werden fuer Sirup und Saft verwendet.,Helles bis volles Licht,10-25 °C,7,flowering|tree|medicinal,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch1.ts,8,Weihnachtskaktus,Schlumbergera truncata,"Der Weihnachtskaktus erfreut zur Weihnachtszeit mit leuchtenden Blueten in Rosa, Rot oder Weiss.",Helles indirektes Licht,15-21 °C,7,easy|flowering|succulent,,,,, +flowering,constants/lexiconBatch2.ts,222,Spierstrauch,Spiraea japonica,Spierstrauch ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch2.ts,25,Aasblume,Stapelia grandiflora,"Die Aasblume hat fleischige, gruene Staengel und riesige, sternfoermige Blueten mit aasartigem Duft.",Helles bis volles Licht,18-30 °C,14,flowering|succulent|sun,,,,, +flowering,constants/lexiconBatch1.ts,60,Madagaskar-Jasmin,Stephanotis floribunda,"Der Madagaskar-Jasmin hat dicke, glaenzende Blaetter und wachsweisse, intensiv duftende Blueten. Klassische Hochzeitsblume.",Helles indirektes Licht,18-25 °C,7,flowering,,,,, +flowering,constants/lexiconBatch1.ts,3,Paradiesvogelblume,Strelitzia reginae,"Die Paradiesvogelblume beeindruckt mit leuchtend orangefarbenen und blauen Blueten, die einem Vogel aehneln.",Volles Sonnenlicht,18-26 °C,7,flowering|large|sun,,,,, +flowering,constants/lexiconBatch1.ts,95,Drehfrucht,Streptocarpus hybridus,"Die Drehfrucht ist ein Gesneriengewaechs mit langen, gerippten Blaettern und trichterfoermigen Blueten in Lila oder Rosa.",Helles indirektes Licht,15-22 °C,7,flowering,,,,, +flowering,constants/lexiconBatch2.ts,166,Herbstaster,Symphyotrichum novi-belgii,"Herbstaster ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,149,Flieder,Syringa vulgaris,"Flieder ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch2.ts,66,Studentenblume,Tagetes patula,Die Studentenblume ist eine robuste Sommerblume mit orangen oder gelben Blueten. Sie haelt Schadlinge fern.,Volles Sonnenlicht,15-28 °C,3,easy|flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,151,Kapuzinerkresse,Tropaeolum majus,"Kapuzinerkresse ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,107,Tulpe,Tulipa gesneriana,Die Tulpe ist eine der beliebtesten Fruehjahrsblueher mit kelchfoermigen Blueten in unzaehligen Farben.,Helles bis volles Licht,8-18 °C,5,easy|flowering,,,,, +flowering,constants/lexiconBatch2.ts,104,Baldrian,Valeriana officinalis,Baldrian ist ein bekanntes Heilkraut mit weissen bis roeslichen Blueten. Die Wurzeln werden zur Schlaffoerderung verwendet.,Helles bis volles Licht,15-25 °C,7,flowering|medicinal,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch1.ts,72,Vanda-Orchidee,Vanda coerulea,Die Vanda-Orchidee ist bekannt fuer ihre seltene blaue Bluetenfarbe. Epiphytische Orchidee mit grossen Blueten.,Helles bis volles Licht,20-30 °C,3,flowering|bright_light|high_humidity,,,,, +flowering,constants/lexiconBatch1.ts,76,Vanille,Vanilla planifolia,"Die Vanille ist eine kletternde Orchidee, aus deren Fruechten das beliebte Gewuerz gewonnen wird.",Helles indirektes Licht,20-30 °C,5,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,192,Koenigskerze,Verbascum thapsus,"Koenigskerze ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,164,Eisenkraut,Verbena bonariensis,"Eisenkraut ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,198,Hornveilchen,Viola cornuta,"Hornveilchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,35,Stiefmuetterchen,Viola wittrockiana,Das Stiefmuetterchen ist ein bekannter Fruehjahrsblueher mit charakteristisch gezeichneten Blueten.,Helles bis volles Licht,5-18 °C,3,easy|flowering,,,,, +flowering,constants/lexiconBatch2.ts,35,Flammen-Bromelie,Vriesea splendens,"Die Flammen-Bromelie hat gebänderte, dunkelgruene Blaetter und einen spektakulaeren, roten Bluetenstand.",Helles indirektes Licht,18-25 °C,7,flowering|patterned|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,221,Weigelie,Weigela florida,Weigelie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch1.ts,65,Chinesischer Blauregen,Wisteria sinensis,"Der Chinesische Blauregen ist ein ueppiger Kletterkuenstler mit langen, duftenden Bluetentrauben in Lila.",Volles Sonnenlicht,10-25 °C,7,flowering|large|sun,,,,, +flowering,constants/lexiconBatch2.ts,70,Calla,Zantedeschia aethiopica,"Die Calla hat elegante, trichterfoermige weisse Hochblaetter und glaenzende, herzfoermige Blaetter. Sehr edel.",Helles indirektes Licht,15-24 °C,7,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,65,Zinnie,Zinnia elegans,"Die Zinnie ist eine leuchtende Sommerblume mit grossen, dahlienaehnlichen Blueten. Sehr robust und hitzetolerant.",Volles Sonnenlicht,18-30 °C,3,easy|flowering|sun,,,,, diff --git a/audits/semantic-search/categories/hanging.csv b/audits/semantic-search/categories/hanging.csv new file mode 100644 index 0000000..dc38e3c --- /dev/null +++ b/audits/semantic-search/categories/hanging.csv @@ -0,0 +1,35 @@ +category,source_file,source_index,name,botanical_name,description,light,temp,water_interval_days,all_categories,risk_flags,audit_status,evidence_source,evidence_url,notes +hanging,constants/lexiconBatch1.ts,98,Lippenstiftpflanze,Aeschynanthus radicans,Die Lippenstiftpflanze hat haengende Triebe mit glaenzenden Blaettern und leuchtend roten Roehrenbluten.,Helles indirektes Licht,18-27 °C,7,flowering|hanging|high_humidity,,,,, +hanging,constants/lexiconBatch2.ts,63,Calibrachoa,Calibrachoa hybrida,"Calibrachoa ist eine petunienaehnliche Haengepflanze mit unzaehligen, kleinen Trichterbluten in allen Farben.",Volles Sonnenlicht,15-25 °C,2,easy|flowering|hanging|sun,,,,, +hanging,constants/lexiconBatch2.ts,56,Callisia,Callisia repens,"Callisia repens ist ein kleines, kriechendes Kraut mit winzigen, gruenen Blaettern. Ideal fuer haengende Behaelter.",Helles indirektes Licht,15-25 °C,5,easy|hanging,,,,, +hanging,constants/lexiconBatch1.ts,99,Herzkette,Ceropegia woodii,"Die Herzkette hat duenne, haengende Ranken mit herzfoermigen, silbergrau gemusterten Blaettchen.",Helles indirektes Licht,15-27 °C,14,easy|succulent|patterned|hanging,,,,, +hanging,constants/lexiconBatch1.ts,97,Columnea,Columnea gloriosa,"Die Columnea ist eine haengende Zimmerpflanze mit kleinen, behaarten Blaettern und leuchtend roten, roehrenfoermigen Blueten.",Helles indirektes Licht,18-25 °C,7,flowering|hanging|high_humidity,,,,, +hanging,constants/lexiconBatch2.ts,236,String of Bananas,Curio radicans,String of Bananas ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,succulent|hanging|sun,,,,, +hanging,constants/lexiconBatch2.ts,237,String of Dolphins,Curio x peregrinus,String of Dolphins ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,succulent|hanging|sun,,,,, +hanging,constants/lexiconBatch1.ts,101,Dischidia,Dischidia ruscifolia,"Die Dischidia ist eine epiphytische Haengepflanze mit kleinen, runden Blaettern entlang duenner Ranken.",Helles indirektes Licht,18-27 °C,7,succulent|hanging,,,,, +hanging,constants/lexiconBatch1.ts,16,Marmor-Efeutute,Epipremnum aureum Marble Queen,Die Marmor-Efeutute hat cremeweiss-gruen marmorierte Blaetter. Eine dekorative Variante der klassischen Efeutute.,Helles indirektes Licht,15-30 °C,7,easy|hanging|air_purifier,air_purifier_requires_external_evidence,,,, +hanging,constants/lexiconBatch2.ts,53,Neon-Efeutute,Epipremnum pinnatum Neon,Die Neon-Efeutute hat leuchtend limonengruene Blaetter. Sehr auffaellig und pflegeleicht.,Helles indirektes Licht,15-30 °C,7,easy|hanging|air_purifier,air_purifier_requires_external_evidence,,,, +hanging,constants/lexiconBatch1.ts,33,Fuchsie,Fuchsia hybrida,"Die Fuchsie haengt mit eleganten, zweifarbigen Blueten wie kleine Ohrringe herab. Ideal fuer Ampeln.",Helles indirektes Licht,14-22 °C,3,flowering|hanging,,,,, +hanging,constants/lexiconBatch2.ts,60,Triphylla-Fuchsie,Fuchsia triphylla,"Die Triphylla-Fuchsie hat lange, roehrenfoermige, orangefarbe Blueten in haengenden Trauben. Sehr exotisch.",Helles indirektes Licht,15-22 °C,3,flowering|hanging,,,,, +hanging,constants/lexiconBatch1.ts,37,Efeu,Hedera helix,"Efeu ist eine robuste Kletter- und Haengepflanze mit charakteristischen, dreilappigen Blaettern. Sehr langlebig.",Wenig bis helles Licht,10-20 °C,7,easy|hanging|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +hanging,constants/lexiconBatch1.ts,58,Kleine Wachsblume,Hoya bella,"Die Kleine Wachsblume traegt zierliche, sternfoermige weisse Blueten mit rosa Mitte. Haengende Sukkulente.",Helles indirektes Licht,18-27 °C,10,flowering|succulent|hanging,,,,, +hanging,constants/lexiconBatch1.ts,57,Wachsblume,Hoya carnosa,"Die Wachsblume ist eine Kletterpflanze mit dicken, wachsartigen Blaettern und sternfoermigen, duftenden Blueten.",Helles indirektes Licht,16-27 °C,10,easy|flowering|succulent|hanging,,,,, +hanging,constants/lexiconBatch1.ts,64,Suesskartoffel,Ipomoea batatas,"Die Suesskartoffel-Zierpflanze hat dekorative, herzfoermige Blaetter in gruen oder dunkelviolett. Ideal als Haengepflanze.",Volles Sonnenlicht,20-30 °C,5,easy|hanging|sun,,,,, +hanging,constants/lexiconBatch2.ts,47,Monstera adansonii,Monstera adansonii,Monstera adansonii hat herzfoermige Blaetter mit zahlreichen runden Lochern. Eine rankende Zimmerpflanze.,Helles indirektes Licht,18-27 °C,7,easy|hanging,,,,, +hanging,constants/lexiconBatch2.ts,48,Monstera obliqua,Monstera obliqua,"Monstera obliqua ist eine seltene Monstera-Art mit filigranen Blaettern, die hauptsaechlich aus Lochern bestehen.",Helles indirektes Licht,18-27 °C,7,patterned|hanging,,,,, +hanging,constants/lexiconBatch2.ts,79,Kannenpflanze,Nepenthes alata,"Die Kannenpflanze bildet grosse, gefuellte Kannen als Insekten­fallen. Eine faszinierende, tropische Pflanze.",Helles indirektes Licht,20-30 °C,5,hanging|high_humidity,,,,, +hanging,constants/lexiconBatch2.ts,61,Efeu-Geranie,Pelargonium peltatum,"Die Efeu-Geranie hat efeufoermige, glaenzende Blaetter und bluet den ganzen Sommer in leuchtenden Farben.",Helles bis volles Licht,15-25 °C,5,easy|flowering|hanging|sun,,,,, +hanging,constants/lexiconBatch2.ts,51,Roter Philodendron,Philodendron erubescens,"Der Rote Philodendron hat glaenzende, herzfoermige Blaetter, die jung roetrlich erscheinen. Sehr dekorativ.",Helles indirektes Licht,18-27 °C,7,easy|hanging,,,,, +hanging,constants/lexiconBatch1.ts,15,Herzblatt-Philodendron,Philodendron hederaceum,Der Herzblatt-Philodendron ist eine pflegeleichte Kletter- oder Haengepflanze mit herzfoermigen Blaettern.,Indirektes Licht,18-28 °C,7,easy|hanging|low_light,,,,, +hanging,constants/lexiconBatch2.ts,242,Philodendron Brasil,Philodendron hederaceum Brasil,Philodendron Brasil ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|hanging|low_light,,,,, +hanging,constants/lexiconBatch2.ts,41,Geweihfarn,Platycerium bifurcatum,"Der Geweihfarn hat gespaltene Wedel, die einem Hirschgeweih aehneln. Er ist ein epiphytischer Farn fuer Holz.",Helles indirektes Licht,15-25 °C,7,hanging|high_humidity,,,,, +hanging,constants/lexiconBatch2.ts,52,Mini-Monstera,Rhaphidophora tetrasperma,"Die Mini-Monstera hat monstera­aehnliche, gelochte Blaetter auf einer kompakten, klettternden Pflanze. Sehr trendig.",Helles indirektes Licht,18-27 °C,7,easy|hanging,,,,, +hanging,constants/lexiconBatch1.ts,85,Korallenkaktus,Rhipsalis baccifera,"Der Korallenkaktus ist ein epiphytischer Kaktus mit duennen, haengenden Trieben und kleinen weissen Beeren.",Indirektes Licht,18-27 °C,7,succulent|hanging,,,,, +hanging,constants/lexiconBatch1.ts,55,Satinpothos,Scindapsus pictus,"Der Satinpothos hat samtig-glaenzende, silbrig gefleckte Blaetter auf langen, haengenden Ranken.",Helles indirektes Licht,18-28 °C,7,easy|patterned|hanging,,,,, +hanging,constants/lexiconBatch1.ts,7,Eselschwanz,Sedum morganianum,"Der Eselschwanz ist eine haengende Sukkulente mit langen Trieben aus dichten, blaugruenen Blaettchen.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|hanging|sun,,,,, +hanging,constants/lexiconBatch1.ts,100,Perlenschnur-Pflanze,Senecio rowleyanus,"Die Perlenschnur-Pflanze hat haengende Ranken mit kugelfoermigen, perlenaehnlichen Blaettern. Einzigartige Sukkulente.",Helles bis volles Licht,15-27 °C,14,easy|succulent|hanging,,,,, +hanging,constants/lexiconBatch1.ts,56,Pfeilblatt,Syngonium podophyllum,"Das Pfeilblatt hat charakteristisch pfeilfoermige Blaetter, die sich mit dem Alter weiterentwickeln.",Helles indirektes Licht,16-27 °C,7,easy|hanging,,,,, +hanging,constants/lexiconBatch2.ts,32,Spanisches Moos,Tillandsia usneoides,"Das Spanische Moos ist eine epiphytische Bromelie ohne Wurzeln, die in der Luft haengt. Es benoetigt nur Feuchtigkeitsbespruehing.",Helles bis volles Licht,15-30 °C,3,easy|hanging,,,,, +hanging,constants/lexiconBatch2.ts,55,Weisse Tradescantia,Tradescantia fluminensis,Die Weisse Tradescantia hat gruene Blaetter mit weisslichen Unterseiten. Sehr robust und schnellwachsend.,Helles indirektes Licht,15-25 °C,5,easy|hanging,,,,, +hanging,constants/lexiconBatch2.ts,54,Lila Tradescantia,Tradescantia pallida,Die Lila Tradescantia hat leuchtend purpurrote Blaetter und ist sehr auffaellig. Sie liebt viel Licht.,Helles bis volles Licht,15-25 °C,5,easy|hanging|sun,,,,, +hanging,constants/lexiconBatch1.ts,17,Zebrakraut,Tradescantia zebrina,Das Zebrakraut faellt durch seine silbrig-lila gestreiften Blaetter auf. Schnellwachsende Haengepflanze.,Helles indirektes Licht,15-25 °C,5,easy|patterned|hanging,,,,, diff --git a/audits/semantic-search/categories/high_humidity.csv b/audits/semantic-search/categories/high_humidity.csv new file mode 100644 index 0000000..5b735d4 --- /dev/null +++ b/audits/semantic-search/categories/high_humidity.csv @@ -0,0 +1,52 @@ +category,source_file,source_index,name,botanical_name,description,light,temp,water_interval_days,all_categories,risk_flags,audit_status,evidence_source,evidence_url,notes +high_humidity,constants/lexiconBatch2.ts,42,Frauenhaarfarn,Adiantum raddianum,"Der Frauenhaarfarn hat zarte, feingliedrige Wedel auf schwarzen, draht­aehnlichen Stielen. Liebt Feuchtigkeit.",Helles indirektes Licht,18-27 °C,3,high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,98,Lippenstiftpflanze,Aeschynanthus radicans,Die Lippenstiftpflanze hat haengende Triebe mit glaenzenden Blaettern und leuchtend roten Roehrenbluten.,Helles indirektes Licht,18-27 °C,7,flowering|hanging|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,46,Amazona-Taro,Alocasia amazonica,"Der Amazona-Taro besticht mit dunkelgruenen, pfeilfoermigen Blaettern mit markant weissen Rippen.",Indirektes Licht,18-27 °C,5,patterned|large|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,225,Alocasia zebrina,Alocasia zebrina,Alocasia zebrina ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,bright_light|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,73,Muschelingwer,Alpinia zerumbet,"Der Muschelingwer hat lange, elegante Blaetter und haengende Bluetenrispen mit weiss-rosa Bluetchen.",Helles bis volles Licht,20-30 °C,5,flowering|large|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,233,Samt-Anthurie,Anthurium clarinervium,Samt-Anthurie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,234,Kristall-Anthurie,Anthurium crystallinum,Kristall-Anthurie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,43,Vogelnest-Farn,Asplenium nidus,"Der Vogelnest-Farn hat ganzrandige, glaenzende Wedel, die eine Nestform bilden. Sehr dekorativ und robust.",Helles indirektes Licht,18-27 °C,5,easy|low_light|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,57,Forellen-Begonie,Begonia maculata,Die Forellen-Begonie hat olivgruene Blaetter mit silbernen Punkten und einer roten Unterseite. Atemberaubend.,Helles indirektes Licht,18-27 °C,7,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,18,Koenigsbegonie,Begonia rex,"Die Koenigsbegonie beeindruckt mit prachtvoll gemusterten Blaettern in Silber, Rot und Gruen.",Indirektes Licht,18-25 °C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,58,Knollen-Begonie,Begonia tuberhybrida,"Die Knollen-Begonie hat riesige, rosenaehnliche Blueten in leuchtendem Rot, Orange, Gelb oder Weiss.",Helles indirektes Licht,15-22 °C,5,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,49,Buntblatt,Caladium bicolor,"Das Buntblatt beeindruckt mit transparenten, bunt gemusterten Blaettern in Pink, Rot, Weiss und Gruen.",Indirektes Licht,20-30 °C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,73,Cattleya-Orchidee,Cattleya labiata,"Die Cattleya ist die Koenigin der Orchideen mit ueppigen, duftenden Blueten in Lila, Rosa und Weiss.",Helles indirektes Licht,18-28 °C,7,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,47,Taro,Colocasia esculenta,"Der Taro ist eine tropische Pflanze mit grossen, herzfoermigen Blaettern. Die Knollen sind Nahrungsquelle.",Helles indirektes Licht,18-30 °C,3,large|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,97,Columnea,Columnea gloriosa,"Die Columnea ist eine haengende Zimmerpflanze mit kleinen, behaarten Blaettern und leuchtend roten, roehrenfoermigen Blueten.",Helles indirektes Licht,18-25 °C,7,flowering|hanging|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,39,Cryptanthus,Cryptanthus bivittatus,Cryptanthus ist eine niedrig wachsende Bromelie mit sternfoermigen Rosetten und gemusterten Blaettern. Fuer Terrarien.,Helles indirektes Licht,18-27 °C,7,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,53,Ctenanthe,Ctenanthe burle-marxii,Die Ctenanthe hat faszinierend gemusterte Blaetter mit dunkelgruunem Fischgraetenmuster auf hellgruunem Hintergrund.,Indirektes Licht,18-25 °C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,74,Kurkuma,Curcuma longa,Kurkuma ist eine tropische Gewuerzpflanze mit breiten Blaettern und leuchtend gelber Wurzel. Wichtiges Heilgewuerz.,Helles bis volles Licht,20-30 °C,7,medicinal|high_humidity,medicinal_requires_external_evidence,,,, +high_humidity,constants/lexiconBatch2.ts,9,Paragraphenpflanze,Cyperus alternifolius,"Die Paragraphenpflanze hat lange, grasartige Blaetter, die sternfoermig vom Stiel abstehen. Sie liebt viel Wasser.",Helles bis volles Licht,18-27 °C,3,high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,70,Dendrobium,Dendrobium nobile,"Das Dendrobium ist eine beliebte Zimmerorchidee mit langen Pseudobulben, die im Winter mit Blueten besetzt werden.",Helles indirektes Licht,15-28 °C,10,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,80,Sonnentau,Drosera capensis,Der Sonnentau faengt Insekten mit klebrigen Tropfen auf seinen Blaettern. Eine faszinierende fleischfressende Pflanze.,Volles Sonnenlicht,15-25 °C,5,high_humidity|sun,,,,, +high_humidity,constants/lexiconBatch2.ts,137,Wasabi,Eutrema japonicum,"Wasabi ist ein seltenes Wuerzkraut, das gleichmaessige Feuchte und eher kuehle Bedingungen bevorzugt.",Helles indirektes Licht,8-20 C,4,bright_light|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,226,Nervenpflanze,Fittonia albivenis,Nervenpflanze ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,22,Gardenie,Gardenia jasminoides,"Die Gardenie fasziniert mit cremefarbenen, intensiv duftenden Blueten. Anspruchsvoll in der Pflege.",Helles indirektes Licht,18-23 °C,5,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,96,Gloxinie,Gloxinia speciosa,"Die Gloxinie hat grosse, samtartige Blueten in Violett, Rosa oder Weiss mit farbigen Raendern.",Helles indirektes Licht,18-25 °C,5,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,240,Calathea lancifolia,Goeppertia insignis,Calathea lancifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +high_humidity,constants/lexiconBatch2.ts,241,Calathea ornata,Goeppertia ornata,Calathea ornata ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +high_humidity,constants/lexiconBatch2.ts,36,Guzmania,Guzmania lingulata,"Die Guzmania ist eine Bromelie mit glänzenden, gruenen Blaettern und einem leuchtend roten, sternfoermigen Bluetenstand.",Helles indirektes Licht,18-27 °C,7,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,83,Heliamphora,Heliamphora nutans,Heliamphora ist eine urtuemliche Kannenpflanze aus den Tafelbergen Venezuelas. Sehr dekorativ und selten.,Helles indirektes Licht,15-25 °C,5,high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,72,Heliconia,Heliconia psittacorum,"Die Heliconia hat leuchtend orangefarbe oder rote, bootsfoermige Hochblaetter. Eine exotische Tropenpflanze.",Helles bis volles Licht,20-30 °C,5,flowering|bright_light|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,51,Gebet-Pflanze,Maranta leuconeura,Die Gebet-Pflanze faltet ihre gemusterten Blaetter nachts wie Haende zusammen. Faszinierende rote und gruene Muster.,Indirektes Licht,18-27 °C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +high_humidity,constants/lexiconBatch2.ts,46,Tueipelfarn (Microsorum),Microsorum punctatum,"Microsorum punctatum ist ein tropischer Farn mit langen, ungeteilten, glaenzenden Wedeln. Fuer feuchte Standorte.",Helles indirektes Licht,18-27 °C,7,high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,75,Stiefmuetterchen-Orchidee,Miltoniopsis roezlii,"Die Stiefmuetterchen-Orchidee hat grosse, flache Blueten. Bevorzugt kuehle Temperaturen und hohe Luftfeuchtigkeit.",Indirektes Licht,15-22 °C,5,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,2,Bananenpflanze,Musa acuminata,"Die Bananenpflanze ist eine tropische Staude mit riesigen, glaenzenden Blaettern. Im Zimmer selten fruechttragend.",Helles bis volles Licht,20-30 °C,5,large|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,79,Kannenpflanze,Nepenthes alata,"Die Kannenpflanze bildet grosse, gefuellte Kannen als Insekten­fallen. Eine faszinierende, tropische Pflanze.",Helles indirektes Licht,20-30 °C,5,hanging|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,74,Tanzerinnen-Orchidee,Oncidium sphacelatum,"Die Tanzerinnen-Orchidee traegt lange Rispen mit Hunderten kleiner, gelb-brauner Blueten. Sehr reichliche Bluetracht.",Helles indirektes Licht,18-27 °C,7,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,69,Schmetterlingsorchidee,Phalaenopsis amabilis,Die Schmetterlingsorchidee ist die bekannteste Zimmerorchidee. Sie bluet bei guter Pflege monatelang.,Helles indirektes Licht,18-28 °C,10,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,49,Philodendron gloriosum,Philodendron gloriosum,"Philodendron gloriosum hat grosse, samtige, herzfoermige Blaetter mit weissen Rippen. Eine atemberaubende Pflanze.",Helles indirektes Licht,18-27 °C,7,patterned|large|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,40,Blaues Kanaelfarn,Phlebodium aureum,"Der Blaue Kanaelfarn hat wachsartige, blaugruene Wedel und glaenzende Wurzelstaemme. Sehr dekorativ.",Helles indirektes Licht,18-27 °C,7,high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,81,Fettkraut,Pinguicula grandiflora,"Das Fettkraut faengt Insekten mit klebrigen Blaettern. Es bluet mit violetten, sporenartigen Blueten.",Helles indirektes Licht,10-20 °C,5,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,41,Geweihfarn,Platycerium bifurcatum,"Der Geweihfarn hat gespaltene Wedel, die einem Hirschgeweih aehneln. Er ist ein epiphytischer Farn fuer Holz.",Helles indirektes Licht,15-25 °C,7,hanging|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,78,Purpursonnentau,Sarracenia purpurea,Der Purpursonnentau ist eine fleischfressende Kannenpflanze mit purpurroten Kannen. Faengt Insekten.,Volles Sonnenlicht,5-25 °C,3,high_humidity|sun,,,,, +high_humidity,constants/lexiconBatch2.ts,45,Regenbogenmoos,Selaginella uncinata,"Das Regenbogenmoos hat schuppenfoermige Blaetter, die im Licht schillernd irisieren. Dekorativ fuer Terrarien.",Helles indirektes Licht,18-27 °C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,238,Bubikopf,Soleirolia soleirolii,Bubikopf ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,15-24 C,4,pet_friendly|high_humidity,pet_friendly_requires_external_evidence,,,, +high_humidity,constants/lexiconBatch1.ts,52,Stromanthe,Stromanthe sanguinea,Die Stromanthe hat dekorative Blaetter mit weissem Muster und leuchtend roter Unterseite. Familie der Marantaceen.,Helles indirektes Licht,18-25 °C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,82,Wasserschlauch,Utricularia gibba,Der Wasserschlauch ist eine wasserbewohnende fleischfressende Pflanze mit Schlaeuchen als Insekten­fallen.,Helles bis volles Licht,15-25 °C,2,high_humidity|sun,,,,, +high_humidity,constants/lexiconBatch1.ts,72,Vanda-Orchidee,Vanda coerulea,Die Vanda-Orchidee ist bekannt fuer ihre seltene blaue Bluetenfarbe. Epiphytische Orchidee mit grossen Blueten.,Helles bis volles Licht,20-30 °C,3,flowering|bright_light|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,76,Vanille,Vanilla planifolia,"Die Vanille ist eine kletternde Orchidee, aus deren Fruechten das beliebte Gewuerz gewonnen wird.",Helles indirektes Licht,20-30 °C,5,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,35,Flammen-Bromelie,Vriesea splendens,"Die Flammen-Bromelie hat gebänderte, dunkelgruene Blaetter und einen spektakulaeren, roten Bluetenstand.",Helles indirektes Licht,18-25 °C,7,flowering|patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,70,Calla,Zantedeschia aethiopica,"Die Calla hat elegante, trichterfoermige weisse Hochblaetter und glaenzende, herzfoermige Blaetter. Sehr edel.",Helles indirektes Licht,15-24 °C,7,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,75,Ingwer,Zingiber officinale,Ingwer ist eine tropische Gewuerzpflanze mit aromatischen Knollen. Die Blaetter sind schilfartig.,Helles indirektes Licht,20-30 °C,5,medicinal|high_humidity,medicinal_requires_external_evidence,,,, diff --git a/audits/semantic-search/categories/large.csv b/audits/semantic-search/categories/large.csv new file mode 100644 index 0000000..61eb1e7 --- /dev/null +++ b/audits/semantic-search/categories/large.csv @@ -0,0 +1,36 @@ +category,source_file,source_index,name,botanical_name,description,light,temp,water_interval_days,all_categories,risk_flags,audit_status,evidence_source,evidence_url,notes +large,constants/lexiconBatch2.ts,212,Spitzahorn,Acer platanoides,Spitzahorn ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch1.ts,11,Agave,Agave americana,"Die Agave ist eine imposante Sukkulente mit steifen, blaugruenen Blaettern mit Stacheln. Sie bluet nur einmal.",Volles Sonnenlicht,10-35 °C,21,succulent|large|sun,,,,, +large,constants/lexiconBatch1.ts,46,Amazona-Taro,Alocasia amazonica,"Der Amazona-Taro besticht mit dunkelgruenen, pfeilfoermigen Blaettern mit markant weissen Rippen.",Indirektes Licht,18-27 °C,5,patterned|large|high_humidity,,,,, +large,constants/lexiconBatch2.ts,18,Kap-Aloe (ferox),Aloe ferox,"Aloe ferox ist eine grosse, imposante Aloe mit stachligen, blaugruenen Blaettern und leuchtend roten Bluetenaehren.",Volles Sonnenlicht,10-30 °C,14,succulent|large|medicinal|sun,medicinal_requires_external_evidence,,,, +large,constants/lexiconBatch2.ts,73,Muschelingwer,Alpinia zerumbet,"Der Muschelingwer hat lange, elegante Blaetter und haengende Bluetenrispen mit weiss-rosa Bluetchen.",Helles bis volles Licht,20-30 °C,5,flowering|large|high_humidity,,,,, +large,constants/lexiconBatch2.ts,7,Bambusrohr,Bambusa vulgaris,Das Bambusrohr ist eine schnell wachsende Bambusart mit gelbgruenen Halmen. Sehr dekorativ und vielseitig nutzbar.,Helles bis volles Licht,15-30 °C,5,easy|large,,,,, +large,constants/lexiconBatch2.ts,114,Hange-Birke,Betula pendula,Die Haenge-Birke hat charakteristisch weisse Rinde und haengende Zweige. Die Blaetter werden in der Heilkunde genutzt.,Volles Sonnenlicht,10-25 °C,7,tree|large|medicinal,medicinal_requires_external_evidence,,,, +large,constants/lexiconBatch2.ts,67,Blumenschilfrohr,Canna indica,"Das Blumenschilfrohr hat grosse, tropisch wirkende Blaetter und auffaellige Blueten in Rot, Orange oder Gelb.",Volles Sonnenlicht,18-28 °C,5,flowering|large|sun,,,,, +large,constants/lexiconBatch2.ts,90,Papaya,Carica papaya,"Die Papaya ist eine tropische Fruchtpflanze mit grossen, gelappten Blaettern und orangen Fruechten.",Volles Sonnenlicht,20-35 °C,5,large|sun,,,,, +large,constants/lexiconBatch2.ts,217,Trompetenbaum,Catalpa bignonioides,Trompetenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,208,Zeder,Cedrus libani,Zeder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch1.ts,81,Peruanischer Fackelkaktus,Cereus peruvianus,"Der Peruanische Fackelkaktus ist ein saeulenfoermiger Kaktus, der im Innenraum bis zu 2 m hoch werden kann.",Volles Sonnenlicht,15-35 °C,21,easy|succulent|large|sun,,,,, +large,constants/lexiconBatch1.ts,47,Taro,Colocasia esculenta,"Der Taro ist eine tropische Pflanze mit grossen, herzfoermigen Blaettern. Die Knollen sind Nahrungsquelle.",Helles indirektes Licht,18-30 °C,3,large|high_humidity,,,,, +large,constants/lexiconBatch2.ts,209,Zypresse,Cupressus sempervirens,Zypresse ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,239,Palmfarn,Cycas revoluta,Palmfarn ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,215,Flammenbaum,Delonix regia,Flammenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +large,constants/lexiconBatch1.ts,39,Geigenfeige,Ficus lyrata,"Die Geigenfeige ist ein Trendbaum mit grossen, geigenfoermigen Blaettern. Benoetigt viel Licht.",Helles indirektes Licht,18-27 °C,7,tree|large|bright_light,,,,, +large,constants/lexiconBatch2.ts,211,Jacaranda,Jacaranda mimosifolia,Jacaranda ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +large,constants/lexiconBatch2.ts,204,Magnolie,Magnolia grandiflora,Magnolie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +large,constants/lexiconBatch2.ts,2,Bananenpflanze,Musa acuminata,"Die Bananenpflanze ist eine tropische Staude mit riesigen, glaenzenden Blaettern. Im Zimmer selten fruechttragend.",Helles bis volles Licht,20-30 °C,5,large|high_humidity,,,,, +large,constants/lexiconBatch2.ts,50,Philodendron bipinnatifidum,Philodendron bipinnatifidum,"Philodendron bipinnatifidum hat grosse, tief gelappte Blaetter. Er entwickelt einen beeindruckenden, baumfoermigen Wuchs.",Helles indirektes Licht,18-27 °C,7,easy|large,,,,, +large,constants/lexiconBatch2.ts,49,Philodendron gloriosum,Philodendron gloriosum,"Philodendron gloriosum hat grosse, samtige, herzfoermige Blaetter mit weissen Rippen. Eine atemberaubende Pflanze.",Helles indirektes Licht,18-27 °C,7,patterned|large|high_humidity,,,,, +large,constants/lexiconBatch2.ts,8,Goldener Bambus,Phyllostachys aurea,"Der Goldene Bambus hat elegante, goldgelbe Halme mit engstehenden Knoten. Sehr dekorativ als Sichtschutz.",Helles bis volles Licht,10-30 °C,5,easy|large,,,,, +large,constants/lexiconBatch2.ts,207,Fichte,Picea abies,Fichte ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,206,Kiefer,Pinus sylvestris,Kiefer ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,71,Koenigs-Protea,Protea cynaroides,"Die Koenigs-Protea ist die Nationalblume Suedafrikas mit riesigen, imposanten Bluetenkoepfen. Eine echte Besonderheit.",Volles Sonnenlicht,10-25 °C,7,flowering|large|sun,,,,, +large,constants/lexiconBatch2.ts,205,Eiche,Quercus robur,Eiche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,214,Robinie,Robinia pseudoacacia,Robinie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,113,Silber-Weide,Salix alba,"Die Silber-Weide hat silbrig-glaenzende Blaetter. Weidenrinde enthält Salicylsaeure, die Grundlage von Aspirin.",Helles bis volles Licht,10-25 °C,7,tree|large|medicinal,medicinal_requires_external_evidence,,,, +large,constants/lexiconBatch2.ts,11,Grosse Strahlenaralie,Schefflera actinophylla,"Die Grosse Strahlenaralie kann grosse, handfoermige Blaetter entwickeln. Sie ist ideal als Zimmerstrauch.",Helles indirektes Licht,18-27 °C,7,easy|tree|large,,,,, +large,constants/lexiconBatch2.ts,213,Eberesche,Sorbus aucuparia,Eberesche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,1,Weisse Strelitzie,Strelitzia nicolai,"Die Weisse Strelitzie ist ein beeindruckender Zimmerstrauch mit grossen, blaugruenen Blaettern und weiss-blauen Blueten.",Helles bis volles Licht,18-27 °C,7,tree|large|bright_light,,,,, +large,constants/lexiconBatch1.ts,3,Paradiesvogelblume,Strelitzia reginae,"Die Paradiesvogelblume beeindruckt mit leuchtend orangefarbenen und blauen Blueten, die einem Vogel aehneln.",Volles Sonnenlicht,18-26 °C,7,flowering|large|sun,,,,, +large,constants/lexiconBatch2.ts,5,Mexikanische Fächerpalme,Washingtonia robusta,"Die Mexikanische Fächerpalme ist eine schlanke, hohe Palme mit faecher­foermigen Blaettern. Sehr hitzetolerant.",Volles Sonnenlicht,15-35 °C,10,tree|large|sun,,,,, +large,constants/lexiconBatch1.ts,65,Chinesischer Blauregen,Wisteria sinensis,"Der Chinesische Blauregen ist ein ueppiger Kletterkuenstler mit langen, duftenden Bluetentrauben in Lila.",Volles Sonnenlicht,10-25 °C,7,flowering|large|sun,,,,, diff --git a/audits/semantic-search/categories/low_light.csv b/audits/semantic-search/categories/low_light.csv new file mode 100644 index 0000000..7e04e9b --- /dev/null +++ b/audits/semantic-search/categories/low_light.csv @@ -0,0 +1,17 @@ +category,source_file,source_index,name,botanical_name,description,light,temp,water_interval_days,all_categories,risk_flags,audit_status,evidence_source,evidence_url,notes +low_light,constants/lexiconBatch1.ts,50,Aglaoneme,Aglaonema commutatum,Die Aglaoneme ist eine dekorative Zimmerpflanze mit silbrig-gruen gemusterten Blaettern. Tolerant gegenueber wenig Licht.,Wenig bis helles Licht,15-26 °C,7,easy|patterned|low_light,,,,, +low_light,constants/lexiconBatch2.ts,16,Schusterpflanze,Aspidistra elatior,"Die Schusterpflanze ist eine extrem robuste Zimmerpflanze mit langen, dunkelgruenen Blaettern. Vertraegt tiefe Temperaturen.",Wenig bis helles Licht,10-20 °C,14,easy|low_light,,,,, +low_light,constants/lexiconBatch2.ts,43,Vogelnest-Farn,Asplenium nidus,"Der Vogelnest-Farn hat ganzrandige, glaenzende Wedel, die eine Nestform bilden. Sehr dekorativ und robust.",Helles indirektes Licht,18-27 °C,5,easy|low_light|high_humidity,,,,, +low_light,constants/lexiconBatch2.ts,13,Japanische Aucube,Aucuba japonica,"Die Japanische Aucube hat glaenzende, gruene oder gelbgefleckte Blaetter. Sehr schattenvertraeglich.",Wenig bis helles Licht,10-20 °C,7,easy|low_light,,,,, +low_light,constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,Die Bergpalme ist eine kompakte Zimmerpalme fuer schattigere Standorte. Ideal fuer dunkle Innenraeume.,Wenig bis helles Licht,15-25 °C,7,easy|pet_friendly|tree|air_purifier|low_light,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +low_light,constants/lexiconBatch1.ts,48,Dieffenbachie,Dieffenbachia seguine,"Die Dieffenbachie ist eine tropische Blattschmuckpflanze mit grossen, gruen-weiss gefleckten Blaettern.",Helles indirektes Licht,18-26 °C,7,easy|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +low_light,constants/lexiconBatch1.ts,14,Maisstrauch,Dracaena fragrans,"Der Maisstrauch ist eine robuste Zimmerpflanze mit breiten, gestreiften Blaettern. Gedeiht auch bei wenig Licht.",Helles indirektes Licht,15-25 °C,10,easy|tree|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +low_light,constants/lexiconBatch2.ts,12,Fatsia,Fatsia japonica,"Die Fatsia ist ein dekorativer Zimmerstrauch mit grossen, handfoermigen, glaenzenden Blaettern. Sehr robust.",Helles indirektes Licht,10-20 °C,7,easy|low_light,,,,, +low_light,constants/lexiconBatch1.ts,90,Gasteria,Gasteria carinata,"Die Gasteria ist eine kleine Sukkulente mit zweireihig angeordneten, zungenfoermigen, gefleckten Blaettern.",Helles indirektes Licht,15-25 °C,14,easy|succulent|low_light,,,,, +low_light,constants/lexiconBatch1.ts,6,Zebra-Haworthie,Haworthia fasciata,Die Zebra-Haworthie ist eine kompakte Sukkulente mit weissen Querstreifen auf dunkelgruenen Blaettern.,Helles indirektes Licht,15-25 °C,14,easy|succulent|low_light,,,,, +low_light,constants/lexiconBatch1.ts,37,Efeu,Hedera helix,"Efeu ist eine robuste Kletter- und Haengepflanze mit charakteristischen, dreilappigen Blaettern. Sehr langlebig.",Wenig bis helles Licht,10-20 °C,7,easy|hanging|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +low_light,constants/lexiconBatch2.ts,3,Kentia-Palme,Howea forsteriana,"Die Kentia-Palme ist eine der elegantesten Zimmerpalmen mit langen, herabhängenden Fiederblaettern.",Helles indirektes Licht,18-25 °C,7,pet_friendly|tree|low_light,pet_friendly_requires_external_evidence,,,, +low_light,constants/lexiconBatch1.ts,103,Spiegelpeperomie,Peperomia obtusifolia,"Die Spiegelpeperomie hat glaenzende, lederartige, oval-runde Blaetter in tiefem Gruen. Sehr robust.",Helles indirektes Licht,16-26 °C,10,easy|pet_friendly|low_light,pet_friendly_requires_external_evidence,,,, +low_light,constants/lexiconBatch1.ts,15,Herzblatt-Philodendron,Philodendron hederaceum,Der Herzblatt-Philodendron ist eine pflegeleichte Kletter- oder Haengepflanze mit herzfoermigen Blaettern.,Indirektes Licht,18-28 °C,7,easy|hanging|low_light,,,,, +low_light,constants/lexiconBatch2.ts,242,Philodendron Brasil,Philodendron hederaceum Brasil,Philodendron Brasil ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|hanging|low_light,,,,, +low_light,constants/lexiconBatch1.ts,45,Stab-Palme,Rhapis excelsa,"Die Stab-Palme ist eine elegante Zimmerpalme mit faecher­foermigen Blaettern auf duennen, bambusartigen Staemmen.",Helles indirektes Licht,15-25 °C,7,tree|low_light,,,,, diff --git a/audits/semantic-search/categories/medicinal.csv b/audits/semantic-search/categories/medicinal.csv new file mode 100644 index 0000000..0746445 --- /dev/null +++ b/audits/semantic-search/categories/medicinal.csv @@ -0,0 +1,33 @@ +category,source_file,source_index,name,botanical_name,description,light,temp,water_interval_days,all_categories,risk_flags,audit_status,evidence_source,evidence_url,notes +medicinal,constants/lexiconBatch2.ts,108,Schafgarbe,Achillea millefolium,Die Schafgarbe hat weisse oder rosafarbene Bluetenschirme und fein gefiederte Blaetter. Wichtige Heilpflanze.,Volles Sonnenlicht,10-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch1.ts,89,Kap-Aloe,Aloe arborescens,"Die Kap-Aloe ist eine strauchige Aloe mit schmalen, gezaehnten Blaettern und leuchtend roten Bluetenaehren im Winter.",Volles Sonnenlicht,10-30 °C,14,easy|succulent|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,18,Kap-Aloe (ferox),Aloe ferox,"Aloe ferox ist eine grosse, imposante Aloe mit stachligen, blaugruenen Blaettern und leuchtend roten Bluetenaehren.",Volles Sonnenlicht,10-30 °C,14,succulent|large|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,107,Arnika,Arnica montana,Arnika ist eine bekannte Heilpflanze aus den Alpen mit goldgelben Korbbluten. Sie wird fuer Muskeln und Gelenke verwendet.,Volles Sonnenlicht,10-20 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,110,Wermut,Artemisia absinthium,"Wermut ist ein stark aromatisches Heilkraut mit silbrig-gruenen, tief eingeschnittenen Blaettern. Fuer Kraeuterlikoere.",Volles Sonnenlicht,10-25 °C,14,medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,114,Hange-Birke,Betula pendula,Die Haenge-Birke hat charakteristisch weisse Rinde und haengende Zweige. Die Blaetter werden in der Heilkunde genutzt.,Volles Sonnenlicht,10-25 °C,7,tree|large|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,187,Ringelblume,Calendula officinalis,"Ringelblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,92,Chili,Capsicum annuum,"Chili ist eine beliebte Gemuese- und Zierpflanze mit leuchtenden, roten oder orangen Fruechten. Im Topf kultivierbar.",Volles Sonnenlicht,20-30 °C,4,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,138,Roemische Kamille,Chamaemelum nobile,Roemische Kamille ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,101,Kamille,Chamomilla recutita,"Die Kamille ist ein beliebtes Heilkraut mit kleinen, weiss-gelben Blueten. Das aetherische Oel wirkt beruhigend.",Volles Sonnenlicht,15-25 °C,5,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,160,Maigloeckchen,Convallaria majalis,"Maigloeckchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,74,Kurkuma,Curcuma longa,Kurkuma ist eine tropische Gewuerzpflanze mit breiten Blaettern und leuchtend gelber Wurzel. Wichtiges Heilgewuerz.,Helles bis volles Licht,20-30 °C,7,medicinal|high_humidity,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,109,Roter Fingerhut,Digitalis purpurea,"Der Rote Fingerhut hat hohe Bluetenstaende mit roehrenfoermigen, gepunkteten Blueten in Rosa. Wichtige Arzneipflanze.",Helles bis volles Licht,10-20 °C,7,flowering|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,106,Sonnenhut,Echinacea purpurea,"Der Sonnenhut ist eine beliebte Heilpflanze mit grossen, pinkfarbenen Blueten. Er staerkt das Immunsystem.",Helles bis volles Licht,15-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,210,Eukalyptus,Eucalyptus globulus,Eukalyptus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,216,Ginkgo,Ginkgo biloba,Ginkgo ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,119,Zaubernuss,Hamamelis mollis,"Die Zaubernuss bluet im Winter mit fadendunnen, gelben Bluetenkranzeln, die bis -10 Grad standhalten.",Helles bis volles Licht,10-20 °C,10,flowering|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,105,Johanniskraut,Hypericum perforatum,Das Johanniskraut hat leuchtend gelbe Blueten und ist ein wichtiges Heilkraut gegen Depressionen und Stimmungstiefs.,Volles Sonnenlicht,10-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch1.ts,23,Echter Lavendel,Lavandula angustifolia,Der Echte Lavendel ist ein aromatischer Halbstrauch mit lilafarbenen Bluetenaehren. Herrlicher Duft.,Volles Sonnenlicht,10-25 °C,10,medicinal|bright_light|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,102,Zitronenmelisse,Melissa officinalis,Die Zitronenmelisse ist ein zitronig duftendes Heilkraut. Sie beruhigt die Nerven und foerdert den Schlaf.,Helles bis volles Licht,15-25 °C,5,easy|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch1.ts,25,Basilikum,Ocimum basilicum,"Basilikum ist das beliebteste Kuechenkraut mit intensiv aromatischen, gruenen Blaettern. Fuer Pesto verwendet.",Volles Sonnenlicht,18-30 °C,2,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch1.ts,28,Oregano,Origanum vulgare,"Oregano ist ein aromatisches Kuechenkraut mit runden, behaarten Blaettern. In mediterraner Kueche beliebt.",Volles Sonnenlicht,15-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch1.ts,31,Rosengeranie,Pelargonium graveolens,Die Rosengeranie ist eine Duftpflanze mit tief eingeschnittenen Blaettern und rosaenlichem Aroma.,Volles Sonnenlicht,15-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch1.ts,24,Rosmarin,Rosmarinus officinalis,Rosmarin ist ein aromatisches Kraut mit nadelartigen Blaettern und blauen Blueten. In der Kueche unverzichtbar.,Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,113,Silber-Weide,Salix alba,"Die Silber-Weide hat silbrig-glaenzende Blaetter. Weidenrinde enthält Salicylsaeure, die Grundlage von Aspirin.",Helles bis volles Licht,10-25 °C,7,tree|large|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,103,Salbei,Salvia officinalis,Salbei ist ein aromatisches Heilkraut mit silbrig-gruenen Blaettern. Er hat antibakterielle und entzuendungshem­mende Wirkung.,Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,112,Schwarzer Holunder,Sambucus nigra,Der Schwarze Holunder hat weisse Doldenbluten und schwarze Beeren. Die Fruechte werden fuer Sirup und Saft verwendet.,Helles bis volles Licht,10-25 °C,7,flowering|tree|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch1.ts,27,Thymian,Thymus vulgaris,"Thymian ist ein kleiner, aromatischer Strauch mit winzigen Blaettern und rosa Blueten. Wichtiges Kuechenkraut.",Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,111,Grosse Brennessel,Urtica dioica,Die Grosse Brennessel ist eine Heilpflanze mit brennenden Haaren. Die Blaetter sind reich an Vitaminen und Mineralien.,Helles bis volles Licht,10-25 °C,7,medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,104,Baldrian,Valeriana officinalis,Baldrian ist ein bekanntes Heilkraut mit weissen bis roeslichen Blueten. Die Wurzeln werden zur Schlaffoerderung verwendet.,Helles bis volles Licht,15-25 °C,7,flowering|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,192,Koenigskerze,Verbascum thapsus,"Koenigskerze ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,75,Ingwer,Zingiber officinale,Ingwer ist eine tropische Gewuerzpflanze mit aromatischen Knollen. Die Blaetter sind schilfartig.,Helles indirektes Licht,20-30 °C,5,medicinal|high_humidity,medicinal_requires_external_evidence,,,, diff --git a/audits/semantic-search/categories/patterned.csv b/audits/semantic-search/categories/patterned.csv new file mode 100644 index 0000000..1dc8895 --- /dev/null +++ b/audits/semantic-search/categories/patterned.csv @@ -0,0 +1,32 @@ +category,source_file,source_index,name,botanical_name,description,light,temp,water_interval_days,all_categories,risk_flags,audit_status,evidence_source,evidence_url,notes +patterned,constants/lexiconBatch2.ts,34,Silbervase,Aechmea fasciata,Die Silbervase ist eine Bromelie mit silbrig gebänderten Blaettern und einem rosafarbenen Bluetenstand.,Helles indirektes Licht,18-25 °C,10,flowering|patterned,,,,, +patterned,constants/lexiconBatch1.ts,50,Aglaoneme,Aglaonema commutatum,Die Aglaoneme ist eine dekorative Zimmerpflanze mit silbrig-gruen gemusterten Blaettern. Tolerant gegenueber wenig Licht.,Wenig bis helles Licht,15-26 °C,7,easy|patterned|low_light,,,,, +patterned,constants/lexiconBatch1.ts,46,Amazona-Taro,Alocasia amazonica,"Der Amazona-Taro besticht mit dunkelgruenen, pfeilfoermigen Blaettern mit markant weissen Rippen.",Indirektes Licht,18-27 °C,5,patterned|large|high_humidity,,,,, +patterned,constants/lexiconBatch2.ts,233,Samt-Anthurie,Anthurium clarinervium,Samt-Anthurie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch2.ts,234,Kristall-Anthurie,Anthurium crystallinum,Kristall-Anthurie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch2.ts,57,Forellen-Begonie,Begonia maculata,Die Forellen-Begonie hat olivgruene Blaetter mit silbernen Punkten und einer roten Unterseite. Atemberaubend.,Helles indirektes Licht,18-27 °C,7,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch1.ts,18,Koenigsbegonie,Begonia rex,"Die Koenigsbegonie beeindruckt mit prachtvoll gemusterten Blaettern in Silber, Rot und Gruen.",Indirektes Licht,18-25 °C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch1.ts,49,Buntblatt,Caladium bicolor,"Das Buntblatt beeindruckt mit transparenten, bunt gemusterten Blaettern in Pink, Rot, Weiss und Gruen.",Indirektes Licht,20-30 °C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch1.ts,99,Herzkette,Ceropegia woodii,"Die Herzkette hat duenne, haengende Ranken mit herzfoermigen, silbergrau gemusterten Blaettchen.",Helles indirektes Licht,15-27 °C,14,easy|succulent|patterned|hanging,,,,, +patterned,constants/lexiconBatch2.ts,224,Kroton,Codiaeum variegatum,Kroton ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,patterned|bright_light,,,,, +patterned,constants/lexiconBatch2.ts,39,Cryptanthus,Cryptanthus bivittatus,Cryptanthus ist eine niedrig wachsende Bromelie mit sternfoermigen Rosetten und gemusterten Blaettern. Fuer Terrarien.,Helles indirektes Licht,18-27 °C,7,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch1.ts,53,Ctenanthe,Ctenanthe burle-marxii,Die Ctenanthe hat faszinierend gemusterte Blaetter mit dunkelgruunem Fischgraetenmuster auf hellgruunem Hintergrund.,Indirektes Licht,18-25 °C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch2.ts,226,Nervenpflanze,Fittonia albivenis,Nervenpflanze ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch2.ts,240,Calathea lancifolia,Goeppertia insignis,Calathea lancifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +patterned,constants/lexiconBatch2.ts,241,Calathea ornata,Goeppertia ornata,Calathea ornata ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +patterned,constants/lexiconBatch2.ts,227,Punktblatt,Hypoestes phyllostachya,Punktblatt ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,patterned|bright_light,,,,, +patterned,constants/lexiconBatch1.ts,51,Gebet-Pflanze,Maranta leuconeura,Die Gebet-Pflanze faltet ihre gemusterten Blaetter nachts wie Haende zusammen. Faszinierende rote und gruene Muster.,Indirektes Licht,18-27 °C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +patterned,constants/lexiconBatch2.ts,48,Monstera obliqua,Monstera obliqua,"Monstera obliqua ist eine seltene Monstera-Art mit filigranen Blaettern, die hauptsaechlich aus Lochern bestehen.",Helles indirektes Licht,18-27 °C,7,patterned|hanging,,,,, +patterned,constants/lexiconBatch2.ts,37,Neoregelia,Neoregelia carolinae,"Die Neoregelia ist eine Bromelie, bei der das Herzblatt zur Bluetzeit leuchtend rot wird. Sehr dekorativ.",Helles bis volles Licht,18-27 °C,7,flowering|patterned|bright_light,,,,, +patterned,constants/lexiconBatch1.ts,54,Kleeblume,Oxalis triangularis,"Die Kleeblume hat tiefviolette, dreieckige Blaetter und zarte rosa Blueten. Sie faltet die Blaetter bei Dunkelheit.",Helles indirektes Licht,15-24 °C,7,flowering|patterned,,,,, +patterned,constants/lexiconBatch2.ts,6,Schraubenbaum,Pandanus veitchii,"Der Schraubenbaum hat spiralfoermig angeordnete, gruenweiss gestreifte Blaetter. Sehr dekorativ und exotisch.",Helles bis volles Licht,18-27 °C,7,patterned|bright_light,,,,, +patterned,constants/lexiconBatch2.ts,229,Wassermelonen-Peperomie,Peperomia argyreia,Wassermelonen-Peperomie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,pet_friendly|patterned,pet_friendly_requires_external_evidence,,,, +patterned,constants/lexiconBatch2.ts,243,Philodendron Pink Princess,Philodendron erubescens Pink Princess,Philodendron Pink Princess ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,patterned|bright_light,,,,, +patterned,constants/lexiconBatch2.ts,49,Philodendron gloriosum,Philodendron gloriosum,"Philodendron gloriosum hat grosse, samtige, herzfoermige Blaetter mit weissen Rippen. Eine atemberaubende Pflanze.",Helles indirektes Licht,18-27 °C,7,patterned|large|high_humidity,,,,, +patterned,constants/lexiconBatch2.ts,228,Aluminium-Pflanze,Pilea cadierei,Aluminium-Pflanze ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|pet_friendly|patterned,pet_friendly_requires_external_evidence,,,, +patterned,constants/lexiconBatch2.ts,152,Buntnessel,Plectranthus scutellarioides,"Buntnessel ist eine farbstarke Zierpflanze, die vor allem fuer ihr dekoratives Laub beliebt ist.",Volles bis helles Licht,10-24 C,4,patterned|bright_light,,,,, +patterned,constants/lexiconBatch1.ts,55,Satinpothos,Scindapsus pictus,"Der Satinpothos hat samtig-glaenzende, silbrig gefleckte Blaetter auf langen, haengenden Ranken.",Helles indirektes Licht,18-28 °C,7,easy|patterned|hanging,,,,, +patterned,constants/lexiconBatch2.ts,45,Regenbogenmoos,Selaginella uncinata,"Das Regenbogenmoos hat schuppenfoermige Blaetter, die im Licht schillernd irisieren. Dekorativ fuer Terrarien.",Helles indirektes Licht,18-27 °C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch1.ts,52,Stromanthe,Stromanthe sanguinea,Die Stromanthe hat dekorative Blaetter mit weissem Muster und leuchtend roter Unterseite. Familie der Marantaceen.,Helles indirektes Licht,18-25 °C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch1.ts,17,Zebrakraut,Tradescantia zebrina,Das Zebrakraut faellt durch seine silbrig-lila gestreiften Blaetter auf. Schnellwachsende Haengepflanze.,Helles indirektes Licht,15-25 °C,5,easy|patterned|hanging,,,,, +patterned,constants/lexiconBatch2.ts,35,Flammen-Bromelie,Vriesea splendens,"Die Flammen-Bromelie hat gebänderte, dunkelgruene Blaetter und einen spektakulaeren, roten Bluetenstand.",Helles indirektes Licht,18-25 °C,7,flowering|patterned|high_humidity,,,,, diff --git a/audits/semantic-search/categories/pet_friendly.csv b/audits/semantic-search/categories/pet_friendly.csv new file mode 100644 index 0000000..748faa2 --- /dev/null +++ b/audits/semantic-search/categories/pet_friendly.csv @@ -0,0 +1,16 @@ +category,source_file,source_index,name,botanical_name,description,light,temp,water_interval_days,all_categories,risk_flags,audit_status,evidence_source,evidence_url,notes +pet_friendly,constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,Die Bergpalme ist eine kompakte Zimmerpalme fuer schattigere Standorte. Ideal fuer dunkle Innenraeume.,Wenig bis helles Licht,15-25 °C,7,easy|pet_friendly|tree|air_purifier|low_light,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch1.ts,42,Goldfruchtpalme,Dypsis lutescens,Die Goldfruchtpalme ist eine elegante Zimmerpalme mit gelblich-gruenen Stielen und gefiederten Wedeln.,Helles indirektes Licht,18-27 °C,5,pet_friendly|tree|air_purifier,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,100,Erdbeere,Fragaria ananassa,"Die Erdbeere ist ein beliebtes Obst fuer Balkon und Terrasse mit aromatischen, roten Fruechten.",Helles bis volles Licht,15-25 °C,3,easy|pet_friendly|sun,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,240,Calathea lancifolia,Goeppertia insignis,Calathea lancifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,241,Calathea ornata,Goeppertia ornata,Calathea ornata ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,3,Kentia-Palme,Howea forsteriana,"Die Kentia-Palme ist eine der elegantesten Zimmerpalmen mit langen, herabhängenden Fiederblaettern.",Helles indirektes Licht,18-25 °C,7,pet_friendly|tree|low_light,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch1.ts,51,Gebet-Pflanze,Maranta leuconeura,Die Gebet-Pflanze faltet ihre gemusterten Blaetter nachts wie Haende zusammen. Faszinierende rote und gruene Muster.,Indirektes Licht,18-27 °C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,229,Wassermelonen-Peperomie,Peperomia argyreia,Wassermelonen-Peperomie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,pet_friendly|patterned,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch1.ts,102,Rippenpeperomie,Peperomia caperata,"Die Rippenpeperomie hat tief gerippte, dunkelgruene bis violette Blaetter mit einer samtigen Textur.",Helles indirektes Licht,18-26 °C,10,easy|pet_friendly,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch1.ts,103,Spiegelpeperomie,Peperomia obtusifolia,"Die Spiegelpeperomie hat glaenzende, lederartige, oval-runde Blaetter in tiefem Gruen. Sehr robust.",Helles indirektes Licht,16-26 °C,10,easy|pet_friendly|low_light,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,230,Raindrop-Peperomie,Peperomia polybotrya,Raindrop-Peperomie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|pet_friendly,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch1.ts,34,Petunie,Petunia hybrida,Die Petunie ist eine der beliebtesten Balkonpflanzen mit trichterfoermigen Blueten in unzaehligen Farben.,Volles Sonnenlicht,15-25 °C,2,easy|pet_friendly|flowering|sun,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,228,Aluminium-Pflanze,Pilea cadierei,Aluminium-Pflanze ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|pet_friendly|patterned,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch1.ts,2,Ufopflanze,Pilea peperomioides,"Die Ufopflanze hat unverwechselbare, runde Blaetter auf langen Stielen. Bildet leicht Ableger zum Verschenken.",Helles indirektes Licht,13-30 °C,7,easy|pet_friendly,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,238,Bubikopf,Soleirolia soleirolii,Bubikopf ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,15-24 C,4,pet_friendly|high_humidity,pet_friendly_requires_external_evidence,,,, diff --git a/audits/semantic-search/categories/succulent.csv b/audits/semantic-search/categories/succulent.csv new file mode 100644 index 0000000..aef06dc --- /dev/null +++ b/audits/semantic-search/categories/succulent.csv @@ -0,0 +1,47 @@ +category,source_file,source_index,name,botanical_name,description,light,temp,water_interval_days,all_categories,risk_flags,audit_status,evidence_source,evidence_url,notes +succulent,constants/lexiconBatch1.ts,86,Wuestenrose,Adenium obesum,Die Wuestenrose ist eine sukkulente Zimmerpflanze mit dickem Stamm und leuchtend pinken Blueten.,Volles Sonnenlicht,20-35 °C,10,flowering|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,117,Socotra-Wuestenrose,Adenium socotranum,"Die Socotra-Wuestenrose ist eine seltene, endemische Art mit einem sehr dicken, knolligen Stamm und rosa Blueten.",Volles Sonnenlicht,20-35 °C,14,flowering|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,31,Adromischus,Adromischus cristatus,Adromischus ist eine kompakte Sukkulente mit ungewoehnlich wellenrandigen Blaettern auf kurzen Staengeln.,Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,10,Schwarze Rose (Aeonium),Aeonium arboreum,"Das Aeonium bildet dekorative, rosettenfoermige Sukkulenten an verzweigten Stielen.",Volles Sonnenlicht,10-25 °C,10,succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,11,Agave,Agave americana,"Die Agave ist eine imposante Sukkulente mit steifen, blaugruenen Blaettern mit Stacheln. Sie bluet nur einmal.",Volles Sonnenlicht,10-35 °C,21,succulent|large|sun,,,,, +succulent,constants/lexiconBatch1.ts,89,Kap-Aloe,Aloe arborescens,"Die Kap-Aloe ist eine strauchige Aloe mit schmalen, gezaehnten Blaettern und leuchtend roten Bluetenaehren im Winter.",Volles Sonnenlicht,10-30 °C,14,easy|succulent|medicinal|sun,medicinal_requires_external_evidence,,,, +succulent,constants/lexiconBatch2.ts,18,Kap-Aloe (ferox),Aloe ferox,"Aloe ferox ist eine grosse, imposante Aloe mit stachligen, blaugruenen Blaettern und leuchtend roten Bluetenaehren.",Volles Sonnenlicht,10-30 °C,14,succulent|large|medicinal|sun,medicinal_requires_external_evidence,,,, +succulent,constants/lexiconBatch1.ts,41,Pferdeschwanzpalme,Beaucarnea recurvata,"Die Pferdeschwanzpalme hat einen verdickten Stammbasis als Wasserspeicher und lange, schmale Blaetter.",Volles Sonnenlicht,15-30 °C,21,easy|succulent|tree|sun,,,,, +succulent,constants/lexiconBatch1.ts,81,Peruanischer Fackelkaktus,Cereus peruvianus,"Der Peruanische Fackelkaktus ist ein saeulenfoermiger Kaktus, der im Innenraum bis zu 2 m hoch werden kann.",Volles Sonnenlicht,15-35 °C,21,easy|succulent|large|sun,,,,, +succulent,constants/lexiconBatch1.ts,99,Herzkette,Ceropegia woodii,"Die Herzkette hat duenne, haengende Ranken mit herzfoermigen, silbergrau gemusterten Blaettchen.",Helles indirektes Licht,15-27 °C,14,easy|succulent|patterned|hanging,,,,, +succulent,constants/lexiconBatch2.ts,24,Konophytum,Conophytum calculus,"Das Konophytum ist eine sehr kompakte Sukkulente, die zwei Blaetter zu einer kugelfoermigen Form verschmilzt.",Volles Sonnenlicht,10-25 °C,21,succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,29,Kotyledon,Cotyledon orbiculata,"Kotyledon hat dickfleischige, runde Blaetter mit einem mehligen, weisslichen Belag. Sehr trockenheitsresistent.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,26,Moos-Crassula,Crassula muscosa,"Die Moos-Crassula hat dicht aneinandergereihte, winzige gruene Blaetter auf unverzweigten Trieben. Sieht aus wie Moos.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,5,Jadepflanze,Crassula ovata,"Die Jadepflanze ist eine langlebige Sukkulente mit dicken, ovalen Blaettern. In Japan gilt sie als Gluecksbringer.",Helles bis volles Licht,15-24 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,236,String of Bananas,Curio radicans,String of Bananas ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,succulent|hanging|sun,,,,, +succulent,constants/lexiconBatch2.ts,237,String of Dolphins,Curio x peregrinus,String of Dolphins ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,succulent|hanging|sun,,,,, +succulent,constants/lexiconBatch1.ts,101,Dischidia,Dischidia ruscifolia,"Die Dischidia ist eine epiphytische Haengepflanze mit kleinen, runden Blaettern entlang duenner Ranken.",Helles indirektes Licht,18-27 °C,7,succulent|hanging,,,,, +succulent,constants/lexiconBatch2.ts,30,Dudleya,Dudleya brittonii,"Dudleya ist eine rosetten­bildende Sukkulente mit silbrig-weissen, mehligen Blaettern. Sehr elegant.",Volles Sonnenlicht,10-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,4,Echeverie,Echeveria elegans,"Die Echeverie bildet symmetrische, rosettenfoermige Sukkulenten mit blaugruenen Blaettern. Pflegeleicht.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,77,Goldene Tonne,Echinocactus grusonii,Die Goldene Tonne ist ein ikonischer kugelfoermiger Kaktus mit goldgelben Stacheln. Waechst langsam aber imposant.,Volles Sonnenlicht,15-35 °C,21,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,83,San-Pedro-Kaktus,Echinopsis pachanoi,"Der San-Pedro-Kaktus ist ein schnell wachsender, saeulenfoermiger Kaktus aus den Anden.",Volles Sonnenlicht,10-35 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,84,Koenigin der Nacht,Epiphyllum oxypetalum,"Die Koenigin der Nacht bluet nur eine einzige Nacht lang mit riesigen, intensiv duftenden weissen Blueten.",Indirektes Licht,18-27 °C,7,flowering|succulent,,,,, +succulent,constants/lexiconBatch2.ts,19,Christusdorn,Euphorbia milii,Der Christusdorn ist eine sukkulente Wolfsmilch mit stacheligen Zweigen und kleinen roten oder gelben Hochblaettern.,Helles bis volles Licht,15-28 °C,10,easy|flowering|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,12,Bleistiftkaktus,Euphorbia tirucalli,"Der Bleistiftkaktus ist eine sukkulente Wolfsmilch mit duennen, zylindrischen Zweigen ohne Blaetter.",Volles Sonnenlicht,18-30 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,78,Fass-Kaktus,Ferocactus cylindraceus,"Der Fass-Kaktus ist ein zylindrischer Wuestenkaktus mit langen, roten Stacheln. Sehr langlebig.",Volles Sonnenlicht,15-35 °C,21,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,90,Gasteria,Gasteria carinata,"Die Gasteria ist eine kleine Sukkulente mit zweireihig angeordneten, zungenfoermigen, gefleckten Blaettern.",Helles indirektes Licht,15-25 °C,14,easy|succulent|low_light,,,,, +succulent,constants/lexiconBatch1.ts,87,Geisterpflanze,Graptopetalum paraguayense,"Die Geisterpflanze hat zartgraue bis perlmutt-rosafarbene, rosettenfoermige Blaetter. Sehr robuste Sukkulente.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,80,Mond-Kaktus,Gymnocalycium mihanovichii,Der Mond-Kaktus ist eine farbenfrohe Veredelung eines chlorophylllosen Kaktus auf einem gruenen Unterlagekaktus.,Indirektes Licht,15-30 °C,14,easy|succulent,,,,, +succulent,constants/lexiconBatch1.ts,6,Zebra-Haworthie,Haworthia fasciata,Die Zebra-Haworthie ist eine kompakte Sukkulente mit weissen Querstreifen auf dunkelgruenen Blaettern.,Helles indirektes Licht,15-25 °C,14,easy|succulent|low_light,,,,, +succulent,constants/lexiconBatch1.ts,58,Kleine Wachsblume,Hoya bella,"Die Kleine Wachsblume traegt zierliche, sternfoermige weisse Blueten mit rosa Mitte. Haengende Sukkulente.",Helles indirektes Licht,18-27 °C,10,flowering|succulent|hanging,,,,, +succulent,constants/lexiconBatch1.ts,57,Wachsblume,Hoya carnosa,"Die Wachsblume ist eine Kletterpflanze mit dicken, wachsartigen Blaettern und sternfoermigen, duftenden Blueten.",Helles indirektes Licht,16-27 °C,10,easy|flowering|succulent|hanging,,,,, +succulent,constants/lexiconBatch1.ts,9,Kalanchoe,Kalanchoe blossfeldiana,"Die Kalanchoe ist eine beliebte Bluehpflanze mit leuchtenden Blueten in Rot, Orange, Gelb oder Rosa.",Helles bis volles Licht,15-25 °C,10,easy|flowering|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,22,Brutblatt,Kalanchoe daigremontiana,Das Brutblatt bildet entlang des Blattrandes zahlreiche kleine Jungpflanzen. Eine faszinierende Sukkulente.,Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,21,Kaninchen-Ohren,Kalanchoe tomentosa,"Kaninchen-Ohren haben weisslich-filzige Blaetter mit braunen Raendern, die Kaninchen­ohren aehneln. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,23,Lebende Steine,Lithops julii,"Lebende Steine sind faszinierende Mimikry-Sukkulenten, die Kieselsteinen taeuschen aehnlich sehen. Sehr trockenheitsresistent.",Volles Sonnenlicht,10-30 °C,21,succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,79,Mammillaria,Mammillaria zeilmanniana,"Die Mammillaria ist ein kompakter, kugelfoermiger Kaktus, der im Fruehling einen Kranz aus rosa Blueten traegt.",Volles Sonnenlicht,15-35 °C,14,easy|flowering|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,82,Hasenohren-Kaktus,Opuntia microdasys,"Der Hasenohren-Kaktus hat flache, ovale Triebe mit dichten weissen Glochiden. Klassischer Zimmerkaktus.",Volles Sonnenlicht,10-35 °C,21,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,88,Mondstein-Pflanze,Pachyphytum oviferum,"Die Mondstein-Pflanze hat dicke, ovale Blaetter mit einem pastellrosafarbenen, mehligen Ueberzug.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,27,Speckbaum,Portulacaria afra,"Der Speckbaum ist eine sukkulente Pflanze mit roten Stielen und kleinen, runden, glaenzenden Blaettern.",Helles bis volles Licht,15-30 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,85,Korallenkaktus,Rhipsalis baccifera,"Der Korallenkaktus ist ein epiphytischer Kaktus mit duennen, haengenden Trieben und kleinen weissen Beeren.",Indirektes Licht,18-27 °C,7,succulent|hanging,,,,, +succulent,constants/lexiconBatch2.ts,17,Zylindrischer Bogenhanf,Sansevieria cylindrica,"Der Zylindrische Bogenhanf hat zylindrische, aufrechte Blaetter, die sich nach oben verjuengen. Sehr pflegeleicht.",Helles bis volles Licht,15-27 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,8,Weihnachtskaktus,Schlumbergera truncata,"Der Weihnachtskaktus erfreut zur Weihnachtszeit mit leuchtenden Blueten in Rosa, Rot oder Weiss.",Helles indirektes Licht,15-21 °C,7,easy|flowering|succulent,,,,, +succulent,constants/lexiconBatch1.ts,7,Eselschwanz,Sedum morganianum,"Der Eselschwanz ist eine haengende Sukkulente mit langen Trieben aus dichten, blaugruenen Blaettchen.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|hanging|sun,,,,, +succulent,constants/lexiconBatch1.ts,100,Perlenschnur-Pflanze,Senecio rowleyanus,"Die Perlenschnur-Pflanze hat haengende Ranken mit kugelfoermigen, perlenaehnlichen Blaettern. Einzigartige Sukkulente.",Helles bis volles Licht,15-27 °C,14,easy|succulent|hanging,,,,, +succulent,constants/lexiconBatch2.ts,28,Blauer Kreuzkraut,Senecio serpens,"Der Blaue Kreuzkraut hat zylindrische, blaublaugruene Blaetter und einen kriechenden Wuchs. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,25,Aasblume,Stapelia grandiflora,"Die Aasblume hat fleischige, gruene Staengel und riesige, sternfoermige Blueten mit aasartigem Duft.",Helles bis volles Licht,18-30 °C,14,flowering|succulent|sun,,,,, diff --git a/audits/semantic-search/categories/sun.csv b/audits/semantic-search/categories/sun.csv new file mode 100644 index 0000000..e617d0b --- /dev/null +++ b/audits/semantic-search/categories/sun.csv @@ -0,0 +1,173 @@ +category,source_file,source_index,name,botanical_name,description,light,temp,water_interval_days,all_categories,risk_flags,audit_status,evidence_source,evidence_url,notes +sun,constants/lexiconBatch2.ts,212,Spitzahorn,Acer platanoides,Spitzahorn ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,108,Schafgarbe,Achillea millefolium,Die Schafgarbe hat weisse oder rosafarbene Bluetenschirme und fein gefiederte Blaetter. Wichtige Heilpflanze.,Volles Sonnenlicht,10-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch1.ts,86,Wuestenrose,Adenium obesum,Die Wuestenrose ist eine sukkulente Zimmerpflanze mit dickem Stamm und leuchtend pinken Blueten.,Volles Sonnenlicht,20-35 °C,10,flowering|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,117,Socotra-Wuestenrose,Adenium socotranum,"Die Socotra-Wuestenrose ist eine seltene, endemische Art mit einem sehr dicken, knolligen Stamm und rosa Blueten.",Volles Sonnenlicht,20-35 °C,14,flowering|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,31,Adromischus,Adromischus cristatus,Adromischus ist eine kompakte Sukkulente mit ungewoehnlich wellenrandigen Blaettern auf kurzen Staengeln.,Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch1.ts,10,Schwarze Rose (Aeonium),Aeonium arboreum,"Das Aeonium bildet dekorative, rosettenfoermige Sukkulenten an verzweigten Stielen.",Volles Sonnenlicht,10-25 °C,10,succulent|sun,,,,, +sun,constants/lexiconBatch1.ts,11,Agave,Agave americana,"Die Agave ist eine imposante Sukkulente mit steifen, blaugruenen Blaettern mit Stacheln. Sie bluet nur einmal.",Volles Sonnenlicht,10-35 °C,21,succulent|large|sun,,,,, +sun,constants/lexiconBatch2.ts,155,Stockrose,Alcea rosea,"Stockrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,135,Schnittknoblauch,Allium tuberosum,Schnittknoblauch ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch1.ts,89,Kap-Aloe,Aloe arborescens,"Die Kap-Aloe ist eine strauchige Aloe mit schmalen, gezaehnten Blaettern und leuchtend roten Bluetenaehren im Winter.",Volles Sonnenlicht,10-30 °C,14,easy|succulent|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,18,Kap-Aloe (ferox),Aloe ferox,"Aloe ferox ist eine grosse, imposante Aloe mit stachligen, blaugruenen Blaettern und leuchtend roten Bluetenaehren.",Volles Sonnenlicht,10-30 °C,14,succulent|large|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,128,Zitronenverbene,Aloysia citrodora,Zitronenverbene ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,194,Fuchsschwanz,Amaranthus caudatus,"Fuchsschwanz ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,163,Anemone,Anemone coronaria,"Anemone ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,140,Dill,Anethum graveolens,Dill ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,125,Kerbel,Anthriscus cerefolium,Kerbel ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,147,Loewenmaeulchen,Antirrhinum majus,"Loewenmaeulchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,107,Arnika,Arnica montana,Arnika ist eine bekannte Heilpflanze aus den Alpen mit goldgelben Korbbluten. Sie wird fuer Muskeln und Gelenke verwendet.,Volles Sonnenlicht,10-20 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,110,Wermut,Artemisia absinthium,"Wermut ist ein stark aromatisches Heilkraut mit silbrig-gruenen, tief eingeschnittenen Blaettern. Fuer Kraeuterlikoere.",Volles Sonnenlicht,10-25 °C,14,medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,122,Estragon,Artemisia dracunculus,Estragon ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,178,Seidenpflanze,Asclepias tuberosa,"Seidenpflanze ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,41,Pferdeschwanzpalme,Beaucarnea recurvata,"Die Pferdeschwanzpalme hat einen verdickten Stammbasis als Wasserspeicher und lange, schmale Blaetter.",Volles Sonnenlicht,15-30 °C,21,easy|succulent|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,145,Gaensebluemchen,Bellis perennis,"Gaensebluemchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,129,Borretsch,Borago officinalis,Borretsch ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch1.ts,62,Bougainvillea,Bougainvillea spectabilis,"Die Bougainvillea ist eine rankenreiche Kletterpflanze mit leuchtend farbigen Hochblaettern in Rot, Orange oder Pink.",Volles Sonnenlicht,18-30 °C,5,flowering|bright_light|sun,,,,, +sun,constants/lexiconBatch2.ts,223,Schmetterlingsflieder,Buddleja davidii,Schmetterlingsflieder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,202,Buchsbaum,Buxus sempervirens,Buchsbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|sun,,,,, +sun,constants/lexiconBatch2.ts,187,Ringelblume,Calendula officinalis,"Ringelblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,63,Calibrachoa,Calibrachoa hybrida,"Calibrachoa ist eine petunienaehnliche Haengepflanze mit unzaehligen, kleinen Trichterbluten in allen Farben.",Volles Sonnenlicht,15-25 °C,2,easy|flowering|hanging|sun,,,,, +sun,constants/lexiconBatch2.ts,67,Blumenschilfrohr,Canna indica,"Das Blumenschilfrohr hat grosse, tropisch wirkende Blaetter und auffaellige Blueten in Rot, Orange oder Gelb.",Volles Sonnenlicht,18-28 °C,5,flowering|large|sun,,,,, +sun,constants/lexiconBatch2.ts,92,Chili,Capsicum annuum,"Chili ist eine beliebte Gemuese- und Zierpflanze mit leuchtenden, roten oder orangen Fruechten. Im Topf kultivierbar.",Volles Sonnenlicht,20-30 °C,4,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,90,Papaya,Carica papaya,"Die Papaya ist eine tropische Fruchtpflanze mit grossen, gelappten Blaettern und orangen Fruechten.",Volles Sonnenlicht,20-35 °C,5,large|sun,,,,, +sun,constants/lexiconBatch2.ts,217,Trompetenbaum,Catalpa bignonioides,Trompetenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,208,Zeder,Cedrus libani,Zeder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,188,Kornblume,Centaurea cyanus,"Kornblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,81,Peruanischer Fackelkaktus,Cereus peruvianus,"Der Peruanische Fackelkaktus ist ein saeulenfoermiger Kaktus, der im Innenraum bis zu 2 m hoch werden kann.",Volles Sonnenlicht,15-35 °C,21,easy|succulent|large|sun,,,,, +sun,constants/lexiconBatch2.ts,138,Roemische Kamille,Chamaemelum nobile,Roemische Kamille ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,101,Kamille,Chamomilla recutita,"Die Kamille ist ein beliebtes Heilkraut mit kleinen, weiss-gelben Blueten. Das aetherische Oel wirkt beruhigend.",Volles Sonnenlicht,15-25 °C,5,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,86,Zitronenbaum,Citrus limon,"Der Zitronenbaum ist ein kleiner, immergruener Baum mit weissen, duftenden Blueten und gelben Fruechten.",Volles Sonnenlicht,18-28 °C,5,tree|sun,,,,, +sun,constants/lexiconBatch2.ts,87,Orangenbaum,Citrus sinensis,"Der Orangenbaum ist ein kleiner, immergruener Baum mit weissen Blueten und orangen Fruechten.",Volles Sonnenlicht,18-28 °C,5,tree|sun,,,,, +sun,constants/lexiconBatch2.ts,24,Konophytum,Conophytum calculus,"Das Konophytum ist eine sehr kompakte Sukkulente, die zwei Blaetter zu einer kugelfoermigen Form verschmilzt.",Volles Sonnenlicht,10-25 °C,21,succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,14,Keulenlilie,Cordyline australis,"Die Keulenlilie hat lange, schmale, gruene oder rotbraune Blaetter in einem dekorativen Schopf.",Helles bis volles Licht,10-25 °C,7,easy|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,181,Maedchenauge,Coreopsis tinctoria,"Maedchenauge ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,139,Koriander,Coriandrum sativum,Koriander ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,150,Kosmee,Cosmos bipinnatus,"Kosmee ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,29,Kotyledon,Cotyledon orbiculata,"Kotyledon hat dickfleischige, runde Blaetter mit einem mehligen, weisslichen Belag. Sehr trockenheitsresistent.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,26,Moos-Crassula,Crassula muscosa,"Die Moos-Crassula hat dicht aneinandergereihte, winzige gruene Blaetter auf unverzweigten Trieben. Sieht aus wie Moos.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch1.ts,5,Jadepflanze,Crassula ovata,"Die Jadepflanze ist eine langlebige Sukkulente mit dicken, ovalen Blaettern. In Japan gilt sie als Gluecksbringer.",Helles bis volles Licht,15-24 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,94,Gurke,Cucumis sativus,"Die Gurke ist eine rankende Gemuese­pflanze mit gruenen, erfrischenden Fruechten. Im Balkonkasten kultivierbar.",Volles Sonnenlicht,18-28 °C,3,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,209,Zypresse,Cupressus sempervirens,Zypresse ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,236,String of Bananas,Curio radicans,String of Bananas ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,succulent|hanging|sun,,,,, +sun,constants/lexiconBatch2.ts,237,String of Dolphins,Curio x peregrinus,String of Dolphins ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,succulent|hanging|sun,,,,, +sun,constants/lexiconBatch2.ts,239,Palmfarn,Cycas revoluta,Palmfarn ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,127,Zitronengras,Cymbopogon citratus,Zitronengras ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,68,Dahlie,Dahlia pinnata,Die Dahlie ist eine prachtvolle Sommerblume mit Blueten in allen Groessen und Formen. Sie wird aus Knollen gezogen.,Volles Sonnenlicht,15-25 °C,5,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,153,Rittersporn,Delphinium elatum,"Rittersporn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,189,Bartnelke,Dianthus barbatus,"Bartnelke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,146,Nelke,Dianthus caryophyllus,"Nelke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,77,Venusfliegenfalle,Dionaea muscipula,Die Venusfliegenfalle ist eine fleischfressende Pflanze mit klappfallartigen Blaettern. Faengt Insekten.,Volles Sonnenlicht,15-30 °C,5,sun,,,,, +sun,constants/lexiconBatch2.ts,80,Sonnentau,Drosera capensis,Der Sonnentau faengt Insekten mit klebrigen Tropfen auf seinen Blaettern. Eine faszinierende fleischfressende Pflanze.,Volles Sonnenlicht,15-25 °C,5,high_humidity|sun,,,,, +sun,constants/lexiconBatch2.ts,30,Dudleya,Dudleya brittonii,"Dudleya ist eine rosetten­bildende Sukkulente mit silbrig-weissen, mehligen Blaettern. Sehr elegant.",Volles Sonnenlicht,10-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch1.ts,4,Echeverie,Echeveria elegans,"Die Echeverie bildet symmetrische, rosettenfoermige Sukkulenten mit blaugruenen Blaettern. Pflegeleicht.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,106,Sonnenhut,Echinacea purpurea,"Der Sonnenhut ist eine beliebte Heilpflanze mit grossen, pinkfarbenen Blueten. Er staerkt das Immunsystem.",Helles bis volles Licht,15-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch1.ts,77,Goldene Tonne,Echinocactus grusonii,Die Goldene Tonne ist ein ikonischer kugelfoermiger Kaktus mit goldgelben Stacheln. Waechst langsam aber imposant.,Volles Sonnenlicht,15-35 °C,21,easy|succulent|sun,,,,, +sun,constants/lexiconBatch1.ts,83,San-Pedro-Kaktus,Echinopsis pachanoi,"Der San-Pedro-Kaktus ist ein schnell wachsender, saeulenfoermiger Kaktus aus den Anden.",Volles Sonnenlicht,10-35 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,186,Kalifornischer Mohn,Eschscholzia californica,"Kalifornischer Mohn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,210,Eukalyptus,Eucalyptus globulus,Eukalyptus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,19,Christusdorn,Euphorbia milii,Der Christusdorn ist eine sukkulente Wolfsmilch mit stacheligen Zweigen und kleinen roten oder gelben Hochblaettern.,Helles bis volles Licht,15-28 °C,10,easy|flowering|succulent|sun,,,,, +sun,constants/lexiconBatch1.ts,12,Bleistiftkaktus,Euphorbia tirucalli,"Der Bleistiftkaktus ist eine sukkulente Wolfsmilch mit duennen, zylindrischen Zweigen ohne Blaetter.",Volles Sonnenlicht,18-30 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch1.ts,78,Fass-Kaktus,Ferocactus cylindraceus,"Der Fass-Kaktus ist ein zylindrischer Wuestenkaktus mit langen, roten Stacheln. Sehr langlebig.",Volles Sonnenlicht,15-35 °C,21,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,219,Forsythie,Forsythia x intermedia,Forsythie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,100,Erdbeere,Fragaria ananassa,"Die Erdbeere ist ein beliebtes Obst fuer Balkon und Terrasse mit aromatischen, roten Fruechten.",Helles bis volles Licht,15-25 °C,3,easy|pet_friendly|sun,pet_friendly_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,169,Freesie,Freesia refracta,"Freesie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,196,Kokardenblume,Gaillardia aristata,"Kokardenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,190,Mittagsgold,Gazania rigens,"Mittagsgold ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,216,Ginkgo,Ginkgo biloba,Ginkgo ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,161,Gladiole,Gladiolus hortulanus,"Gladiole ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,87,Geisterpflanze,Graptopetalum paraguayense,"Die Geisterpflanze hat zartgraue bis perlmutt-rosafarbene, rosettenfoermige Blaetter. Sehr robuste Sukkulente.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,141,Sonnenblume,Helianthus annuus,"Sonnenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,133,Currykraut,Helichrysum italicum,Currykraut ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,191,Heliotrop,Heliotropium arborescens,"Heliotrop ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,182,Taglilie,Hemerocallis fulva,"Taglilie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,21,Hibiskus,Hibiscus rosa-sinensis,"Der Hibiskus begeistert mit grossen, trompetenfoermigen Blueten in Rot, Orange und Rosa.",Volles Sonnenlicht,18-28 °C,3,flowering|bright_light|sun,,,,, +sun,constants/lexiconBatch2.ts,220,Gartenhibiskus,Hibiscus syriacus,Gartenhibiskus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,159,Hasengloeckchen,Hyacinthoides non-scripta,"Hasengloeckchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,105,Johanniskraut,Hypericum perforatum,Das Johanniskraut hat leuchtend gelbe Blueten und ist ein wichtiges Heilkraut gegen Depressionen und Stimmungstiefs.,Volles Sonnenlicht,10-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,136,Ysop,Hyssopus officinalis,Ysop ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,203,Stechpalme,Ilex aquifolium,Stechpalme ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|sun,,,,, +sun,constants/lexiconBatch1.ts,64,Suesskartoffel,Ipomoea batatas,"Die Suesskartoffel-Zierpflanze hat dekorative, herzfoermige Blaetter in gruen oder dunkelviolett. Ideal als Haengepflanze.",Volles Sonnenlicht,20-30 °C,5,easy|hanging|sun,,,,, +sun,constants/lexiconBatch2.ts,156,Prunkwinde,Ipomoea purpurea,"Prunkwinde ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,144,Bart-Iris,Iris germanica,"Bart-Iris ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,9,Kalanchoe,Kalanchoe blossfeldiana,"Die Kalanchoe ist eine beliebte Bluehpflanze mit leuchtenden Blueten in Rot, Orange, Gelb oder Rosa.",Helles bis volles Licht,15-25 °C,10,easy|flowering|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,22,Brutblatt,Kalanchoe daigremontiana,Das Brutblatt bildet entlang des Blattrandes zahlreiche kleine Jungpflanzen. Eine faszinierende Sukkulente.,Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,21,Kaninchen-Ohren,Kalanchoe tomentosa,"Kaninchen-Ohren haben weisslich-filzige Blaetter mit braunen Raendern, die Kaninchen­ohren aehneln. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,64,Wandelroeschen,Lantana camara,"Das Wandelroeschen hat kugelige Bluetenkoepfe, die die Farbe von Gelb ueber Orange zu Rot wechseln. Sehr attraktiv.",Volles Sonnenlicht,18-28 °C,5,flowering|bright_light|sun,,,,, +sun,constants/lexiconBatch2.ts,158,Duftwicke,Lathyrus odoratus,"Duftwicke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,121,Lorbeer,Laurus nobilis,Lorbeer ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch1.ts,23,Echter Lavendel,Lavandula angustifolia,Der Echte Lavendel ist ein aromatischer Halbstrauch mit lilafarbenen Bluetenaehren. Herrlicher Duft.,Volles Sonnenlicht,10-25 °C,10,medicinal|bright_light|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,180,Bechermalve,Lavatera trimestris,"Bechermalve ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,173,Margerite,Leucanthemum vulgare,"Margerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,201,Shasta-Margerite,Leucanthemum x superbum,"Shasta-Margerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,126,Liebstoeckel,Levisticum officinale,Liebstoeckel ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,23,Lebende Steine,Lithops julii,"Lebende Steine sind faszinierende Mimikry-Sukkulenten, die Kieselsteinen taeuschen aehnlich sehen. Sehr trockenheitsresistent.",Volles Sonnenlicht,10-30 °C,21,succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,154,Lupine,Lupinus polyphyllus,"Lupine ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,79,Mammillaria,Mammillaria zeilmanniana,"Die Mammillaria ist ein kompakter, kugelfoermiger Kaktus, der im Fruehling einen Kranz aus rosa Blueten traegt.",Volles Sonnenlicht,15-35 °C,14,easy|flowering|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,179,Indianernessel,Monarda didyma,"Indianernessel ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,177,Vergissmeinnicht,Myosotis sylvatica,"Vergissmeinnicht ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,199,Nemesie,Nemesia strumosa,"Nemesie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,132,Katzenminze,Nepeta cataria,Katzenminze ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,120,Oleander,Nerium oleander,"Der Oleander ist ein mediteraner Strauch mit leuchtend roten, rosa oder weissen Blueten. Sehr hitzetolerant.",Volles Sonnenlicht,15-28 °C,7,flowering|bright_light|sun,,,,, +sun,constants/lexiconBatch2.ts,193,Ziertabak,Nicotiana alata,"Ziertabak ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,25,Basilikum,Ocimum basilicum,"Basilikum ist das beliebteste Kuechenkraut mit intensiv aromatischen, gruenen Blaettern. Fuer Pesto verwendet.",Volles Sonnenlicht,18-30 °C,2,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch1.ts,82,Hasenohren-Kaktus,Opuntia microdasys,"Der Hasenohren-Kaktus hat flache, ovale Triebe mit dichten weissen Glochiden. Klassischer Zimmerkaktus.",Volles Sonnenlicht,10-35 °C,21,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,124,Majoran,Origanum majorana,Majoran ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch1.ts,28,Oregano,Origanum vulgare,"Oregano ist ein aromatisches Kuechenkraut mit runden, behaarten Blaettern. In mediterraner Kueche beliebt.",Volles Sonnenlicht,15-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,200,Kapmargerite,Osteospermum ecklonis,"Kapmargerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,88,Mondstein-Pflanze,Pachyphytum oviferum,"Die Mondstein-Pflanze hat dicke, ovale Blaetter mit einem pastellrosafarbenen, mehligen Ueberzug.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,143,Pfingstrose,Paeonia lactiflora,"Pfingstrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,185,Mohn,Papaver rhoeas,"Mohn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,31,Rosengeranie,Pelargonium graveolens,Die Rosengeranie ist eine Duftpflanze mit tief eingeschnittenen Blaettern und rosaenlichem Aroma.,Volles Sonnenlicht,15-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,61,Efeu-Geranie,Pelargonium peltatum,"Die Efeu-Geranie hat efeufoermige, glaenzende Blaetter und bluet den ganzen Sommer in leuchtenden Farben.",Helles bis volles Licht,15-25 °C,5,easy|flowering|hanging|sun,,,,, +sun,constants/lexiconBatch2.ts,174,Stehende Geranie,Pelargonium zonale,"Stehende Geranie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,134,Shiso,Perilla frutescens,Shiso ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch1.ts,34,Petunie,Petunia hybrida,Die Petunie ist eine der beliebtesten Balkonpflanzen mit trichterfoermigen Blueten in unzaehligen Farben.,Volles Sonnenlicht,15-25 °C,2,easy|pet_friendly|flowering|sun,pet_friendly_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,165,Flammenblume,Phlox paniculata,"Flammenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,207,Fichte,Picea abies,Fichte ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,206,Kiefer,Pinus sylvestris,Kiefer ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch1.ts,61,Bleiwurz,Plumbago auriculata,"Die Bleiwurz ist ein halbimmergruener Strauch mit himmelblauen Blueten, der fast das ganze Jahr bluet.",Volles Sonnenlicht,15-27 °C,5,flowering|bright_light|sun,,,,, +sun,constants/lexiconBatch2.ts,118,Tempel-Baum,Plumeria rubra,"Der Tempel-Baum hat intensiv duftende, sternfoermige Blueten in Weiss, Gelb oder Rosa. Klassische Tropenblume.",Volles Sonnenlicht,20-30 °C,7,flowering|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,27,Speckbaum,Portulacaria afra,"Der Speckbaum ist eine sukkulente Pflanze mit roten Stielen und kleinen, runden, glaenzenden Blaettern.",Helles bis volles Licht,15-30 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,71,Koenigs-Protea,Protea cynaroides,"Die Koenigs-Protea ist die Nationalblume Suedafrikas mit riesigen, imposanten Bluetenkoepfen. Eine echte Besonderheit.",Volles Sonnenlicht,10-25 °C,7,flowering|large|sun,,,,, +sun,constants/lexiconBatch2.ts,218,Kirschlorbeer,Prunus laurocerasus,Kirschlorbeer ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|sun,,,,, +sun,constants/lexiconBatch2.ts,89,Guave,Psidium guajava,Die Guave ist ein tropischer Obstbaum mit gelblich-weissen Fruechten. Sie ist reich an Vitamin C.,Volles Sonnenlicht,18-30 °C,7,tree|sun,,,,, +sun,constants/lexiconBatch2.ts,88,Granatapfelbaum,Punica granatum,"Der Granatapfelbaum hat leuchtend rote Blueten und rote, essbare Fruechte mit rubinroten Kernen.",Volles Sonnenlicht,15-28 °C,7,flowering|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,205,Eiche,Quercus robur,Eiche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,162,Ranunkel,Ranunculus asiaticus,"Ranunkel ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,214,Robinie,Robinia pseudoacacia,Robinie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch1.ts,66,Chinesische Rose,Rosa chinensis,Die Chinesische Rose ist eine der Stammarten vieler Gartenrosen und bluet fast ununterbrochen.,Volles Sonnenlicht,15-25 °C,5,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,142,Rose,Rosa x hybrida,"Rose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light|sun,,,,, +sun,constants/lexiconBatch1.ts,24,Rosmarin,Rosmarinus officinalis,Rosmarin ist ein aromatisches Kraut mit nadelartigen Blaettern und blauen Blueten. In der Kueche unverzichtbar.,Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,167,Rudbeckie,Rudbeckia hirta,"Rudbeckie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,130,Sauerampfer,Rumex acetosa,Sauerampfer ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,195,Mehlsalbei,Salvia farinacea,"Mehlsalbei ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,103,Salbei,Salvia officinalis,Salbei ist ein aromatisches Heilkraut mit silbrig-gruenen Blaettern. Er hat antibakterielle und entzuendungshem­mende Wirkung.,Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,168,Feuersalbei,Salvia splendens,"Feuersalbei ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,17,Zylindrischer Bogenhanf,Sansevieria cylindrica,"Der Zylindrische Bogenhanf hat zylindrische, aufrechte Blaetter, die sich nach oben verjuengen. Sehr pflegeleicht.",Helles bis volles Licht,15-27 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,78,Purpursonnentau,Sarracenia purpurea,Der Purpursonnentau ist eine fleischfressende Kannenpflanze mit purpurroten Kannen. Faengt Insekten.,Volles Sonnenlicht,5-25 °C,3,high_humidity|sun,,,,, +sun,constants/lexiconBatch2.ts,123,Bohnenkraut,Satureja hortensis,Bohnenkraut ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch1.ts,7,Eselschwanz,Sedum morganianum,"Der Eselschwanz ist eine haengende Sukkulente mit langen Trieben aus dichten, blaugruenen Blaettchen.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|hanging|sun,,,,, +sun,constants/lexiconBatch2.ts,28,Blauer Kreuzkraut,Senecio serpens,"Der Blaue Kreuzkraut hat zylindrische, blaublaugruene Blaetter und einen kriechenden Wuchs. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,93,Aubergine,Solanum melongena,"Die Aubergine ist eine Gemuese­pflanze mit grossen, violetten Fruechten. Sie benoetigt viel Waerme und Sonne.",Volles Sonnenlicht,20-30 °C,5,bright_light|sun,,,,, +sun,constants/lexiconBatch2.ts,213,Eberesche,Sorbus aucuparia,Eberesche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,222,Spierstrauch,Spiraea japonica,Spierstrauch ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,25,Aasblume,Stapelia grandiflora,"Die Aasblume hat fleischige, gruene Staengel und riesige, sternfoermige Blueten mit aasartigem Duft.",Helles bis volles Licht,18-30 °C,14,flowering|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,131,Stevia,Stevia rebaudiana,Stevia ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch1.ts,3,Paradiesvogelblume,Strelitzia reginae,"Die Paradiesvogelblume beeindruckt mit leuchtend orangefarbenen und blauen Blueten, die einem Vogel aehneln.",Volles Sonnenlicht,18-26 °C,7,flowering|large|sun,,,,, +sun,constants/lexiconBatch2.ts,166,Herbstaster,Symphyotrichum novi-belgii,"Herbstaster ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,149,Flieder,Syringa vulgaris,"Flieder ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,66,Studentenblume,Tagetes patula,Die Studentenblume ist eine robuste Sommerblume mit orangen oder gelben Blueten. Sie haelt Schadlinge fern.,Volles Sonnenlicht,15-28 °C,3,easy|flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,27,Thymian,Thymus vulgaris,"Thymian ist ein kleiner, aromatischer Strauch mit winzigen Blaettern und rosa Blueten. Wichtiges Kuechenkraut.",Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,54,Lila Tradescantia,Tradescantia pallida,Die Lila Tradescantia hat leuchtend purpurrote Blaetter und ist sehr auffaellig. Sie liebt viel Licht.,Helles bis volles Licht,15-25 °C,5,easy|hanging|sun,,,,, +sun,constants/lexiconBatch2.ts,151,Kapuzinerkresse,Tropaeolum majus,"Kapuzinerkresse ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,82,Wasserschlauch,Utricularia gibba,Der Wasserschlauch ist eine wasserbewohnende fleischfressende Pflanze mit Schlaeuchen als Insekten­fallen.,Helles bis volles Licht,15-25 °C,2,high_humidity|sun,,,,, +sun,constants/lexiconBatch2.ts,192,Koenigskerze,Verbascum thapsus,"Koenigskerze ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,164,Eisenkraut,Verbena bonariensis,"Eisenkraut ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,198,Hornveilchen,Viola cornuta,"Hornveilchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,5,Mexikanische Fächerpalme,Washingtonia robusta,"Die Mexikanische Fächerpalme ist eine schlanke, hohe Palme mit faecher­foermigen Blaettern. Sehr hitzetolerant.",Volles Sonnenlicht,15-35 °C,10,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,221,Weigelie,Weigela florida,Weigelie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +sun,constants/lexiconBatch1.ts,65,Chinesischer Blauregen,Wisteria sinensis,"Der Chinesische Blauregen ist ein ueppiger Kletterkuenstler mit langen, duftenden Bluetentrauben in Lila.",Volles Sonnenlicht,10-25 °C,7,flowering|large|sun,,,,, +sun,constants/lexiconBatch2.ts,246,Yucca aloifolia,Yucca aloifolia,Yucca aloifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Volles Sonnenlicht,18-30 C,10,easy|tree|sun,,,,, +sun,constants/lexiconBatch1.ts,40,Yucca-Palme,Yucca elephantipes,"Die Yucca-Palme ist eine robuste Zimmerpflanze mit starrem, immergruenem Blaetterschopf auf einem dicken Stamm.",Helles bis volles Licht,15-28 °C,14,easy|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,65,Zinnie,Zinnia elegans,"Die Zinnie ist eine leuchtende Sommerblume mit grossen, dahlienaehnlichen Blueten. Sehr robust und hitzetolerant.",Volles Sonnenlicht,18-30 °C,3,easy|flowering|sun,,,,, diff --git a/audits/semantic-search/categories/tree.csv b/audits/semantic-search/categories/tree.csv new file mode 100644 index 0000000..bdddaba --- /dev/null +++ b/audits/semantic-search/categories/tree.csv @@ -0,0 +1,60 @@ +category,source_file,source_index,name,botanical_name,description,light,temp,water_interval_days,all_categories,risk_flags,audit_status,evidence_source,evidence_url,notes +tree,constants/lexiconBatch2.ts,115,Faecherahorn,Acer palmatum,"Der Faecherahorn ist ein japanischer Zierahorn mit feingeschnittenen, faecherfoermigen Blaettern in Gruen oder Rot.",Helles bis volles Licht,10-22 °C,5,tree,,,,, +tree,constants/lexiconBatch2.ts,212,Spitzahorn,Acer platanoides,Spitzahorn ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,232,Norfolk-Tanne,Araucaria heterophylla,Norfolk-Tanne ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,tree|bright_light,,,,, +tree,constants/lexiconBatch1.ts,41,Pferdeschwanzpalme,Beaucarnea recurvata,"Die Pferdeschwanzpalme hat einen verdickten Stammbasis als Wasserspeicher und lange, schmale Blaetter.",Volles Sonnenlicht,15-30 °C,21,easy|succulent|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,114,Hange-Birke,Betula pendula,Die Haenge-Birke hat charakteristisch weisse Rinde und haengende Zweige. Die Blaetter werden in der Heilkunde genutzt.,Volles Sonnenlicht,10-25 °C,7,tree|large|medicinal,medicinal_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,223,Schmetterlingsflieder,Buddleja davidii,Schmetterlingsflieder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,202,Buchsbaum,Buxus sempervirens,Buchsbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|sun,,,,, +tree,constants/lexiconBatch2.ts,217,Trompetenbaum,Catalpa bignonioides,Trompetenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,208,Zeder,Cedrus libani,Zeder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,Die Bergpalme ist eine kompakte Zimmerpalme fuer schattigere Standorte. Ideal fuer dunkle Innenraeume.,Wenig bis helles Licht,15-25 °C,7,easy|pet_friendly|tree|air_purifier|low_light,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,86,Zitronenbaum,Citrus limon,"Der Zitronenbaum ist ein kleiner, immergruener Baum mit weissen, duftenden Blueten und gelben Fruechten.",Volles Sonnenlicht,18-28 °C,5,tree|sun,,,,, +tree,constants/lexiconBatch2.ts,87,Orangenbaum,Citrus sinensis,"Der Orangenbaum ist ein kleiner, immergruener Baum mit weissen Blueten und orangen Fruechten.",Volles Sonnenlicht,18-28 °C,5,tree|sun,,,,, +tree,constants/lexiconBatch2.ts,14,Keulenlilie,Cordyline australis,"Die Keulenlilie hat lange, schmale, gruene oder rotbraune Blaetter in einem dekorativen Schopf.",Helles bis volles Licht,10-25 °C,7,easy|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,209,Zypresse,Cupressus sempervirens,Zypresse ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,239,Palmfarn,Cycas revoluta,Palmfarn ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,215,Flammenbaum,Delonix regia,Flammenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +tree,constants/lexiconBatch1.ts,14,Maisstrauch,Dracaena fragrans,"Der Maisstrauch ist eine robuste Zimmerpflanze mit breiten, gestreiften Blaettern. Gedeiht auch bei wenig Licht.",Helles indirektes Licht,15-25 °C,10,easy|tree|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +tree,constants/lexiconBatch1.ts,13,Drachenbaum,Dracaena marginata,"Der Drachenbaum ist eine schlanke Zimmerpflanze mit roten, schmalen Blaettern auf langen Staemmen.",Helles indirektes Licht,15-25 °C,10,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +tree,constants/lexiconBatch1.ts,42,Goldfruchtpalme,Dypsis lutescens,Die Goldfruchtpalme ist eine elegante Zimmerpalme mit gelblich-gruenen Stielen und gefiederten Wedeln.,Helles indirektes Licht,18-27 °C,5,pet_friendly|tree|air_purifier,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,210,Eukalyptus,Eucalyptus globulus,Eukalyptus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|medicinal|sun,medicinal_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,248,Ficus altissima,Ficus altissima,Ficus altissima ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,tree|bright_light,,,,, +tree,constants/lexiconBatch1.ts,1,Birkenfeige,Ficus benjamina,"Die Birkenfeige ist ein eleganter Zimmerstrauch mit haengenden Aesten und kleinen, glaenzenden Blaettern.",Helles indirektes Licht,16-24 °C,7,tree|air_purifier,air_purifier_requires_external_evidence,,,, +tree,constants/lexiconBatch1.ts,38,Gummibaum,Ficus elastica,"Der Gummibaum ist eine imposante Zimmerpflanze mit grossen, glaenzenden, lederartigen Blaettern. Reinigt die Luft.",Helles indirektes Licht,16-24 °C,10,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +tree,constants/lexiconBatch1.ts,39,Geigenfeige,Ficus lyrata,"Die Geigenfeige ist ein Trendbaum mit grossen, geigenfoermigen Blaettern. Benoetigt viel Licht.",Helles indirektes Licht,18-27 °C,7,tree|large|bright_light,,,,, +tree,constants/lexiconBatch2.ts,247,Ficus microcarpa,Ficus microcarpa,Ficus microcarpa ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|tree|bright_light,,,,, +tree,constants/lexiconBatch2.ts,116,Bonsai-Feige,Ficus retusa,"Die Bonsai-Feige ist eine klassische Bonsai-Art mit kleinen, elliptischen Blaettern. Sehr formbar.",Helles indirektes Licht,16-24 °C,7,tree,,,,, +tree,constants/lexiconBatch2.ts,219,Forsythie,Forsythia x intermedia,Forsythie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,216,Ginkgo,Ginkgo biloba,Ginkgo ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|medicinal|sun,medicinal_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,220,Gartenhibiskus,Hibiscus syriacus,Gartenhibiskus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,3,Kentia-Palme,Howea forsteriana,"Die Kentia-Palme ist eine der elegantesten Zimmerpalmen mit langen, herabhängenden Fiederblaettern.",Helles indirektes Licht,18-25 °C,7,pet_friendly|tree|low_light,pet_friendly_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,203,Stechpalme,Ilex aquifolium,Stechpalme ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|sun,,,,, +tree,constants/lexiconBatch2.ts,211,Jacaranda,Jacaranda mimosifolia,Jacaranda ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +tree,constants/lexiconBatch2.ts,4,Chinesische Fächerpalme,Livistona chinensis,"Die Chinesische Fächerpalme hat grosse, faecher­foermige Blaetter auf einem einzelnen Stamm. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,7,tree|bright_light,,,,, +tree,constants/lexiconBatch2.ts,204,Magnolie,Magnolia grandiflora,Magnolie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +tree,constants/lexiconBatch2.ts,231,Glueckskastanie,Pachira aquatica,Glueckskastanie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|tree|bright_light,,,,, +tree,constants/lexiconBatch1.ts,44,Zwergdattelpalme,Phoenix roebelenii,"Die Zwergdattelpalme ist eine zierliche Palme mit eleganten, gebogenen Fiederblaettern. Tropisches Flair.",Helles bis volles Licht,18-27 °C,7,tree|bright_light,,,,, +tree,constants/lexiconBatch2.ts,207,Fichte,Picea abies,Fichte ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,206,Kiefer,Pinus sylvestris,Kiefer ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,118,Tempel-Baum,Plumeria rubra,"Der Tempel-Baum hat intensiv duftende, sternfoermige Blueten in Weiss, Gelb oder Rosa. Klassische Tropenblume.",Volles Sonnenlicht,20-30 °C,7,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,218,Kirschlorbeer,Prunus laurocerasus,Kirschlorbeer ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|sun,,,,, +tree,constants/lexiconBatch2.ts,89,Guave,Psidium guajava,Die Guave ist ein tropischer Obstbaum mit gelblich-weissen Fruechten. Sie ist reich an Vitamin C.,Volles Sonnenlicht,18-30 °C,7,tree|sun,,,,, +tree,constants/lexiconBatch2.ts,88,Granatapfelbaum,Punica granatum,"Der Granatapfelbaum hat leuchtend rote Blueten und rote, essbare Fruechte mit rubinroten Kernen.",Volles Sonnenlicht,15-28 °C,7,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,205,Eiche,Quercus robur,Eiche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch1.ts,45,Stab-Palme,Rhapis excelsa,"Die Stab-Palme ist eine elegante Zimmerpalme mit faecher­foermigen Blaettern auf duennen, bambusartigen Staemmen.",Helles indirektes Licht,15-25 °C,7,tree|low_light,,,,, +tree,constants/lexiconBatch2.ts,170,Rhododendron,Rhododendron catawbiense,"Rhododendron ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|tree|bright_light,,,,, +tree,constants/lexiconBatch2.ts,214,Robinie,Robinia pseudoacacia,Robinie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,113,Silber-Weide,Salix alba,"Die Silber-Weide hat silbrig-glaenzende Blaetter. Weidenrinde enthält Salicylsaeure, die Grundlage von Aspirin.",Helles bis volles Licht,10-25 °C,7,tree|large|medicinal,medicinal_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,112,Schwarzer Holunder,Sambucus nigra,Der Schwarze Holunder hat weisse Doldenbluten und schwarze Beeren. Die Fruechte werden fuer Sirup und Saft verwendet.,Helles bis volles Licht,10-25 °C,7,flowering|tree|medicinal,medicinal_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,11,Grosse Strahlenaralie,Schefflera actinophylla,"Die Grosse Strahlenaralie kann grosse, handfoermige Blaetter entwickeln. Sie ist ideal als Zimmerstrauch.",Helles indirektes Licht,18-27 °C,7,easy|tree|large,,,,, +tree,constants/lexiconBatch2.ts,10,Strahlenaralie,Schefflera arboricola,"Die Strahlenaralie hat fingerfoermig angeordnete, glaenzende Blaetter auf langen Stielen. Sehr robuste Zimmerpflanze.",Helles indirektes Licht,15-25 °C,7,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,235,Falsche Aralie,Schefflera elegantissima,Falsche Aralie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,tree|bright_light,,,,, +tree,constants/lexiconBatch2.ts,213,Eberesche,Sorbus aucuparia,Eberesche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,222,Spierstrauch,Spiraea japonica,Spierstrauch ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,1,Weisse Strelitzie,Strelitzia nicolai,"Die Weisse Strelitzie ist ein beeindruckender Zimmerstrauch mit grossen, blaugruenen Blaettern und weiss-blauen Blueten.",Helles bis volles Licht,18-27 °C,7,tree|large|bright_light,,,,, +tree,constants/lexiconBatch2.ts,149,Flieder,Syringa vulgaris,"Flieder ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,5,Mexikanische Fächerpalme,Washingtonia robusta,"Die Mexikanische Fächerpalme ist eine schlanke, hohe Palme mit faecher­foermigen Blaettern. Sehr hitzetolerant.",Volles Sonnenlicht,15-35 °C,10,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,221,Weigelie,Weigela florida,Weigelie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,246,Yucca aloifolia,Yucca aloifolia,Yucca aloifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Volles Sonnenlicht,18-30 C,10,easy|tree|sun,,,,, +tree,constants/lexiconBatch1.ts,40,Yucca-Palme,Yucca elephantipes,"Die Yucca-Palme ist eine robuste Zimmerpflanze mit starrem, immergruenem Blaetterschopf auf einem dicken Stamm.",Helles bis volles Licht,15-28 °C,14,easy|tree|sun,,,,, diff --git a/audits/semantic-search/master.csv b/audits/semantic-search/master.csv new file mode 100644 index 0000000..5b9caae --- /dev/null +++ b/audits/semantic-search/master.csv @@ -0,0 +1,835 @@ +category,source_file,source_index,name,botanical_name,description,light,temp,water_interval_days,all_categories,risk_flags,audit_status,evidence_source,evidence_url,notes +air_purifier,constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,Die Bergpalme ist eine kompakte Zimmerpalme fuer schattigere Standorte. Ideal fuer dunkle Innenraeume.,Wenig bis helles Licht,15-25 °C,7,easy|pet_friendly|tree|air_purifier|low_light,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,48,Dieffenbachie,Dieffenbachia seguine,"Die Dieffenbachie ist eine tropische Blattschmuckpflanze mit grossen, gruen-weiss gefleckten Blaettern.",Helles indirektes Licht,18-26 °C,7,easy|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,14,Maisstrauch,Dracaena fragrans,"Der Maisstrauch ist eine robuste Zimmerpflanze mit breiten, gestreiften Blaettern. Gedeiht auch bei wenig Licht.",Helles indirektes Licht,15-25 °C,10,easy|tree|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,13,Drachenbaum,Dracaena marginata,"Der Drachenbaum ist eine schlanke Zimmerpflanze mit roten, schmalen Blaettern auf langen Staemmen.",Helles indirektes Licht,15-25 °C,10,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,42,Goldfruchtpalme,Dypsis lutescens,Die Goldfruchtpalme ist eine elegante Zimmerpalme mit gelblich-gruenen Stielen und gefiederten Wedeln.,Helles indirektes Licht,18-27 °C,5,pet_friendly|tree|air_purifier,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,16,Marmor-Efeutute,Epipremnum aureum Marble Queen,Die Marmor-Efeutute hat cremeweiss-gruen marmorierte Blaetter. Eine dekorative Variante der klassischen Efeutute.,Helles indirektes Licht,15-30 °C,7,easy|hanging|air_purifier,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch2.ts,53,Neon-Efeutute,Epipremnum pinnatum Neon,Die Neon-Efeutute hat leuchtend limonengruene Blaetter. Sehr auffaellig und pflegeleicht.,Helles indirektes Licht,15-30 °C,7,easy|hanging|air_purifier,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,1,Birkenfeige,Ficus benjamina,"Die Birkenfeige ist ein eleganter Zimmerstrauch mit haengenden Aesten und kleinen, glaenzenden Blaettern.",Helles indirektes Licht,16-24 °C,7,tree|air_purifier,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,38,Gummibaum,Ficus elastica,"Der Gummibaum ist eine imposante Zimmerpflanze mit grossen, glaenzenden, lederartigen Blaettern. Reinigt die Luft.",Helles indirektes Licht,16-24 °C,10,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,68,Gerbera,Gerbera jamesonii,"Die Gerbera ist eine farbenfrohe Schnittblume mit grossen, sonnenblumenaehnlichen Blueten. Sehr beliebt.",Helles bis volles Licht,15-25 °C,5,flowering|air_purifier|bright_light,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch1.ts,37,Efeu,Hedera helix,"Efeu ist eine robuste Kletter- und Haengepflanze mit charakteristischen, dreilappigen Blaettern. Sehr langlebig.",Wenig bis helles Licht,10-20 °C,7,easy|hanging|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +air_purifier,constants/lexiconBatch2.ts,10,Strahlenaralie,Schefflera arboricola,"Die Strahlenaralie hat fingerfoermig angeordnete, glaenzende Blaetter auf langen Stielen. Sehr robuste Zimmerpflanze.",Helles indirektes Licht,15-25 °C,7,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +bright_light,constants/lexiconBatch2.ts,225,Alocasia zebrina,Alocasia zebrina,Alocasia zebrina ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,bright_light|high_humidity,,,,, +bright_light,constants/lexiconBatch2.ts,232,Norfolk-Tanne,Araucaria heterophylla,Norfolk-Tanne ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,tree|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,175,Eisbegonie,Begonia semperflorens-cultorum,"Eisbegonie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch1.ts,62,Bougainvillea,Bougainvillea spectabilis,"Die Bougainvillea ist eine rankenreiche Kletterpflanze mit leuchtend farbigen Hochblaettern in Rot, Orange oder Pink.",Volles Sonnenlicht,18-30 °C,5,flowering|bright_light|sun,,,,, +bright_light,constants/lexiconBatch2.ts,184,Trompetenwinde,Campsis radicans,"Trompetenwinde ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,157,Clematis,Clematis viticella,"Clematis ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,224,Kroton,Codiaeum variegatum,Kroton ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,patterned|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,245,Kaffeepflanze arabica nana,Coffea arabica Nana,Kaffeepflanze arabica nana ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,137,Wasabi,Eutrema japonicum,"Wasabi ist ein seltenes Wuerzkraut, das gleichmaessige Feuchte und eher kuehle Bedingungen bevorzugt.",Helles indirektes Licht,8-20 C,4,bright_light|high_humidity,,,,, +bright_light,constants/lexiconBatch2.ts,248,Ficus altissima,Ficus altissima,Ficus altissima ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,tree|bright_light,,,,, +bright_light,constants/lexiconBatch1.ts,39,Geigenfeige,Ficus lyrata,"Die Geigenfeige ist ein Trendbaum mit grossen, geigenfoermigen Blaettern. Benoetigt viel Licht.",Helles indirektes Licht,18-27 °C,7,tree|large|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,247,Ficus microcarpa,Ficus microcarpa,Ficus microcarpa ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|tree|bright_light,,,,, +bright_light,constants/lexiconBatch1.ts,68,Gerbera,Gerbera jamesonii,"Die Gerbera ist eine farbenfrohe Schnittblume mit grossen, sonnenblumenaehnlichen Blueten. Sehr beliebt.",Helles bis volles Licht,15-25 °C,5,flowering|air_purifier|bright_light,air_purifier_requires_external_evidence,,,, +bright_light,constants/lexiconBatch2.ts,72,Heliconia,Heliconia psittacorum,"Die Heliconia hat leuchtend orangefarbe oder rote, bootsfoermige Hochblaetter. Eine exotische Tropenpflanze.",Helles bis volles Licht,20-30 °C,5,flowering|bright_light|high_humidity,,,,, +bright_light,constants/lexiconBatch1.ts,21,Hibiskus,Hibiscus rosa-sinensis,"Der Hibiskus begeistert mit grossen, trompetenfoermigen Blueten in Rot, Orange und Rosa.",Volles Sonnenlicht,18-28 °C,3,flowering|bright_light|sun,,,,, +bright_light,constants/lexiconBatch1.ts,105,Ritterstern,Hippeastrum hybrid,"Der Ritterstern beeindruckt im Winter mit riesigen, trompetenfoermigen Blueten in Rot, Pink oder Weiss.",Helles bis volles Licht,18-25 °C,7,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,148,Hortensie,Hydrangea macrophylla,"Hortensie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Helles bis halbschattiges Licht,8-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,227,Punktblatt,Hypoestes phyllostachya,Punktblatt ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,patterned|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,176,Gartenbalsamine,Impatiens balsamina,"Gartenbalsamine ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,172,Arabischer Jasmin,Jasminum sambac,"Arabischer Jasmin ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,197,Traenendes Herz,Lamprocapnos spectabilis,"Traenendes Herz ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,64,Wandelroeschen,Lantana camara,"Das Wandelroeschen hat kugelige Bluetenkoepfe, die die Farbe von Gelb ueber Orange zu Rot wechseln. Sehr attraktiv.",Volles Sonnenlicht,18-28 °C,5,flowering|bright_light|sun,,,,, +bright_light,constants/lexiconBatch1.ts,23,Echter Lavendel,Lavandula angustifolia,Der Echte Lavendel ist ein aromatischer Halbstrauch mit lilafarbenen Bluetenaehren. Herrlicher Duft.,Volles Sonnenlicht,10-25 °C,10,medicinal|bright_light|sun,medicinal_requires_external_evidence,,,, +bright_light,constants/lexiconBatch2.ts,69,Ostertrompete,Lilium longiflorum,"Die Ostertrompete hat grosse, weisse, trichterfoermige Blueten mit intensivem Duft. Klassische Osterblume.",Helles bis volles Licht,15-25 °C,5,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,4,Chinesische Fächerpalme,Livistona chinensis,"Die Chinesische Fächerpalme hat grosse, faecher­foermige Blaetter auf einem einzelnen Stamm. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,7,tree|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,171,Geissblatt,Lonicera japonica,"Geissblatt ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,76,Schamkraut,Mimosa pudica,"Das Schamkraut faltet seine Blaettchen blitzschnell zusammen, wenn man sie beruehrt. Ein faszinierendes Erlebnis.",Helles bis volles Licht,20-28 °C,5,flowering|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,37,Neoregelia,Neoregelia carolinae,"Die Neoregelia ist eine Bromelie, bei der das Herzblatt zur Bluetzeit leuchtend rot wird. Sehr dekorativ.",Helles bis volles Licht,18-27 °C,7,flowering|patterned|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,120,Oleander,Nerium oleander,"Der Oleander ist ein mediteraner Strauch mit leuchtend roten, rosa oder weissen Blueten. Sehr hitzetolerant.",Volles Sonnenlicht,15-28 °C,7,flowering|bright_light|sun,,,,, +bright_light,constants/lexiconBatch2.ts,231,Glueckskastanie,Pachira aquatica,Glueckskastanie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|tree|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,6,Schraubenbaum,Pandanus veitchii,"Der Schraubenbaum hat spiralfoermig angeordnete, gruenweiss gestreifte Blaetter. Sehr dekorativ und exotisch.",Helles bis volles Licht,18-27 °C,7,patterned|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,243,Philodendron Pink Princess,Philodendron erubescens Pink Princess,Philodendron Pink Princess ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,patterned|bright_light,,,,, +bright_light,constants/lexiconBatch1.ts,44,Zwergdattelpalme,Phoenix roebelenii,"Die Zwergdattelpalme ist eine zierliche Palme mit eleganten, gebogenen Fiederblaettern. Tropisches Flair.",Helles bis volles Licht,18-27 °C,7,tree|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,152,Buntnessel,Plectranthus scutellarioides,"Buntnessel ist eine farbstarke Zierpflanze, die vor allem fuer ihr dekoratives Laub beliebt ist.",Volles bis helles Licht,10-24 C,4,patterned|bright_light,,,,, +bright_light,constants/lexiconBatch1.ts,61,Bleiwurz,Plumbago auriculata,"Die Bleiwurz ist ein halbimmergruener Strauch mit himmelblauen Blueten, der fast das ganze Jahr bluet.",Volles Sonnenlicht,15-27 °C,5,flowering|bright_light|sun,,,,, +bright_light,constants/lexiconBatch2.ts,170,Rhododendron,Rhododendron catawbiense,"Rhododendron ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|tree|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,142,Rose,Rosa x hybrida,"Rose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light|sun,,,,, +bright_light,constants/lexiconBatch2.ts,235,Falsche Aralie,Schefflera elegantissima,Falsche Aralie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,tree|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,93,Aubergine,Solanum melongena,"Die Aubergine ist eine Gemuese­pflanze mit grossen, violetten Fruechten. Sie benoetigt viel Waerme und Sonne.",Volles Sonnenlicht,20-30 °C,5,bright_light|sun,,,,, +bright_light,constants/lexiconBatch2.ts,1,Weisse Strelitzie,Strelitzia nicolai,"Die Weisse Strelitzie ist ein beeindruckender Zimmerstrauch mit grossen, blaugruenen Blaettern und weiss-blauen Blueten.",Helles bis volles Licht,18-27 °C,7,tree|large|bright_light,,,,, +bright_light,constants/lexiconBatch2.ts,244,Philodendron Xanadu,Thaumatophyllum xanadu,Philodendron Xanadu ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,bright_light,,,,, +bright_light,constants/lexiconBatch1.ts,72,Vanda-Orchidee,Vanda coerulea,Die Vanda-Orchidee ist bekannt fuer ihre seltene blaue Bluetenfarbe. Epiphytische Orchidee mit grossen Blueten.,Helles bis volles Licht,20-30 °C,3,flowering|bright_light|high_humidity,,,,, +easy,constants/lexiconBatch2.ts,31,Adromischus,Adromischus cristatus,Adromischus ist eine kompakte Sukkulente mit ungewoehnlich wellenrandigen Blaettern auf kurzen Staengeln.,Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,50,Aglaoneme,Aglaonema commutatum,Die Aglaoneme ist eine dekorative Zimmerpflanze mit silbrig-gruen gemusterten Blaettern. Tolerant gegenueber wenig Licht.,Wenig bis helles Licht,15-26 °C,7,easy|patterned|low_light,,,,, +easy,constants/lexiconBatch1.ts,30,Schnittlauch,Allium schoenoprasum,Schnittlauch ist ein beliebtes Kuechenkraut mit roehrenfoermigen Blaettern und lila Blueten.,Helles bis volles Licht,10-25 °C,3,easy,,,,, +easy,constants/lexiconBatch2.ts,135,Schnittknoblauch,Allium tuberosum,Schnittknoblauch ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch1.ts,89,Kap-Aloe,Aloe arborescens,"Die Kap-Aloe ist eine strauchige Aloe mit schmalen, gezaehnten Blaettern und leuchtend roten Bluetenaehren im Winter.",Volles Sonnenlicht,10-30 °C,14,easy|succulent|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,128,Zitronenverbene,Aloysia citrodora,Zitronenverbene ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,140,Dill,Anethum graveolens,Dill ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,125,Kerbel,Anthriscus cerefolium,Kerbel ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,122,Estragon,Artemisia dracunculus,Estragon ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,16,Schusterpflanze,Aspidistra elatior,"Die Schusterpflanze ist eine extrem robuste Zimmerpflanze mit langen, dunkelgruenen Blaettern. Vertraegt tiefe Temperaturen.",Wenig bis helles Licht,10-20 °C,14,easy|low_light,,,,, +easy,constants/lexiconBatch2.ts,43,Vogelnest-Farn,Asplenium nidus,"Der Vogelnest-Farn hat ganzrandige, glaenzende Wedel, die eine Nestform bilden. Sehr dekorativ und robust.",Helles indirektes Licht,18-27 °C,5,easy|low_light|high_humidity,,,,, +easy,constants/lexiconBatch2.ts,13,Japanische Aucube,Aucuba japonica,"Die Japanische Aucube hat glaenzende, gruene oder gelbgefleckte Blaetter. Sehr schattenvertraeglich.",Wenig bis helles Licht,10-20 °C,7,easy|low_light,,,,, +easy,constants/lexiconBatch2.ts,7,Bambusrohr,Bambusa vulgaris,Das Bambusrohr ist eine schnell wachsende Bambusart mit gelbgruenen Halmen. Sehr dekorativ und vielseitig nutzbar.,Helles bis volles Licht,15-30 °C,5,easy|large,,,,, +easy,constants/lexiconBatch1.ts,41,Pferdeschwanzpalme,Beaucarnea recurvata,"Die Pferdeschwanzpalme hat einen verdickten Stammbasis als Wasserspeicher und lange, schmale Blaetter.",Volles Sonnenlicht,15-30 °C,21,easy|succulent|tree|sun,,,,, +easy,constants/lexiconBatch2.ts,97,Mangold,Beta vulgaris,"Mangold ist ein farbenfrohes Blattgemuese mit bunten Stielen in Rot, Gelb, Orange und Weiss.",Helles bis volles Licht,10-25 °C,3,easy,,,,, +easy,constants/lexiconBatch2.ts,38,Billbergia,Billbergia nutans,"Die Billbergia ist eine robuste Bromelie mit schmalen, gruenen Blaettern und hängenden, blauen und gruenen Blueten.",Helles indirektes Licht,15-25 °C,7,easy|flowering,,,,, +easy,constants/lexiconBatch2.ts,129,Borretsch,Borago officinalis,Borretsch ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,63,Calibrachoa,Calibrachoa hybrida,"Calibrachoa ist eine petunienaehnliche Haengepflanze mit unzaehligen, kleinen Trichterbluten in allen Farben.",Volles Sonnenlicht,15-25 °C,2,easy|flowering|hanging|sun,,,,, +easy,constants/lexiconBatch2.ts,56,Callisia,Callisia repens,"Callisia repens ist ein kleines, kriechendes Kraut mit winzigen, gruenen Blaettern. Ideal fuer haengende Behaelter.",Helles indirektes Licht,15-25 °C,5,easy|hanging,,,,, +easy,constants/lexiconBatch2.ts,92,Chili,Capsicum annuum,"Chili ist eine beliebte Gemuese- und Zierpflanze mit leuchtenden, roten oder orangen Fruechten. Im Topf kultivierbar.",Volles Sonnenlicht,20-30 °C,4,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,81,Peruanischer Fackelkaktus,Cereus peruvianus,"Der Peruanische Fackelkaktus ist ein saeulenfoermiger Kaktus, der im Innenraum bis zu 2 m hoch werden kann.",Volles Sonnenlicht,15-35 °C,21,easy|succulent|large|sun,,,,, +easy,constants/lexiconBatch1.ts,99,Herzkette,Ceropegia woodii,"Die Herzkette hat duenne, haengende Ranken mit herzfoermigen, silbergrau gemusterten Blaettchen.",Helles indirektes Licht,15-27 °C,14,easy|succulent|patterned|hanging,,,,, +easy,constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,Die Bergpalme ist eine kompakte Zimmerpalme fuer schattigere Standorte. Ideal fuer dunkle Innenraeume.,Wenig bis helles Licht,15-25 °C,7,easy|pet_friendly|tree|air_purifier|low_light,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,138,Roemische Kamille,Chamaemelum nobile,Roemische Kamille ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,101,Kamille,Chamomilla recutita,"Die Kamille ist ein beliebtes Heilkraut mit kleinen, weiss-gelben Blueten. Das aetherische Oel wirkt beruhigend.",Volles Sonnenlicht,15-25 °C,5,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,84,Kaffeestrauch,Coffea arabica,"Der Kaffeestrauch hat glaenzende, dunkelgruene Blaetter und entwickelt rote Kaffe­ekirschen. Kann im Topf gehalten werden.",Helles indirektes Licht,18-25 °C,7,easy,,,,, +easy,constants/lexiconBatch2.ts,14,Keulenlilie,Cordyline australis,"Die Keulenlilie hat lange, schmale, gruene oder rotbraune Blaetter in einem dekorativen Schopf.",Helles bis volles Licht,10-25 °C,7,easy|tree|sun,,,,, +easy,constants/lexiconBatch2.ts,15,Tiroler Keulenlilie,Cordyline fruticosa,"Die Tiroler Keulenlilie hat leuchtend rote, gruene oder buntlaubige Blaetter. Eine exotische Zimmerpflanze.",Helles indirektes Licht,18-27 °C,7,easy,,,,, +easy,constants/lexiconBatch2.ts,139,Koriander,Coriandrum sativum,Koriander ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,29,Kotyledon,Cotyledon orbiculata,"Kotyledon hat dickfleischige, runde Blaetter mit einem mehligen, weisslichen Belag. Sehr trockenheitsresistent.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,26,Moos-Crassula,Crassula muscosa,"Die Moos-Crassula hat dicht aneinandergereihte, winzige gruene Blaetter auf unverzweigten Trieben. Sieht aus wie Moos.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,5,Jadepflanze,Crassula ovata,"Die Jadepflanze ist eine langlebige Sukkulente mit dicken, ovalen Blaettern. In Japan gilt sie als Gluecksbringer.",Helles bis volles Licht,15-24 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,110,Krokus,Crocus vernus,"Der Krokus ist einer der ersten Fruehjahrs­boten mit kelchfoermigen Blueten in Lila, Weiss und Gelb.",Helles bis volles Licht,5-15 °C,7,easy|flowering,,,,, +easy,constants/lexiconBatch2.ts,94,Gurke,Cucumis sativus,"Die Gurke ist eine rankende Gemuese­pflanze mit gruenen, erfrischenden Fruechten. Im Balkonkasten kultivierbar.",Volles Sonnenlicht,18-28 °C,3,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,127,Zitronengras,Cymbopogon citratus,Zitronengras ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,99,Karotte,Daucus carota,Die Karotte ist eine beliebte Gemuese­pflanze mit orangefarbenen Wurzeln. Im tiefen Topf kultivierbar.,Helles bis volles Licht,15-22 °C,5,easy,,,,, +easy,constants/lexiconBatch1.ts,48,Dieffenbachie,Dieffenbachia seguine,"Die Dieffenbachie ist eine tropische Blattschmuckpflanze mit grossen, gruen-weiss gefleckten Blaettern.",Helles indirektes Licht,18-26 °C,7,easy|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,14,Maisstrauch,Dracaena fragrans,"Der Maisstrauch ist eine robuste Zimmerpflanze mit breiten, gestreiften Blaettern. Gedeiht auch bei wenig Licht.",Helles indirektes Licht,15-25 °C,10,easy|tree|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,13,Drachenbaum,Dracaena marginata,"Der Drachenbaum ist eine schlanke Zimmerpflanze mit roten, schmalen Blaettern auf langen Staemmen.",Helles indirektes Licht,15-25 °C,10,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,30,Dudleya,Dudleya brittonii,"Dudleya ist eine rosetten­bildende Sukkulente mit silbrig-weissen, mehligen Blaettern. Sehr elegant.",Volles Sonnenlicht,10-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,4,Echeverie,Echeveria elegans,"Die Echeverie bildet symmetrische, rosettenfoermige Sukkulenten mit blaugruenen Blaettern. Pflegeleicht.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,77,Goldene Tonne,Echinocactus grusonii,Die Goldene Tonne ist ein ikonischer kugelfoermiger Kaktus mit goldgelben Stacheln. Waechst langsam aber imposant.,Volles Sonnenlicht,15-35 °C,21,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,83,San-Pedro-Kaktus,Echinopsis pachanoi,"Der San-Pedro-Kaktus ist ein schnell wachsender, saeulenfoermiger Kaktus aus den Anden.",Volles Sonnenlicht,10-35 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,16,Marmor-Efeutute,Epipremnum aureum Marble Queen,Die Marmor-Efeutute hat cremeweiss-gruen marmorierte Blaetter. Eine dekorative Variante der klassischen Efeutute.,Helles indirektes Licht,15-30 °C,7,easy|hanging|air_purifier,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,53,Neon-Efeutute,Epipremnum pinnatum Neon,Die Neon-Efeutute hat leuchtend limonengruene Blaetter. Sehr auffaellig und pflegeleicht.,Helles indirektes Licht,15-30 °C,7,easy|hanging|air_purifier,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,19,Christusdorn,Euphorbia milii,Der Christusdorn ist eine sukkulente Wolfsmilch mit stacheligen Zweigen und kleinen roten oder gelben Hochblaettern.,Helles bis volles Licht,15-28 °C,10,easy|flowering|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,12,Bleistiftkaktus,Euphorbia tirucalli,"Der Bleistiftkaktus ist eine sukkulente Wolfsmilch mit duennen, zylindrischen Zweigen ohne Blaetter.",Volles Sonnenlicht,18-30 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,12,Fatsia,Fatsia japonica,"Die Fatsia ist ein dekorativer Zimmerstrauch mit grossen, handfoermigen, glaenzenden Blaettern. Sehr robust.",Helles indirektes Licht,10-20 °C,7,easy|low_light,,,,, +easy,constants/lexiconBatch1.ts,78,Fass-Kaktus,Ferocactus cylindraceus,"Der Fass-Kaktus ist ein zylindrischer Wuestenkaktus mit langen, roten Stacheln. Sehr langlebig.",Volles Sonnenlicht,15-35 °C,21,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,38,Gummibaum,Ficus elastica,"Der Gummibaum ist eine imposante Zimmerpflanze mit grossen, glaenzenden, lederartigen Blaettern. Reinigt die Luft.",Helles indirektes Licht,16-24 °C,10,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,247,Ficus microcarpa,Ficus microcarpa,Ficus microcarpa ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|tree|bright_light,,,,, +easy,constants/lexiconBatch2.ts,100,Erdbeere,Fragaria ananassa,"Die Erdbeere ist ein beliebtes Obst fuer Balkon und Terrasse mit aromatischen, roten Fruechten.",Helles bis volles Licht,15-25 °C,3,easy|pet_friendly|sun,pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,90,Gasteria,Gasteria carinata,"Die Gasteria ist eine kleine Sukkulente mit zweireihig angeordneten, zungenfoermigen, gefleckten Blaettern.",Helles indirektes Licht,15-25 °C,14,easy|succulent|low_light,,,,, +easy,constants/lexiconBatch1.ts,32,Blutroter Storchschnabel,Geranium sanguineum,Der Blutrote Storchschnabel ist ein zierlicher Storchschnabel mit intensiv magentafarbenen Blueten.,Helles bis volles Licht,10-25 °C,7,easy|flowering,,,,, +easy,constants/lexiconBatch1.ts,87,Geisterpflanze,Graptopetalum paraguayense,"Die Geisterpflanze hat zartgraue bis perlmutt-rosafarbene, rosettenfoermige Blaetter. Sehr robuste Sukkulente.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,80,Mond-Kaktus,Gymnocalycium mihanovichii,Der Mond-Kaktus ist eine farbenfrohe Veredelung eines chlorophylllosen Kaktus auf einem gruenen Unterlagekaktus.,Indirektes Licht,15-30 °C,14,easy|succulent,,,,, +easy,constants/lexiconBatch1.ts,6,Zebra-Haworthie,Haworthia fasciata,Die Zebra-Haworthie ist eine kompakte Sukkulente mit weissen Querstreifen auf dunkelgruenen Blaettern.,Helles indirektes Licht,15-25 °C,14,easy|succulent|low_light,,,,, +easy,constants/lexiconBatch1.ts,37,Efeu,Hedera helix,"Efeu ist eine robuste Kletter- und Haengepflanze mit charakteristischen, dreilappigen Blaettern. Sehr langlebig.",Wenig bis helles Licht,10-20 °C,7,easy|hanging|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,133,Currykraut,Helichrysum italicum,Currykraut ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch1.ts,57,Wachsblume,Hoya carnosa,"Die Wachsblume ist eine Kletterpflanze mit dicken, wachsartigen Blaettern und sternfoermigen, duftenden Blueten.",Helles indirektes Licht,16-27 °C,10,easy|flowering|succulent|hanging,,,,, +easy,constants/lexiconBatch1.ts,108,Hyazinthe,Hyacinthus orientalis,"Die Hyazinthe bezaubert mit dichten Bluetenrispen und intensivem Duft in Blau, Rosa, Weiss oder Gelb.",Helles bis volles Licht,10-18 °C,5,easy|flowering,,,,, +easy,constants/lexiconBatch2.ts,136,Ysop,Hyssopus officinalis,Ysop ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,59,Neuguinea-Balsamine,Impatiens hawkeri,"Die Neuguinea-Balsamine hat grosse, leuchtende Blueten und ist sehr bluehfreudig. Ideal fuer Terrassen.",Helles indirektes Licht,18-27 °C,3,easy|flowering,,,,, +easy,constants/lexiconBatch1.ts,20,Fleissiges Lieschen,Impatiens walleriana,Das Fleissige Lieschen bluet von Fruehling bis Herbst unermudlich in vielen Farben.,Helles indirektes Licht,16-24 °C,2,easy|flowering,,,,, +easy,constants/lexiconBatch1.ts,64,Suesskartoffel,Ipomoea batatas,"Die Suesskartoffel-Zierpflanze hat dekorative, herzfoermige Blaetter in gruen oder dunkelviolett. Ideal als Haengepflanze.",Volles Sonnenlicht,20-30 °C,5,easy|hanging|sun,,,,, +easy,constants/lexiconBatch1.ts,9,Kalanchoe,Kalanchoe blossfeldiana,"Die Kalanchoe ist eine beliebte Bluehpflanze mit leuchtenden Blueten in Rot, Orange, Gelb oder Rosa.",Helles bis volles Licht,15-25 °C,10,easy|flowering|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,22,Brutblatt,Kalanchoe daigremontiana,Das Brutblatt bildet entlang des Blattrandes zahlreiche kleine Jungpflanzen. Eine faszinierende Sukkulente.,Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,21,Kaninchen-Ohren,Kalanchoe tomentosa,"Kaninchen-Ohren haben weisslich-filzige Blaetter mit braunen Raendern, die Kaninchen­ohren aehneln. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,95,Salat,Lactuca sativa,Salat ist eine schnell wachsende Blattgemuese­pflanze. Im Topf und Balkonkasten sehr gut zu kultivieren.,Helles bis volles Licht,10-22 °C,3,easy,,,,, +easy,constants/lexiconBatch2.ts,121,Lorbeer,Laurus nobilis,Lorbeer ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,126,Liebstoeckel,Levisticum officinale,Liebstoeckel ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,62,Duftsteinrich,Lobularia maritima,"Der Duftsteinrich ist ein niedrig wachsendes Pflanzchen mit winzigen, weissen oder lilafarbenen Blueten und suessem Duft.",Helles bis volles Licht,10-22 °C,3,easy|flowering,,,,, +easy,constants/lexiconBatch1.ts,79,Mammillaria,Mammillaria zeilmanniana,"Die Mammillaria ist ein kompakter, kugelfoermiger Kaktus, der im Fruehling einen Kranz aus rosa Blueten traegt.",Volles Sonnenlicht,15-35 °C,14,easy|flowering|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,102,Zitronenmelisse,Melissa officinalis,Die Zitronenmelisse ist ein zitronig duftendes Heilkraut. Sie beruhigt die Nerven und foerdert den Schlaf.,Helles bis volles Licht,15-25 °C,5,easy|medicinal,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,26,Gruene Minze,Mentha spicata,"Die Gruene Minze ist ein wuchsfreudiges Kuechenkraut mit frischem, minzigem Duft. Fuer Tee und Cocktails.",Helles bis volles Licht,15-25 °C,3,easy,,,,, +easy,constants/lexiconBatch2.ts,47,Monstera adansonii,Monstera adansonii,Monstera adansonii hat herzfoermige Blaetter mit zahlreichen runden Lochern. Eine rankende Zimmerpflanze.,Helles indirektes Licht,18-27 °C,7,easy|hanging,,,,, +easy,constants/lexiconBatch1.ts,109,Traubenhyazinthe,Muscari armeniacum,"Die Traubenhyazinthe bildet dichte Trauben aus kleinen, blauen bis violetten Gloeckchen. Zuverlaessige Fruejahrszwiebel.",Helles bis volles Licht,8-18 °C,7,easy|flowering,,,,, +easy,constants/lexiconBatch2.ts,132,Katzenminze,Nepeta cataria,Katzenminze ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch1.ts,25,Basilikum,Ocimum basilicum,"Basilikum ist das beliebteste Kuechenkraut mit intensiv aromatischen, gruenen Blaettern. Fuer Pesto verwendet.",Volles Sonnenlicht,18-30 °C,2,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,82,Hasenohren-Kaktus,Opuntia microdasys,"Der Hasenohren-Kaktus hat flache, ovale Triebe mit dichten weissen Glochiden. Klassischer Zimmerkaktus.",Volles Sonnenlicht,10-35 °C,21,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,124,Majoran,Origanum majorana,Majoran ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch1.ts,28,Oregano,Origanum vulgare,"Oregano ist ein aromatisches Kuechenkraut mit runden, behaarten Blaettern. In mediterraner Kueche beliebt.",Volles Sonnenlicht,15-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,231,Glueckskastanie,Pachira aquatica,Glueckskastanie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|tree|bright_light,,,,, +easy,constants/lexiconBatch1.ts,88,Mondstein-Pflanze,Pachyphytum oviferum,"Die Mondstein-Pflanze hat dicke, ovale Blaetter mit einem pastellrosafarbenen, mehligen Ueberzug.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch1.ts,31,Rosengeranie,Pelargonium graveolens,Die Rosengeranie ist eine Duftpflanze mit tief eingeschnittenen Blaettern und rosaenlichem Aroma.,Volles Sonnenlicht,15-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,61,Efeu-Geranie,Pelargonium peltatum,"Die Efeu-Geranie hat efeufoermige, glaenzende Blaetter und bluet den ganzen Sommer in leuchtenden Farben.",Helles bis volles Licht,15-25 °C,5,easy|flowering|hanging|sun,,,,, +easy,constants/lexiconBatch1.ts,102,Rippenpeperomie,Peperomia caperata,"Die Rippenpeperomie hat tief gerippte, dunkelgruene bis violette Blaetter mit einer samtigen Textur.",Helles indirektes Licht,18-26 °C,10,easy|pet_friendly,pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,103,Spiegelpeperomie,Peperomia obtusifolia,"Die Spiegelpeperomie hat glaenzende, lederartige, oval-runde Blaetter in tiefem Gruen. Sehr robust.",Helles indirektes Licht,16-26 °C,10,easy|pet_friendly|low_light,pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,230,Raindrop-Peperomie,Peperomia polybotrya,Raindrop-Peperomie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|pet_friendly,pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,134,Shiso,Perilla frutescens,Shiso ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch1.ts,29,Petersilie,Petroselinum crispum,Petersilie ist eines der meistgenutzten Kuechenkraeuter mit frisch-aromatischem Geschmack. Reich an Vitaminen.,Helles Licht,10-25 °C,3,easy,,,,, +easy,constants/lexiconBatch1.ts,34,Petunie,Petunia hybrida,Die Petunie ist eine der beliebtesten Balkonpflanzen mit trichterfoermigen Blueten in unzaehligen Farben.,Volles Sonnenlicht,15-25 °C,2,easy|pet_friendly|flowering|sun,pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,50,Philodendron bipinnatifidum,Philodendron bipinnatifidum,"Philodendron bipinnatifidum hat grosse, tief gelappte Blaetter. Er entwickelt einen beeindruckenden, baumfoermigen Wuchs.",Helles indirektes Licht,18-27 °C,7,easy|large,,,,, +easy,constants/lexiconBatch2.ts,51,Roter Philodendron,Philodendron erubescens,"Der Rote Philodendron hat glaenzende, herzfoermige Blaetter, die jung roetrlich erscheinen. Sehr dekorativ.",Helles indirektes Licht,18-27 °C,7,easy|hanging,,,,, +easy,constants/lexiconBatch1.ts,15,Herzblatt-Philodendron,Philodendron hederaceum,Der Herzblatt-Philodendron ist eine pflegeleichte Kletter- oder Haengepflanze mit herzfoermigen Blaettern.,Indirektes Licht,18-28 °C,7,easy|hanging|low_light,,,,, +easy,constants/lexiconBatch2.ts,242,Philodendron Brasil,Philodendron hederaceum Brasil,Philodendron Brasil ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|hanging|low_light,,,,, +easy,constants/lexiconBatch2.ts,8,Goldener Bambus,Phyllostachys aurea,"Der Goldene Bambus hat elegante, goldgelbe Halme mit engstehenden Knoten. Sehr dekorativ als Sichtschutz.",Helles bis volles Licht,10-30 °C,5,easy|large,,,,, +easy,constants/lexiconBatch2.ts,228,Aluminium-Pflanze,Pilea cadierei,Aluminium-Pflanze ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|pet_friendly|patterned,pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,2,Ufopflanze,Pilea peperomioides,"Die Ufopflanze hat unverwechselbare, runde Blaetter auf langen Stielen. Bildet leicht Ableger zum Verschenken.",Helles indirektes Licht,13-30 °C,7,easy|pet_friendly,pet_friendly_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,44,Tueipelfarn,Polypodium vulgare,Der Tueipelfarn ist ein heimischer Farn mit gelappten Wedeln und runden Sporenhaeufchen auf der Unterseite.,Helles indirektes Licht,10-20 °C,7,easy,,,,, +easy,constants/lexiconBatch2.ts,27,Speckbaum,Portulacaria afra,"Der Speckbaum ist eine sukkulente Pflanze mit roten Stielen und kleinen, runden, glaenzenden Blaettern.",Helles bis volles Licht,15-30 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,98,Radieschen,Raphanus sativus,"Das Radieschen ist ein schnellwachsendes Gemuese mit runden, roten Knollen. Es reift in nur 3-4 Wochen.",Helles bis volles Licht,10-22 °C,2,easy,,,,, +easy,constants/lexiconBatch2.ts,52,Mini-Monstera,Rhaphidophora tetrasperma,"Die Mini-Monstera hat monstera­aehnliche, gelochte Blaetter auf einer kompakten, klettternden Pflanze. Sehr trendig.",Helles indirektes Licht,18-27 °C,7,easy|hanging,,,,, +easy,constants/lexiconBatch1.ts,24,Rosmarin,Rosmarinus officinalis,Rosmarin ist ein aromatisches Kraut mit nadelartigen Blaettern und blauen Blueten. In der Kueche unverzichtbar.,Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,130,Sauerampfer,Rumex acetosa,Sauerampfer ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch1.ts,94,Afrikanisches Veilchen,Saintpaulia ionantha,"Das Afrikanische Veilchen ist eine kleine, kompakte Bluehpflanze mit samtigen Blaettern und violetten Blueten.",Helles indirektes Licht,18-25 °C,7,easy|flowering,,,,, +easy,constants/lexiconBatch2.ts,103,Salbei,Salvia officinalis,Salbei ist ein aromatisches Heilkraut mit silbrig-gruenen Blaettern. Er hat antibakterielle und entzuendungshem­mende Wirkung.,Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,17,Zylindrischer Bogenhanf,Sansevieria cylindrica,"Der Zylindrische Bogenhanf hat zylindrische, aufrechte Blaetter, die sich nach oben verjuengen. Sehr pflegeleicht.",Helles bis volles Licht,15-27 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,123,Bohnenkraut,Satureja hortensis,Bohnenkraut ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch2.ts,11,Grosse Strahlenaralie,Schefflera actinophylla,"Die Grosse Strahlenaralie kann grosse, handfoermige Blaetter entwickeln. Sie ist ideal als Zimmerstrauch.",Helles indirektes Licht,18-27 °C,7,easy|tree|large,,,,, +easy,constants/lexiconBatch2.ts,10,Strahlenaralie,Schefflera arboricola,"Die Strahlenaralie hat fingerfoermig angeordnete, glaenzende Blaetter auf langen Stielen. Sehr robuste Zimmerpflanze.",Helles indirektes Licht,15-25 °C,7,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +easy,constants/lexiconBatch1.ts,8,Weihnachtskaktus,Schlumbergera truncata,"Der Weihnachtskaktus erfreut zur Weihnachtszeit mit leuchtenden Blueten in Rosa, Rot oder Weiss.",Helles indirektes Licht,15-21 °C,7,easy|flowering|succulent,,,,, +easy,constants/lexiconBatch1.ts,55,Satinpothos,Scindapsus pictus,"Der Satinpothos hat samtig-glaenzende, silbrig gefleckte Blaetter auf langen, haengenden Ranken.",Helles indirektes Licht,18-28 °C,7,easy|patterned|hanging,,,,, +easy,constants/lexiconBatch1.ts,7,Eselschwanz,Sedum morganianum,"Der Eselschwanz ist eine haengende Sukkulente mit langen Trieben aus dichten, blaugruenen Blaettchen.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|hanging|sun,,,,, +easy,constants/lexiconBatch1.ts,100,Perlenschnur-Pflanze,Senecio rowleyanus,"Die Perlenschnur-Pflanze hat haengende Ranken mit kugelfoermigen, perlenaehnlichen Blaettern. Einzigartige Sukkulente.",Helles bis volles Licht,15-27 °C,14,easy|succulent|hanging,,,,, +easy,constants/lexiconBatch2.ts,28,Blauer Kreuzkraut,Senecio serpens,"Der Blaue Kreuzkraut hat zylindrische, blaublaugruene Blaetter und einen kriechenden Wuchs. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +easy,constants/lexiconBatch2.ts,91,Tomate,Solanum lycopersicum,"Die Tomate ist eine beliebte Gemuese- und Balkonpflanze mit roten, saftigen Fruechten. Im Topf kultivierbar.",Volles Sonnenlicht,18-28 °C,3,easy,,,,, +easy,constants/lexiconBatch2.ts,96,Spinat,Spinacia oleracea,Spinat ist ein naehrstoffreiches Blattgemuese mit dunkelgruenen Blaettern. Reich an Eisen und Vitaminen.,Helles bis volles Licht,10-20 °C,3,easy,,,,, +easy,constants/lexiconBatch2.ts,131,Stevia,Stevia rebaudiana,Stevia ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +easy,constants/lexiconBatch1.ts,56,Pfeilblatt,Syngonium podophyllum,"Das Pfeilblatt hat charakteristisch pfeilfoermige Blaetter, die sich mit dem Alter weiterentwickeln.",Helles indirektes Licht,16-27 °C,7,easy|hanging,,,,, +easy,constants/lexiconBatch2.ts,66,Studentenblume,Tagetes patula,Die Studentenblume ist eine robuste Sommerblume mit orangen oder gelben Blueten. Sie haelt Schadlinge fern.,Volles Sonnenlicht,15-28 °C,3,easy|flowering|sun,,,,, +easy,constants/lexiconBatch1.ts,27,Thymian,Thymus vulgaris,"Thymian ist ein kleiner, aromatischer Strauch mit winzigen Blaettern und rosa Blueten. Wichtiges Kuechenkraut.",Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +easy,constants/lexiconBatch2.ts,33,Luftpflanze,Tillandsia ionantha,Die Luftpflanze ist eine kompakte Bromelie ohne Topferde. Sie nimmt Wasser und Naehrstoffe ueber die Blattschuppen auf.,Helles bis volles Licht,15-30 °C,3,easy,,,,, +easy,constants/lexiconBatch2.ts,32,Spanisches Moos,Tillandsia usneoides,"Das Spanische Moos ist eine epiphytische Bromelie ohne Wurzeln, die in der Luft haengt. Es benoetigt nur Feuchtigkeitsbespruehing.",Helles bis volles Licht,15-30 °C,3,easy|hanging,,,,, +easy,constants/lexiconBatch2.ts,55,Weisse Tradescantia,Tradescantia fluminensis,Die Weisse Tradescantia hat gruene Blaetter mit weisslichen Unterseiten. Sehr robust und schnellwachsend.,Helles indirektes Licht,15-25 °C,5,easy|hanging,,,,, +easy,constants/lexiconBatch2.ts,54,Lila Tradescantia,Tradescantia pallida,Die Lila Tradescantia hat leuchtend purpurrote Blaetter und ist sehr auffaellig. Sie liebt viel Licht.,Helles bis volles Licht,15-25 °C,5,easy|hanging|sun,,,,, +easy,constants/lexiconBatch1.ts,17,Zebrakraut,Tradescantia zebrina,Das Zebrakraut faellt durch seine silbrig-lila gestreiften Blaetter auf. Schnellwachsende Haengepflanze.,Helles indirektes Licht,15-25 °C,5,easy|patterned|hanging,,,,, +easy,constants/lexiconBatch1.ts,107,Tulpe,Tulipa gesneriana,Die Tulpe ist eine der beliebtesten Fruehjahrsblueher mit kelchfoermigen Blueten in unzaehligen Farben.,Helles bis volles Licht,8-18 °C,5,easy|flowering,,,,, +easy,constants/lexiconBatch1.ts,35,Stiefmuetterchen,Viola wittrockiana,Das Stiefmuetterchen ist ein bekannter Fruehjahrsblueher mit charakteristisch gezeichneten Blueten.,Helles bis volles Licht,5-18 °C,3,easy|flowering,,,,, +easy,constants/lexiconBatch2.ts,246,Yucca aloifolia,Yucca aloifolia,Yucca aloifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Volles Sonnenlicht,18-30 C,10,easy|tree|sun,,,,, +easy,constants/lexiconBatch1.ts,40,Yucca-Palme,Yucca elephantipes,"Die Yucca-Palme ist eine robuste Zimmerpflanze mit starrem, immergruenem Blaetterschopf auf einem dicken Stamm.",Helles bis volles Licht,15-28 °C,14,easy|tree|sun,,,,, +easy,constants/lexiconBatch2.ts,65,Zinnie,Zinnia elegans,"Die Zinnie ist eine leuchtende Sommerblume mit grossen, dahlienaehnlichen Blueten. Sehr robust und hitzetolerant.",Volles Sonnenlicht,18-30 °C,3,easy|flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,108,Schafgarbe,Achillea millefolium,Die Schafgarbe hat weisse oder rosafarbene Bluetenschirme und fein gefiederte Blaetter. Wichtige Heilpflanze.,Volles Sonnenlicht,10-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch1.ts,86,Wuestenrose,Adenium obesum,Die Wuestenrose ist eine sukkulente Zimmerpflanze mit dickem Stamm und leuchtend pinken Blueten.,Volles Sonnenlicht,20-35 °C,10,flowering|succulent|sun,,,,, +flowering,constants/lexiconBatch2.ts,117,Socotra-Wuestenrose,Adenium socotranum,"Die Socotra-Wuestenrose ist eine seltene, endemische Art mit einem sehr dicken, knolligen Stamm und rosa Blueten.",Volles Sonnenlicht,20-35 °C,14,flowering|succulent|sun,,,,, +flowering,constants/lexiconBatch2.ts,34,Silbervase,Aechmea fasciata,Die Silbervase ist eine Bromelie mit silbrig gebänderten Blaettern und einem rosafarbenen Bluetenstand.,Helles indirektes Licht,18-25 °C,10,flowering|patterned,,,,, +flowering,constants/lexiconBatch1.ts,98,Lippenstiftpflanze,Aeschynanthus radicans,Die Lippenstiftpflanze hat haengende Triebe mit glaenzenden Blaettern und leuchtend roten Roehrenbluten.,Helles indirektes Licht,18-27 °C,7,flowering|hanging|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,155,Stockrose,Alcea rosea,"Stockrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,73,Muschelingwer,Alpinia zerumbet,"Der Muschelingwer hat lange, elegante Blaetter und haengende Bluetenrispen mit weiss-rosa Bluetchen.",Helles bis volles Licht,20-30 °C,5,flowering|large|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,194,Fuchsschwanz,Amaranthus caudatus,"Fuchsschwanz ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,163,Anemone,Anemone coronaria,"Anemone ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,147,Loewenmaeulchen,Antirrhinum majus,"Loewenmaeulchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,107,Arnika,Arnica montana,Arnika ist eine bekannte Heilpflanze aus den Alpen mit goldgelben Korbbluten. Sie wird fuer Muskeln und Gelenke verwendet.,Volles Sonnenlicht,10-20 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,178,Seidenpflanze,Asclepias tuberosa,"Seidenpflanze ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,92,Indische Azalee,Azalea indica,"Die Indische Azalee ist ein beliebter Zierstrauch mit grossen, auffaelligen Blueten in Rosa- und Rottönen.",Helles indirektes Licht,10-20 °C,4,flowering,,,,, +flowering,constants/lexiconBatch2.ts,175,Eisbegonie,Begonia semperflorens-cultorum,"Eisbegonie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,58,Knollen-Begonie,Begonia tuberhybrida,"Die Knollen-Begonie hat riesige, rosenaehnliche Blueten in leuchtendem Rot, Orange, Gelb oder Weiss.",Helles indirektes Licht,15-22 °C,5,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,145,Gaensebluemchen,Bellis perennis,"Gaensebluemchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,38,Billbergia,Billbergia nutans,"Die Billbergia ist eine robuste Bromelie mit schmalen, gruenen Blaettern und hängenden, blauen und gruenen Blueten.",Helles indirektes Licht,15-25 °C,7,easy|flowering,,,,, +flowering,constants/lexiconBatch1.ts,62,Bougainvillea,Bougainvillea spectabilis,"Die Bougainvillea ist eine rankenreiche Kletterpflanze mit leuchtend farbigen Hochblaettern in Rot, Orange oder Pink.",Volles Sonnenlicht,18-30 °C,5,flowering|bright_light|sun,,,,, +flowering,constants/lexiconBatch2.ts,223,Schmetterlingsflieder,Buddleja davidii,Schmetterlingsflieder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch2.ts,187,Ringelblume,Calendula officinalis,"Ringelblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,63,Calibrachoa,Calibrachoa hybrida,"Calibrachoa ist eine petunienaehnliche Haengepflanze mit unzaehligen, kleinen Trichterbluten in allen Farben.",Volles Sonnenlicht,15-25 °C,2,easy|flowering|hanging|sun,,,,, +flowering,constants/lexiconBatch1.ts,93,Kamelie,Camellia japonica,Die Kamelie ist ein eleganter Zierstrauch mit glaenzenden Blaettern und rosenaehnlichen Blueten von Januar bis April.,Helles indirektes Licht,7-18 °C,5,flowering,,,,, +flowering,constants/lexiconBatch2.ts,85,Teestrauch,Camellia sinensis,"Der Teestrauch ist die Pflanze, aus deren Blaettern Tee gewonnen wird. Er hat weisse Blueten und glaenzende Blaetter.",Helles indirektes Licht,15-22 °C,7,flowering,,,,, +flowering,constants/lexiconBatch2.ts,184,Trompetenwinde,Campsis radicans,"Trompetenwinde ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,67,Blumenschilfrohr,Canna indica,"Das Blumenschilfrohr hat grosse, tropisch wirkende Blaetter und auffaellige Blueten in Rot, Orange oder Gelb.",Volles Sonnenlicht,18-28 °C,5,flowering|large|sun,,,,, +flowering,constants/lexiconBatch1.ts,73,Cattleya-Orchidee,Cattleya labiata,"Die Cattleya ist die Koenigin der Orchideen mit ueppigen, duftenden Blueten in Lila, Rosa und Weiss.",Helles indirektes Licht,18-28 °C,7,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,188,Kornblume,Centaurea cyanus,"Kornblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,67,Chrysantheme,Chrysanthemum indicum,"Die Chrysantheme ist die klassische Herbstblume mit ueppigen, dichten Blueten in vielen Farben.",Helles bis volles Licht,12-22 °C,4,flowering,,,,, +flowering,constants/lexiconBatch2.ts,157,Clematis,Clematis viticella,"Clematis ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch1.ts,104,Riemenblatt,Clivia miniata,Das Riemenblatt ist eine dekorative Zimmerpflanze mit leuchtend orangefarbenen Blueten im Fruehling.,Helles indirektes Licht,15-24 °C,10,flowering,,,,, +flowering,constants/lexiconBatch1.ts,97,Columnea,Columnea gloriosa,"Die Columnea ist eine haengende Zimmerpflanze mit kleinen, behaarten Blaettern und leuchtend roten, roehrenfoermigen Blueten.",Helles indirektes Licht,18-25 °C,7,flowering|hanging|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,160,Maigloeckchen,Convallaria majalis,"Maigloeckchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,181,Maedchenauge,Coreopsis tinctoria,"Maedchenauge ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,150,Kosmee,Cosmos bipinnatus,"Kosmee ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,110,Krokus,Crocus vernus,"Der Krokus ist einer der ersten Fruehjahrs­boten mit kelchfoermigen Blueten in Lila, Weiss und Gelb.",Helles bis volles Licht,5-15 °C,7,easy|flowering,,,,, +flowering,constants/lexiconBatch1.ts,19,Alpenveilchen,Cyclamen persicum,"Das Alpenveilchen bluet im Herbst und Winter mit eleganten Blueten in Rosa, Rot oder Weiss.",Helles indirektes Licht,12-18 °C,5,flowering,,,,, +flowering,constants/lexiconBatch1.ts,71,Zymbidium,Cymbidium lowianum,"Das Zymbidium ist eine robuste Orchidee mit langen, grassartigen Blaettern und eleganten Bluetenrispen.",Helles Licht,12-24 °C,7,flowering,,,,, +flowering,constants/lexiconBatch2.ts,68,Dahlie,Dahlia pinnata,Die Dahlie ist eine prachtvolle Sommerblume mit Blueten in allen Groessen und Formen. Sie wird aus Knollen gezogen.,Volles Sonnenlicht,15-25 °C,5,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,215,Flammenbaum,Delonix regia,Flammenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +flowering,constants/lexiconBatch2.ts,153,Rittersporn,Delphinium elatum,"Rittersporn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,70,Dendrobium,Dendrobium nobile,"Das Dendrobium ist eine beliebte Zimmerorchidee mit langen Pseudobulben, die im Winter mit Blueten besetzt werden.",Helles indirektes Licht,15-28 °C,10,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,189,Bartnelke,Dianthus barbatus,"Bartnelke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,146,Nelke,Dianthus caryophyllus,"Nelke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,109,Roter Fingerhut,Digitalis purpurea,"Der Rote Fingerhut hat hohe Bluetenstaende mit roehrenfoermigen, gepunkteten Blueten in Rosa. Wichtige Arzneipflanze.",Helles bis volles Licht,10-20 °C,7,flowering|medicinal,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,106,Sonnenhut,Echinacea purpurea,"Der Sonnenhut ist eine beliebte Heilpflanze mit grossen, pinkfarbenen Blueten. Er staerkt das Immunsystem.",Helles bis volles Licht,15-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch1.ts,84,Koenigin der Nacht,Epiphyllum oxypetalum,"Die Koenigin der Nacht bluet nur eine einzige Nacht lang mit riesigen, intensiv duftenden weissen Blueten.",Indirektes Licht,18-27 °C,7,flowering|succulent,,,,, +flowering,constants/lexiconBatch2.ts,186,Kalifornischer Mohn,Eschscholzia californica,"Kalifornischer Mohn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,19,Christusdorn,Euphorbia milii,Der Christusdorn ist eine sukkulente Wolfsmilch mit stacheligen Zweigen und kleinen roten oder gelben Hochblaettern.,Helles bis volles Licht,15-28 °C,10,easy|flowering|succulent|sun,,,,, +flowering,constants/lexiconBatch2.ts,20,Weihnachtsstern,Euphorbia pulcherrima,Der Weihnachtsstern ist die klassische Winterpflanze mit leuchtend roten Hochblaettern. Er steht symbolisch fuer Weihnachten.,Helles indirektes Licht,15-22 °C,7,flowering,,,,, +flowering,constants/lexiconBatch2.ts,219,Forsythie,Forsythia x intermedia,Forsythie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch2.ts,169,Freesie,Freesia refracta,"Freesie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,33,Fuchsie,Fuchsia hybrida,"Die Fuchsie haengt mit eleganten, zweifarbigen Blueten wie kleine Ohrringe herab. Ideal fuer Ampeln.",Helles indirektes Licht,14-22 °C,3,flowering|hanging,,,,, +flowering,constants/lexiconBatch2.ts,60,Triphylla-Fuchsie,Fuchsia triphylla,"Die Triphylla-Fuchsie hat lange, roehrenfoermige, orangefarbe Blueten in haengenden Trauben. Sehr exotisch.",Helles indirektes Licht,15-22 °C,3,flowering|hanging,,,,, +flowering,constants/lexiconBatch2.ts,196,Kokardenblume,Gaillardia aristata,"Kokardenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,22,Gardenie,Gardenia jasminoides,"Die Gardenie fasziniert mit cremefarbenen, intensiv duftenden Blueten. Anspruchsvoll in der Pflege.",Helles indirektes Licht,18-23 °C,5,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,190,Mittagsgold,Gazania rigens,"Mittagsgold ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,32,Blutroter Storchschnabel,Geranium sanguineum,Der Blutrote Storchschnabel ist ein zierlicher Storchschnabel mit intensiv magentafarbenen Blueten.,Helles bis volles Licht,10-25 °C,7,easy|flowering,,,,, +flowering,constants/lexiconBatch1.ts,68,Gerbera,Gerbera jamesonii,"Die Gerbera ist eine farbenfrohe Schnittblume mit grossen, sonnenblumenaehnlichen Blueten. Sehr beliebt.",Helles bis volles Licht,15-25 °C,5,flowering|air_purifier|bright_light,air_purifier_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,161,Gladiole,Gladiolus hortulanus,"Gladiole ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,96,Gloxinie,Gloxinia speciosa,"Die Gloxinie hat grosse, samtartige Blueten in Violett, Rosa oder Weiss mit farbigen Raendern.",Helles indirektes Licht,18-25 °C,5,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,36,Guzmania,Guzmania lingulata,"Die Guzmania ist eine Bromelie mit glänzenden, gruenen Blaettern und einem leuchtend roten, sternfoermigen Bluetenstand.",Helles indirektes Licht,18-27 °C,7,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,119,Zaubernuss,Hamamelis mollis,"Die Zaubernuss bluet im Winter mit fadendunnen, gelben Bluetenkranzeln, die bis -10 Grad standhalten.",Helles bis volles Licht,10-20 °C,10,flowering|medicinal,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,141,Sonnenblume,Helianthus annuus,"Sonnenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,72,Heliconia,Heliconia psittacorum,"Die Heliconia hat leuchtend orangefarbe oder rote, bootsfoermige Hochblaetter. Eine exotische Tropenpflanze.",Helles bis volles Licht,20-30 °C,5,flowering|bright_light|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,191,Heliotrop,Heliotropium arborescens,"Heliotrop ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,183,Lenzrose,Helleborus orientalis,"Lenzrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering,,,,, +flowering,constants/lexiconBatch2.ts,182,Taglilie,Hemerocallis fulva,"Taglilie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,21,Hibiskus,Hibiscus rosa-sinensis,"Der Hibiskus begeistert mit grossen, trompetenfoermigen Blueten in Rot, Orange und Rosa.",Volles Sonnenlicht,18-28 °C,3,flowering|bright_light|sun,,,,, +flowering,constants/lexiconBatch2.ts,220,Gartenhibiskus,Hibiscus syriacus,Gartenhibiskus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch1.ts,105,Ritterstern,Hippeastrum hybrid,"Der Ritterstern beeindruckt im Winter mit riesigen, trompetenfoermigen Blueten in Rot, Pink oder Weiss.",Helles bis volles Licht,18-25 °C,7,flowering|bright_light,,,,, +flowering,constants/lexiconBatch1.ts,58,Kleine Wachsblume,Hoya bella,"Die Kleine Wachsblume traegt zierliche, sternfoermige weisse Blueten mit rosa Mitte. Haengende Sukkulente.",Helles indirektes Licht,18-27 °C,10,flowering|succulent|hanging,,,,, +flowering,constants/lexiconBatch1.ts,57,Wachsblume,Hoya carnosa,"Die Wachsblume ist eine Kletterpflanze mit dicken, wachsartigen Blaettern und sternfoermigen, duftenden Blueten.",Helles indirektes Licht,16-27 °C,10,easy|flowering|succulent|hanging,,,,, +flowering,constants/lexiconBatch2.ts,159,Hasengloeckchen,Hyacinthoides non-scripta,"Hasengloeckchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,108,Hyazinthe,Hyacinthus orientalis,"Die Hyazinthe bezaubert mit dichten Bluetenrispen und intensivem Duft in Blau, Rosa, Weiss oder Gelb.",Helles bis volles Licht,10-18 °C,5,easy|flowering,,,,, +flowering,constants/lexiconBatch2.ts,148,Hortensie,Hydrangea macrophylla,"Hortensie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Helles bis halbschattiges Licht,8-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,105,Johanniskraut,Hypericum perforatum,Das Johanniskraut hat leuchtend gelbe Blueten und ist ein wichtiges Heilkraut gegen Depressionen und Stimmungstiefs.,Volles Sonnenlicht,10-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,176,Gartenbalsamine,Impatiens balsamina,"Gartenbalsamine ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,59,Neuguinea-Balsamine,Impatiens hawkeri,"Die Neuguinea-Balsamine hat grosse, leuchtende Blueten und ist sehr bluehfreudig. Ideal fuer Terrassen.",Helles indirektes Licht,18-27 °C,3,easy|flowering,,,,, +flowering,constants/lexiconBatch1.ts,20,Fleissiges Lieschen,Impatiens walleriana,Das Fleissige Lieschen bluet von Fruehling bis Herbst unermudlich in vielen Farben.,Helles indirektes Licht,16-24 °C,2,easy|flowering,,,,, +flowering,constants/lexiconBatch2.ts,156,Prunkwinde,Ipomoea purpurea,"Prunkwinde ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,144,Bart-Iris,Iris germanica,"Bart-Iris ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,211,Jacaranda,Jacaranda mimosifolia,Jacaranda ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +flowering,constants/lexiconBatch1.ts,59,Jasmin,Jasminum polyanthum,"Der Jasmin ist eine Kletterpflanze mit intensiv duftenden, weissen Blueten. Er bluet im Winter und Fruehling.",Helles bis volles Licht,10-22 °C,5,flowering,,,,, +flowering,constants/lexiconBatch2.ts,172,Arabischer Jasmin,Jasminum sambac,"Arabischer Jasmin ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch1.ts,9,Kalanchoe,Kalanchoe blossfeldiana,"Die Kalanchoe ist eine beliebte Bluehpflanze mit leuchtenden Blueten in Rot, Orange, Gelb oder Rosa.",Helles bis volles Licht,15-25 °C,10,easy|flowering|succulent|sun,,,,, +flowering,constants/lexiconBatch2.ts,197,Traenendes Herz,Lamprocapnos spectabilis,"Traenendes Herz ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,64,Wandelroeschen,Lantana camara,"Das Wandelroeschen hat kugelige Bluetenkoepfe, die die Farbe von Gelb ueber Orange zu Rot wechseln. Sehr attraktiv.",Volles Sonnenlicht,18-28 °C,5,flowering|bright_light|sun,,,,, +flowering,constants/lexiconBatch2.ts,158,Duftwicke,Lathyrus odoratus,"Duftwicke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,180,Bechermalve,Lavatera trimestris,"Bechermalve ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,173,Margerite,Leucanthemum vulgare,"Margerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,201,Shasta-Margerite,Leucanthemum x superbum,"Shasta-Margerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,69,Ostertrompete,Lilium longiflorum,"Die Ostertrompete hat grosse, weisse, trichterfoermige Blueten mit intensivem Duft. Klassische Osterblume.",Helles bis volles Licht,15-25 °C,5,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,62,Duftsteinrich,Lobularia maritima,"Der Duftsteinrich ist ein niedrig wachsendes Pflanzchen mit winzigen, weissen oder lilafarbenen Blueten und suessem Duft.",Helles bis volles Licht,10-22 °C,3,easy|flowering,,,,, +flowering,constants/lexiconBatch2.ts,171,Geissblatt,Lonicera japonica,"Geissblatt ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,154,Lupine,Lupinus polyphyllus,"Lupine ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,204,Magnolie,Magnolia grandiflora,Magnolie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +flowering,constants/lexiconBatch1.ts,79,Mammillaria,Mammillaria zeilmanniana,"Die Mammillaria ist ein kompakter, kugelfoermiger Kaktus, der im Fruehling einen Kranz aus rosa Blueten traegt.",Volles Sonnenlicht,15-35 °C,14,easy|flowering|succulent|sun,,,,, +flowering,constants/lexiconBatch1.ts,75,Stiefmuetterchen-Orchidee,Miltoniopsis roezlii,"Die Stiefmuetterchen-Orchidee hat grosse, flache Blueten. Bevorzugt kuehle Temperaturen und hohe Luftfeuchtigkeit.",Indirektes Licht,15-22 °C,5,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,76,Schamkraut,Mimosa pudica,"Das Schamkraut faltet seine Blaettchen blitzschnell zusammen, wenn man sie beruehrt. Ein faszinierendes Erlebnis.",Helles bis volles Licht,20-28 °C,5,flowering|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,179,Indianernessel,Monarda didyma,"Indianernessel ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,109,Traubenhyazinthe,Muscari armeniacum,"Die Traubenhyazinthe bildet dichte Trauben aus kleinen, blauen bis violetten Gloeckchen. Zuverlaessige Fruejahrszwiebel.",Helles bis volles Licht,8-18 °C,7,easy|flowering,,,,, +flowering,constants/lexiconBatch2.ts,177,Vergissmeinnicht,Myosotis sylvatica,"Vergissmeinnicht ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,106,Osterglocke,Narcissus pseudonarcissus,"Die Osterglocke ist der klassische Fruehjahrsblueher mit leuchtend gelben, trompetenfoermigen Blueten.",Helles bis volles Licht,10-18 °C,5,flowering,,,,, +flowering,constants/lexiconBatch2.ts,199,Nemesie,Nemesia strumosa,"Nemesie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,37,Neoregelia,Neoregelia carolinae,"Die Neoregelia ist eine Bromelie, bei der das Herzblatt zur Bluetzeit leuchtend rot wird. Sehr dekorativ.",Helles bis volles Licht,18-27 °C,7,flowering|patterned|bright_light,,,,, +flowering,constants/lexiconBatch2.ts,120,Oleander,Nerium oleander,"Der Oleander ist ein mediteraner Strauch mit leuchtend roten, rosa oder weissen Blueten. Sehr hitzetolerant.",Volles Sonnenlicht,15-28 °C,7,flowering|bright_light|sun,,,,, +flowering,constants/lexiconBatch2.ts,193,Ziertabak,Nicotiana alata,"Ziertabak ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,74,Tanzerinnen-Orchidee,Oncidium sphacelatum,"Die Tanzerinnen-Orchidee traegt lange Rispen mit Hunderten kleiner, gelb-brauner Blueten. Sehr reichliche Bluetracht.",Helles indirektes Licht,18-27 °C,7,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,200,Kapmargerite,Osteospermum ecklonis,"Kapmargerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,54,Kleeblume,Oxalis triangularis,"Die Kleeblume hat tiefviolette, dreieckige Blaetter und zarte rosa Blueten. Sie faltet die Blaetter bei Dunkelheit.",Helles indirektes Licht,15-24 °C,7,flowering|patterned,,,,, +flowering,constants/lexiconBatch2.ts,143,Pfingstrose,Paeonia lactiflora,"Pfingstrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,185,Mohn,Papaver rhoeas,"Mohn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,63,Passionsblume,Passiflora caerulea,"Die Passionsblume ist eine faszinierende Kletterpflanze mit komplex strukturierten, blau-weissen Blueten.",Helles bis volles Licht,15-27 °C,5,flowering,,,,, +flowering,constants/lexiconBatch2.ts,61,Efeu-Geranie,Pelargonium peltatum,"Die Efeu-Geranie hat efeufoermige, glaenzende Blaetter und bluet den ganzen Sommer in leuchtenden Farben.",Helles bis volles Licht,15-25 °C,5,easy|flowering|hanging|sun,,,,, +flowering,constants/lexiconBatch2.ts,174,Stehende Geranie,Pelargonium zonale,"Stehende Geranie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,34,Petunie,Petunia hybrida,Die Petunie ist eine der beliebtesten Balkonpflanzen mit trichterfoermigen Blueten in unzaehligen Farben.,Volles Sonnenlicht,15-25 °C,2,easy|pet_friendly|flowering|sun,pet_friendly_requires_external_evidence,,,, +flowering,constants/lexiconBatch1.ts,69,Schmetterlingsorchidee,Phalaenopsis amabilis,Die Schmetterlingsorchidee ist die bekannteste Zimmerorchidee. Sie bluet bei guter Pflege monatelang.,Helles indirektes Licht,18-28 °C,10,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,165,Flammenblume,Phlox paniculata,"Flammenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,81,Fettkraut,Pinguicula grandiflora,"Das Fettkraut faengt Insekten mit klebrigen Blaettern. Es bluet mit violetten, sporenartigen Blueten.",Helles indirektes Licht,10-20 °C,5,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch1.ts,61,Bleiwurz,Plumbago auriculata,"Die Bleiwurz ist ein halbimmergruener Strauch mit himmelblauen Blueten, der fast das ganze Jahr bluet.",Volles Sonnenlicht,15-27 °C,5,flowering|bright_light|sun,,,,, +flowering,constants/lexiconBatch2.ts,118,Tempel-Baum,Plumeria rubra,"Der Tempel-Baum hat intensiv duftende, sternfoermige Blueten in Weiss, Gelb oder Rosa. Klassische Tropenblume.",Volles Sonnenlicht,20-30 °C,7,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch1.ts,36,Primel,Primula vulgaris,"Die Primel ist einer der ersten Fruehjahrs­boten mit lebhaften Blueten in Gelb, Pink, Rot und Lila.",Helles indirektes Licht,10-18 °C,4,flowering,,,,, +flowering,constants/lexiconBatch2.ts,71,Koenigs-Protea,Protea cynaroides,"Die Koenigs-Protea ist die Nationalblume Suedafrikas mit riesigen, imposanten Bluetenkoepfen. Eine echte Besonderheit.",Volles Sonnenlicht,10-25 °C,7,flowering|large|sun,,,,, +flowering,constants/lexiconBatch2.ts,88,Granatapfelbaum,Punica granatum,"Der Granatapfelbaum hat leuchtend rote Blueten und rote, essbare Fruechte mit rubinroten Kernen.",Volles Sonnenlicht,15-28 °C,7,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch2.ts,162,Ranunkel,Ranunculus asiaticus,"Ranunkel ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,170,Rhododendron,Rhododendron catawbiense,"Rhododendron ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|tree|bright_light,,,,, +flowering,constants/lexiconBatch1.ts,91,Japanische Azalee,Rhododendron simsii,"Die Japanische Azalee bluet im Winter und Fruehling ueppig mit leuchtend roten, rosa oder weissen Blueten.",Helles indirektes Licht,10-18 °C,4,flowering,,,,, +flowering,constants/lexiconBatch1.ts,66,Chinesische Rose,Rosa chinensis,Die Chinesische Rose ist eine der Stammarten vieler Gartenrosen und bluet fast ununterbrochen.,Volles Sonnenlicht,15-25 °C,5,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,142,Rose,Rosa x hybrida,"Rose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light|sun,,,,, +flowering,constants/lexiconBatch2.ts,167,Rudbeckie,Rudbeckia hirta,"Rudbeckie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,94,Afrikanisches Veilchen,Saintpaulia ionantha,"Das Afrikanische Veilchen ist eine kleine, kompakte Bluehpflanze mit samtigen Blaettern und violetten Blueten.",Helles indirektes Licht,18-25 °C,7,easy|flowering,,,,, +flowering,constants/lexiconBatch2.ts,195,Mehlsalbei,Salvia farinacea,"Mehlsalbei ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,168,Feuersalbei,Salvia splendens,"Feuersalbei ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,112,Schwarzer Holunder,Sambucus nigra,Der Schwarze Holunder hat weisse Doldenbluten und schwarze Beeren. Die Fruechte werden fuer Sirup und Saft verwendet.,Helles bis volles Licht,10-25 °C,7,flowering|tree|medicinal,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch1.ts,8,Weihnachtskaktus,Schlumbergera truncata,"Der Weihnachtskaktus erfreut zur Weihnachtszeit mit leuchtenden Blueten in Rosa, Rot oder Weiss.",Helles indirektes Licht,15-21 °C,7,easy|flowering|succulent,,,,, +flowering,constants/lexiconBatch2.ts,222,Spierstrauch,Spiraea japonica,Spierstrauch ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch2.ts,25,Aasblume,Stapelia grandiflora,"Die Aasblume hat fleischige, gruene Staengel und riesige, sternfoermige Blueten mit aasartigem Duft.",Helles bis volles Licht,18-30 °C,14,flowering|succulent|sun,,,,, +flowering,constants/lexiconBatch1.ts,60,Madagaskar-Jasmin,Stephanotis floribunda,"Der Madagaskar-Jasmin hat dicke, glaenzende Blaetter und wachsweisse, intensiv duftende Blueten. Klassische Hochzeitsblume.",Helles indirektes Licht,18-25 °C,7,flowering,,,,, +flowering,constants/lexiconBatch1.ts,3,Paradiesvogelblume,Strelitzia reginae,"Die Paradiesvogelblume beeindruckt mit leuchtend orangefarbenen und blauen Blueten, die einem Vogel aehneln.",Volles Sonnenlicht,18-26 °C,7,flowering|large|sun,,,,, +flowering,constants/lexiconBatch1.ts,95,Drehfrucht,Streptocarpus hybridus,"Die Drehfrucht ist ein Gesneriengewaechs mit langen, gerippten Blaettern und trichterfoermigen Blueten in Lila oder Rosa.",Helles indirektes Licht,15-22 °C,7,flowering,,,,, +flowering,constants/lexiconBatch2.ts,166,Herbstaster,Symphyotrichum novi-belgii,"Herbstaster ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,149,Flieder,Syringa vulgaris,"Flieder ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch2.ts,66,Studentenblume,Tagetes patula,Die Studentenblume ist eine robuste Sommerblume mit orangen oder gelben Blueten. Sie haelt Schadlinge fern.,Volles Sonnenlicht,15-28 °C,3,easy|flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,151,Kapuzinerkresse,Tropaeolum majus,"Kapuzinerkresse ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,107,Tulpe,Tulipa gesneriana,Die Tulpe ist eine der beliebtesten Fruehjahrsblueher mit kelchfoermigen Blueten in unzaehligen Farben.,Helles bis volles Licht,8-18 °C,5,easy|flowering,,,,, +flowering,constants/lexiconBatch2.ts,104,Baldrian,Valeriana officinalis,Baldrian ist ein bekanntes Heilkraut mit weissen bis roeslichen Blueten. Die Wurzeln werden zur Schlaffoerderung verwendet.,Helles bis volles Licht,15-25 °C,7,flowering|medicinal,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch1.ts,72,Vanda-Orchidee,Vanda coerulea,Die Vanda-Orchidee ist bekannt fuer ihre seltene blaue Bluetenfarbe. Epiphytische Orchidee mit grossen Blueten.,Helles bis volles Licht,20-30 °C,3,flowering|bright_light|high_humidity,,,,, +flowering,constants/lexiconBatch1.ts,76,Vanille,Vanilla planifolia,"Die Vanille ist eine kletternde Orchidee, aus deren Fruechten das beliebte Gewuerz gewonnen wird.",Helles indirektes Licht,20-30 °C,5,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,192,Koenigskerze,Verbascum thapsus,"Koenigskerze ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +flowering,constants/lexiconBatch2.ts,164,Eisenkraut,Verbena bonariensis,"Eisenkraut ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch2.ts,198,Hornveilchen,Viola cornuta,"Hornveilchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +flowering,constants/lexiconBatch1.ts,35,Stiefmuetterchen,Viola wittrockiana,Das Stiefmuetterchen ist ein bekannter Fruehjahrsblueher mit charakteristisch gezeichneten Blueten.,Helles bis volles Licht,5-18 °C,3,easy|flowering,,,,, +flowering,constants/lexiconBatch2.ts,35,Flammen-Bromelie,Vriesea splendens,"Die Flammen-Bromelie hat gebänderte, dunkelgruene Blaetter und einen spektakulaeren, roten Bluetenstand.",Helles indirektes Licht,18-25 °C,7,flowering|patterned|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,221,Weigelie,Weigela florida,Weigelie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +flowering,constants/lexiconBatch1.ts,65,Chinesischer Blauregen,Wisteria sinensis,"Der Chinesische Blauregen ist ein ueppiger Kletterkuenstler mit langen, duftenden Bluetentrauben in Lila.",Volles Sonnenlicht,10-25 °C,7,flowering|large|sun,,,,, +flowering,constants/lexiconBatch2.ts,70,Calla,Zantedeschia aethiopica,"Die Calla hat elegante, trichterfoermige weisse Hochblaetter und glaenzende, herzfoermige Blaetter. Sehr edel.",Helles indirektes Licht,15-24 °C,7,flowering|high_humidity,,,,, +flowering,constants/lexiconBatch2.ts,65,Zinnie,Zinnia elegans,"Die Zinnie ist eine leuchtende Sommerblume mit grossen, dahlienaehnlichen Blueten. Sehr robust und hitzetolerant.",Volles Sonnenlicht,18-30 °C,3,easy|flowering|sun,,,,, +hanging,constants/lexiconBatch1.ts,98,Lippenstiftpflanze,Aeschynanthus radicans,Die Lippenstiftpflanze hat haengende Triebe mit glaenzenden Blaettern und leuchtend roten Roehrenbluten.,Helles indirektes Licht,18-27 °C,7,flowering|hanging|high_humidity,,,,, +hanging,constants/lexiconBatch2.ts,63,Calibrachoa,Calibrachoa hybrida,"Calibrachoa ist eine petunienaehnliche Haengepflanze mit unzaehligen, kleinen Trichterbluten in allen Farben.",Volles Sonnenlicht,15-25 °C,2,easy|flowering|hanging|sun,,,,, +hanging,constants/lexiconBatch2.ts,56,Callisia,Callisia repens,"Callisia repens ist ein kleines, kriechendes Kraut mit winzigen, gruenen Blaettern. Ideal fuer haengende Behaelter.",Helles indirektes Licht,15-25 °C,5,easy|hanging,,,,, +hanging,constants/lexiconBatch1.ts,99,Herzkette,Ceropegia woodii,"Die Herzkette hat duenne, haengende Ranken mit herzfoermigen, silbergrau gemusterten Blaettchen.",Helles indirektes Licht,15-27 °C,14,easy|succulent|patterned|hanging,,,,, +hanging,constants/lexiconBatch1.ts,97,Columnea,Columnea gloriosa,"Die Columnea ist eine haengende Zimmerpflanze mit kleinen, behaarten Blaettern und leuchtend roten, roehrenfoermigen Blueten.",Helles indirektes Licht,18-25 °C,7,flowering|hanging|high_humidity,,,,, +hanging,constants/lexiconBatch2.ts,236,String of Bananas,Curio radicans,String of Bananas ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,succulent|hanging|sun,,,,, +hanging,constants/lexiconBatch2.ts,237,String of Dolphins,Curio x peregrinus,String of Dolphins ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,succulent|hanging|sun,,,,, +hanging,constants/lexiconBatch1.ts,101,Dischidia,Dischidia ruscifolia,"Die Dischidia ist eine epiphytische Haengepflanze mit kleinen, runden Blaettern entlang duenner Ranken.",Helles indirektes Licht,18-27 °C,7,succulent|hanging,,,,, +hanging,constants/lexiconBatch1.ts,16,Marmor-Efeutute,Epipremnum aureum Marble Queen,Die Marmor-Efeutute hat cremeweiss-gruen marmorierte Blaetter. Eine dekorative Variante der klassischen Efeutute.,Helles indirektes Licht,15-30 °C,7,easy|hanging|air_purifier,air_purifier_requires_external_evidence,,,, +hanging,constants/lexiconBatch2.ts,53,Neon-Efeutute,Epipremnum pinnatum Neon,Die Neon-Efeutute hat leuchtend limonengruene Blaetter. Sehr auffaellig und pflegeleicht.,Helles indirektes Licht,15-30 °C,7,easy|hanging|air_purifier,air_purifier_requires_external_evidence,,,, +hanging,constants/lexiconBatch1.ts,33,Fuchsie,Fuchsia hybrida,"Die Fuchsie haengt mit eleganten, zweifarbigen Blueten wie kleine Ohrringe herab. Ideal fuer Ampeln.",Helles indirektes Licht,14-22 °C,3,flowering|hanging,,,,, +hanging,constants/lexiconBatch2.ts,60,Triphylla-Fuchsie,Fuchsia triphylla,"Die Triphylla-Fuchsie hat lange, roehrenfoermige, orangefarbe Blueten in haengenden Trauben. Sehr exotisch.",Helles indirektes Licht,15-22 °C,3,flowering|hanging,,,,, +hanging,constants/lexiconBatch1.ts,37,Efeu,Hedera helix,"Efeu ist eine robuste Kletter- und Haengepflanze mit charakteristischen, dreilappigen Blaettern. Sehr langlebig.",Wenig bis helles Licht,10-20 °C,7,easy|hanging|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +hanging,constants/lexiconBatch1.ts,58,Kleine Wachsblume,Hoya bella,"Die Kleine Wachsblume traegt zierliche, sternfoermige weisse Blueten mit rosa Mitte. Haengende Sukkulente.",Helles indirektes Licht,18-27 °C,10,flowering|succulent|hanging,,,,, +hanging,constants/lexiconBatch1.ts,57,Wachsblume,Hoya carnosa,"Die Wachsblume ist eine Kletterpflanze mit dicken, wachsartigen Blaettern und sternfoermigen, duftenden Blueten.",Helles indirektes Licht,16-27 °C,10,easy|flowering|succulent|hanging,,,,, +hanging,constants/lexiconBatch1.ts,64,Suesskartoffel,Ipomoea batatas,"Die Suesskartoffel-Zierpflanze hat dekorative, herzfoermige Blaetter in gruen oder dunkelviolett. Ideal als Haengepflanze.",Volles Sonnenlicht,20-30 °C,5,easy|hanging|sun,,,,, +hanging,constants/lexiconBatch2.ts,47,Monstera adansonii,Monstera adansonii,Monstera adansonii hat herzfoermige Blaetter mit zahlreichen runden Lochern. Eine rankende Zimmerpflanze.,Helles indirektes Licht,18-27 °C,7,easy|hanging,,,,, +hanging,constants/lexiconBatch2.ts,48,Monstera obliqua,Monstera obliqua,"Monstera obliqua ist eine seltene Monstera-Art mit filigranen Blaettern, die hauptsaechlich aus Lochern bestehen.",Helles indirektes Licht,18-27 °C,7,patterned|hanging,,,,, +hanging,constants/lexiconBatch2.ts,79,Kannenpflanze,Nepenthes alata,"Die Kannenpflanze bildet grosse, gefuellte Kannen als Insekten­fallen. Eine faszinierende, tropische Pflanze.",Helles indirektes Licht,20-30 °C,5,hanging|high_humidity,,,,, +hanging,constants/lexiconBatch2.ts,61,Efeu-Geranie,Pelargonium peltatum,"Die Efeu-Geranie hat efeufoermige, glaenzende Blaetter und bluet den ganzen Sommer in leuchtenden Farben.",Helles bis volles Licht,15-25 °C,5,easy|flowering|hanging|sun,,,,, +hanging,constants/lexiconBatch2.ts,51,Roter Philodendron,Philodendron erubescens,"Der Rote Philodendron hat glaenzende, herzfoermige Blaetter, die jung roetrlich erscheinen. Sehr dekorativ.",Helles indirektes Licht,18-27 °C,7,easy|hanging,,,,, +hanging,constants/lexiconBatch1.ts,15,Herzblatt-Philodendron,Philodendron hederaceum,Der Herzblatt-Philodendron ist eine pflegeleichte Kletter- oder Haengepflanze mit herzfoermigen Blaettern.,Indirektes Licht,18-28 °C,7,easy|hanging|low_light,,,,, +hanging,constants/lexiconBatch2.ts,242,Philodendron Brasil,Philodendron hederaceum Brasil,Philodendron Brasil ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|hanging|low_light,,,,, +hanging,constants/lexiconBatch2.ts,41,Geweihfarn,Platycerium bifurcatum,"Der Geweihfarn hat gespaltene Wedel, die einem Hirschgeweih aehneln. Er ist ein epiphytischer Farn fuer Holz.",Helles indirektes Licht,15-25 °C,7,hanging|high_humidity,,,,, +hanging,constants/lexiconBatch2.ts,52,Mini-Monstera,Rhaphidophora tetrasperma,"Die Mini-Monstera hat monstera­aehnliche, gelochte Blaetter auf einer kompakten, klettternden Pflanze. Sehr trendig.",Helles indirektes Licht,18-27 °C,7,easy|hanging,,,,, +hanging,constants/lexiconBatch1.ts,85,Korallenkaktus,Rhipsalis baccifera,"Der Korallenkaktus ist ein epiphytischer Kaktus mit duennen, haengenden Trieben und kleinen weissen Beeren.",Indirektes Licht,18-27 °C,7,succulent|hanging,,,,, +hanging,constants/lexiconBatch1.ts,55,Satinpothos,Scindapsus pictus,"Der Satinpothos hat samtig-glaenzende, silbrig gefleckte Blaetter auf langen, haengenden Ranken.",Helles indirektes Licht,18-28 °C,7,easy|patterned|hanging,,,,, +hanging,constants/lexiconBatch1.ts,7,Eselschwanz,Sedum morganianum,"Der Eselschwanz ist eine haengende Sukkulente mit langen Trieben aus dichten, blaugruenen Blaettchen.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|hanging|sun,,,,, +hanging,constants/lexiconBatch1.ts,100,Perlenschnur-Pflanze,Senecio rowleyanus,"Die Perlenschnur-Pflanze hat haengende Ranken mit kugelfoermigen, perlenaehnlichen Blaettern. Einzigartige Sukkulente.",Helles bis volles Licht,15-27 °C,14,easy|succulent|hanging,,,,, +hanging,constants/lexiconBatch1.ts,56,Pfeilblatt,Syngonium podophyllum,"Das Pfeilblatt hat charakteristisch pfeilfoermige Blaetter, die sich mit dem Alter weiterentwickeln.",Helles indirektes Licht,16-27 °C,7,easy|hanging,,,,, +hanging,constants/lexiconBatch2.ts,32,Spanisches Moos,Tillandsia usneoides,"Das Spanische Moos ist eine epiphytische Bromelie ohne Wurzeln, die in der Luft haengt. Es benoetigt nur Feuchtigkeitsbespruehing.",Helles bis volles Licht,15-30 °C,3,easy|hanging,,,,, +hanging,constants/lexiconBatch2.ts,55,Weisse Tradescantia,Tradescantia fluminensis,Die Weisse Tradescantia hat gruene Blaetter mit weisslichen Unterseiten. Sehr robust und schnellwachsend.,Helles indirektes Licht,15-25 °C,5,easy|hanging,,,,, +hanging,constants/lexiconBatch2.ts,54,Lila Tradescantia,Tradescantia pallida,Die Lila Tradescantia hat leuchtend purpurrote Blaetter und ist sehr auffaellig. Sie liebt viel Licht.,Helles bis volles Licht,15-25 °C,5,easy|hanging|sun,,,,, +hanging,constants/lexiconBatch1.ts,17,Zebrakraut,Tradescantia zebrina,Das Zebrakraut faellt durch seine silbrig-lila gestreiften Blaetter auf. Schnellwachsende Haengepflanze.,Helles indirektes Licht,15-25 °C,5,easy|patterned|hanging,,,,, +high_humidity,constants/lexiconBatch2.ts,42,Frauenhaarfarn,Adiantum raddianum,"Der Frauenhaarfarn hat zarte, feingliedrige Wedel auf schwarzen, draht­aehnlichen Stielen. Liebt Feuchtigkeit.",Helles indirektes Licht,18-27 °C,3,high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,98,Lippenstiftpflanze,Aeschynanthus radicans,Die Lippenstiftpflanze hat haengende Triebe mit glaenzenden Blaettern und leuchtend roten Roehrenbluten.,Helles indirektes Licht,18-27 °C,7,flowering|hanging|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,46,Amazona-Taro,Alocasia amazonica,"Der Amazona-Taro besticht mit dunkelgruenen, pfeilfoermigen Blaettern mit markant weissen Rippen.",Indirektes Licht,18-27 °C,5,patterned|large|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,225,Alocasia zebrina,Alocasia zebrina,Alocasia zebrina ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,bright_light|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,73,Muschelingwer,Alpinia zerumbet,"Der Muschelingwer hat lange, elegante Blaetter und haengende Bluetenrispen mit weiss-rosa Bluetchen.",Helles bis volles Licht,20-30 °C,5,flowering|large|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,233,Samt-Anthurie,Anthurium clarinervium,Samt-Anthurie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,234,Kristall-Anthurie,Anthurium crystallinum,Kristall-Anthurie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,43,Vogelnest-Farn,Asplenium nidus,"Der Vogelnest-Farn hat ganzrandige, glaenzende Wedel, die eine Nestform bilden. Sehr dekorativ und robust.",Helles indirektes Licht,18-27 °C,5,easy|low_light|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,57,Forellen-Begonie,Begonia maculata,Die Forellen-Begonie hat olivgruene Blaetter mit silbernen Punkten und einer roten Unterseite. Atemberaubend.,Helles indirektes Licht,18-27 °C,7,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,18,Koenigsbegonie,Begonia rex,"Die Koenigsbegonie beeindruckt mit prachtvoll gemusterten Blaettern in Silber, Rot und Gruen.",Indirektes Licht,18-25 °C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,58,Knollen-Begonie,Begonia tuberhybrida,"Die Knollen-Begonie hat riesige, rosenaehnliche Blueten in leuchtendem Rot, Orange, Gelb oder Weiss.",Helles indirektes Licht,15-22 °C,5,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,49,Buntblatt,Caladium bicolor,"Das Buntblatt beeindruckt mit transparenten, bunt gemusterten Blaettern in Pink, Rot, Weiss und Gruen.",Indirektes Licht,20-30 °C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,73,Cattleya-Orchidee,Cattleya labiata,"Die Cattleya ist die Koenigin der Orchideen mit ueppigen, duftenden Blueten in Lila, Rosa und Weiss.",Helles indirektes Licht,18-28 °C,7,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,47,Taro,Colocasia esculenta,"Der Taro ist eine tropische Pflanze mit grossen, herzfoermigen Blaettern. Die Knollen sind Nahrungsquelle.",Helles indirektes Licht,18-30 °C,3,large|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,97,Columnea,Columnea gloriosa,"Die Columnea ist eine haengende Zimmerpflanze mit kleinen, behaarten Blaettern und leuchtend roten, roehrenfoermigen Blueten.",Helles indirektes Licht,18-25 °C,7,flowering|hanging|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,39,Cryptanthus,Cryptanthus bivittatus,Cryptanthus ist eine niedrig wachsende Bromelie mit sternfoermigen Rosetten und gemusterten Blaettern. Fuer Terrarien.,Helles indirektes Licht,18-27 °C,7,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,53,Ctenanthe,Ctenanthe burle-marxii,Die Ctenanthe hat faszinierend gemusterte Blaetter mit dunkelgruunem Fischgraetenmuster auf hellgruunem Hintergrund.,Indirektes Licht,18-25 °C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,74,Kurkuma,Curcuma longa,Kurkuma ist eine tropische Gewuerzpflanze mit breiten Blaettern und leuchtend gelber Wurzel. Wichtiges Heilgewuerz.,Helles bis volles Licht,20-30 °C,7,medicinal|high_humidity,medicinal_requires_external_evidence,,,, +high_humidity,constants/lexiconBatch2.ts,9,Paragraphenpflanze,Cyperus alternifolius,"Die Paragraphenpflanze hat lange, grasartige Blaetter, die sternfoermig vom Stiel abstehen. Sie liebt viel Wasser.",Helles bis volles Licht,18-27 °C,3,high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,70,Dendrobium,Dendrobium nobile,"Das Dendrobium ist eine beliebte Zimmerorchidee mit langen Pseudobulben, die im Winter mit Blueten besetzt werden.",Helles indirektes Licht,15-28 °C,10,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,80,Sonnentau,Drosera capensis,Der Sonnentau faengt Insekten mit klebrigen Tropfen auf seinen Blaettern. Eine faszinierende fleischfressende Pflanze.,Volles Sonnenlicht,15-25 °C,5,high_humidity|sun,,,,, +high_humidity,constants/lexiconBatch2.ts,137,Wasabi,Eutrema japonicum,"Wasabi ist ein seltenes Wuerzkraut, das gleichmaessige Feuchte und eher kuehle Bedingungen bevorzugt.",Helles indirektes Licht,8-20 C,4,bright_light|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,226,Nervenpflanze,Fittonia albivenis,Nervenpflanze ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,22,Gardenie,Gardenia jasminoides,"Die Gardenie fasziniert mit cremefarbenen, intensiv duftenden Blueten. Anspruchsvoll in der Pflege.",Helles indirektes Licht,18-23 °C,5,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,96,Gloxinie,Gloxinia speciosa,"Die Gloxinie hat grosse, samtartige Blueten in Violett, Rosa oder Weiss mit farbigen Raendern.",Helles indirektes Licht,18-25 °C,5,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,240,Calathea lancifolia,Goeppertia insignis,Calathea lancifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +high_humidity,constants/lexiconBatch2.ts,241,Calathea ornata,Goeppertia ornata,Calathea ornata ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +high_humidity,constants/lexiconBatch2.ts,36,Guzmania,Guzmania lingulata,"Die Guzmania ist eine Bromelie mit glänzenden, gruenen Blaettern und einem leuchtend roten, sternfoermigen Bluetenstand.",Helles indirektes Licht,18-27 °C,7,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,83,Heliamphora,Heliamphora nutans,Heliamphora ist eine urtuemliche Kannenpflanze aus den Tafelbergen Venezuelas. Sehr dekorativ und selten.,Helles indirektes Licht,15-25 °C,5,high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,72,Heliconia,Heliconia psittacorum,"Die Heliconia hat leuchtend orangefarbe oder rote, bootsfoermige Hochblaetter. Eine exotische Tropenpflanze.",Helles bis volles Licht,20-30 °C,5,flowering|bright_light|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,51,Gebet-Pflanze,Maranta leuconeura,Die Gebet-Pflanze faltet ihre gemusterten Blaetter nachts wie Haende zusammen. Faszinierende rote und gruene Muster.,Indirektes Licht,18-27 °C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +high_humidity,constants/lexiconBatch2.ts,46,Tueipelfarn (Microsorum),Microsorum punctatum,"Microsorum punctatum ist ein tropischer Farn mit langen, ungeteilten, glaenzenden Wedeln. Fuer feuchte Standorte.",Helles indirektes Licht,18-27 °C,7,high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,75,Stiefmuetterchen-Orchidee,Miltoniopsis roezlii,"Die Stiefmuetterchen-Orchidee hat grosse, flache Blueten. Bevorzugt kuehle Temperaturen und hohe Luftfeuchtigkeit.",Indirektes Licht,15-22 °C,5,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,2,Bananenpflanze,Musa acuminata,"Die Bananenpflanze ist eine tropische Staude mit riesigen, glaenzenden Blaettern. Im Zimmer selten fruechttragend.",Helles bis volles Licht,20-30 °C,5,large|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,79,Kannenpflanze,Nepenthes alata,"Die Kannenpflanze bildet grosse, gefuellte Kannen als Insekten­fallen. Eine faszinierende, tropische Pflanze.",Helles indirektes Licht,20-30 °C,5,hanging|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,74,Tanzerinnen-Orchidee,Oncidium sphacelatum,"Die Tanzerinnen-Orchidee traegt lange Rispen mit Hunderten kleiner, gelb-brauner Blueten. Sehr reichliche Bluetracht.",Helles indirektes Licht,18-27 °C,7,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,69,Schmetterlingsorchidee,Phalaenopsis amabilis,Die Schmetterlingsorchidee ist die bekannteste Zimmerorchidee. Sie bluet bei guter Pflege monatelang.,Helles indirektes Licht,18-28 °C,10,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,49,Philodendron gloriosum,Philodendron gloriosum,"Philodendron gloriosum hat grosse, samtige, herzfoermige Blaetter mit weissen Rippen. Eine atemberaubende Pflanze.",Helles indirektes Licht,18-27 °C,7,patterned|large|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,40,Blaues Kanaelfarn,Phlebodium aureum,"Der Blaue Kanaelfarn hat wachsartige, blaugruene Wedel und glaenzende Wurzelstaemme. Sehr dekorativ.",Helles indirektes Licht,18-27 °C,7,high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,81,Fettkraut,Pinguicula grandiflora,"Das Fettkraut faengt Insekten mit klebrigen Blaettern. Es bluet mit violetten, sporenartigen Blueten.",Helles indirektes Licht,10-20 °C,5,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,41,Geweihfarn,Platycerium bifurcatum,"Der Geweihfarn hat gespaltene Wedel, die einem Hirschgeweih aehneln. Er ist ein epiphytischer Farn fuer Holz.",Helles indirektes Licht,15-25 °C,7,hanging|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,78,Purpursonnentau,Sarracenia purpurea,Der Purpursonnentau ist eine fleischfressende Kannenpflanze mit purpurroten Kannen. Faengt Insekten.,Volles Sonnenlicht,5-25 °C,3,high_humidity|sun,,,,, +high_humidity,constants/lexiconBatch2.ts,45,Regenbogenmoos,Selaginella uncinata,"Das Regenbogenmoos hat schuppenfoermige Blaetter, die im Licht schillernd irisieren. Dekorativ fuer Terrarien.",Helles indirektes Licht,18-27 °C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,238,Bubikopf,Soleirolia soleirolii,Bubikopf ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,15-24 C,4,pet_friendly|high_humidity,pet_friendly_requires_external_evidence,,,, +high_humidity,constants/lexiconBatch1.ts,52,Stromanthe,Stromanthe sanguinea,Die Stromanthe hat dekorative Blaetter mit weissem Muster und leuchtend roter Unterseite. Familie der Marantaceen.,Helles indirektes Licht,18-25 °C,5,patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,82,Wasserschlauch,Utricularia gibba,Der Wasserschlauch ist eine wasserbewohnende fleischfressende Pflanze mit Schlaeuchen als Insekten­fallen.,Helles bis volles Licht,15-25 °C,2,high_humidity|sun,,,,, +high_humidity,constants/lexiconBatch1.ts,72,Vanda-Orchidee,Vanda coerulea,Die Vanda-Orchidee ist bekannt fuer ihre seltene blaue Bluetenfarbe. Epiphytische Orchidee mit grossen Blueten.,Helles bis volles Licht,20-30 °C,3,flowering|bright_light|high_humidity,,,,, +high_humidity,constants/lexiconBatch1.ts,76,Vanille,Vanilla planifolia,"Die Vanille ist eine kletternde Orchidee, aus deren Fruechten das beliebte Gewuerz gewonnen wird.",Helles indirektes Licht,20-30 °C,5,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,35,Flammen-Bromelie,Vriesea splendens,"Die Flammen-Bromelie hat gebänderte, dunkelgruene Blaetter und einen spektakulaeren, roten Bluetenstand.",Helles indirektes Licht,18-25 °C,7,flowering|patterned|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,70,Calla,Zantedeschia aethiopica,"Die Calla hat elegante, trichterfoermige weisse Hochblaetter und glaenzende, herzfoermige Blaetter. Sehr edel.",Helles indirektes Licht,15-24 °C,7,flowering|high_humidity,,,,, +high_humidity,constants/lexiconBatch2.ts,75,Ingwer,Zingiber officinale,Ingwer ist eine tropische Gewuerzpflanze mit aromatischen Knollen. Die Blaetter sind schilfartig.,Helles indirektes Licht,20-30 °C,5,medicinal|high_humidity,medicinal_requires_external_evidence,,,, +large,constants/lexiconBatch2.ts,212,Spitzahorn,Acer platanoides,Spitzahorn ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch1.ts,11,Agave,Agave americana,"Die Agave ist eine imposante Sukkulente mit steifen, blaugruenen Blaettern mit Stacheln. Sie bluet nur einmal.",Volles Sonnenlicht,10-35 °C,21,succulent|large|sun,,,,, +large,constants/lexiconBatch1.ts,46,Amazona-Taro,Alocasia amazonica,"Der Amazona-Taro besticht mit dunkelgruenen, pfeilfoermigen Blaettern mit markant weissen Rippen.",Indirektes Licht,18-27 °C,5,patterned|large|high_humidity,,,,, +large,constants/lexiconBatch2.ts,18,Kap-Aloe (ferox),Aloe ferox,"Aloe ferox ist eine grosse, imposante Aloe mit stachligen, blaugruenen Blaettern und leuchtend roten Bluetenaehren.",Volles Sonnenlicht,10-30 °C,14,succulent|large|medicinal|sun,medicinal_requires_external_evidence,,,, +large,constants/lexiconBatch2.ts,73,Muschelingwer,Alpinia zerumbet,"Der Muschelingwer hat lange, elegante Blaetter und haengende Bluetenrispen mit weiss-rosa Bluetchen.",Helles bis volles Licht,20-30 °C,5,flowering|large|high_humidity,,,,, +large,constants/lexiconBatch2.ts,7,Bambusrohr,Bambusa vulgaris,Das Bambusrohr ist eine schnell wachsende Bambusart mit gelbgruenen Halmen. Sehr dekorativ und vielseitig nutzbar.,Helles bis volles Licht,15-30 °C,5,easy|large,,,,, +large,constants/lexiconBatch2.ts,114,Hange-Birke,Betula pendula,Die Haenge-Birke hat charakteristisch weisse Rinde und haengende Zweige. Die Blaetter werden in der Heilkunde genutzt.,Volles Sonnenlicht,10-25 °C,7,tree|large|medicinal,medicinal_requires_external_evidence,,,, +large,constants/lexiconBatch2.ts,67,Blumenschilfrohr,Canna indica,"Das Blumenschilfrohr hat grosse, tropisch wirkende Blaetter und auffaellige Blueten in Rot, Orange oder Gelb.",Volles Sonnenlicht,18-28 °C,5,flowering|large|sun,,,,, +large,constants/lexiconBatch2.ts,90,Papaya,Carica papaya,"Die Papaya ist eine tropische Fruchtpflanze mit grossen, gelappten Blaettern und orangen Fruechten.",Volles Sonnenlicht,20-35 °C,5,large|sun,,,,, +large,constants/lexiconBatch2.ts,217,Trompetenbaum,Catalpa bignonioides,Trompetenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,208,Zeder,Cedrus libani,Zeder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch1.ts,81,Peruanischer Fackelkaktus,Cereus peruvianus,"Der Peruanische Fackelkaktus ist ein saeulenfoermiger Kaktus, der im Innenraum bis zu 2 m hoch werden kann.",Volles Sonnenlicht,15-35 °C,21,easy|succulent|large|sun,,,,, +large,constants/lexiconBatch1.ts,47,Taro,Colocasia esculenta,"Der Taro ist eine tropische Pflanze mit grossen, herzfoermigen Blaettern. Die Knollen sind Nahrungsquelle.",Helles indirektes Licht,18-30 °C,3,large|high_humidity,,,,, +large,constants/lexiconBatch2.ts,209,Zypresse,Cupressus sempervirens,Zypresse ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,239,Palmfarn,Cycas revoluta,Palmfarn ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,215,Flammenbaum,Delonix regia,Flammenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +large,constants/lexiconBatch1.ts,39,Geigenfeige,Ficus lyrata,"Die Geigenfeige ist ein Trendbaum mit grossen, geigenfoermigen Blaettern. Benoetigt viel Licht.",Helles indirektes Licht,18-27 °C,7,tree|large|bright_light,,,,, +large,constants/lexiconBatch2.ts,211,Jacaranda,Jacaranda mimosifolia,Jacaranda ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +large,constants/lexiconBatch2.ts,204,Magnolie,Magnolia grandiflora,Magnolie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +large,constants/lexiconBatch2.ts,2,Bananenpflanze,Musa acuminata,"Die Bananenpflanze ist eine tropische Staude mit riesigen, glaenzenden Blaettern. Im Zimmer selten fruechttragend.",Helles bis volles Licht,20-30 °C,5,large|high_humidity,,,,, +large,constants/lexiconBatch2.ts,50,Philodendron bipinnatifidum,Philodendron bipinnatifidum,"Philodendron bipinnatifidum hat grosse, tief gelappte Blaetter. Er entwickelt einen beeindruckenden, baumfoermigen Wuchs.",Helles indirektes Licht,18-27 °C,7,easy|large,,,,, +large,constants/lexiconBatch2.ts,49,Philodendron gloriosum,Philodendron gloriosum,"Philodendron gloriosum hat grosse, samtige, herzfoermige Blaetter mit weissen Rippen. Eine atemberaubende Pflanze.",Helles indirektes Licht,18-27 °C,7,patterned|large|high_humidity,,,,, +large,constants/lexiconBatch2.ts,8,Goldener Bambus,Phyllostachys aurea,"Der Goldene Bambus hat elegante, goldgelbe Halme mit engstehenden Knoten. Sehr dekorativ als Sichtschutz.",Helles bis volles Licht,10-30 °C,5,easy|large,,,,, +large,constants/lexiconBatch2.ts,207,Fichte,Picea abies,Fichte ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,206,Kiefer,Pinus sylvestris,Kiefer ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,71,Koenigs-Protea,Protea cynaroides,"Die Koenigs-Protea ist die Nationalblume Suedafrikas mit riesigen, imposanten Bluetenkoepfen. Eine echte Besonderheit.",Volles Sonnenlicht,10-25 °C,7,flowering|large|sun,,,,, +large,constants/lexiconBatch2.ts,205,Eiche,Quercus robur,Eiche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,214,Robinie,Robinia pseudoacacia,Robinie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,113,Silber-Weide,Salix alba,"Die Silber-Weide hat silbrig-glaenzende Blaetter. Weidenrinde enthält Salicylsaeure, die Grundlage von Aspirin.",Helles bis volles Licht,10-25 °C,7,tree|large|medicinal,medicinal_requires_external_evidence,,,, +large,constants/lexiconBatch2.ts,11,Grosse Strahlenaralie,Schefflera actinophylla,"Die Grosse Strahlenaralie kann grosse, handfoermige Blaetter entwickeln. Sie ist ideal als Zimmerstrauch.",Helles indirektes Licht,18-27 °C,7,easy|tree|large,,,,, +large,constants/lexiconBatch2.ts,213,Eberesche,Sorbus aucuparia,Eberesche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +large,constants/lexiconBatch2.ts,1,Weisse Strelitzie,Strelitzia nicolai,"Die Weisse Strelitzie ist ein beeindruckender Zimmerstrauch mit grossen, blaugruenen Blaettern und weiss-blauen Blueten.",Helles bis volles Licht,18-27 °C,7,tree|large|bright_light,,,,, +large,constants/lexiconBatch1.ts,3,Paradiesvogelblume,Strelitzia reginae,"Die Paradiesvogelblume beeindruckt mit leuchtend orangefarbenen und blauen Blueten, die einem Vogel aehneln.",Volles Sonnenlicht,18-26 °C,7,flowering|large|sun,,,,, +large,constants/lexiconBatch2.ts,5,Mexikanische Fächerpalme,Washingtonia robusta,"Die Mexikanische Fächerpalme ist eine schlanke, hohe Palme mit faecher­foermigen Blaettern. Sehr hitzetolerant.",Volles Sonnenlicht,15-35 °C,10,tree|large|sun,,,,, +large,constants/lexiconBatch1.ts,65,Chinesischer Blauregen,Wisteria sinensis,"Der Chinesische Blauregen ist ein ueppiger Kletterkuenstler mit langen, duftenden Bluetentrauben in Lila.",Volles Sonnenlicht,10-25 °C,7,flowering|large|sun,,,,, +low_light,constants/lexiconBatch1.ts,50,Aglaoneme,Aglaonema commutatum,Die Aglaoneme ist eine dekorative Zimmerpflanze mit silbrig-gruen gemusterten Blaettern. Tolerant gegenueber wenig Licht.,Wenig bis helles Licht,15-26 °C,7,easy|patterned|low_light,,,,, +low_light,constants/lexiconBatch2.ts,16,Schusterpflanze,Aspidistra elatior,"Die Schusterpflanze ist eine extrem robuste Zimmerpflanze mit langen, dunkelgruenen Blaettern. Vertraegt tiefe Temperaturen.",Wenig bis helles Licht,10-20 °C,14,easy|low_light,,,,, +low_light,constants/lexiconBatch2.ts,43,Vogelnest-Farn,Asplenium nidus,"Der Vogelnest-Farn hat ganzrandige, glaenzende Wedel, die eine Nestform bilden. Sehr dekorativ und robust.",Helles indirektes Licht,18-27 °C,5,easy|low_light|high_humidity,,,,, +low_light,constants/lexiconBatch2.ts,13,Japanische Aucube,Aucuba japonica,"Die Japanische Aucube hat glaenzende, gruene oder gelbgefleckte Blaetter. Sehr schattenvertraeglich.",Wenig bis helles Licht,10-20 °C,7,easy|low_light,,,,, +low_light,constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,Die Bergpalme ist eine kompakte Zimmerpalme fuer schattigere Standorte. Ideal fuer dunkle Innenraeume.,Wenig bis helles Licht,15-25 °C,7,easy|pet_friendly|tree|air_purifier|low_light,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +low_light,constants/lexiconBatch1.ts,48,Dieffenbachie,Dieffenbachia seguine,"Die Dieffenbachie ist eine tropische Blattschmuckpflanze mit grossen, gruen-weiss gefleckten Blaettern.",Helles indirektes Licht,18-26 °C,7,easy|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +low_light,constants/lexiconBatch1.ts,14,Maisstrauch,Dracaena fragrans,"Der Maisstrauch ist eine robuste Zimmerpflanze mit breiten, gestreiften Blaettern. Gedeiht auch bei wenig Licht.",Helles indirektes Licht,15-25 °C,10,easy|tree|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +low_light,constants/lexiconBatch2.ts,12,Fatsia,Fatsia japonica,"Die Fatsia ist ein dekorativer Zimmerstrauch mit grossen, handfoermigen, glaenzenden Blaettern. Sehr robust.",Helles indirektes Licht,10-20 °C,7,easy|low_light,,,,, +low_light,constants/lexiconBatch1.ts,90,Gasteria,Gasteria carinata,"Die Gasteria ist eine kleine Sukkulente mit zweireihig angeordneten, zungenfoermigen, gefleckten Blaettern.",Helles indirektes Licht,15-25 °C,14,easy|succulent|low_light,,,,, +low_light,constants/lexiconBatch1.ts,6,Zebra-Haworthie,Haworthia fasciata,Die Zebra-Haworthie ist eine kompakte Sukkulente mit weissen Querstreifen auf dunkelgruenen Blaettern.,Helles indirektes Licht,15-25 °C,14,easy|succulent|low_light,,,,, +low_light,constants/lexiconBatch1.ts,37,Efeu,Hedera helix,"Efeu ist eine robuste Kletter- und Haengepflanze mit charakteristischen, dreilappigen Blaettern. Sehr langlebig.",Wenig bis helles Licht,10-20 °C,7,easy|hanging|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +low_light,constants/lexiconBatch2.ts,3,Kentia-Palme,Howea forsteriana,"Die Kentia-Palme ist eine der elegantesten Zimmerpalmen mit langen, herabhängenden Fiederblaettern.",Helles indirektes Licht,18-25 °C,7,pet_friendly|tree|low_light,pet_friendly_requires_external_evidence,,,, +low_light,constants/lexiconBatch1.ts,103,Spiegelpeperomie,Peperomia obtusifolia,"Die Spiegelpeperomie hat glaenzende, lederartige, oval-runde Blaetter in tiefem Gruen. Sehr robust.",Helles indirektes Licht,16-26 °C,10,easy|pet_friendly|low_light,pet_friendly_requires_external_evidence,,,, +low_light,constants/lexiconBatch1.ts,15,Herzblatt-Philodendron,Philodendron hederaceum,Der Herzblatt-Philodendron ist eine pflegeleichte Kletter- oder Haengepflanze mit herzfoermigen Blaettern.,Indirektes Licht,18-28 °C,7,easy|hanging|low_light,,,,, +low_light,constants/lexiconBatch2.ts,242,Philodendron Brasil,Philodendron hederaceum Brasil,Philodendron Brasil ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|hanging|low_light,,,,, +low_light,constants/lexiconBatch1.ts,45,Stab-Palme,Rhapis excelsa,"Die Stab-Palme ist eine elegante Zimmerpalme mit faecher­foermigen Blaettern auf duennen, bambusartigen Staemmen.",Helles indirektes Licht,15-25 °C,7,tree|low_light,,,,, +medicinal,constants/lexiconBatch2.ts,108,Schafgarbe,Achillea millefolium,Die Schafgarbe hat weisse oder rosafarbene Bluetenschirme und fein gefiederte Blaetter. Wichtige Heilpflanze.,Volles Sonnenlicht,10-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch1.ts,89,Kap-Aloe,Aloe arborescens,"Die Kap-Aloe ist eine strauchige Aloe mit schmalen, gezaehnten Blaettern und leuchtend roten Bluetenaehren im Winter.",Volles Sonnenlicht,10-30 °C,14,easy|succulent|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,18,Kap-Aloe (ferox),Aloe ferox,"Aloe ferox ist eine grosse, imposante Aloe mit stachligen, blaugruenen Blaettern und leuchtend roten Bluetenaehren.",Volles Sonnenlicht,10-30 °C,14,succulent|large|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,107,Arnika,Arnica montana,Arnika ist eine bekannte Heilpflanze aus den Alpen mit goldgelben Korbbluten. Sie wird fuer Muskeln und Gelenke verwendet.,Volles Sonnenlicht,10-20 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,110,Wermut,Artemisia absinthium,"Wermut ist ein stark aromatisches Heilkraut mit silbrig-gruenen, tief eingeschnittenen Blaettern. Fuer Kraeuterlikoere.",Volles Sonnenlicht,10-25 °C,14,medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,114,Hange-Birke,Betula pendula,Die Haenge-Birke hat charakteristisch weisse Rinde und haengende Zweige. Die Blaetter werden in der Heilkunde genutzt.,Volles Sonnenlicht,10-25 °C,7,tree|large|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,187,Ringelblume,Calendula officinalis,"Ringelblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,92,Chili,Capsicum annuum,"Chili ist eine beliebte Gemuese- und Zierpflanze mit leuchtenden, roten oder orangen Fruechten. Im Topf kultivierbar.",Volles Sonnenlicht,20-30 °C,4,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,138,Roemische Kamille,Chamaemelum nobile,Roemische Kamille ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,101,Kamille,Chamomilla recutita,"Die Kamille ist ein beliebtes Heilkraut mit kleinen, weiss-gelben Blueten. Das aetherische Oel wirkt beruhigend.",Volles Sonnenlicht,15-25 °C,5,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,160,Maigloeckchen,Convallaria majalis,"Maigloeckchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,74,Kurkuma,Curcuma longa,Kurkuma ist eine tropische Gewuerzpflanze mit breiten Blaettern und leuchtend gelber Wurzel. Wichtiges Heilgewuerz.,Helles bis volles Licht,20-30 °C,7,medicinal|high_humidity,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,109,Roter Fingerhut,Digitalis purpurea,"Der Rote Fingerhut hat hohe Bluetenstaende mit roehrenfoermigen, gepunkteten Blueten in Rosa. Wichtige Arzneipflanze.",Helles bis volles Licht,10-20 °C,7,flowering|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,106,Sonnenhut,Echinacea purpurea,"Der Sonnenhut ist eine beliebte Heilpflanze mit grossen, pinkfarbenen Blueten. Er staerkt das Immunsystem.",Helles bis volles Licht,15-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,210,Eukalyptus,Eucalyptus globulus,Eukalyptus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,216,Ginkgo,Ginkgo biloba,Ginkgo ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,119,Zaubernuss,Hamamelis mollis,"Die Zaubernuss bluet im Winter mit fadendunnen, gelben Bluetenkranzeln, die bis -10 Grad standhalten.",Helles bis volles Licht,10-20 °C,10,flowering|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,105,Johanniskraut,Hypericum perforatum,Das Johanniskraut hat leuchtend gelbe Blueten und ist ein wichtiges Heilkraut gegen Depressionen und Stimmungstiefs.,Volles Sonnenlicht,10-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch1.ts,23,Echter Lavendel,Lavandula angustifolia,Der Echte Lavendel ist ein aromatischer Halbstrauch mit lilafarbenen Bluetenaehren. Herrlicher Duft.,Volles Sonnenlicht,10-25 °C,10,medicinal|bright_light|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,102,Zitronenmelisse,Melissa officinalis,Die Zitronenmelisse ist ein zitronig duftendes Heilkraut. Sie beruhigt die Nerven und foerdert den Schlaf.,Helles bis volles Licht,15-25 °C,5,easy|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch1.ts,25,Basilikum,Ocimum basilicum,"Basilikum ist das beliebteste Kuechenkraut mit intensiv aromatischen, gruenen Blaettern. Fuer Pesto verwendet.",Volles Sonnenlicht,18-30 °C,2,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch1.ts,28,Oregano,Origanum vulgare,"Oregano ist ein aromatisches Kuechenkraut mit runden, behaarten Blaettern. In mediterraner Kueche beliebt.",Volles Sonnenlicht,15-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch1.ts,31,Rosengeranie,Pelargonium graveolens,Die Rosengeranie ist eine Duftpflanze mit tief eingeschnittenen Blaettern und rosaenlichem Aroma.,Volles Sonnenlicht,15-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch1.ts,24,Rosmarin,Rosmarinus officinalis,Rosmarin ist ein aromatisches Kraut mit nadelartigen Blaettern und blauen Blueten. In der Kueche unverzichtbar.,Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,113,Silber-Weide,Salix alba,"Die Silber-Weide hat silbrig-glaenzende Blaetter. Weidenrinde enthält Salicylsaeure, die Grundlage von Aspirin.",Helles bis volles Licht,10-25 °C,7,tree|large|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,103,Salbei,Salvia officinalis,Salbei ist ein aromatisches Heilkraut mit silbrig-gruenen Blaettern. Er hat antibakterielle und entzuendungshem­mende Wirkung.,Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,112,Schwarzer Holunder,Sambucus nigra,Der Schwarze Holunder hat weisse Doldenbluten und schwarze Beeren. Die Fruechte werden fuer Sirup und Saft verwendet.,Helles bis volles Licht,10-25 °C,7,flowering|tree|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch1.ts,27,Thymian,Thymus vulgaris,"Thymian ist ein kleiner, aromatischer Strauch mit winzigen Blaettern und rosa Blueten. Wichtiges Kuechenkraut.",Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,111,Grosse Brennessel,Urtica dioica,Die Grosse Brennessel ist eine Heilpflanze mit brennenden Haaren. Die Blaetter sind reich an Vitaminen und Mineralien.,Helles bis volles Licht,10-25 °C,7,medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,104,Baldrian,Valeriana officinalis,Baldrian ist ein bekanntes Heilkraut mit weissen bis roeslichen Blueten. Die Wurzeln werden zur Schlaffoerderung verwendet.,Helles bis volles Licht,15-25 °C,7,flowering|medicinal,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,192,Koenigskerze,Verbascum thapsus,"Koenigskerze ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +medicinal,constants/lexiconBatch2.ts,75,Ingwer,Zingiber officinale,Ingwer ist eine tropische Gewuerzpflanze mit aromatischen Knollen. Die Blaetter sind schilfartig.,Helles indirektes Licht,20-30 °C,5,medicinal|high_humidity,medicinal_requires_external_evidence,,,, +patterned,constants/lexiconBatch2.ts,34,Silbervase,Aechmea fasciata,Die Silbervase ist eine Bromelie mit silbrig gebänderten Blaettern und einem rosafarbenen Bluetenstand.,Helles indirektes Licht,18-25 °C,10,flowering|patterned,,,,, +patterned,constants/lexiconBatch1.ts,50,Aglaoneme,Aglaonema commutatum,Die Aglaoneme ist eine dekorative Zimmerpflanze mit silbrig-gruen gemusterten Blaettern. Tolerant gegenueber wenig Licht.,Wenig bis helles Licht,15-26 °C,7,easy|patterned|low_light,,,,, +patterned,constants/lexiconBatch1.ts,46,Amazona-Taro,Alocasia amazonica,"Der Amazona-Taro besticht mit dunkelgruenen, pfeilfoermigen Blaettern mit markant weissen Rippen.",Indirektes Licht,18-27 °C,5,patterned|large|high_humidity,,,,, +patterned,constants/lexiconBatch2.ts,233,Samt-Anthurie,Anthurium clarinervium,Samt-Anthurie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch2.ts,234,Kristall-Anthurie,Anthurium crystallinum,Kristall-Anthurie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch2.ts,57,Forellen-Begonie,Begonia maculata,Die Forellen-Begonie hat olivgruene Blaetter mit silbernen Punkten und einer roten Unterseite. Atemberaubend.,Helles indirektes Licht,18-27 °C,7,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch1.ts,18,Koenigsbegonie,Begonia rex,"Die Koenigsbegonie beeindruckt mit prachtvoll gemusterten Blaettern in Silber, Rot und Gruen.",Indirektes Licht,18-25 °C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch1.ts,49,Buntblatt,Caladium bicolor,"Das Buntblatt beeindruckt mit transparenten, bunt gemusterten Blaettern in Pink, Rot, Weiss und Gruen.",Indirektes Licht,20-30 °C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch1.ts,99,Herzkette,Ceropegia woodii,"Die Herzkette hat duenne, haengende Ranken mit herzfoermigen, silbergrau gemusterten Blaettchen.",Helles indirektes Licht,15-27 °C,14,easy|succulent|patterned|hanging,,,,, +patterned,constants/lexiconBatch2.ts,224,Kroton,Codiaeum variegatum,Kroton ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,patterned|bright_light,,,,, +patterned,constants/lexiconBatch2.ts,39,Cryptanthus,Cryptanthus bivittatus,Cryptanthus ist eine niedrig wachsende Bromelie mit sternfoermigen Rosetten und gemusterten Blaettern. Fuer Terrarien.,Helles indirektes Licht,18-27 °C,7,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch1.ts,53,Ctenanthe,Ctenanthe burle-marxii,Die Ctenanthe hat faszinierend gemusterte Blaetter mit dunkelgruunem Fischgraetenmuster auf hellgruunem Hintergrund.,Indirektes Licht,18-25 °C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch2.ts,226,Nervenpflanze,Fittonia albivenis,Nervenpflanze ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch2.ts,240,Calathea lancifolia,Goeppertia insignis,Calathea lancifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +patterned,constants/lexiconBatch2.ts,241,Calathea ornata,Goeppertia ornata,Calathea ornata ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +patterned,constants/lexiconBatch2.ts,227,Punktblatt,Hypoestes phyllostachya,Punktblatt ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,patterned|bright_light,,,,, +patterned,constants/lexiconBatch1.ts,51,Gebet-Pflanze,Maranta leuconeura,Die Gebet-Pflanze faltet ihre gemusterten Blaetter nachts wie Haende zusammen. Faszinierende rote und gruene Muster.,Indirektes Licht,18-27 °C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +patterned,constants/lexiconBatch2.ts,48,Monstera obliqua,Monstera obliqua,"Monstera obliqua ist eine seltene Monstera-Art mit filigranen Blaettern, die hauptsaechlich aus Lochern bestehen.",Helles indirektes Licht,18-27 °C,7,patterned|hanging,,,,, +patterned,constants/lexiconBatch2.ts,37,Neoregelia,Neoregelia carolinae,"Die Neoregelia ist eine Bromelie, bei der das Herzblatt zur Bluetzeit leuchtend rot wird. Sehr dekorativ.",Helles bis volles Licht,18-27 °C,7,flowering|patterned|bright_light,,,,, +patterned,constants/lexiconBatch1.ts,54,Kleeblume,Oxalis triangularis,"Die Kleeblume hat tiefviolette, dreieckige Blaetter und zarte rosa Blueten. Sie faltet die Blaetter bei Dunkelheit.",Helles indirektes Licht,15-24 °C,7,flowering|patterned,,,,, +patterned,constants/lexiconBatch2.ts,6,Schraubenbaum,Pandanus veitchii,"Der Schraubenbaum hat spiralfoermig angeordnete, gruenweiss gestreifte Blaetter. Sehr dekorativ und exotisch.",Helles bis volles Licht,18-27 °C,7,patterned|bright_light,,,,, +patterned,constants/lexiconBatch2.ts,229,Wassermelonen-Peperomie,Peperomia argyreia,Wassermelonen-Peperomie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,pet_friendly|patterned,pet_friendly_requires_external_evidence,,,, +patterned,constants/lexiconBatch2.ts,243,Philodendron Pink Princess,Philodendron erubescens Pink Princess,Philodendron Pink Princess ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,patterned|bright_light,,,,, +patterned,constants/lexiconBatch2.ts,49,Philodendron gloriosum,Philodendron gloriosum,"Philodendron gloriosum hat grosse, samtige, herzfoermige Blaetter mit weissen Rippen. Eine atemberaubende Pflanze.",Helles indirektes Licht,18-27 °C,7,patterned|large|high_humidity,,,,, +patterned,constants/lexiconBatch2.ts,228,Aluminium-Pflanze,Pilea cadierei,Aluminium-Pflanze ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|pet_friendly|patterned,pet_friendly_requires_external_evidence,,,, +patterned,constants/lexiconBatch2.ts,152,Buntnessel,Plectranthus scutellarioides,"Buntnessel ist eine farbstarke Zierpflanze, die vor allem fuer ihr dekoratives Laub beliebt ist.",Volles bis helles Licht,10-24 C,4,patterned|bright_light,,,,, +patterned,constants/lexiconBatch1.ts,55,Satinpothos,Scindapsus pictus,"Der Satinpothos hat samtig-glaenzende, silbrig gefleckte Blaetter auf langen, haengenden Ranken.",Helles indirektes Licht,18-28 °C,7,easy|patterned|hanging,,,,, +patterned,constants/lexiconBatch2.ts,45,Regenbogenmoos,Selaginella uncinata,"Das Regenbogenmoos hat schuppenfoermige Blaetter, die im Licht schillernd irisieren. Dekorativ fuer Terrarien.",Helles indirektes Licht,18-27 °C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch1.ts,52,Stromanthe,Stromanthe sanguinea,Die Stromanthe hat dekorative Blaetter mit weissem Muster und leuchtend roter Unterseite. Familie der Marantaceen.,Helles indirektes Licht,18-25 °C,5,patterned|high_humidity,,,,, +patterned,constants/lexiconBatch1.ts,17,Zebrakraut,Tradescantia zebrina,Das Zebrakraut faellt durch seine silbrig-lila gestreiften Blaetter auf. Schnellwachsende Haengepflanze.,Helles indirektes Licht,15-25 °C,5,easy|patterned|hanging,,,,, +patterned,constants/lexiconBatch2.ts,35,Flammen-Bromelie,Vriesea splendens,"Die Flammen-Bromelie hat gebänderte, dunkelgruene Blaetter und einen spektakulaeren, roten Bluetenstand.",Helles indirektes Licht,18-25 °C,7,flowering|patterned|high_humidity,,,,, +pet_friendly,constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,Die Bergpalme ist eine kompakte Zimmerpalme fuer schattigere Standorte. Ideal fuer dunkle Innenraeume.,Wenig bis helles Licht,15-25 °C,7,easy|pet_friendly|tree|air_purifier|low_light,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch1.ts,42,Goldfruchtpalme,Dypsis lutescens,Die Goldfruchtpalme ist eine elegante Zimmerpalme mit gelblich-gruenen Stielen und gefiederten Wedeln.,Helles indirektes Licht,18-27 °C,5,pet_friendly|tree|air_purifier,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,100,Erdbeere,Fragaria ananassa,"Die Erdbeere ist ein beliebtes Obst fuer Balkon und Terrasse mit aromatischen, roten Fruechten.",Helles bis volles Licht,15-25 °C,3,easy|pet_friendly|sun,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,240,Calathea lancifolia,Goeppertia insignis,Calathea lancifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,241,Calathea ornata,Goeppertia ornata,Calathea ornata ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-28 C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,3,Kentia-Palme,Howea forsteriana,"Die Kentia-Palme ist eine der elegantesten Zimmerpalmen mit langen, herabhängenden Fiederblaettern.",Helles indirektes Licht,18-25 °C,7,pet_friendly|tree|low_light,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch1.ts,51,Gebet-Pflanze,Maranta leuconeura,Die Gebet-Pflanze faltet ihre gemusterten Blaetter nachts wie Haende zusammen. Faszinierende rote und gruene Muster.,Indirektes Licht,18-27 °C,5,pet_friendly|patterned|high_humidity,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,229,Wassermelonen-Peperomie,Peperomia argyreia,Wassermelonen-Peperomie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,pet_friendly|patterned,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch1.ts,102,Rippenpeperomie,Peperomia caperata,"Die Rippenpeperomie hat tief gerippte, dunkelgruene bis violette Blaetter mit einer samtigen Textur.",Helles indirektes Licht,18-26 °C,10,easy|pet_friendly,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch1.ts,103,Spiegelpeperomie,Peperomia obtusifolia,"Die Spiegelpeperomie hat glaenzende, lederartige, oval-runde Blaetter in tiefem Gruen. Sehr robust.",Helles indirektes Licht,16-26 °C,10,easy|pet_friendly|low_light,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,230,Raindrop-Peperomie,Peperomia polybotrya,Raindrop-Peperomie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|pet_friendly,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch1.ts,34,Petunie,Petunia hybrida,Die Petunie ist eine der beliebtesten Balkonpflanzen mit trichterfoermigen Blueten in unzaehligen Farben.,Volles Sonnenlicht,15-25 °C,2,easy|pet_friendly|flowering|sun,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,228,Aluminium-Pflanze,Pilea cadierei,Aluminium-Pflanze ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|pet_friendly|patterned,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch1.ts,2,Ufopflanze,Pilea peperomioides,"Die Ufopflanze hat unverwechselbare, runde Blaetter auf langen Stielen. Bildet leicht Ableger zum Verschenken.",Helles indirektes Licht,13-30 °C,7,easy|pet_friendly,pet_friendly_requires_external_evidence,,,, +pet_friendly,constants/lexiconBatch2.ts,238,Bubikopf,Soleirolia soleirolii,Bubikopf ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,15-24 C,4,pet_friendly|high_humidity,pet_friendly_requires_external_evidence,,,, +succulent,constants/lexiconBatch1.ts,86,Wuestenrose,Adenium obesum,Die Wuestenrose ist eine sukkulente Zimmerpflanze mit dickem Stamm und leuchtend pinken Blueten.,Volles Sonnenlicht,20-35 °C,10,flowering|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,117,Socotra-Wuestenrose,Adenium socotranum,"Die Socotra-Wuestenrose ist eine seltene, endemische Art mit einem sehr dicken, knolligen Stamm und rosa Blueten.",Volles Sonnenlicht,20-35 °C,14,flowering|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,31,Adromischus,Adromischus cristatus,Adromischus ist eine kompakte Sukkulente mit ungewoehnlich wellenrandigen Blaettern auf kurzen Staengeln.,Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,10,Schwarze Rose (Aeonium),Aeonium arboreum,"Das Aeonium bildet dekorative, rosettenfoermige Sukkulenten an verzweigten Stielen.",Volles Sonnenlicht,10-25 °C,10,succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,11,Agave,Agave americana,"Die Agave ist eine imposante Sukkulente mit steifen, blaugruenen Blaettern mit Stacheln. Sie bluet nur einmal.",Volles Sonnenlicht,10-35 °C,21,succulent|large|sun,,,,, +succulent,constants/lexiconBatch1.ts,89,Kap-Aloe,Aloe arborescens,"Die Kap-Aloe ist eine strauchige Aloe mit schmalen, gezaehnten Blaettern und leuchtend roten Bluetenaehren im Winter.",Volles Sonnenlicht,10-30 °C,14,easy|succulent|medicinal|sun,medicinal_requires_external_evidence,,,, +succulent,constants/lexiconBatch2.ts,18,Kap-Aloe (ferox),Aloe ferox,"Aloe ferox ist eine grosse, imposante Aloe mit stachligen, blaugruenen Blaettern und leuchtend roten Bluetenaehren.",Volles Sonnenlicht,10-30 °C,14,succulent|large|medicinal|sun,medicinal_requires_external_evidence,,,, +succulent,constants/lexiconBatch1.ts,41,Pferdeschwanzpalme,Beaucarnea recurvata,"Die Pferdeschwanzpalme hat einen verdickten Stammbasis als Wasserspeicher und lange, schmale Blaetter.",Volles Sonnenlicht,15-30 °C,21,easy|succulent|tree|sun,,,,, +succulent,constants/lexiconBatch1.ts,81,Peruanischer Fackelkaktus,Cereus peruvianus,"Der Peruanische Fackelkaktus ist ein saeulenfoermiger Kaktus, der im Innenraum bis zu 2 m hoch werden kann.",Volles Sonnenlicht,15-35 °C,21,easy|succulent|large|sun,,,,, +succulent,constants/lexiconBatch1.ts,99,Herzkette,Ceropegia woodii,"Die Herzkette hat duenne, haengende Ranken mit herzfoermigen, silbergrau gemusterten Blaettchen.",Helles indirektes Licht,15-27 °C,14,easy|succulent|patterned|hanging,,,,, +succulent,constants/lexiconBatch2.ts,24,Konophytum,Conophytum calculus,"Das Konophytum ist eine sehr kompakte Sukkulente, die zwei Blaetter zu einer kugelfoermigen Form verschmilzt.",Volles Sonnenlicht,10-25 °C,21,succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,29,Kotyledon,Cotyledon orbiculata,"Kotyledon hat dickfleischige, runde Blaetter mit einem mehligen, weisslichen Belag. Sehr trockenheitsresistent.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,26,Moos-Crassula,Crassula muscosa,"Die Moos-Crassula hat dicht aneinandergereihte, winzige gruene Blaetter auf unverzweigten Trieben. Sieht aus wie Moos.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,5,Jadepflanze,Crassula ovata,"Die Jadepflanze ist eine langlebige Sukkulente mit dicken, ovalen Blaettern. In Japan gilt sie als Gluecksbringer.",Helles bis volles Licht,15-24 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,236,String of Bananas,Curio radicans,String of Bananas ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,succulent|hanging|sun,,,,, +succulent,constants/lexiconBatch2.ts,237,String of Dolphins,Curio x peregrinus,String of Dolphins ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,succulent|hanging|sun,,,,, +succulent,constants/lexiconBatch1.ts,101,Dischidia,Dischidia ruscifolia,"Die Dischidia ist eine epiphytische Haengepflanze mit kleinen, runden Blaettern entlang duenner Ranken.",Helles indirektes Licht,18-27 °C,7,succulent|hanging,,,,, +succulent,constants/lexiconBatch2.ts,30,Dudleya,Dudleya brittonii,"Dudleya ist eine rosetten­bildende Sukkulente mit silbrig-weissen, mehligen Blaettern. Sehr elegant.",Volles Sonnenlicht,10-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,4,Echeverie,Echeveria elegans,"Die Echeverie bildet symmetrische, rosettenfoermige Sukkulenten mit blaugruenen Blaettern. Pflegeleicht.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,77,Goldene Tonne,Echinocactus grusonii,Die Goldene Tonne ist ein ikonischer kugelfoermiger Kaktus mit goldgelben Stacheln. Waechst langsam aber imposant.,Volles Sonnenlicht,15-35 °C,21,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,83,San-Pedro-Kaktus,Echinopsis pachanoi,"Der San-Pedro-Kaktus ist ein schnell wachsender, saeulenfoermiger Kaktus aus den Anden.",Volles Sonnenlicht,10-35 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,84,Koenigin der Nacht,Epiphyllum oxypetalum,"Die Koenigin der Nacht bluet nur eine einzige Nacht lang mit riesigen, intensiv duftenden weissen Blueten.",Indirektes Licht,18-27 °C,7,flowering|succulent,,,,, +succulent,constants/lexiconBatch2.ts,19,Christusdorn,Euphorbia milii,Der Christusdorn ist eine sukkulente Wolfsmilch mit stacheligen Zweigen und kleinen roten oder gelben Hochblaettern.,Helles bis volles Licht,15-28 °C,10,easy|flowering|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,12,Bleistiftkaktus,Euphorbia tirucalli,"Der Bleistiftkaktus ist eine sukkulente Wolfsmilch mit duennen, zylindrischen Zweigen ohne Blaetter.",Volles Sonnenlicht,18-30 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,78,Fass-Kaktus,Ferocactus cylindraceus,"Der Fass-Kaktus ist ein zylindrischer Wuestenkaktus mit langen, roten Stacheln. Sehr langlebig.",Volles Sonnenlicht,15-35 °C,21,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,90,Gasteria,Gasteria carinata,"Die Gasteria ist eine kleine Sukkulente mit zweireihig angeordneten, zungenfoermigen, gefleckten Blaettern.",Helles indirektes Licht,15-25 °C,14,easy|succulent|low_light,,,,, +succulent,constants/lexiconBatch1.ts,87,Geisterpflanze,Graptopetalum paraguayense,"Die Geisterpflanze hat zartgraue bis perlmutt-rosafarbene, rosettenfoermige Blaetter. Sehr robuste Sukkulente.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,80,Mond-Kaktus,Gymnocalycium mihanovichii,Der Mond-Kaktus ist eine farbenfrohe Veredelung eines chlorophylllosen Kaktus auf einem gruenen Unterlagekaktus.,Indirektes Licht,15-30 °C,14,easy|succulent,,,,, +succulent,constants/lexiconBatch1.ts,6,Zebra-Haworthie,Haworthia fasciata,Die Zebra-Haworthie ist eine kompakte Sukkulente mit weissen Querstreifen auf dunkelgruenen Blaettern.,Helles indirektes Licht,15-25 °C,14,easy|succulent|low_light,,,,, +succulent,constants/lexiconBatch1.ts,58,Kleine Wachsblume,Hoya bella,"Die Kleine Wachsblume traegt zierliche, sternfoermige weisse Blueten mit rosa Mitte. Haengende Sukkulente.",Helles indirektes Licht,18-27 °C,10,flowering|succulent|hanging,,,,, +succulent,constants/lexiconBatch1.ts,57,Wachsblume,Hoya carnosa,"Die Wachsblume ist eine Kletterpflanze mit dicken, wachsartigen Blaettern und sternfoermigen, duftenden Blueten.",Helles indirektes Licht,16-27 °C,10,easy|flowering|succulent|hanging,,,,, +succulent,constants/lexiconBatch1.ts,9,Kalanchoe,Kalanchoe blossfeldiana,"Die Kalanchoe ist eine beliebte Bluehpflanze mit leuchtenden Blueten in Rot, Orange, Gelb oder Rosa.",Helles bis volles Licht,15-25 °C,10,easy|flowering|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,22,Brutblatt,Kalanchoe daigremontiana,Das Brutblatt bildet entlang des Blattrandes zahlreiche kleine Jungpflanzen. Eine faszinierende Sukkulente.,Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,21,Kaninchen-Ohren,Kalanchoe tomentosa,"Kaninchen-Ohren haben weisslich-filzige Blaetter mit braunen Raendern, die Kaninchen­ohren aehneln. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,23,Lebende Steine,Lithops julii,"Lebende Steine sind faszinierende Mimikry-Sukkulenten, die Kieselsteinen taeuschen aehnlich sehen. Sehr trockenheitsresistent.",Volles Sonnenlicht,10-30 °C,21,succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,79,Mammillaria,Mammillaria zeilmanniana,"Die Mammillaria ist ein kompakter, kugelfoermiger Kaktus, der im Fruehling einen Kranz aus rosa Blueten traegt.",Volles Sonnenlicht,15-35 °C,14,easy|flowering|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,82,Hasenohren-Kaktus,Opuntia microdasys,"Der Hasenohren-Kaktus hat flache, ovale Triebe mit dichten weissen Glochiden. Klassischer Zimmerkaktus.",Volles Sonnenlicht,10-35 °C,21,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,88,Mondstein-Pflanze,Pachyphytum oviferum,"Die Mondstein-Pflanze hat dicke, ovale Blaetter mit einem pastellrosafarbenen, mehligen Ueberzug.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,27,Speckbaum,Portulacaria afra,"Der Speckbaum ist eine sukkulente Pflanze mit roten Stielen und kleinen, runden, glaenzenden Blaettern.",Helles bis volles Licht,15-30 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,85,Korallenkaktus,Rhipsalis baccifera,"Der Korallenkaktus ist ein epiphytischer Kaktus mit duennen, haengenden Trieben und kleinen weissen Beeren.",Indirektes Licht,18-27 °C,7,succulent|hanging,,,,, +succulent,constants/lexiconBatch2.ts,17,Zylindrischer Bogenhanf,Sansevieria cylindrica,"Der Zylindrische Bogenhanf hat zylindrische, aufrechte Blaetter, die sich nach oben verjuengen. Sehr pflegeleicht.",Helles bis volles Licht,15-27 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch1.ts,8,Weihnachtskaktus,Schlumbergera truncata,"Der Weihnachtskaktus erfreut zur Weihnachtszeit mit leuchtenden Blueten in Rosa, Rot oder Weiss.",Helles indirektes Licht,15-21 °C,7,easy|flowering|succulent,,,,, +succulent,constants/lexiconBatch1.ts,7,Eselschwanz,Sedum morganianum,"Der Eselschwanz ist eine haengende Sukkulente mit langen Trieben aus dichten, blaugruenen Blaettchen.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|hanging|sun,,,,, +succulent,constants/lexiconBatch1.ts,100,Perlenschnur-Pflanze,Senecio rowleyanus,"Die Perlenschnur-Pflanze hat haengende Ranken mit kugelfoermigen, perlenaehnlichen Blaettern. Einzigartige Sukkulente.",Helles bis volles Licht,15-27 °C,14,easy|succulent|hanging,,,,, +succulent,constants/lexiconBatch2.ts,28,Blauer Kreuzkraut,Senecio serpens,"Der Blaue Kreuzkraut hat zylindrische, blaublaugruene Blaetter und einen kriechenden Wuchs. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +succulent,constants/lexiconBatch2.ts,25,Aasblume,Stapelia grandiflora,"Die Aasblume hat fleischige, gruene Staengel und riesige, sternfoermige Blueten mit aasartigem Duft.",Helles bis volles Licht,18-30 °C,14,flowering|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,212,Spitzahorn,Acer platanoides,Spitzahorn ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,108,Schafgarbe,Achillea millefolium,Die Schafgarbe hat weisse oder rosafarbene Bluetenschirme und fein gefiederte Blaetter. Wichtige Heilpflanze.,Volles Sonnenlicht,10-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch1.ts,86,Wuestenrose,Adenium obesum,Die Wuestenrose ist eine sukkulente Zimmerpflanze mit dickem Stamm und leuchtend pinken Blueten.,Volles Sonnenlicht,20-35 °C,10,flowering|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,117,Socotra-Wuestenrose,Adenium socotranum,"Die Socotra-Wuestenrose ist eine seltene, endemische Art mit einem sehr dicken, knolligen Stamm und rosa Blueten.",Volles Sonnenlicht,20-35 °C,14,flowering|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,31,Adromischus,Adromischus cristatus,Adromischus ist eine kompakte Sukkulente mit ungewoehnlich wellenrandigen Blaettern auf kurzen Staengeln.,Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch1.ts,10,Schwarze Rose (Aeonium),Aeonium arboreum,"Das Aeonium bildet dekorative, rosettenfoermige Sukkulenten an verzweigten Stielen.",Volles Sonnenlicht,10-25 °C,10,succulent|sun,,,,, +sun,constants/lexiconBatch1.ts,11,Agave,Agave americana,"Die Agave ist eine imposante Sukkulente mit steifen, blaugruenen Blaettern mit Stacheln. Sie bluet nur einmal.",Volles Sonnenlicht,10-35 °C,21,succulent|large|sun,,,,, +sun,constants/lexiconBatch2.ts,155,Stockrose,Alcea rosea,"Stockrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,135,Schnittknoblauch,Allium tuberosum,Schnittknoblauch ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch1.ts,89,Kap-Aloe,Aloe arborescens,"Die Kap-Aloe ist eine strauchige Aloe mit schmalen, gezaehnten Blaettern und leuchtend roten Bluetenaehren im Winter.",Volles Sonnenlicht,10-30 °C,14,easy|succulent|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,18,Kap-Aloe (ferox),Aloe ferox,"Aloe ferox ist eine grosse, imposante Aloe mit stachligen, blaugruenen Blaettern und leuchtend roten Bluetenaehren.",Volles Sonnenlicht,10-30 °C,14,succulent|large|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,128,Zitronenverbene,Aloysia citrodora,Zitronenverbene ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,194,Fuchsschwanz,Amaranthus caudatus,"Fuchsschwanz ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,163,Anemone,Anemone coronaria,"Anemone ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,140,Dill,Anethum graveolens,Dill ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,125,Kerbel,Anthriscus cerefolium,Kerbel ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,147,Loewenmaeulchen,Antirrhinum majus,"Loewenmaeulchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,107,Arnika,Arnica montana,Arnika ist eine bekannte Heilpflanze aus den Alpen mit goldgelben Korbbluten. Sie wird fuer Muskeln und Gelenke verwendet.,Volles Sonnenlicht,10-20 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,110,Wermut,Artemisia absinthium,"Wermut ist ein stark aromatisches Heilkraut mit silbrig-gruenen, tief eingeschnittenen Blaettern. Fuer Kraeuterlikoere.",Volles Sonnenlicht,10-25 °C,14,medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,122,Estragon,Artemisia dracunculus,Estragon ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,178,Seidenpflanze,Asclepias tuberosa,"Seidenpflanze ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,41,Pferdeschwanzpalme,Beaucarnea recurvata,"Die Pferdeschwanzpalme hat einen verdickten Stammbasis als Wasserspeicher und lange, schmale Blaetter.",Volles Sonnenlicht,15-30 °C,21,easy|succulent|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,145,Gaensebluemchen,Bellis perennis,"Gaensebluemchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,129,Borretsch,Borago officinalis,Borretsch ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch1.ts,62,Bougainvillea,Bougainvillea spectabilis,"Die Bougainvillea ist eine rankenreiche Kletterpflanze mit leuchtend farbigen Hochblaettern in Rot, Orange oder Pink.",Volles Sonnenlicht,18-30 °C,5,flowering|bright_light|sun,,,,, +sun,constants/lexiconBatch2.ts,223,Schmetterlingsflieder,Buddleja davidii,Schmetterlingsflieder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,202,Buchsbaum,Buxus sempervirens,Buchsbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|sun,,,,, +sun,constants/lexiconBatch2.ts,187,Ringelblume,Calendula officinalis,"Ringelblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,63,Calibrachoa,Calibrachoa hybrida,"Calibrachoa ist eine petunienaehnliche Haengepflanze mit unzaehligen, kleinen Trichterbluten in allen Farben.",Volles Sonnenlicht,15-25 °C,2,easy|flowering|hanging|sun,,,,, +sun,constants/lexiconBatch2.ts,67,Blumenschilfrohr,Canna indica,"Das Blumenschilfrohr hat grosse, tropisch wirkende Blaetter und auffaellige Blueten in Rot, Orange oder Gelb.",Volles Sonnenlicht,18-28 °C,5,flowering|large|sun,,,,, +sun,constants/lexiconBatch2.ts,92,Chili,Capsicum annuum,"Chili ist eine beliebte Gemuese- und Zierpflanze mit leuchtenden, roten oder orangen Fruechten. Im Topf kultivierbar.",Volles Sonnenlicht,20-30 °C,4,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,90,Papaya,Carica papaya,"Die Papaya ist eine tropische Fruchtpflanze mit grossen, gelappten Blaettern und orangen Fruechten.",Volles Sonnenlicht,20-35 °C,5,large|sun,,,,, +sun,constants/lexiconBatch2.ts,217,Trompetenbaum,Catalpa bignonioides,Trompetenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,208,Zeder,Cedrus libani,Zeder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,188,Kornblume,Centaurea cyanus,"Kornblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,81,Peruanischer Fackelkaktus,Cereus peruvianus,"Der Peruanische Fackelkaktus ist ein saeulenfoermiger Kaktus, der im Innenraum bis zu 2 m hoch werden kann.",Volles Sonnenlicht,15-35 °C,21,easy|succulent|large|sun,,,,, +sun,constants/lexiconBatch2.ts,138,Roemische Kamille,Chamaemelum nobile,Roemische Kamille ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,101,Kamille,Chamomilla recutita,"Die Kamille ist ein beliebtes Heilkraut mit kleinen, weiss-gelben Blueten. Das aetherische Oel wirkt beruhigend.",Volles Sonnenlicht,15-25 °C,5,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,86,Zitronenbaum,Citrus limon,"Der Zitronenbaum ist ein kleiner, immergruener Baum mit weissen, duftenden Blueten und gelben Fruechten.",Volles Sonnenlicht,18-28 °C,5,tree|sun,,,,, +sun,constants/lexiconBatch2.ts,87,Orangenbaum,Citrus sinensis,"Der Orangenbaum ist ein kleiner, immergruener Baum mit weissen Blueten und orangen Fruechten.",Volles Sonnenlicht,18-28 °C,5,tree|sun,,,,, +sun,constants/lexiconBatch2.ts,24,Konophytum,Conophytum calculus,"Das Konophytum ist eine sehr kompakte Sukkulente, die zwei Blaetter zu einer kugelfoermigen Form verschmilzt.",Volles Sonnenlicht,10-25 °C,21,succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,14,Keulenlilie,Cordyline australis,"Die Keulenlilie hat lange, schmale, gruene oder rotbraune Blaetter in einem dekorativen Schopf.",Helles bis volles Licht,10-25 °C,7,easy|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,181,Maedchenauge,Coreopsis tinctoria,"Maedchenauge ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,139,Koriander,Coriandrum sativum,Koriander ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,150,Kosmee,Cosmos bipinnatus,"Kosmee ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,29,Kotyledon,Cotyledon orbiculata,"Kotyledon hat dickfleischige, runde Blaetter mit einem mehligen, weisslichen Belag. Sehr trockenheitsresistent.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,26,Moos-Crassula,Crassula muscosa,"Die Moos-Crassula hat dicht aneinandergereihte, winzige gruene Blaetter auf unverzweigten Trieben. Sieht aus wie Moos.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch1.ts,5,Jadepflanze,Crassula ovata,"Die Jadepflanze ist eine langlebige Sukkulente mit dicken, ovalen Blaettern. In Japan gilt sie als Gluecksbringer.",Helles bis volles Licht,15-24 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,94,Gurke,Cucumis sativus,"Die Gurke ist eine rankende Gemuese­pflanze mit gruenen, erfrischenden Fruechten. Im Balkonkasten kultivierbar.",Volles Sonnenlicht,18-28 °C,3,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,209,Zypresse,Cupressus sempervirens,Zypresse ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,236,String of Bananas,Curio radicans,String of Bananas ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,succulent|hanging|sun,,,,, +sun,constants/lexiconBatch2.ts,237,String of Dolphins,Curio x peregrinus,String of Dolphins ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,succulent|hanging|sun,,,,, +sun,constants/lexiconBatch2.ts,239,Palmfarn,Cycas revoluta,Palmfarn ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,127,Zitronengras,Cymbopogon citratus,Zitronengras ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,68,Dahlie,Dahlia pinnata,Die Dahlie ist eine prachtvolle Sommerblume mit Blueten in allen Groessen und Formen. Sie wird aus Knollen gezogen.,Volles Sonnenlicht,15-25 °C,5,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,153,Rittersporn,Delphinium elatum,"Rittersporn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,189,Bartnelke,Dianthus barbatus,"Bartnelke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,146,Nelke,Dianthus caryophyllus,"Nelke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,77,Venusfliegenfalle,Dionaea muscipula,Die Venusfliegenfalle ist eine fleischfressende Pflanze mit klappfallartigen Blaettern. Faengt Insekten.,Volles Sonnenlicht,15-30 °C,5,sun,,,,, +sun,constants/lexiconBatch2.ts,80,Sonnentau,Drosera capensis,Der Sonnentau faengt Insekten mit klebrigen Tropfen auf seinen Blaettern. Eine faszinierende fleischfressende Pflanze.,Volles Sonnenlicht,15-25 °C,5,high_humidity|sun,,,,, +sun,constants/lexiconBatch2.ts,30,Dudleya,Dudleya brittonii,"Dudleya ist eine rosetten­bildende Sukkulente mit silbrig-weissen, mehligen Blaettern. Sehr elegant.",Volles Sonnenlicht,10-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch1.ts,4,Echeverie,Echeveria elegans,"Die Echeverie bildet symmetrische, rosettenfoermige Sukkulenten mit blaugruenen Blaettern. Pflegeleicht.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,106,Sonnenhut,Echinacea purpurea,"Der Sonnenhut ist eine beliebte Heilpflanze mit grossen, pinkfarbenen Blueten. Er staerkt das Immunsystem.",Helles bis volles Licht,15-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch1.ts,77,Goldene Tonne,Echinocactus grusonii,Die Goldene Tonne ist ein ikonischer kugelfoermiger Kaktus mit goldgelben Stacheln. Waechst langsam aber imposant.,Volles Sonnenlicht,15-35 °C,21,easy|succulent|sun,,,,, +sun,constants/lexiconBatch1.ts,83,San-Pedro-Kaktus,Echinopsis pachanoi,"Der San-Pedro-Kaktus ist ein schnell wachsender, saeulenfoermiger Kaktus aus den Anden.",Volles Sonnenlicht,10-35 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,186,Kalifornischer Mohn,Eschscholzia californica,"Kalifornischer Mohn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,210,Eukalyptus,Eucalyptus globulus,Eukalyptus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,19,Christusdorn,Euphorbia milii,Der Christusdorn ist eine sukkulente Wolfsmilch mit stacheligen Zweigen und kleinen roten oder gelben Hochblaettern.,Helles bis volles Licht,15-28 °C,10,easy|flowering|succulent|sun,,,,, +sun,constants/lexiconBatch1.ts,12,Bleistiftkaktus,Euphorbia tirucalli,"Der Bleistiftkaktus ist eine sukkulente Wolfsmilch mit duennen, zylindrischen Zweigen ohne Blaetter.",Volles Sonnenlicht,18-30 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch1.ts,78,Fass-Kaktus,Ferocactus cylindraceus,"Der Fass-Kaktus ist ein zylindrischer Wuestenkaktus mit langen, roten Stacheln. Sehr langlebig.",Volles Sonnenlicht,15-35 °C,21,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,219,Forsythie,Forsythia x intermedia,Forsythie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,100,Erdbeere,Fragaria ananassa,"Die Erdbeere ist ein beliebtes Obst fuer Balkon und Terrasse mit aromatischen, roten Fruechten.",Helles bis volles Licht,15-25 °C,3,easy|pet_friendly|sun,pet_friendly_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,169,Freesie,Freesia refracta,"Freesie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,196,Kokardenblume,Gaillardia aristata,"Kokardenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,190,Mittagsgold,Gazania rigens,"Mittagsgold ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,216,Ginkgo,Ginkgo biloba,Ginkgo ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,161,Gladiole,Gladiolus hortulanus,"Gladiole ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,87,Geisterpflanze,Graptopetalum paraguayense,"Die Geisterpflanze hat zartgraue bis perlmutt-rosafarbene, rosettenfoermige Blaetter. Sehr robuste Sukkulente.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,141,Sonnenblume,Helianthus annuus,"Sonnenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,133,Currykraut,Helichrysum italicum,Currykraut ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,191,Heliotrop,Heliotropium arborescens,"Heliotrop ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,182,Taglilie,Hemerocallis fulva,"Taglilie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,21,Hibiskus,Hibiscus rosa-sinensis,"Der Hibiskus begeistert mit grossen, trompetenfoermigen Blueten in Rot, Orange und Rosa.",Volles Sonnenlicht,18-28 °C,3,flowering|bright_light|sun,,,,, +sun,constants/lexiconBatch2.ts,220,Gartenhibiskus,Hibiscus syriacus,Gartenhibiskus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,159,Hasengloeckchen,Hyacinthoides non-scripta,"Hasengloeckchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,105,Johanniskraut,Hypericum perforatum,Das Johanniskraut hat leuchtend gelbe Blueten und ist ein wichtiges Heilkraut gegen Depressionen und Stimmungstiefs.,Volles Sonnenlicht,10-25 °C,7,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,136,Ysop,Hyssopus officinalis,Ysop ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,203,Stechpalme,Ilex aquifolium,Stechpalme ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|sun,,,,, +sun,constants/lexiconBatch1.ts,64,Suesskartoffel,Ipomoea batatas,"Die Suesskartoffel-Zierpflanze hat dekorative, herzfoermige Blaetter in gruen oder dunkelviolett. Ideal als Haengepflanze.",Volles Sonnenlicht,20-30 °C,5,easy|hanging|sun,,,,, +sun,constants/lexiconBatch2.ts,156,Prunkwinde,Ipomoea purpurea,"Prunkwinde ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,144,Bart-Iris,Iris germanica,"Bart-Iris ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,9,Kalanchoe,Kalanchoe blossfeldiana,"Die Kalanchoe ist eine beliebte Bluehpflanze mit leuchtenden Blueten in Rot, Orange, Gelb oder Rosa.",Helles bis volles Licht,15-25 °C,10,easy|flowering|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,22,Brutblatt,Kalanchoe daigremontiana,Das Brutblatt bildet entlang des Blattrandes zahlreiche kleine Jungpflanzen. Eine faszinierende Sukkulente.,Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,21,Kaninchen-Ohren,Kalanchoe tomentosa,"Kaninchen-Ohren haben weisslich-filzige Blaetter mit braunen Raendern, die Kaninchen­ohren aehneln. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,64,Wandelroeschen,Lantana camara,"Das Wandelroeschen hat kugelige Bluetenkoepfe, die die Farbe von Gelb ueber Orange zu Rot wechseln. Sehr attraktiv.",Volles Sonnenlicht,18-28 °C,5,flowering|bright_light|sun,,,,, +sun,constants/lexiconBatch2.ts,158,Duftwicke,Lathyrus odoratus,"Duftwicke ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,121,Lorbeer,Laurus nobilis,Lorbeer ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch1.ts,23,Echter Lavendel,Lavandula angustifolia,Der Echte Lavendel ist ein aromatischer Halbstrauch mit lilafarbenen Bluetenaehren. Herrlicher Duft.,Volles Sonnenlicht,10-25 °C,10,medicinal|bright_light|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,180,Bechermalve,Lavatera trimestris,"Bechermalve ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,173,Margerite,Leucanthemum vulgare,"Margerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,201,Shasta-Margerite,Leucanthemum x superbum,"Shasta-Margerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,126,Liebstoeckel,Levisticum officinale,Liebstoeckel ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,23,Lebende Steine,Lithops julii,"Lebende Steine sind faszinierende Mimikry-Sukkulenten, die Kieselsteinen taeuschen aehnlich sehen. Sehr trockenheitsresistent.",Volles Sonnenlicht,10-30 °C,21,succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,154,Lupine,Lupinus polyphyllus,"Lupine ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,79,Mammillaria,Mammillaria zeilmanniana,"Die Mammillaria ist ein kompakter, kugelfoermiger Kaktus, der im Fruehling einen Kranz aus rosa Blueten traegt.",Volles Sonnenlicht,15-35 °C,14,easy|flowering|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,179,Indianernessel,Monarda didyma,"Indianernessel ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,177,Vergissmeinnicht,Myosotis sylvatica,"Vergissmeinnicht ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,199,Nemesie,Nemesia strumosa,"Nemesie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,132,Katzenminze,Nepeta cataria,Katzenminze ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,120,Oleander,Nerium oleander,"Der Oleander ist ein mediteraner Strauch mit leuchtend roten, rosa oder weissen Blueten. Sehr hitzetolerant.",Volles Sonnenlicht,15-28 °C,7,flowering|bright_light|sun,,,,, +sun,constants/lexiconBatch2.ts,193,Ziertabak,Nicotiana alata,"Ziertabak ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,25,Basilikum,Ocimum basilicum,"Basilikum ist das beliebteste Kuechenkraut mit intensiv aromatischen, gruenen Blaettern. Fuer Pesto verwendet.",Volles Sonnenlicht,18-30 °C,2,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch1.ts,82,Hasenohren-Kaktus,Opuntia microdasys,"Der Hasenohren-Kaktus hat flache, ovale Triebe mit dichten weissen Glochiden. Klassischer Zimmerkaktus.",Volles Sonnenlicht,10-35 °C,21,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,124,Majoran,Origanum majorana,Majoran ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch1.ts,28,Oregano,Origanum vulgare,"Oregano ist ein aromatisches Kuechenkraut mit runden, behaarten Blaettern. In mediterraner Kueche beliebt.",Volles Sonnenlicht,15-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,200,Kapmargerite,Osteospermum ecklonis,"Kapmargerite ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,88,Mondstein-Pflanze,Pachyphytum oviferum,"Die Mondstein-Pflanze hat dicke, ovale Blaetter mit einem pastellrosafarbenen, mehligen Ueberzug.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,143,Pfingstrose,Paeonia lactiflora,"Pfingstrose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,185,Mohn,Papaver rhoeas,"Mohn ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,31,Rosengeranie,Pelargonium graveolens,Die Rosengeranie ist eine Duftpflanze mit tief eingeschnittenen Blaettern und rosaenlichem Aroma.,Volles Sonnenlicht,15-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,61,Efeu-Geranie,Pelargonium peltatum,"Die Efeu-Geranie hat efeufoermige, glaenzende Blaetter und bluet den ganzen Sommer in leuchtenden Farben.",Helles bis volles Licht,15-25 °C,5,easy|flowering|hanging|sun,,,,, +sun,constants/lexiconBatch2.ts,174,Stehende Geranie,Pelargonium zonale,"Stehende Geranie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,134,Shiso,Perilla frutescens,Shiso ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch1.ts,34,Petunie,Petunia hybrida,Die Petunie ist eine der beliebtesten Balkonpflanzen mit trichterfoermigen Blueten in unzaehligen Farben.,Volles Sonnenlicht,15-25 °C,2,easy|pet_friendly|flowering|sun,pet_friendly_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,165,Flammenblume,Phlox paniculata,"Flammenblume ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,207,Fichte,Picea abies,Fichte ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,206,Kiefer,Pinus sylvestris,Kiefer ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch1.ts,61,Bleiwurz,Plumbago auriculata,"Die Bleiwurz ist ein halbimmergruener Strauch mit himmelblauen Blueten, der fast das ganze Jahr bluet.",Volles Sonnenlicht,15-27 °C,5,flowering|bright_light|sun,,,,, +sun,constants/lexiconBatch2.ts,118,Tempel-Baum,Plumeria rubra,"Der Tempel-Baum hat intensiv duftende, sternfoermige Blueten in Weiss, Gelb oder Rosa. Klassische Tropenblume.",Volles Sonnenlicht,20-30 °C,7,flowering|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,27,Speckbaum,Portulacaria afra,"Der Speckbaum ist eine sukkulente Pflanze mit roten Stielen und kleinen, runden, glaenzenden Blaettern.",Helles bis volles Licht,15-30 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,71,Koenigs-Protea,Protea cynaroides,"Die Koenigs-Protea ist die Nationalblume Suedafrikas mit riesigen, imposanten Bluetenkoepfen. Eine echte Besonderheit.",Volles Sonnenlicht,10-25 °C,7,flowering|large|sun,,,,, +sun,constants/lexiconBatch2.ts,218,Kirschlorbeer,Prunus laurocerasus,Kirschlorbeer ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|sun,,,,, +sun,constants/lexiconBatch2.ts,89,Guave,Psidium guajava,Die Guave ist ein tropischer Obstbaum mit gelblich-weissen Fruechten. Sie ist reich an Vitamin C.,Volles Sonnenlicht,18-30 °C,7,tree|sun,,,,, +sun,constants/lexiconBatch2.ts,88,Granatapfelbaum,Punica granatum,"Der Granatapfelbaum hat leuchtend rote Blueten und rote, essbare Fruechte mit rubinroten Kernen.",Volles Sonnenlicht,15-28 °C,7,flowering|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,205,Eiche,Quercus robur,Eiche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,162,Ranunkel,Ranunculus asiaticus,"Ranunkel ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,214,Robinie,Robinia pseudoacacia,Robinie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch1.ts,66,Chinesische Rose,Rosa chinensis,Die Chinesische Rose ist eine der Stammarten vieler Gartenrosen und bluet fast ununterbrochen.,Volles Sonnenlicht,15-25 °C,5,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,142,Rose,Rosa x hybrida,"Rose ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|bright_light|sun,,,,, +sun,constants/lexiconBatch1.ts,24,Rosmarin,Rosmarinus officinalis,Rosmarin ist ein aromatisches Kraut mit nadelartigen Blaettern und blauen Blueten. In der Kueche unverzichtbar.,Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,167,Rudbeckie,Rudbeckia hirta,"Rudbeckie ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,130,Sauerampfer,Rumex acetosa,Sauerampfer ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch2.ts,195,Mehlsalbei,Salvia farinacea,"Mehlsalbei ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,103,Salbei,Salvia officinalis,Salbei ist ein aromatisches Heilkraut mit silbrig-gruenen Blaettern. Er hat antibakterielle und entzuendungshem­mende Wirkung.,Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,168,Feuersalbei,Salvia splendens,"Feuersalbei ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,17,Zylindrischer Bogenhanf,Sansevieria cylindrica,"Der Zylindrische Bogenhanf hat zylindrische, aufrechte Blaetter, die sich nach oben verjuengen. Sehr pflegeleicht.",Helles bis volles Licht,15-27 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,78,Purpursonnentau,Sarracenia purpurea,Der Purpursonnentau ist eine fleischfressende Kannenpflanze mit purpurroten Kannen. Faengt Insekten.,Volles Sonnenlicht,5-25 °C,3,high_humidity|sun,,,,, +sun,constants/lexiconBatch2.ts,123,Bohnenkraut,Satureja hortensis,Bohnenkraut ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch1.ts,7,Eselschwanz,Sedum morganianum,"Der Eselschwanz ist eine haengende Sukkulente mit langen Trieben aus dichten, blaugruenen Blaettchen.",Volles Sonnenlicht,15-25 °C,14,easy|succulent|hanging|sun,,,,, +sun,constants/lexiconBatch2.ts,28,Blauer Kreuzkraut,Senecio serpens,"Der Blaue Kreuzkraut hat zylindrische, blaublaugruene Blaetter und einen kriechenden Wuchs. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,14,easy|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,93,Aubergine,Solanum melongena,"Die Aubergine ist eine Gemuese­pflanze mit grossen, violetten Fruechten. Sie benoetigt viel Waerme und Sonne.",Volles Sonnenlicht,20-30 °C,5,bright_light|sun,,,,, +sun,constants/lexiconBatch2.ts,213,Eberesche,Sorbus aucuparia,Eberesche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,222,Spierstrauch,Spiraea japonica,Spierstrauch ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,25,Aasblume,Stapelia grandiflora,"Die Aasblume hat fleischige, gruene Staengel und riesige, sternfoermige Blueten mit aasartigem Duft.",Helles bis volles Licht,18-30 °C,14,flowering|succulent|sun,,,,, +sun,constants/lexiconBatch2.ts,131,Stevia,Stevia rebaudiana,Stevia ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.,Helles bis volles Licht,12-24 C,5,easy|sun,,,,, +sun,constants/lexiconBatch1.ts,3,Paradiesvogelblume,Strelitzia reginae,"Die Paradiesvogelblume beeindruckt mit leuchtend orangefarbenen und blauen Blueten, die einem Vogel aehneln.",Volles Sonnenlicht,18-26 °C,7,flowering|large|sun,,,,, +sun,constants/lexiconBatch2.ts,166,Herbstaster,Symphyotrichum novi-belgii,"Herbstaster ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,149,Flieder,Syringa vulgaris,"Flieder ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,66,Studentenblume,Tagetes patula,Die Studentenblume ist eine robuste Sommerblume mit orangen oder gelben Blueten. Sie haelt Schadlinge fern.,Volles Sonnenlicht,15-28 °C,3,easy|flowering|sun,,,,, +sun,constants/lexiconBatch1.ts,27,Thymian,Thymus vulgaris,"Thymian ist ein kleiner, aromatischer Strauch mit winzigen Blaettern und rosa Blueten. Wichtiges Kuechenkraut.",Volles Sonnenlicht,10-25 °C,7,easy|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,54,Lila Tradescantia,Tradescantia pallida,Die Lila Tradescantia hat leuchtend purpurrote Blaetter und ist sehr auffaellig. Sie liebt viel Licht.,Helles bis volles Licht,15-25 °C,5,easy|hanging|sun,,,,, +sun,constants/lexiconBatch2.ts,151,Kapuzinerkresse,Tropaeolum majus,"Kapuzinerkresse ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,82,Wasserschlauch,Utricularia gibba,Der Wasserschlauch ist eine wasserbewohnende fleischfressende Pflanze mit Schlaeuchen als Insekten­fallen.,Helles bis volles Licht,15-25 °C,2,high_humidity|sun,,,,, +sun,constants/lexiconBatch2.ts,192,Koenigskerze,Verbascum thapsus,"Koenigskerze ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|medicinal|sun,medicinal_requires_external_evidence,,,, +sun,constants/lexiconBatch2.ts,164,Eisenkraut,Verbena bonariensis,"Eisenkraut ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,198,Hornveilchen,Viola cornuta,"Hornveilchen ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|sun,,,,, +sun,constants/lexiconBatch2.ts,5,Mexikanische Fächerpalme,Washingtonia robusta,"Die Mexikanische Fächerpalme ist eine schlanke, hohe Palme mit faecher­foermigen Blaettern. Sehr hitzetolerant.",Volles Sonnenlicht,15-35 °C,10,tree|large|sun,,,,, +sun,constants/lexiconBatch2.ts,221,Weigelie,Weigela florida,Weigelie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +sun,constants/lexiconBatch1.ts,65,Chinesischer Blauregen,Wisteria sinensis,"Der Chinesische Blauregen ist ein ueppiger Kletterkuenstler mit langen, duftenden Bluetentrauben in Lila.",Volles Sonnenlicht,10-25 °C,7,flowering|large|sun,,,,, +sun,constants/lexiconBatch2.ts,246,Yucca aloifolia,Yucca aloifolia,Yucca aloifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Volles Sonnenlicht,18-30 C,10,easy|tree|sun,,,,, +sun,constants/lexiconBatch1.ts,40,Yucca-Palme,Yucca elephantipes,"Die Yucca-Palme ist eine robuste Zimmerpflanze mit starrem, immergruenem Blaetterschopf auf einem dicken Stamm.",Helles bis volles Licht,15-28 °C,14,easy|tree|sun,,,,, +sun,constants/lexiconBatch2.ts,65,Zinnie,Zinnia elegans,"Die Zinnie ist eine leuchtende Sommerblume mit grossen, dahlienaehnlichen Blueten. Sehr robust und hitzetolerant.",Volles Sonnenlicht,18-30 °C,3,easy|flowering|sun,,,,, +tree,constants/lexiconBatch2.ts,115,Faecherahorn,Acer palmatum,"Der Faecherahorn ist ein japanischer Zierahorn mit feingeschnittenen, faecherfoermigen Blaettern in Gruen oder Rot.",Helles bis volles Licht,10-22 °C,5,tree,,,,, +tree,constants/lexiconBatch2.ts,212,Spitzahorn,Acer platanoides,Spitzahorn ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,232,Norfolk-Tanne,Araucaria heterophylla,Norfolk-Tanne ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,tree|bright_light,,,,, +tree,constants/lexiconBatch1.ts,41,Pferdeschwanzpalme,Beaucarnea recurvata,"Die Pferdeschwanzpalme hat einen verdickten Stammbasis als Wasserspeicher und lange, schmale Blaetter.",Volles Sonnenlicht,15-30 °C,21,easy|succulent|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,114,Hange-Birke,Betula pendula,Die Haenge-Birke hat charakteristisch weisse Rinde und haengende Zweige. Die Blaetter werden in der Heilkunde genutzt.,Volles Sonnenlicht,10-25 °C,7,tree|large|medicinal,medicinal_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,223,Schmetterlingsflieder,Buddleja davidii,Schmetterlingsflieder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,202,Buchsbaum,Buxus sempervirens,Buchsbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|sun,,,,, +tree,constants/lexiconBatch2.ts,217,Trompetenbaum,Catalpa bignonioides,Trompetenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,208,Zeder,Cedrus libani,Zeder ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,Die Bergpalme ist eine kompakte Zimmerpalme fuer schattigere Standorte. Ideal fuer dunkle Innenraeume.,Wenig bis helles Licht,15-25 °C,7,easy|pet_friendly|tree|air_purifier|low_light,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,86,Zitronenbaum,Citrus limon,"Der Zitronenbaum ist ein kleiner, immergruener Baum mit weissen, duftenden Blueten und gelben Fruechten.",Volles Sonnenlicht,18-28 °C,5,tree|sun,,,,, +tree,constants/lexiconBatch2.ts,87,Orangenbaum,Citrus sinensis,"Der Orangenbaum ist ein kleiner, immergruener Baum mit weissen Blueten und orangen Fruechten.",Volles Sonnenlicht,18-28 °C,5,tree|sun,,,,, +tree,constants/lexiconBatch2.ts,14,Keulenlilie,Cordyline australis,"Die Keulenlilie hat lange, schmale, gruene oder rotbraune Blaetter in einem dekorativen Schopf.",Helles bis volles Licht,10-25 °C,7,easy|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,209,Zypresse,Cupressus sempervirens,Zypresse ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,239,Palmfarn,Cycas revoluta,Palmfarn ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles bis volles Licht,18-30 C,10,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,215,Flammenbaum,Delonix regia,Flammenbaum ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +tree,constants/lexiconBatch1.ts,14,Maisstrauch,Dracaena fragrans,"Der Maisstrauch ist eine robuste Zimmerpflanze mit breiten, gestreiften Blaettern. Gedeiht auch bei wenig Licht.",Helles indirektes Licht,15-25 °C,10,easy|tree|air_purifier|low_light,air_purifier_requires_external_evidence,,,, +tree,constants/lexiconBatch1.ts,13,Drachenbaum,Dracaena marginata,"Der Drachenbaum ist eine schlanke Zimmerpflanze mit roten, schmalen Blaettern auf langen Staemmen.",Helles indirektes Licht,15-25 °C,10,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +tree,constants/lexiconBatch1.ts,42,Goldfruchtpalme,Dypsis lutescens,Die Goldfruchtpalme ist eine elegante Zimmerpalme mit gelblich-gruenen Stielen und gefiederten Wedeln.,Helles indirektes Licht,18-27 °C,5,pet_friendly|tree|air_purifier,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,210,Eukalyptus,Eucalyptus globulus,Eukalyptus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|medicinal|sun,medicinal_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,248,Ficus altissima,Ficus altissima,Ficus altissima ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,tree|bright_light,,,,, +tree,constants/lexiconBatch1.ts,1,Birkenfeige,Ficus benjamina,"Die Birkenfeige ist ein eleganter Zimmerstrauch mit haengenden Aesten und kleinen, glaenzenden Blaettern.",Helles indirektes Licht,16-24 °C,7,tree|air_purifier,air_purifier_requires_external_evidence,,,, +tree,constants/lexiconBatch1.ts,38,Gummibaum,Ficus elastica,"Der Gummibaum ist eine imposante Zimmerpflanze mit grossen, glaenzenden, lederartigen Blaettern. Reinigt die Luft.",Helles indirektes Licht,16-24 °C,10,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +tree,constants/lexiconBatch1.ts,39,Geigenfeige,Ficus lyrata,"Die Geigenfeige ist ein Trendbaum mit grossen, geigenfoermigen Blaettern. Benoetigt viel Licht.",Helles indirektes Licht,18-27 °C,7,tree|large|bright_light,,,,, +tree,constants/lexiconBatch2.ts,247,Ficus microcarpa,Ficus microcarpa,Ficus microcarpa ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|tree|bright_light,,,,, +tree,constants/lexiconBatch2.ts,116,Bonsai-Feige,Ficus retusa,"Die Bonsai-Feige ist eine klassische Bonsai-Art mit kleinen, elliptischen Blaettern. Sehr formbar.",Helles indirektes Licht,16-24 °C,7,tree,,,,, +tree,constants/lexiconBatch2.ts,219,Forsythie,Forsythia x intermedia,Forsythie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,216,Ginkgo,Ginkgo biloba,Ginkgo ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|medicinal|sun,medicinal_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,220,Gartenhibiskus,Hibiscus syriacus,Gartenhibiskus ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,3,Kentia-Palme,Howea forsteriana,"Die Kentia-Palme ist eine der elegantesten Zimmerpalmen mit langen, herabhängenden Fiederblaettern.",Helles indirektes Licht,18-25 °C,7,pet_friendly|tree|low_light,pet_friendly_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,203,Stechpalme,Ilex aquifolium,Stechpalme ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|sun,,,,, +tree,constants/lexiconBatch2.ts,211,Jacaranda,Jacaranda mimosifolia,Jacaranda ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +tree,constants/lexiconBatch2.ts,4,Chinesische Fächerpalme,Livistona chinensis,"Die Chinesische Fächerpalme hat grosse, faecher­foermige Blaetter auf einem einzelnen Stamm. Sehr dekorativ.",Helles bis volles Licht,15-25 °C,7,tree|bright_light,,,,, +tree,constants/lexiconBatch2.ts,204,Magnolie,Magnolia grandiflora,Magnolie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|large,,,,, +tree,constants/lexiconBatch2.ts,231,Glueckskastanie,Pachira aquatica,Glueckskastanie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,easy|tree|bright_light,,,,, +tree,constants/lexiconBatch1.ts,44,Zwergdattelpalme,Phoenix roebelenii,"Die Zwergdattelpalme ist eine zierliche Palme mit eleganten, gebogenen Fiederblaettern. Tropisches Flair.",Helles bis volles Licht,18-27 °C,7,tree|bright_light,,,,, +tree,constants/lexiconBatch2.ts,207,Fichte,Picea abies,Fichte ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,206,Kiefer,Pinus sylvestris,Kiefer ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,118,Tempel-Baum,Plumeria rubra,"Der Tempel-Baum hat intensiv duftende, sternfoermige Blueten in Weiss, Gelb oder Rosa. Klassische Tropenblume.",Volles Sonnenlicht,20-30 °C,7,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,218,Kirschlorbeer,Prunus laurocerasus,Kirschlorbeer ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|sun,,,,, +tree,constants/lexiconBatch2.ts,89,Guave,Psidium guajava,Die Guave ist ein tropischer Obstbaum mit gelblich-weissen Fruechten. Sie ist reich an Vitamin C.,Volles Sonnenlicht,18-30 °C,7,tree|sun,,,,, +tree,constants/lexiconBatch2.ts,88,Granatapfelbaum,Punica granatum,"Der Granatapfelbaum hat leuchtend rote Blueten und rote, essbare Fruechte mit rubinroten Kernen.",Volles Sonnenlicht,15-28 °C,7,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,205,Eiche,Quercus robur,Eiche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch1.ts,45,Stab-Palme,Rhapis excelsa,"Die Stab-Palme ist eine elegante Zimmerpalme mit faecher­foermigen Blaettern auf duennen, bambusartigen Staemmen.",Helles indirektes Licht,15-25 °C,7,tree|low_light,,,,, +tree,constants/lexiconBatch2.ts,170,Rhododendron,Rhododendron catawbiense,"Rhododendron ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|tree|bright_light,,,,, +tree,constants/lexiconBatch2.ts,214,Robinie,Robinia pseudoacacia,Robinie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,113,Silber-Weide,Salix alba,"Die Silber-Weide hat silbrig-glaenzende Blaetter. Weidenrinde enthält Salicylsaeure, die Grundlage von Aspirin.",Helles bis volles Licht,10-25 °C,7,tree|large|medicinal,medicinal_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,112,Schwarzer Holunder,Sambucus nigra,Der Schwarze Holunder hat weisse Doldenbluten und schwarze Beeren. Die Fruechte werden fuer Sirup und Saft verwendet.,Helles bis volles Licht,10-25 °C,7,flowering|tree|medicinal,medicinal_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,11,Grosse Strahlenaralie,Schefflera actinophylla,"Die Grosse Strahlenaralie kann grosse, handfoermige Blaetter entwickeln. Sie ist ideal als Zimmerstrauch.",Helles indirektes Licht,18-27 °C,7,easy|tree|large,,,,, +tree,constants/lexiconBatch2.ts,10,Strahlenaralie,Schefflera arboricola,"Die Strahlenaralie hat fingerfoermig angeordnete, glaenzende Blaetter auf langen Stielen. Sehr robuste Zimmerpflanze.",Helles indirektes Licht,15-25 °C,7,easy|tree|air_purifier,air_purifier_requires_external_evidence,,,, +tree,constants/lexiconBatch2.ts,235,Falsche Aralie,Schefflera elegantissima,Falsche Aralie ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Helles indirektes Licht,18-27 C,7,tree|bright_light,,,,, +tree,constants/lexiconBatch2.ts,213,Eberesche,Sorbus aucuparia,Eberesche ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,222,Spierstrauch,Spiraea japonica,Spierstrauch ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,1,Weisse Strelitzie,Strelitzia nicolai,"Die Weisse Strelitzie ist ein beeindruckender Zimmerstrauch mit grossen, blaugruenen Blaettern und weiss-blauen Blueten.",Helles bis volles Licht,18-27 °C,7,tree|large|bright_light,,,,, +tree,constants/lexiconBatch2.ts,149,Flieder,Syringa vulgaris,"Flieder ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.",Volles bis helles Licht,10-24 C,4,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,5,Mexikanische Fächerpalme,Washingtonia robusta,"Die Mexikanische Fächerpalme ist eine schlanke, hohe Palme mit faecher­foermigen Blaettern. Sehr hitzetolerant.",Volles Sonnenlicht,15-35 °C,10,tree|large|sun,,,,, +tree,constants/lexiconBatch2.ts,221,Weigelie,Weigela florida,Weigelie ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.,Volles bis helles Licht,5-25 C,7,flowering|tree|sun,,,,, +tree,constants/lexiconBatch2.ts,246,Yucca aloifolia,Yucca aloifolia,Yucca aloifolia ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.,Volles Sonnenlicht,18-30 C,10,easy|tree|sun,,,,, +tree,constants/lexiconBatch1.ts,40,Yucca-Palme,Yucca elephantipes,"Die Yucca-Palme ist eine robuste Zimmerpflanze mit starrem, immergruenem Blaetterschopf auf einem dicken Stamm.",Helles bis volles Licht,15-28 °C,14,easy|tree|sun,,,,, diff --git a/audits/semantic-search/review-change-candidates.md b/audits/semantic-search/review-change-candidates.md new file mode 100644 index 0000000..90d2129 --- /dev/null +++ b/audits/semantic-search/review-change-candidates.md @@ -0,0 +1,98 @@ +# Review Change Candidates + +Date: 2026-03-12 + +Purpose: +- collect the user-provided `AENDERN` review items in one place +- separate already-applied semantic fixes from deferred raw source array reordering + +Status summary: +- semantic fixes: applied +- export ordering: already normalized in `all-plants-categories.csv` +- source-array ordering in the batch files: deferred on purpose + +## Applied Semantic Fixes + +- `Anthurium clarinervium`: `patterned|high_humidity|pet_friendly` -> `patterned|high_humidity` +- `Anthurium crystallinum`: `patterned|high_humidity|pet_friendly` -> `patterned|high_humidity` +- `Camellia sinensis`: `[]` -> `flowering` +- `Mimosa pudica`: `[]` -> `flowering|bright_light` +- `Spinacia oleracea`: `[]` -> `easy` + +## Deferred Raw Source Array Reordering + +These were left out of the source files because the export generator now canonicalizes category order in `all-plants-categories.csv`. If you still want the raw `categories` arrays in the batch files normalized too, these are the deferred candidates from the review list. + +- `Acer platanoides`: `tree|sun|large` -> `tree|large|sun` +- `Achillea millefolium`: `medicinal|flowering|sun` -> `flowering|medicinal|sun` +- `Adenium obesum`: `succulent|flowering|sun` -> `flowering|succulent|sun` +- `Adenium socotranum`: `succulent|flowering|sun` -> `flowering|succulent|sun` +- `Agave americana`: `succulent|sun|large` -> `succulent|large|sun` +- `Aglaonema commutatum`: `easy|low_light|patterned` -> `easy|patterned|low_light` +- `Alocasia amazonica`: `patterned|high_humidity|large` -> `patterned|large|high_humidity` +- `Aloe ferox`: `succulent|medicinal|sun|large` -> `succulent|medicinal|large|sun` +- `Alpinia zerumbet`: `flowering|high_humidity|large` -> `flowering|large|high_humidity` +- `Solanum aviculare`: `medicinal|flowering|sun` -> `flowering|medicinal|sun` +- `Solanum laciniatum`: `medicinal|flowering|sun` -> `flowering|medicinal|sun` +- `Strelitzia reginae`: `flowering|sun|large` -> `flowering|large|sun` +- `Agapanthus africanus`: `flowering|sun|large` -> `flowering|large|sun` +- `Aquilegia vulgaris`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Momordica balsamina`: `flowering|sun|medicinal` -> `flowering|medicinal|sun` +- `Thunbergia alata`: `flowering|sun|hanging` -> `flowering|hanging|sun` +- `Gerbera jamesonii`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Hibiscus rosa-sinensis`: `flowering|sun|large` -> `flowering|large|sun` +- `Bergenia cordifolia`: `flowering|low_light|large` -> `flowering|large|low_light` +- `Photinia serratifolia`: `tree|sun|large` -> `tree|large|sun` +- `Chrysanthemum morifolium`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Galanthus nivalis`: `flowering|low_light|pet_friendly` -> `flowering|pet_friendly|low_light` +- `Leucojum aestivum`: `flowering|low_light|pet_friendly` -> `flowering|pet_friendly|low_light` +- `Cyclamen persicum`: `flowering|low_light|pet_friendly` -> `flowering|pet_friendly|low_light` +- `Narcissus pseudonarcissus`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Dahlia pinnata`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Photinia fraseri`: `tree|sun|large` -> `tree|large|sun` +- `Rosa canina`: `flowering|sun|medicinal` -> `flowering|medicinal|sun` +- `Acer campestre`: `tree|sun|large` -> `tree|large|sun` +- `Amelanchier ovalis`: `flowering|sun|large` -> `flowering|large|sun` +- `Howea forsteriana`: `easy|pet_friendly|large|air_purifier|bright_light` -> `easy|pet_friendly|air_purifier|large|bright_light` +- `Dracaena trifasciata`: `easy|air_purifier|low_light|large` -> `easy|air_purifier|large|low_light` +- `Lobularia maritima`: `flowering|sun|hanging` -> `flowering|hanging|sun` +- `Buxus sempervirens`: `tree|sun|large` -> `tree|large|sun` +- `Cosmos bipinnatus`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Lilium candidum`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Origanum vulgare`: `medicinal|sun|pet_friendly` -> `medicinal|pet_friendly|sun` +- `Rudbeckia hirta`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Hibiscus syriacus`: `flowering|sun|large` -> `flowering|large|sun` +- `Sedum acre`: `succulent|sun|pet_friendly` -> `succulent|pet_friendly|sun` +- `Fatsia japonica`: `tree|low_light|large` -> `tree|large|low_light` +- `Ocimum tenuiflorum`: `medicinal|sun|flowering` -> `flowering|medicinal|sun` +- `Ulmus minor`: `tree|sun|large` -> `tree|large|sun` +- `Ulmus americana`: `tree|sun|large` -> `tree|large|sun` +- `Ulmus glabra`: `tree|sun|large` -> `tree|large|sun` +- `Aloysia citrodora`: `medicinal|sun|flowering` -> `flowering|medicinal|sun` +- `Cucumis sativus`: `easy|sun|hanging` -> `easy|hanging|sun` +- `Citrullus lanatus`: `easy|sun|hanging` -> `easy|hanging|sun` +- `Hypoestes phyllostachya`: `patterned|bright_light|pet_friendly` -> `patterned|pet_friendly|bright_light` +- `Nephrolepis exaltata`: `air_purifier|high_humidity|pet_friendly` -> `air_purifier|pet_friendly|high_humidity` +- `Phalaenopsis amabilis`: `flowering|high_humidity|pet_friendly` -> `flowering|pet_friendly|high_humidity` +- `Plantago major`: `medicinal|sun|pet_friendly` -> `medicinal|pet_friendly|sun` +- `Chaenomeles japonica`: `flowering|sun|large` -> `flowering|large|sun` +- `Rhododendron ferrugineum`: `flowering|low_light|large` -> `flowering|large|low_light` +- `Brassica napus napobrassica`: `easy|sun|large` -> `easy|large|sun` +- `Salvia apiana`: `medicinal|sun|flowering` -> `flowering|medicinal|sun` +- `Salvia canariensis`: `medicinal|sun|flowering` -> `flowering|medicinal|sun` +- `Helianthus annuus`: `flowering|sun|large` -> `flowering|large|sun` +- `Syringa vulgaris`: `flowering|sun|large` -> `flowering|large|sun` +- `Calystegia sepium`: `flowering|sun|hanging` -> `flowering|hanging|sun` +- `Vanilla planifolia`: `flowering|high_humidity|hanging` -> `flowering|hanging|high_humidity` +- `Vanda coerulea`: `flowering|high_humidity|bright_light` -> `flowering|bright_light|high_humidity` +- `Verbascum thapsus`: `flowering|sun|medicinal` -> `flowering|medicinal|sun` +- `Washingtonia robusta`: `tree|sun|large` -> `tree|large|sun` +- `Wisteria sinensis`: `flowering|sun|large` -> `flowering|large|sun` +- `Yucca aloifolia`: `tree|sun|easy` -> `easy|tree|sun` + +## Notes + +- Some review items were omitted because they were explicit no-ops, duplicate rows, or already effectively normalized by the export layer. +- The obvious no-op reorder rows were removed from this file during cleanup. +- Some older order proposals may now be stale if a later semantic audit intentionally changed the underlying categories. +- The canonical order visible to QA should be taken from `all-plants-categories.csv`, not from the raw category array order inside the batch source files. diff --git a/audits/semantic-search/summary.json b/audits/semantic-search/summary.json new file mode 100644 index 0000000..22189fc --- /dev/null +++ b/audits/semantic-search/summary.json @@ -0,0 +1,76 @@ +{ + "generatedAt": "2026-03-12T14:15:29.567Z", + "totalEntries": 358, + "categories": [ + { + "category": "pet_friendly", + "count": 15, + "priority": 1 + }, + { + "category": "air_purifier", + "count": 12, + "priority": 2 + }, + { + "category": "medicinal", + "count": 32, + "priority": 3 + }, + { + "category": "low_light", + "count": 16, + "priority": 4 + }, + { + "category": "bright_light", + "count": 42, + "priority": 5 + }, + { + "category": "sun", + "count": 172, + "priority": 6 + }, + { + "category": "easy", + "count": 132, + "priority": 7 + }, + { + "category": "high_humidity", + "count": 51, + "priority": 8 + }, + { + "category": "hanging", + "count": 34, + "priority": 9 + }, + { + "category": "tree", + "count": 59, + "priority": 10 + }, + { + "category": "large", + "count": 35, + "priority": 11 + }, + { + "category": "patterned", + "count": 31, + "priority": 12 + }, + { + "category": "flowering", + "count": 157, + "priority": 13 + }, + { + "category": "succulent", + "count": 46, + "priority": 14 + } + ] +} diff --git a/audits/semantic-search/suspicious.csv b/audits/semantic-search/suspicious.csv new file mode 100644 index 0000000..2846fe8 --- /dev/null +++ b/audits/semantic-search/suspicious.csv @@ -0,0 +1,163 @@ +category,source_file,source_index,name,botanical_name,risk_flags +air_purifier,constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence +air_purifier,constants/lexiconBatch1.ts,48,Dieffenbachie,Dieffenbachia seguine,air_purifier_requires_external_evidence +air_purifier,constants/lexiconBatch1.ts,14,Maisstrauch,Dracaena fragrans,air_purifier_requires_external_evidence +air_purifier,constants/lexiconBatch1.ts,13,Drachenbaum,Dracaena marginata,air_purifier_requires_external_evidence +air_purifier,constants/lexiconBatch1.ts,42,Goldfruchtpalme,Dypsis lutescens,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence +air_purifier,constants/lexiconBatch1.ts,16,Marmor-Efeutute,Epipremnum aureum Marble Queen,air_purifier_requires_external_evidence +air_purifier,constants/lexiconBatch2.ts,53,Neon-Efeutute,Epipremnum pinnatum Neon,air_purifier_requires_external_evidence +air_purifier,constants/lexiconBatch1.ts,1,Birkenfeige,Ficus benjamina,air_purifier_requires_external_evidence +air_purifier,constants/lexiconBatch1.ts,38,Gummibaum,Ficus elastica,air_purifier_requires_external_evidence +air_purifier,constants/lexiconBatch1.ts,68,Gerbera,Gerbera jamesonii,air_purifier_requires_external_evidence +air_purifier,constants/lexiconBatch1.ts,37,Efeu,Hedera helix,air_purifier_requires_external_evidence +air_purifier,constants/lexiconBatch2.ts,10,Strahlenaralie,Schefflera arboricola,air_purifier_requires_external_evidence +bright_light,constants/lexiconBatch1.ts,68,Gerbera,Gerbera jamesonii,air_purifier_requires_external_evidence +bright_light,constants/lexiconBatch1.ts,23,Echter Lavendel,Lavandula angustifolia,medicinal_requires_external_evidence +easy,constants/lexiconBatch1.ts,89,Kap-Aloe,Aloe arborescens,medicinal_requires_external_evidence +easy,constants/lexiconBatch2.ts,92,Chili,Capsicum annuum,medicinal_requires_external_evidence +easy,constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence +easy,constants/lexiconBatch2.ts,138,Roemische Kamille,Chamaemelum nobile,medicinal_requires_external_evidence +easy,constants/lexiconBatch2.ts,101,Kamille,Chamomilla recutita,medicinal_requires_external_evidence +easy,constants/lexiconBatch1.ts,48,Dieffenbachie,Dieffenbachia seguine,air_purifier_requires_external_evidence +easy,constants/lexiconBatch1.ts,14,Maisstrauch,Dracaena fragrans,air_purifier_requires_external_evidence +easy,constants/lexiconBatch1.ts,13,Drachenbaum,Dracaena marginata,air_purifier_requires_external_evidence +easy,constants/lexiconBatch1.ts,16,Marmor-Efeutute,Epipremnum aureum Marble Queen,air_purifier_requires_external_evidence +easy,constants/lexiconBatch2.ts,53,Neon-Efeutute,Epipremnum pinnatum Neon,air_purifier_requires_external_evidence +easy,constants/lexiconBatch1.ts,38,Gummibaum,Ficus elastica,air_purifier_requires_external_evidence +easy,constants/lexiconBatch2.ts,100,Erdbeere,Fragaria ananassa,pet_friendly_requires_external_evidence +easy,constants/lexiconBatch1.ts,37,Efeu,Hedera helix,air_purifier_requires_external_evidence +easy,constants/lexiconBatch2.ts,102,Zitronenmelisse,Melissa officinalis,medicinal_requires_external_evidence +easy,constants/lexiconBatch1.ts,25,Basilikum,Ocimum basilicum,medicinal_requires_external_evidence +easy,constants/lexiconBatch1.ts,28,Oregano,Origanum vulgare,medicinal_requires_external_evidence +easy,constants/lexiconBatch1.ts,31,Rosengeranie,Pelargonium graveolens,medicinal_requires_external_evidence +easy,constants/lexiconBatch1.ts,102,Rippenpeperomie,Peperomia caperata,pet_friendly_requires_external_evidence +easy,constants/lexiconBatch1.ts,103,Spiegelpeperomie,Peperomia obtusifolia,pet_friendly_requires_external_evidence +easy,constants/lexiconBatch2.ts,230,Raindrop-Peperomie,Peperomia polybotrya,pet_friendly_requires_external_evidence +easy,constants/lexiconBatch1.ts,34,Petunie,Petunia hybrida,pet_friendly_requires_external_evidence +easy,constants/lexiconBatch2.ts,228,Aluminium-Pflanze,Pilea cadierei,pet_friendly_requires_external_evidence +easy,constants/lexiconBatch1.ts,2,Ufopflanze,Pilea peperomioides,pet_friendly_requires_external_evidence +easy,constants/lexiconBatch1.ts,24,Rosmarin,Rosmarinus officinalis,medicinal_requires_external_evidence +easy,constants/lexiconBatch2.ts,103,Salbei,Salvia officinalis,medicinal_requires_external_evidence +easy,constants/lexiconBatch2.ts,10,Strahlenaralie,Schefflera arboricola,air_purifier_requires_external_evidence +easy,constants/lexiconBatch1.ts,27,Thymian,Thymus vulgaris,medicinal_requires_external_evidence +flowering,constants/lexiconBatch2.ts,108,Schafgarbe,Achillea millefolium,medicinal_requires_external_evidence +flowering,constants/lexiconBatch2.ts,107,Arnika,Arnica montana,medicinal_requires_external_evidence +flowering,constants/lexiconBatch2.ts,187,Ringelblume,Calendula officinalis,medicinal_requires_external_evidence +flowering,constants/lexiconBatch2.ts,160,Maigloeckchen,Convallaria majalis,medicinal_requires_external_evidence +flowering,constants/lexiconBatch2.ts,109,Roter Fingerhut,Digitalis purpurea,medicinal_requires_external_evidence +flowering,constants/lexiconBatch2.ts,106,Sonnenhut,Echinacea purpurea,medicinal_requires_external_evidence +flowering,constants/lexiconBatch1.ts,68,Gerbera,Gerbera jamesonii,air_purifier_requires_external_evidence +flowering,constants/lexiconBatch2.ts,119,Zaubernuss,Hamamelis mollis,medicinal_requires_external_evidence +flowering,constants/lexiconBatch2.ts,105,Johanniskraut,Hypericum perforatum,medicinal_requires_external_evidence +flowering,constants/lexiconBatch1.ts,34,Petunie,Petunia hybrida,pet_friendly_requires_external_evidence +flowering,constants/lexiconBatch2.ts,112,Schwarzer Holunder,Sambucus nigra,medicinal_requires_external_evidence +flowering,constants/lexiconBatch2.ts,104,Baldrian,Valeriana officinalis,medicinal_requires_external_evidence +flowering,constants/lexiconBatch2.ts,192,Koenigskerze,Verbascum thapsus,medicinal_requires_external_evidence +hanging,constants/lexiconBatch1.ts,16,Marmor-Efeutute,Epipremnum aureum Marble Queen,air_purifier_requires_external_evidence +hanging,constants/lexiconBatch2.ts,53,Neon-Efeutute,Epipremnum pinnatum Neon,air_purifier_requires_external_evidence +hanging,constants/lexiconBatch1.ts,37,Efeu,Hedera helix,air_purifier_requires_external_evidence +high_humidity,constants/lexiconBatch2.ts,74,Kurkuma,Curcuma longa,medicinal_requires_external_evidence +high_humidity,constants/lexiconBatch2.ts,240,Calathea lancifolia,Goeppertia insignis,pet_friendly_requires_external_evidence +high_humidity,constants/lexiconBatch2.ts,241,Calathea ornata,Goeppertia ornata,pet_friendly_requires_external_evidence +high_humidity,constants/lexiconBatch1.ts,51,Gebet-Pflanze,Maranta leuconeura,pet_friendly_requires_external_evidence +high_humidity,constants/lexiconBatch2.ts,238,Bubikopf,Soleirolia soleirolii,pet_friendly_requires_external_evidence +high_humidity,constants/lexiconBatch2.ts,75,Ingwer,Zingiber officinale,medicinal_requires_external_evidence +large,constants/lexiconBatch2.ts,18,Kap-Aloe (ferox),Aloe ferox,medicinal_requires_external_evidence +large,constants/lexiconBatch2.ts,114,Hange-Birke,Betula pendula,medicinal_requires_external_evidence +large,constants/lexiconBatch2.ts,113,Silber-Weide,Salix alba,medicinal_requires_external_evidence +low_light,constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence +low_light,constants/lexiconBatch1.ts,48,Dieffenbachie,Dieffenbachia seguine,air_purifier_requires_external_evidence +low_light,constants/lexiconBatch1.ts,14,Maisstrauch,Dracaena fragrans,air_purifier_requires_external_evidence +low_light,constants/lexiconBatch1.ts,37,Efeu,Hedera helix,air_purifier_requires_external_evidence +low_light,constants/lexiconBatch2.ts,3,Kentia-Palme,Howea forsteriana,pet_friendly_requires_external_evidence +low_light,constants/lexiconBatch1.ts,103,Spiegelpeperomie,Peperomia obtusifolia,pet_friendly_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,108,Schafgarbe,Achillea millefolium,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch1.ts,89,Kap-Aloe,Aloe arborescens,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,18,Kap-Aloe (ferox),Aloe ferox,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,107,Arnika,Arnica montana,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,110,Wermut,Artemisia absinthium,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,114,Hange-Birke,Betula pendula,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,187,Ringelblume,Calendula officinalis,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,92,Chili,Capsicum annuum,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,138,Roemische Kamille,Chamaemelum nobile,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,101,Kamille,Chamomilla recutita,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,160,Maigloeckchen,Convallaria majalis,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,74,Kurkuma,Curcuma longa,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,109,Roter Fingerhut,Digitalis purpurea,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,106,Sonnenhut,Echinacea purpurea,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,210,Eukalyptus,Eucalyptus globulus,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,216,Ginkgo,Ginkgo biloba,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,119,Zaubernuss,Hamamelis mollis,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,105,Johanniskraut,Hypericum perforatum,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch1.ts,23,Echter Lavendel,Lavandula angustifolia,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,102,Zitronenmelisse,Melissa officinalis,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch1.ts,25,Basilikum,Ocimum basilicum,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch1.ts,28,Oregano,Origanum vulgare,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch1.ts,31,Rosengeranie,Pelargonium graveolens,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch1.ts,24,Rosmarin,Rosmarinus officinalis,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,113,Silber-Weide,Salix alba,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,103,Salbei,Salvia officinalis,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,112,Schwarzer Holunder,Sambucus nigra,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch1.ts,27,Thymian,Thymus vulgaris,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,111,Grosse Brennessel,Urtica dioica,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,104,Baldrian,Valeriana officinalis,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,192,Koenigskerze,Verbascum thapsus,medicinal_requires_external_evidence +medicinal,constants/lexiconBatch2.ts,75,Ingwer,Zingiber officinale,medicinal_requires_external_evidence +patterned,constants/lexiconBatch2.ts,240,Calathea lancifolia,Goeppertia insignis,pet_friendly_requires_external_evidence +patterned,constants/lexiconBatch2.ts,241,Calathea ornata,Goeppertia ornata,pet_friendly_requires_external_evidence +patterned,constants/lexiconBatch1.ts,51,Gebet-Pflanze,Maranta leuconeura,pet_friendly_requires_external_evidence +patterned,constants/lexiconBatch2.ts,229,Wassermelonen-Peperomie,Peperomia argyreia,pet_friendly_requires_external_evidence +patterned,constants/lexiconBatch2.ts,228,Aluminium-Pflanze,Pilea cadierei,pet_friendly_requires_external_evidence +pet_friendly,constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence +pet_friendly,constants/lexiconBatch1.ts,42,Goldfruchtpalme,Dypsis lutescens,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence +pet_friendly,constants/lexiconBatch2.ts,100,Erdbeere,Fragaria ananassa,pet_friendly_requires_external_evidence +pet_friendly,constants/lexiconBatch2.ts,240,Calathea lancifolia,Goeppertia insignis,pet_friendly_requires_external_evidence +pet_friendly,constants/lexiconBatch2.ts,241,Calathea ornata,Goeppertia ornata,pet_friendly_requires_external_evidence +pet_friendly,constants/lexiconBatch2.ts,3,Kentia-Palme,Howea forsteriana,pet_friendly_requires_external_evidence +pet_friendly,constants/lexiconBatch1.ts,51,Gebet-Pflanze,Maranta leuconeura,pet_friendly_requires_external_evidence +pet_friendly,constants/lexiconBatch2.ts,229,Wassermelonen-Peperomie,Peperomia argyreia,pet_friendly_requires_external_evidence +pet_friendly,constants/lexiconBatch1.ts,102,Rippenpeperomie,Peperomia caperata,pet_friendly_requires_external_evidence +pet_friendly,constants/lexiconBatch1.ts,103,Spiegelpeperomie,Peperomia obtusifolia,pet_friendly_requires_external_evidence +pet_friendly,constants/lexiconBatch2.ts,230,Raindrop-Peperomie,Peperomia polybotrya,pet_friendly_requires_external_evidence +pet_friendly,constants/lexiconBatch1.ts,34,Petunie,Petunia hybrida,pet_friendly_requires_external_evidence +pet_friendly,constants/lexiconBatch2.ts,228,Aluminium-Pflanze,Pilea cadierei,pet_friendly_requires_external_evidence +pet_friendly,constants/lexiconBatch1.ts,2,Ufopflanze,Pilea peperomioides,pet_friendly_requires_external_evidence +pet_friendly,constants/lexiconBatch2.ts,238,Bubikopf,Soleirolia soleirolii,pet_friendly_requires_external_evidence +succulent,constants/lexiconBatch1.ts,89,Kap-Aloe,Aloe arborescens,medicinal_requires_external_evidence +succulent,constants/lexiconBatch2.ts,18,Kap-Aloe (ferox),Aloe ferox,medicinal_requires_external_evidence +sun,constants/lexiconBatch2.ts,108,Schafgarbe,Achillea millefolium,medicinal_requires_external_evidence +sun,constants/lexiconBatch1.ts,89,Kap-Aloe,Aloe arborescens,medicinal_requires_external_evidence +sun,constants/lexiconBatch2.ts,18,Kap-Aloe (ferox),Aloe ferox,medicinal_requires_external_evidence +sun,constants/lexiconBatch2.ts,107,Arnika,Arnica montana,medicinal_requires_external_evidence +sun,constants/lexiconBatch2.ts,110,Wermut,Artemisia absinthium,medicinal_requires_external_evidence +sun,constants/lexiconBatch2.ts,187,Ringelblume,Calendula officinalis,medicinal_requires_external_evidence +sun,constants/lexiconBatch2.ts,92,Chili,Capsicum annuum,medicinal_requires_external_evidence +sun,constants/lexiconBatch2.ts,138,Roemische Kamille,Chamaemelum nobile,medicinal_requires_external_evidence +sun,constants/lexiconBatch2.ts,101,Kamille,Chamomilla recutita,medicinal_requires_external_evidence +sun,constants/lexiconBatch2.ts,106,Sonnenhut,Echinacea purpurea,medicinal_requires_external_evidence +sun,constants/lexiconBatch2.ts,210,Eukalyptus,Eucalyptus globulus,medicinal_requires_external_evidence +sun,constants/lexiconBatch2.ts,100,Erdbeere,Fragaria ananassa,pet_friendly_requires_external_evidence +sun,constants/lexiconBatch2.ts,216,Ginkgo,Ginkgo biloba,medicinal_requires_external_evidence +sun,constants/lexiconBatch2.ts,105,Johanniskraut,Hypericum perforatum,medicinal_requires_external_evidence +sun,constants/lexiconBatch1.ts,23,Echter Lavendel,Lavandula angustifolia,medicinal_requires_external_evidence +sun,constants/lexiconBatch1.ts,25,Basilikum,Ocimum basilicum,medicinal_requires_external_evidence +sun,constants/lexiconBatch1.ts,28,Oregano,Origanum vulgare,medicinal_requires_external_evidence +sun,constants/lexiconBatch1.ts,31,Rosengeranie,Pelargonium graveolens,medicinal_requires_external_evidence +sun,constants/lexiconBatch1.ts,34,Petunie,Petunia hybrida,pet_friendly_requires_external_evidence +sun,constants/lexiconBatch1.ts,24,Rosmarin,Rosmarinus officinalis,medicinal_requires_external_evidence +sun,constants/lexiconBatch2.ts,103,Salbei,Salvia officinalis,medicinal_requires_external_evidence +sun,constants/lexiconBatch1.ts,27,Thymian,Thymus vulgaris,medicinal_requires_external_evidence +sun,constants/lexiconBatch2.ts,192,Koenigskerze,Verbascum thapsus,medicinal_requires_external_evidence +tree,constants/lexiconBatch2.ts,114,Hange-Birke,Betula pendula,medicinal_requires_external_evidence +tree,constants/lexiconBatch1.ts,43,Bergpalme,Chamaedorea elegans,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence +tree,constants/lexiconBatch1.ts,14,Maisstrauch,Dracaena fragrans,air_purifier_requires_external_evidence +tree,constants/lexiconBatch1.ts,13,Drachenbaum,Dracaena marginata,air_purifier_requires_external_evidence +tree,constants/lexiconBatch1.ts,42,Goldfruchtpalme,Dypsis lutescens,air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence +tree,constants/lexiconBatch2.ts,210,Eukalyptus,Eucalyptus globulus,medicinal_requires_external_evidence +tree,constants/lexiconBatch1.ts,1,Birkenfeige,Ficus benjamina,air_purifier_requires_external_evidence +tree,constants/lexiconBatch1.ts,38,Gummibaum,Ficus elastica,air_purifier_requires_external_evidence +tree,constants/lexiconBatch2.ts,216,Ginkgo,Ginkgo biloba,medicinal_requires_external_evidence +tree,constants/lexiconBatch2.ts,3,Kentia-Palme,Howea forsteriana,pet_friendly_requires_external_evidence +tree,constants/lexiconBatch2.ts,113,Silber-Weide,Salix alba,medicinal_requires_external_evidence +tree,constants/lexiconBatch2.ts,112,Schwarzer Holunder,Sambucus nigra,medicinal_requires_external_evidence +tree,constants/lexiconBatch2.ts,10,Strahlenaralie,Schefflera arboricola,air_purifier_requires_external_evidence diff --git a/audits/semantic-search/suspicious.json b/audits/semantic-search/suspicious.json new file mode 100644 index 0000000..7cc72ad --- /dev/null +++ b/audits/semantic-search/suspicious.json @@ -0,0 +1,1298 @@ +[ + { + "category": "air_purifier", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 43, + "name": "Bergpalme", + "botanical_name": "Chamaedorea elegans", + "risk_flags": "air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence" + }, + { + "category": "air_purifier", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 48, + "name": "Dieffenbachie", + "botanical_name": "Dieffenbachia seguine", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "air_purifier", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 14, + "name": "Maisstrauch", + "botanical_name": "Dracaena fragrans", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "air_purifier", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 13, + "name": "Drachenbaum", + "botanical_name": "Dracaena marginata", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "air_purifier", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 42, + "name": "Goldfruchtpalme", + "botanical_name": "Dypsis lutescens", + "risk_flags": "air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence" + }, + { + "category": "air_purifier", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 16, + "name": "Marmor-Efeutute", + "botanical_name": "Epipremnum aureum Marble Queen", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "air_purifier", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 53, + "name": "Neon-Efeutute", + "botanical_name": "Epipremnum pinnatum Neon", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "air_purifier", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 1, + "name": "Birkenfeige", + "botanical_name": "Ficus benjamina", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "air_purifier", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 38, + "name": "Gummibaum", + "botanical_name": "Ficus elastica", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "air_purifier", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 68, + "name": "Gerbera", + "botanical_name": "Gerbera jamesonii", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "air_purifier", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 37, + "name": "Efeu", + "botanical_name": "Hedera helix", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "air_purifier", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 10, + "name": "Strahlenaralie", + "botanical_name": "Schefflera arboricola", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "bright_light", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 68, + "name": "Gerbera", + "botanical_name": "Gerbera jamesonii", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "bright_light", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 23, + "name": "Echter Lavendel", + "botanical_name": "Lavandula angustifolia", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 89, + "name": "Kap-Aloe", + "botanical_name": "Aloe arborescens", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 92, + "name": "Chili", + "botanical_name": "Capsicum annuum", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 43, + "name": "Bergpalme", + "botanical_name": "Chamaedorea elegans", + "risk_flags": "air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 138, + "name": "Roemische Kamille", + "botanical_name": "Chamaemelum nobile", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 101, + "name": "Kamille", + "botanical_name": "Chamomilla recutita", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 48, + "name": "Dieffenbachie", + "botanical_name": "Dieffenbachia seguine", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 14, + "name": "Maisstrauch", + "botanical_name": "Dracaena fragrans", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 13, + "name": "Drachenbaum", + "botanical_name": "Dracaena marginata", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 16, + "name": "Marmor-Efeutute", + "botanical_name": "Epipremnum aureum Marble Queen", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 53, + "name": "Neon-Efeutute", + "botanical_name": "Epipremnum pinnatum Neon", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 38, + "name": "Gummibaum", + "botanical_name": "Ficus elastica", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 100, + "name": "Erdbeere", + "botanical_name": "Fragaria ananassa", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 37, + "name": "Efeu", + "botanical_name": "Hedera helix", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 102, + "name": "Zitronenmelisse", + "botanical_name": "Melissa officinalis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 25, + "name": "Basilikum", + "botanical_name": "Ocimum basilicum", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 28, + "name": "Oregano", + "botanical_name": "Origanum vulgare", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 31, + "name": "Rosengeranie", + "botanical_name": "Pelargonium graveolens", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 102, + "name": "Rippenpeperomie", + "botanical_name": "Peperomia caperata", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 103, + "name": "Spiegelpeperomie", + "botanical_name": "Peperomia obtusifolia", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 230, + "name": "Raindrop-Peperomie", + "botanical_name": "Peperomia polybotrya", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 34, + "name": "Petunie", + "botanical_name": "Petunia hybrida", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 228, + "name": "Aluminium-Pflanze", + "botanical_name": "Pilea cadierei", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 2, + "name": "Ufopflanze", + "botanical_name": "Pilea peperomioides", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 24, + "name": "Rosmarin", + "botanical_name": "Rosmarinus officinalis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 103, + "name": "Salbei", + "botanical_name": "Salvia officinalis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 10, + "name": "Strahlenaralie", + "botanical_name": "Schefflera arboricola", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "easy", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 27, + "name": "Thymian", + "botanical_name": "Thymus vulgaris", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "flowering", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 108, + "name": "Schafgarbe", + "botanical_name": "Achillea millefolium", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "flowering", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 107, + "name": "Arnika", + "botanical_name": "Arnica montana", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "flowering", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 187, + "name": "Ringelblume", + "botanical_name": "Calendula officinalis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "flowering", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 160, + "name": "Maigloeckchen", + "botanical_name": "Convallaria majalis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "flowering", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 109, + "name": "Roter Fingerhut", + "botanical_name": "Digitalis purpurea", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "flowering", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 106, + "name": "Sonnenhut", + "botanical_name": "Echinacea purpurea", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "flowering", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 68, + "name": "Gerbera", + "botanical_name": "Gerbera jamesonii", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "flowering", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 119, + "name": "Zaubernuss", + "botanical_name": "Hamamelis mollis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "flowering", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 105, + "name": "Johanniskraut", + "botanical_name": "Hypericum perforatum", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "flowering", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 34, + "name": "Petunie", + "botanical_name": "Petunia hybrida", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "flowering", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 112, + "name": "Schwarzer Holunder", + "botanical_name": "Sambucus nigra", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "flowering", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 104, + "name": "Baldrian", + "botanical_name": "Valeriana officinalis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "flowering", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 192, + "name": "Koenigskerze", + "botanical_name": "Verbascum thapsus", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "hanging", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 16, + "name": "Marmor-Efeutute", + "botanical_name": "Epipremnum aureum Marble Queen", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "hanging", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 53, + "name": "Neon-Efeutute", + "botanical_name": "Epipremnum pinnatum Neon", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "hanging", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 37, + "name": "Efeu", + "botanical_name": "Hedera helix", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "high_humidity", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 74, + "name": "Kurkuma", + "botanical_name": "Curcuma longa", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "high_humidity", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 240, + "name": "Calathea lancifolia", + "botanical_name": "Goeppertia insignis", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "high_humidity", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 241, + "name": "Calathea ornata", + "botanical_name": "Goeppertia ornata", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "high_humidity", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 51, + "name": "Gebet-Pflanze", + "botanical_name": "Maranta leuconeura", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "high_humidity", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 238, + "name": "Bubikopf", + "botanical_name": "Soleirolia soleirolii", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "high_humidity", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 75, + "name": "Ingwer", + "botanical_name": "Zingiber officinale", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "large", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 18, + "name": "Kap-Aloe (ferox)", + "botanical_name": "Aloe ferox", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "large", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 114, + "name": "Hange-Birke", + "botanical_name": "Betula pendula", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "large", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 113, + "name": "Silber-Weide", + "botanical_name": "Salix alba", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "low_light", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 43, + "name": "Bergpalme", + "botanical_name": "Chamaedorea elegans", + "risk_flags": "air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence" + }, + { + "category": "low_light", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 48, + "name": "Dieffenbachie", + "botanical_name": "Dieffenbachia seguine", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "low_light", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 14, + "name": "Maisstrauch", + "botanical_name": "Dracaena fragrans", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "low_light", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 37, + "name": "Efeu", + "botanical_name": "Hedera helix", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "low_light", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 3, + "name": "Kentia-Palme", + "botanical_name": "Howea forsteriana", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "low_light", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 103, + "name": "Spiegelpeperomie", + "botanical_name": "Peperomia obtusifolia", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 108, + "name": "Schafgarbe", + "botanical_name": "Achillea millefolium", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 89, + "name": "Kap-Aloe", + "botanical_name": "Aloe arborescens", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 18, + "name": "Kap-Aloe (ferox)", + "botanical_name": "Aloe ferox", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 107, + "name": "Arnika", + "botanical_name": "Arnica montana", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 110, + "name": "Wermut", + "botanical_name": "Artemisia absinthium", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 114, + "name": "Hange-Birke", + "botanical_name": "Betula pendula", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 187, + "name": "Ringelblume", + "botanical_name": "Calendula officinalis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 92, + "name": "Chili", + "botanical_name": "Capsicum annuum", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 138, + "name": "Roemische Kamille", + "botanical_name": "Chamaemelum nobile", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 101, + "name": "Kamille", + "botanical_name": "Chamomilla recutita", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 160, + "name": "Maigloeckchen", + "botanical_name": "Convallaria majalis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 74, + "name": "Kurkuma", + "botanical_name": "Curcuma longa", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 109, + "name": "Roter Fingerhut", + "botanical_name": "Digitalis purpurea", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 106, + "name": "Sonnenhut", + "botanical_name": "Echinacea purpurea", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 210, + "name": "Eukalyptus", + "botanical_name": "Eucalyptus globulus", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 216, + "name": "Ginkgo", + "botanical_name": "Ginkgo biloba", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 119, + "name": "Zaubernuss", + "botanical_name": "Hamamelis mollis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 105, + "name": "Johanniskraut", + "botanical_name": "Hypericum perforatum", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 23, + "name": "Echter Lavendel", + "botanical_name": "Lavandula angustifolia", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 102, + "name": "Zitronenmelisse", + "botanical_name": "Melissa officinalis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 25, + "name": "Basilikum", + "botanical_name": "Ocimum basilicum", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 28, + "name": "Oregano", + "botanical_name": "Origanum vulgare", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 31, + "name": "Rosengeranie", + "botanical_name": "Pelargonium graveolens", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 24, + "name": "Rosmarin", + "botanical_name": "Rosmarinus officinalis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 113, + "name": "Silber-Weide", + "botanical_name": "Salix alba", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 103, + "name": "Salbei", + "botanical_name": "Salvia officinalis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 112, + "name": "Schwarzer Holunder", + "botanical_name": "Sambucus nigra", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 27, + "name": "Thymian", + "botanical_name": "Thymus vulgaris", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 111, + "name": "Grosse Brennessel", + "botanical_name": "Urtica dioica", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 104, + "name": "Baldrian", + "botanical_name": "Valeriana officinalis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 192, + "name": "Koenigskerze", + "botanical_name": "Verbascum thapsus", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "medicinal", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 75, + "name": "Ingwer", + "botanical_name": "Zingiber officinale", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "patterned", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 240, + "name": "Calathea lancifolia", + "botanical_name": "Goeppertia insignis", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "patterned", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 241, + "name": "Calathea ornata", + "botanical_name": "Goeppertia ornata", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "patterned", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 51, + "name": "Gebet-Pflanze", + "botanical_name": "Maranta leuconeura", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "patterned", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 229, + "name": "Wassermelonen-Peperomie", + "botanical_name": "Peperomia argyreia", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "patterned", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 228, + "name": "Aluminium-Pflanze", + "botanical_name": "Pilea cadierei", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "pet_friendly", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 43, + "name": "Bergpalme", + "botanical_name": "Chamaedorea elegans", + "risk_flags": "air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence" + }, + { + "category": "pet_friendly", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 42, + "name": "Goldfruchtpalme", + "botanical_name": "Dypsis lutescens", + "risk_flags": "air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence" + }, + { + "category": "pet_friendly", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 100, + "name": "Erdbeere", + "botanical_name": "Fragaria ananassa", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "pet_friendly", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 240, + "name": "Calathea lancifolia", + "botanical_name": "Goeppertia insignis", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "pet_friendly", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 241, + "name": "Calathea ornata", + "botanical_name": "Goeppertia ornata", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "pet_friendly", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 3, + "name": "Kentia-Palme", + "botanical_name": "Howea forsteriana", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "pet_friendly", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 51, + "name": "Gebet-Pflanze", + "botanical_name": "Maranta leuconeura", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "pet_friendly", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 229, + "name": "Wassermelonen-Peperomie", + "botanical_name": "Peperomia argyreia", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "pet_friendly", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 102, + "name": "Rippenpeperomie", + "botanical_name": "Peperomia caperata", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "pet_friendly", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 103, + "name": "Spiegelpeperomie", + "botanical_name": "Peperomia obtusifolia", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "pet_friendly", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 230, + "name": "Raindrop-Peperomie", + "botanical_name": "Peperomia polybotrya", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "pet_friendly", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 34, + "name": "Petunie", + "botanical_name": "Petunia hybrida", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "pet_friendly", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 228, + "name": "Aluminium-Pflanze", + "botanical_name": "Pilea cadierei", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "pet_friendly", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 2, + "name": "Ufopflanze", + "botanical_name": "Pilea peperomioides", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "pet_friendly", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 238, + "name": "Bubikopf", + "botanical_name": "Soleirolia soleirolii", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "succulent", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 89, + "name": "Kap-Aloe", + "botanical_name": "Aloe arborescens", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "succulent", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 18, + "name": "Kap-Aloe (ferox)", + "botanical_name": "Aloe ferox", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 108, + "name": "Schafgarbe", + "botanical_name": "Achillea millefolium", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 89, + "name": "Kap-Aloe", + "botanical_name": "Aloe arborescens", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 18, + "name": "Kap-Aloe (ferox)", + "botanical_name": "Aloe ferox", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 107, + "name": "Arnika", + "botanical_name": "Arnica montana", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 110, + "name": "Wermut", + "botanical_name": "Artemisia absinthium", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 187, + "name": "Ringelblume", + "botanical_name": "Calendula officinalis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 92, + "name": "Chili", + "botanical_name": "Capsicum annuum", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 138, + "name": "Roemische Kamille", + "botanical_name": "Chamaemelum nobile", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 101, + "name": "Kamille", + "botanical_name": "Chamomilla recutita", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 106, + "name": "Sonnenhut", + "botanical_name": "Echinacea purpurea", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 210, + "name": "Eukalyptus", + "botanical_name": "Eucalyptus globulus", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 100, + "name": "Erdbeere", + "botanical_name": "Fragaria ananassa", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 216, + "name": "Ginkgo", + "botanical_name": "Ginkgo biloba", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 105, + "name": "Johanniskraut", + "botanical_name": "Hypericum perforatum", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 23, + "name": "Echter Lavendel", + "botanical_name": "Lavandula angustifolia", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 25, + "name": "Basilikum", + "botanical_name": "Ocimum basilicum", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 28, + "name": "Oregano", + "botanical_name": "Origanum vulgare", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 31, + "name": "Rosengeranie", + "botanical_name": "Pelargonium graveolens", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 34, + "name": "Petunie", + "botanical_name": "Petunia hybrida", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 24, + "name": "Rosmarin", + "botanical_name": "Rosmarinus officinalis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 103, + "name": "Salbei", + "botanical_name": "Salvia officinalis", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 27, + "name": "Thymian", + "botanical_name": "Thymus vulgaris", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "sun", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 192, + "name": "Koenigskerze", + "botanical_name": "Verbascum thapsus", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "tree", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 114, + "name": "Hange-Birke", + "botanical_name": "Betula pendula", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "tree", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 43, + "name": "Bergpalme", + "botanical_name": "Chamaedorea elegans", + "risk_flags": "air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence" + }, + { + "category": "tree", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 14, + "name": "Maisstrauch", + "botanical_name": "Dracaena fragrans", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "tree", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 13, + "name": "Drachenbaum", + "botanical_name": "Dracaena marginata", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "tree", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 42, + "name": "Goldfruchtpalme", + "botanical_name": "Dypsis lutescens", + "risk_flags": "air_purifier_requires_external_evidence|pet_friendly_requires_external_evidence" + }, + { + "category": "tree", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 210, + "name": "Eukalyptus", + "botanical_name": "Eucalyptus globulus", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "tree", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 1, + "name": "Birkenfeige", + "botanical_name": "Ficus benjamina", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "tree", + "source_file": "constants/lexiconBatch1.ts", + "source_index": 38, + "name": "Gummibaum", + "botanical_name": "Ficus elastica", + "risk_flags": "air_purifier_requires_external_evidence" + }, + { + "category": "tree", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 216, + "name": "Ginkgo", + "botanical_name": "Ginkgo biloba", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "tree", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 3, + "name": "Kentia-Palme", + "botanical_name": "Howea forsteriana", + "risk_flags": "pet_friendly_requires_external_evidence" + }, + { + "category": "tree", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 113, + "name": "Silber-Weide", + "botanical_name": "Salix alba", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "tree", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 112, + "name": "Schwarzer Holunder", + "botanical_name": "Sambucus nigra", + "risk_flags": "medicinal_requires_external_evidence" + }, + { + "category": "tree", + "source_file": "constants/lexiconBatch2.ts", + "source_index": 10, + "name": "Strahlenaralie", + "botanical_name": "Schefflera arboricola", + "risk_flags": "air_purifier_requires_external_evidence" + } +] diff --git a/audits/semantic-search/wave1-findings.md b/audits/semantic-search/wave1-findings.md new file mode 100644 index 0000000..6c12942 --- /dev/null +++ b/audits/semantic-search/wave1-findings.md @@ -0,0 +1,30 @@ +# Wave 1 Findings + +Date: 2026-03-12 + +Scope: +- `pet_friendly` +- `air_purifier` + +Changes applied to source data: +- Added `pet_friendly` to `Dypsis lutescens` (`Goldfruchtpalme`) +- Added `pet_friendly` to `Chamaedorea elegans` (`Bergpalme`) +- Added `pet_friendly` to `Howea forsteriana` (`Kentia-Palme`) +- Added `pet_friendly` to `Pilea cadierei` (`Aluminium-Pflanze`) +- Added `pet_friendly` to `Goeppertia insignis` (`Calathea lancifolia`) based on ASPCA `Calathea spp.` coverage +- Added `pet_friendly` to `Goeppertia ornata` (`Calathea ornata`) based on ASPCA `Calathea spp.` coverage +- Removed `air_purifier` from `Tillandsia usneoides` (`Spanisches Moos`) +- Removed `air_purifier` from `Phlebodium aureum` (`Blaues Kanaelfarn`) + +Evidence basis used: +- ASPCA non-toxic entries for `Areca Palm`, `Parlor Palm`, `Kentia Palm` +- ASPCA non-toxic entries for `Aluminum Plant` and `Calathea spp.` +- Conservative removal for `Tillandsia usneoides` and `Phlebodium aureum` because no equally strong primary air-purifier support was confirmed during this wave + +Deliberately not changed in this wave: +- Borderline or genus-adjacent `pet_friendly` candidates without direct enough evidence in hand +- Most remaining `air_purifier` entries, because several are plausible but need a stricter literature pass rather than guesswork + +Operational note: +- These source changes do not update the persisted backend catalog automatically. +- Production still needs a catalog rebuild via `server/scripts/rebuild-from-batches.js` and a deploy. diff --git a/audits/semantic-search/wave2-findings.md b/audits/semantic-search/wave2-findings.md new file mode 100644 index 0000000..a0dc04b --- /dev/null +++ b/audits/semantic-search/wave2-findings.md @@ -0,0 +1,28 @@ +# Wave 2 Findings + +Date: 2026-03-12 + +Scope: +- `low_light` +- `bright_light` +- `sun` + +Changes applied to source data: +- Removed `low_light` from `Saintpaulia ionantha` (`Afrikanisches Veilchen`) +- Removed `low_light` from `Clivia miniata` (`Riemenblatt`) +- Removed `sun` from `Helleborus orientalis` (`Lenzrose`) by overriding the default flower categories to `['flowering']` + +Evidence basis used: +- `Saintpaulia ionantha`: bright indirect light guidance, not a true low-light placement +- `Clivia miniata`: bright indirect / filtered light guidance, not a dark-corner low-light placement +- `Helleborus orientalis`: part-shade / shade-oriented placement, so `sun` was too broad + +Deliberately not changed in this wave: +- `Haworthia fasciata` and `Gasteria carinata` in `low_light`, because they are borderline tolerance cases and need a tighter horticultural pass before retagging +- `Wasabi` in `bright_light`, because the current label can still be read as bright indirect rather than direct sun +- `Hydrangea macrophylla` in `bright_light`, because the existing tag remains plausible for bright, non-scorching conditions +- broad `sun` garden inventories that are locally consistent and would need species-by-species horticultural review rather than heuristic edits + +Operational note: +- These source changes do not update the persisted backend catalog automatically. +- Production still needs a catalog rebuild via `server/scripts/rebuild-from-batches.js` and a deploy. diff --git a/audits/semantic-search/wave3-findings.md b/audits/semantic-search/wave3-findings.md new file mode 100644 index 0000000..d81087b --- /dev/null +++ b/audits/semantic-search/wave3-findings.md @@ -0,0 +1,37 @@ +# Wave 3 Findings + +Date: 2026-03-12 + +Scope: +- `easy` +- `high_humidity` +- `medicinal` + +Changes applied to source data: +- Removed `easy` from `Ficus retusa` (`Bonsai-Feige`) +- Removed `easy` from `Mimosa pudica` (`Schamkraut`) +- Removed `medicinal` from `Petroselinum crispum` (`Petersilie`) +- Removed `medicinal` from `Allium schoenoprasum` (`Schnittlauch`) +- Removed `medicinal` from `Vanilla planifolia` (`Vanille`) +- Removed `medicinal` from `Coffea arabica` (`Kaffeestrauch`) +- Removed `medicinal` from `Camellia sinensis` (`Teestrauch`) +- Removed `medicinal` from `Citrus limon`, `Citrus sinensis`, `Punica granatum`, `Psidium guajava`, `Carica papaya` +- Removed `medicinal` from `Solanum lycopersicum` (`Tomate`), `Spinacia oleracea` (`Spinat`), `Daucus carota` (`Karotte`) +- Removed `medicinal` from `Tagetes patula` (`Studentenblume`) +- Removed `medicinal` from `Eutrema japonicum` (`Wasabi`) +- Removed the implicit `medicinal` default from `createHerbEntry()` so generic kitchen-herb imports no longer auto-enter the medicinal category +- Re-added `medicinal` explicitly for `Chamaemelum nobile` (`Roemische Kamille`) + +Evidence basis used: +- `medicinal` is now treated as a conservative herbal/medical identity tag, not a catch-all for edible, aromatic, vitamin-rich, or beverage plants +- entries whose local descriptions are purely culinary, fruit, vegetable, or ornamental were de-scoped from `medicinal` +- `high_humidity` did not receive source-data changes in this wave because the current set looked locally coherent enough that heuristic edits would add more risk than value + +Deliberately not changed in this wave: +- many classic medicinal herbs that remain intentionally tagged, such as `Kamille`, `Salbei`, `Lavendel`, `Zitronenmelisse`, `Johanniskraut`, `Baldrian`, `Ingwer`, `Kurkuma`, `Eukalyptus`, `Ginkgo`, `Thymian` +- borderline `easy` cases beyond `Bonsai-Feige` and `Schamkraut` +- `high_humidity` entries without clear contradiction in local care/descriptive text + +Operational note: +- These source changes do not update the persisted backend catalog automatically. +- Production still needs a catalog rebuild via `server/scripts/rebuild-from-batches.js` and a deploy. diff --git a/audits/semantic-search/wave4-findings.md b/audits/semantic-search/wave4-findings.md new file mode 100644 index 0000000..682c8cd --- /dev/null +++ b/audits/semantic-search/wave4-findings.md @@ -0,0 +1,32 @@ +# Wave 4 Findings + +Date: 2026-03-12 + +Scope: +- `tree` +- `large` +- `patterned` +- `flowering` + +Changes applied to source data: +- Removed `patterned` from `Acer palmatum` (`Faecherahorn`) +- Removed `patterned` from `Beta vulgaris` (`Mangold`) +- Removed `large` from `Buxus sempervirens` (`Buchsbaum`) +- Removed `large` from `Ilex aquifolium` (`Stechpalme`) +- Removed `large` from `Prunus laurocerasus` (`Kirschlorbeer`) +- Removed `large` from `Thaumatophyllum xanadu` (`Philodendron Xanadu`) +- Removed `tree` from `Coffea arabica Nana` (`Kaffeepflanze arabica nana`) + +Evidence basis used: +- `patterned` is treated as a foliage-pattern identity tag, not a generic color, form, or ornamental-value tag +- `large` is treated conservatively for clearly size-defining growth, not as an automatic consequence of every tree/shrub import +- `tree` on the dwarf coffee plant was too broad in the current houseplant context + +Deliberately not changed in this wave: +- `flowering` received no source-data changes because the current set looked locally coherent enough for this pass +- borderline foliage cases like `Monstera obliqua` remained unchanged because its fenestrated leaf look can still be argued as a visual-pattern discovery target +- clearly large species and true tree-form entries were left intact + +Operational note: +- These source changes do not update the persisted backend catalog automatically. +- Production still needs a catalog rebuild via `server/scripts/rebuild-from-batches.js` and a deploy. diff --git a/audits/semantic-search/wave5-findings.md b/audits/semantic-search/wave5-findings.md new file mode 100644 index 0000000..9afb1e6 --- /dev/null +++ b/audits/semantic-search/wave5-findings.md @@ -0,0 +1,26 @@ +# Wave 5 Findings + +Date: 2026-03-12 + +Scope: +- `hanging` +- `succulent` + +Changes applied to source data: +- Added `succulent` to `Hoya carnosa` (`Wachsblume`) +- Removed `hanging` from `Passiflora caerulea` (`Passionsblume`) +- Removed `hanging` from `Cucumis sativus` (`Gurke`) + +Evidence basis used: +- `succulent` was added only where the local source text explicitly supported water-storing or fleshy foliage traits; `Hoya carnosa` already described `dicken, wachsartigen Blaettern` and sat next to the already-succulent `Hoya bella` +- `hanging` was treated as a trailing, cascading, or hanging-basket discovery tag, not a generic catch-all for any climbing or vining species +- `Passiflora caerulea` and `Cucumis sativus` read locally as climbers/vines rather than clear hanging-basket plants + +Deliberately not changed in this wave: +- `Beaucarnea recurvata` kept `succulent` because the source text explicitly mentions a swollen water-storing stem base +- trailing epiphytes and epiphytic cacti like `Dischidia ruscifolia`, `Rhipsalis baccifera`, and `Hoya bella` remained unchanged because the local descriptions still support `succulent` and/or `hanging` +- carnivorous hanging candidates like `Nepenthes alata` remained unchanged because the category still works for hanging-display discovery + +Operational note: +- These source changes do not update the persisted backend catalog automatically. +- Production still needs a catalog rebuild via `server/scripts/rebuild-from-batches.js` and a deploy. diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..9d89e13 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,6 @@ +module.exports = function (api) { + api.cache(true); + return { + presets: ['babel-preset-expo'], + }; +}; diff --git a/components/AnimatedSplashScreen.tsx b/components/AnimatedSplashScreen.tsx new file mode 100644 index 0000000..81230b1 --- /dev/null +++ b/components/AnimatedSplashScreen.tsx @@ -0,0 +1,60 @@ +import React, { useState, useEffect } from 'react'; +import { StyleSheet } from 'react-native'; +import { Video, ResizeMode } from 'expo-av'; +import * as SplashScreen from 'expo-splash-screen'; +import Animated, { FadeOut } from 'react-native-reanimated'; +import { useApp } from '../context/AppContext'; +import { useColors } from '../constants/Colors'; + +interface Props { + isAppReady: boolean; + onAnimationComplete: () => void; +} + +export function AnimatedSplashScreen({ isAppReady, onAnimationComplete }: Props) { + const [hasPlayedEnough, setHasPlayedEnough] = useState(false); + + useEffect(() => { + // Ensure the video plays for at least 2 seconds before we allow it to finish, + // so it doesn't flash too fast and provides a premium feel. + const timer = setTimeout(() => { + setHasPlayedEnough(true); + }, 2000); + return () => clearTimeout(timer); + }, []); + + useEffect(() => { + if (isAppReady && hasPlayedEnough) { + onAnimationComplete(); + } + }, [isAppReady, hasPlayedEnough, onAnimationComplete]); + + // Determine the background color to blend perfectly + const { isDarkMode, colorPalette } = useApp(); + const colors = useColors(isDarkMode, colorPalette); + return ( + + + + + ); +} diff --git a/components/CoachMarksOverlay.tsx b/components/CoachMarksOverlay.tsx new file mode 100644 index 0000000..7564b3c --- /dev/null +++ b/components/CoachMarksOverlay.tsx @@ -0,0 +1,286 @@ +import React, { useEffect, useRef } from 'react'; +import { + View, + Text, + TouchableOpacity, + StyleSheet, + Dimensions, + Animated, + Platform, +} from 'react-native'; +import { Ionicons } from '@expo/vector-icons'; +import { useCoachMarks } from '../context/CoachMarksContext'; +import { useApp } from '../context/AppContext'; +import { useColors } from '../constants/Colors'; + +const { width: SCREEN_W, height: SCREEN_H } = Dimensions.get('window'); +const HIGHLIGHT_PADDING = 10; +const TOOLTIP_VERTICAL_OFFSET = 32; + +export const CoachMarksOverlay: React.FC = () => { + const { isActive, currentStep, steps, layouts, next, skip } = useCoachMarks(); + const { isDarkMode, colorPalette } = useApp(); + const colors = useColors(isDarkMode, colorPalette); + + const fadeAnim = useRef(new Animated.Value(0)).current; + const scaleAnim = useRef(new Animated.Value(0.88)).current; + const pulseAnim = useRef(new Animated.Value(1)).current; + + // Fade in when tour starts or step changes + useEffect(() => { + if (isActive) { + fadeAnim.setValue(0); + scaleAnim.setValue(0.88); + Animated.parallel([ + Animated.timing(fadeAnim, { toValue: 1, duration: 320, useNativeDriver: true }), + Animated.spring(scaleAnim, { toValue: 1, tension: 80, friction: 9, useNativeDriver: true }), + ]).start(); + + // Pulse animation on highlight + Animated.loop( + Animated.sequence([ + Animated.timing(pulseAnim, { toValue: 1.06, duration: 900, useNativeDriver: true }), + Animated.timing(pulseAnim, { toValue: 1, duration: 900, useNativeDriver: true }), + ]) + ).start(); + } else { + pulseAnim.stopAnimation(); + } + }, [isActive, currentStep]); + + if (!isActive || steps.length === 0) return null; + + const step = steps[currentStep]; + const layout = layouts[step.elementKey]; + + // Fallback wenn Element noch nicht gemessen + const highlight = layout + ? { + x: layout.x - HIGHLIGHT_PADDING, + y: layout.y - HIGHLIGHT_PADDING, + w: layout.width + HIGHLIGHT_PADDING * 2, + h: layout.height + HIGHLIGHT_PADDING * 2, + r: Math.min(layout.width, layout.height) / 2 + HIGHLIGHT_PADDING, + } + : { x: SCREEN_W / 2 - 40, y: SCREEN_H / 2 - 40, w: 80, h: 80, r: 40 }; + + // Tooltip-Position berechnen + const tooltipW = 260; + const tooltipMaxH = 140; + let tooltipX = Math.max(12, Math.min(SCREEN_W - tooltipW - 12, highlight.x + highlight.w / 2 - tooltipW / 2)); + let tooltipY: number; + const spaceBelow = SCREEN_H - (highlight.y + highlight.h); + const spaceAbove = highlight.y; + + if (step.tooltipSide === 'above' || (step.tooltipSide !== 'below' && spaceAbove > spaceBelow)) { + tooltipY = highlight.y - tooltipMaxH - 24; + if (tooltipY < 60) tooltipY = highlight.y + highlight.h + 24; + } else { + tooltipY = highlight.y + highlight.h + 24; + if (tooltipY + tooltipMaxH > SCREEN_H - 60) tooltipY = highlight.y - tooltipMaxH - 24; + } + + // Keep coachmark bubbles slightly higher to avoid overlap with bright focus circles. + tooltipY -= TOOLTIP_VERTICAL_OFFSET; + const minTooltipY = 24; + const maxTooltipY = SCREEN_H - tooltipMaxH - 24; + tooltipY = Math.max(minTooltipY, Math.min(maxTooltipY, tooltipY)); + + const arrowPointsUp = tooltipY > highlight.y; + + return ( + + {/* Dark overlay — 4 Rechtecke um die Aussparung */} + {/* Oben */} + + {/* Links */} + + {/* Rechts */} + + {/* Unten */} + + + {/* Pulsierender Ring um das Highlight */} + + + {/* Tooltip-Karte */} + + {/* Arrow */} + + + {/* Schritt-Indikator */} + + {steps.map((_, i) => ( + + ))} + + + {step.title} + {step.description} + + + + Überspringen + + + + {currentStep === steps.length - 1 ? 'Fertig' : 'Weiter'} + + + + + + + ); +}; + +const styles = StyleSheet.create({ + root: { + zIndex: 9999, + elevation: 9999, + }, + overlay: { + position: 'absolute', + backgroundColor: 'rgba(0,0,0,0.72)', + }, + highlightRing: { + position: 'absolute', + borderWidth: 2.5, + }, + tooltip: { + position: 'absolute', + borderRadius: 18, + borderWidth: 1, + padding: 16, + gap: 8, + shadowOffset: { width: 0, height: 8 }, + shadowOpacity: 0.2, + shadowRadius: 20, + elevation: 12, + }, + stepRow: { + flexDirection: 'row', + gap: 4, + alignItems: 'center', + marginBottom: 2, + }, + stepDot: { + width: 6, + height: 6, + borderRadius: 3, + }, + tooltipTitle: { + fontSize: 15, + fontWeight: '700', + lineHeight: 20, + }, + tooltipDesc: { + fontSize: 13, + lineHeight: 18, + }, + tooltipFooter: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + marginTop: 4, + }, + skipBtn: { + padding: 4, + }, + skipText: { + fontSize: 13, + }, + nextBtn: { + flexDirection: 'row', + alignItems: 'center', + gap: 6, + paddingHorizontal: 16, + paddingVertical: 9, + borderRadius: 20, + }, + nextText: { + fontSize: 13, + fontWeight: '600', + }, + arrow: { + position: 'absolute', + width: 0, + height: 0, + borderLeftWidth: 8, + borderRightWidth: 8, + borderLeftColor: 'transparent', + borderRightColor: 'transparent', + }, + arrowUp: { + top: -8, + borderBottomWidth: 8, + }, + arrowDown: { + bottom: -8, + borderTopWidth: 8, + }, +}); diff --git a/components/PlantCard.tsx b/components/PlantCard.tsx index b6521dd..54bd886 100644 --- a/components/PlantCard.tsx +++ b/components/PlantCard.tsx @@ -1,59 +1,102 @@ import React from 'react'; -import { Plant } from '../types'; -import { Droplets } from 'lucide-react'; +import { View, Text, StyleSheet, TouchableOpacity } from 'react-native'; +import { Ionicons } from '@expo/vector-icons'; +import { ColorPalette } from '../types'; +import { useColors } from '../constants/Colors'; +import { SafeImage } from './SafeImage'; interface PlantCardProps { - plant: Plant; - onClick: () => void; - t: any; // Using any for simplicity with the dynamic translation object + plant: { + name: string; + botanicalName?: string; + imageUri: string; + careInfo: { + waterIntervalDays: number; + }; + }; + width: number; + onPress: () => void; + t: any; + isDark: boolean; + colorPalette: ColorPalette; } -export const PlantCard: React.FC = ({ plant, onClick, t }) => { - const daysUntilWatering = plant.careInfo.waterIntervalDays; - // Very basic check logic for MVP - const isUrgent = daysUntilWatering <= 1; - - const wateringText = isUrgent - ? t.waterToday - : t.inXDays.replace('{0}', daysUntilWatering.toString()); +export const PlantCard: React.FC = ({ + plant, + width, + onPress, + t, + isDark, + colorPalette, +}) => { + const colors = useColors(isDark, colorPalette); + const isUrgent = plant.careInfo?.waterIntervalDays <= 1; + const wateringText = plant.careInfo?.waterIntervalDays + ? (isUrgent + ? t.waterToday + : t.inXDays.replace('{0}', plant.careInfo.waterIntervalDays.toString())) + : t.showDetails; // Default for lexicon entries return ( - + + {plant.name} + {plant.botanicalName} + + ); -}; \ No newline at end of file +}; + +const styles = StyleSheet.create({ + container: { + aspectRatio: 0.8, + borderRadius: 18, + overflow: 'hidden', + shadowColor: '#000', + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.1, + shadowRadius: 6, + elevation: 4, + }, + image: { width: '100%', height: '100%', resizeMode: 'cover' }, + gradient: { + ...StyleSheet.absoluteFillObject, + opacity: 0.8, + }, + badge: { + position: 'absolute', + top: 10, + left: 10, + flexDirection: 'row', + alignItems: 'center', + gap: 4, + paddingHorizontal: 8, + paddingVertical: 4, + borderRadius: 12, + }, + badgeText: { fontSize: 9, fontWeight: '700' }, + content: { position: 'absolute', bottom: 14, left: 10, right: 10 }, + name: { fontSize: 16, fontWeight: '700' }, + botanical: { fontSize: 11 }, +}); diff --git a/components/PlantDetail.tsx b/components/PlantDetail.tsx deleted file mode 100644 index df8fcb3..0000000 --- a/components/PlantDetail.tsx +++ /dev/null @@ -1,302 +0,0 @@ - -import React, { useState } from 'react'; -import { Plant, Language } from '../types'; -import { Droplets, Sun, Thermometer, ArrowLeft, Calendar, Trash2, Share2, Edit2, AlertCircle, Check, Clock, Bell, BellOff } from 'lucide-react'; - -interface PlantDetailProps { - plant: Plant; - onClose: () => void; - onDelete: (id: string) => void; - onUpdate: (plant: Plant) => void; - t: any; - language: Language; -} - -export const PlantDetail: React.FC = ({ plant, onClose, onDelete, onUpdate, t, language }) => { - const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); - - // Map internal language codes to locale strings for Date - const localeMap: Record = { - de: 'de-DE', - en: 'en-US', - es: 'es-ES' - }; - - const formattedAddedDate = new Date(plant.dateAdded).toLocaleDateString(localeMap[language] || 'de-DE'); - const formattedWateredDate = new Date(plant.lastWatered).toLocaleDateString(localeMap[language] || 'de-DE'); - - // Calculate next watering date - const lastWateredObj = new Date(plant.lastWatered); - const nextWateringDate = new Date(lastWateredObj); - nextWateringDate.setDate(lastWateredObj.getDate() + plant.careInfo.waterIntervalDays); - - const formattedNextWatering = nextWateringDate.toLocaleDateString(localeMap[language] || 'de-DE', { weekday: 'long', day: 'numeric', month: 'numeric' }); - const nextWateringText = t.nextWatering.replace('{0}', formattedNextWatering); - const lastWateredText = t.lastWateredDate.replace('{0}', formattedWateredDate); - - // Check if watered today - const isWateredToday = new Date(plant.lastWatered).toDateString() === new Date().toDateString(); - - const handleWaterPlant = () => { - const now = new Date().toISOString(); - // Update history: add new date to the beginning, keep last 10 entries max - const currentHistory = plant.wateringHistory || []; - const newHistory = [now, ...currentHistory].slice(0, 10); - - const updatedPlant = { - ...plant, - lastWatered: now, - wateringHistory: newHistory - }; - onUpdate(updatedPlant); - }; - - const toggleReminder = async () => { - const newValue = !plant.notificationsEnabled; - - if (newValue) { - // Request permission if enabling - if (!('Notification' in window)) { - alert("Notifications are not supported by this browser."); - return; - } - - if (Notification.permission === 'granted') { - onUpdate({ ...plant, notificationsEnabled: true }); - } else if (Notification.permission !== 'denied') { - const permission = await Notification.requestPermission(); - if (permission === 'granted') { - onUpdate({ ...plant, notificationsEnabled: true }); - } - } else { - alert(t.reminderPermissionNeeded); - } - } else { - // Disabling - onUpdate({ ...plant, notificationsEnabled: false }); - } - }; - - const handleDeleteClick = () => { - setShowDeleteConfirm(true); - }; - - const handleConfirmDelete = () => { - onDelete(plant.id); - }; - - const handleCancelDelete = () => { - setShowDeleteConfirm(false); - }; - - return ( -
- - {/* Header */} -
- -
- - -
-
- -
- {/* Hero Image */} -
- {plant.name} -
- -
-

- {plant.name} -

-

- {plant.botanicalName} -

-
-
- - {/* Content Container */} -
- {/* Added Date Info */} -
-
- - {t.addedOn} {formattedAddedDate} -
-
- - {/* Main Action: Water */} -
-
- {lastWateredText} - - {nextWateringText} - -
- -
- - {/* Reminder Toggle */} -
-
-
- {plant.notificationsEnabled ? : } -
-
- {t.reminder} - {plant.notificationsEnabled ? t.reminderOn : t.reminderOff} -
-
- -
- -

{t.aboutPlant}

-

- {plant.description || t.noDescription} -

- - {/* Care Info */} -

{t.careTips}

-
-
-
- -
- {t.water} - - {plant.careInfo.waterIntervalDays} {t.days || 'Tage'} - -
- -
-
- -
- {t.light} - - {plant.careInfo.light} - -
- -
-
- -
- {t.temp} - - {plant.careInfo.temp} - -
-
- - {/* Watering History Section */} -

{t.wateringHistory}

-
- {(!plant.wateringHistory || plant.wateringHistory.length === 0) ? ( -
- - {t.noHistory} -
- ) : ( -
    - {plant.wateringHistory.slice(0, 5).map((dateStr, index) => ( -
  • -
    -
    - -
    - - {new Date(dateStr).toLocaleDateString(localeMap[language] || 'de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' })} - -
    - - {new Date(dateStr).toLocaleTimeString(localeMap[language] || 'de-DE', { hour: '2-digit', minute: '2-digit' })} - -
  • - ))} -
- )} -
- - {/* Danger Zone */} -
- -
-
-
- - {/* Delete Confirmation Modal */} - {showDeleteConfirm && ( -
-
-
- -
-

{t.deleteConfirmTitle}

-

- {t.deleteConfirmMessage} -

- -
- - -
-
-
- )} -
- ); -}; diff --git a/components/PlantSkeleton.tsx b/components/PlantSkeleton.tsx deleted file mode 100644 index 49e122c..0000000 --- a/components/PlantSkeleton.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; - -export const PlantSkeleton: React.FC = () => { - return ( -
- - {/* Badge Placeholder */} -
-
-
- - {/* Content Placeholder */} -
- {/* Title */} -
- {/* Subtitle */} -
-
-
- ); -}; \ No newline at end of file diff --git a/components/ResultCard.tsx b/components/ResultCard.tsx index dfaaf0e..6ca63de 100644 --- a/components/ResultCard.tsx +++ b/components/ResultCard.tsx @@ -1,7 +1,10 @@ - import React, { useState } from 'react'; -import { IdentificationResult } from '../types'; -import { Droplets, Sun, Thermometer, CheckCircle2, ArrowLeft, Share2 } from 'lucide-react'; +import { View, Text, StyleSheet, ScrollView, TouchableOpacity, Share, Alert } from 'react-native'; +import { Ionicons } from '@expo/vector-icons'; +import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'; +import { ColorPalette, IdentificationResult } from '../types'; +import { useColors } from '../constants/Colors'; +import { SafeImage } from './SafeImage'; interface ResultCardProps { result: IdentificationResult; @@ -9,132 +12,255 @@ interface ResultCardProps { onSave: () => void; onClose: () => void; t: any; + isDark: boolean; + colorPalette: ColorPalette; + isGuest?: boolean; } -export const ResultCard: React.FC = ({ result, imageUri, onSave, onClose, t }) => { +export const ResultCard: React.FC = ({ + result, + imageUri, + onSave, + onClose, + t, + isDark, + colorPalette, + isGuest = false, +}) => { + const colors = useColors(isDark, colorPalette); + const insets = useSafeAreaInsets(); const [showDetails, setShowDetails] = useState(false); - return ( -
- - {/* Header */} -
- - {t.result} - -
+ const handleShare = async () => { + try { + await Share.share({ + message: `I just identified a ${result.name} (${result.botanicalName}) with ${Math.round(result.confidence * 100)}% confidence using GreenLens!`, + }); + } catch (error: any) { + Alert.alert('Error', error.message); + } + }; -
+ return ( + + {/* Header */} + + + + + + {t.result} + + + + + + + {/* Hero Image */} -
- Analyzed Plant -
- - {Math.round(result.confidence * 100)}% {t.match} -
-
+ + + + + + {Math.round(result.confidence * 100)}% {t.match} + + + {/* Info */} -
-

- {result.name} -

-

- {result.botanicalName} -

+ {result.name} + {result.botanicalName} + + {result.description || t.noDescription} + -

- {result.description || t.noDescription} -

+ {/* Care Check */} + + {t.careCheck} + setShowDetails(!showDetails)}> + + {showDetails ? t.hideDetails : t.showDetails} + + + - {/* Care Check */} -
-

{t.careCheck}

- -
+ + {[ + { icon: 'water' as const, label: t.water, value: result.careInfo.waterIntervalDays <= 7 ? t.waterModerate : t.waterLittle, color: colors.info, bg: colors.infoSoft }, + { icon: 'sunny' as const, label: t.light, value: result.careInfo.light, color: colors.warning, bg: colors.warningSoft }, + { icon: 'thermometer' as const, label: t.temp, value: result.careInfo.temp, color: colors.danger, bg: colors.dangerSoft }, + ].map((item) => ( + + + + + {item.label} + {item.value} + + ))} + -
-
-
- -
- {t.water} - - {result.careInfo.waterIntervalDays <= 7 ? t.waterModerate : t.waterLittle} - -
+ {showDetails && ( + + {t.detailedCare} + {[ + { text: t.careTextWater.replace('{0}', result.careInfo.waterIntervalDays.toString()), color: colors.success }, + { text: t.careTextLight.replace('{0}', result.careInfo.light), color: colors.warning }, + { text: t.careTextTemp.replace('{0}', result.careInfo.temp), color: colors.danger }, + ].map((item, i) => ( + + + {item.text} + + ))} + + )} -
-
- -
- {t.light} - - {result.careInfo.light} - -
+ {/* Save */} + + + {t.dataSavedLocally} + -
-
- -
- {t.temp} - - {result.careInfo.temp} - -
-
- - {/* Expanded Details */} - {showDetails && ( -
-

{t.detailedCare}

-
    -
  • - - {t.careTextWater.replace('{0}', result.careInfo.waterIntervalDays.toString())} -
  • -
  • - - {t.careTextLight.replace('{0}', result.careInfo.light)} -
  • -
  • - - {t.careTextTemp.replace('{0}', result.careInfo.temp)} -
  • -
-
- )} - - {/* Save Button */} -
-
-
-
- {t.dataSavedLocally} -
- - -
-
-
-
+ + + + {isGuest ? t.registerToSave : t.addToPlants} + + + + ); }; + +const styles = StyleSheet.create({ + container: { flex: 1 }, + header: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + zIndex: 10, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingHorizontal: 20, + }, + headerBtn: { + borderRadius: 20, + padding: 8, + borderWidth: 1, + }, + headerBadge: { + borderRadius: 20, + paddingHorizontal: 12, + paddingVertical: 4, + borderWidth: 1, + }, + headerBadgeText: { fontWeight: '700', fontSize: 13 }, + scrollContent: { paddingHorizontal: 16 }, + heroContainer: { + width: '100%', + aspectRatio: 4 / 3, + borderRadius: 24, + overflow: 'hidden', + marginBottom: 20, + shadowColor: '#000', + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.15, + shadowRadius: 8, + elevation: 6, + }, + heroImage: { width: '100%', height: '100%', resizeMode: 'cover' }, + confidenceBadge: { + position: 'absolute', + bottom: 14, + left: 14, + borderRadius: 20, + paddingHorizontal: 10, + paddingVertical: 6, + flexDirection: 'row', + alignItems: 'center', + gap: 4, + }, + confidenceText: { fontSize: 11, fontWeight: '700' }, + plantName: { fontSize: 28, fontWeight: '700', marginBottom: 2 }, + botanical: { fontSize: 13, fontStyle: 'italic', marginBottom: 14 }, + description: { fontSize: 13, lineHeight: 20, marginBottom: 24 }, + careHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'flex-end', + marginBottom: 12, + }, + sectionTitle: { fontSize: 16, fontWeight: '700' }, + detailsToggle: { fontSize: 10, fontWeight: '700', textTransform: 'uppercase', letterSpacing: 0.5 }, + careGrid: { flexDirection: 'row', gap: 10, marginBottom: 20 }, + careCard: { + flex: 1, + alignItems: 'center', + padding: 12, + borderRadius: 18, + borderWidth: 1, + gap: 6, + }, + careIcon: { width: 32, height: 32, borderRadius: 16, justifyContent: 'center', alignItems: 'center' }, + careLabel: { fontSize: 10, fontWeight: '500' }, + careValue: { + width: '100%', + fontSize: 11, + lineHeight: 14, + fontWeight: '700', + textAlign: 'center', + flexShrink: 1, + }, + detailsBox: { + borderRadius: 18, + borderWidth: 1, + padding: 16, + marginBottom: 20, + gap: 10, + }, + detailsTitle: { fontSize: 11, fontWeight: '700', textTransform: 'uppercase', letterSpacing: 0.5 }, + detailRow: { flexDirection: 'row', alignItems: 'flex-start', gap: 10 }, + detailDot: { width: 6, height: 6, borderRadius: 3, marginTop: 6 }, + detailText: { fontSize: 13, flex: 1 }, + localInfo: { flexDirection: 'row', justifyContent: 'center', alignItems: 'center', gap: 6, marginBottom: 12 }, + localIcon: { width: 12, height: 12, borderRadius: 2, borderWidth: 1, borderColor: '#d6d3d1' }, + localText: { fontSize: 11 }, + saveBtn: { + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + gap: 8, + backgroundColor: '#4ade80', + paddingVertical: 16, + borderRadius: 14, + shadowColor: '#4ade80', + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.3, + shadowRadius: 8, + elevation: 6, + }, + saveBtnText: { fontWeight: '700', fontSize: 14 }, +}); diff --git a/components/SafeImage.tsx b/components/SafeImage.tsx new file mode 100644 index 0000000..df256b2 --- /dev/null +++ b/components/SafeImage.tsx @@ -0,0 +1,134 @@ +import React from 'react'; +import { Image, ImageProps, StyleSheet, Text, View } from 'react-native'; +import { + DEFAULT_PLANT_IMAGE_URI, + getCategoryFallbackImage, + getPlantImageSourceFallbackUri, + getWikimediaFilePathFromThumbnailUrl, + resolveImageUri, + tryResolveImageUri, +} from '../utils/imageUri'; + +type SafeImageFallbackMode = 'category' | 'default' | 'none'; + +interface SafeImageProps extends Omit { + uri?: string | null; + categories?: string[]; + fallbackMode?: SafeImageFallbackMode; + placeholderLabel?: string; +} + +const getPlaceholderInitial = (label?: string): string => { + if (!label) return '?'; + const trimmed = label.trim(); + if (!trimmed) return '?'; + return trimmed.charAt(0).toUpperCase(); +}; + +export const SafeImage: React.FC = ({ + uri, + categories, + fallbackMode = 'category', + placeholderLabel, + onError, + style, + ...props +}) => { + const categoryFallback = categories && categories.length > 0 + ? getCategoryFallbackImage(categories) + : DEFAULT_PLANT_IMAGE_URI; + const selectedFallback = fallbackMode === 'category' + ? categoryFallback + : DEFAULT_PLANT_IMAGE_URI; + + const [resolvedUri, setResolvedUri] = React.useState(() => { + const strictResolved = tryResolveImageUri(uri); + if (strictResolved) return strictResolved; + return fallbackMode === 'none' ? '' : selectedFallback; + }); + const [showPlaceholder, setShowPlaceholder] = React.useState(() => { + if (fallbackMode !== 'none') return false; + return !tryResolveImageUri(uri); + }); + const [retryCount, setRetryCount] = React.useState(0); + const lastAttemptUri = React.useRef(null); + + React.useEffect(() => { + const strictResolved = tryResolveImageUri(uri); + setResolvedUri(strictResolved || (fallbackMode === 'none' ? '' : selectedFallback)); + setShowPlaceholder(fallbackMode === 'none' && !strictResolved); + setRetryCount(0); + lastAttemptUri.current = strictResolved; + }, [uri, fallbackMode, selectedFallback]); + + if (fallbackMode === 'none' && showPlaceholder) { + return ( + + {getPlaceholderInitial(placeholderLabel)} + + ); + } + + return ( + { + onError?.(event); + + const currentUri = resolvedUri || selectedFallback; + + // Smart Retry Logic for Wikimedia (first failure only) + if (retryCount === 0 && currentUri.includes('upload.wikimedia.org')) { + const fileName = getWikimediaFilePathFromThumbnailUrl(currentUri); + if (fileName) { + const redirectUrl = `https://commons.wikimedia.org/wiki/Special:FilePath/${encodeURIComponent(fileName)}`; + setRetryCount(1); + setResolvedUri(redirectUrl); + lastAttemptUri.current = redirectUrl; + return; + } + } + + const sourceFallbackUri = getPlantImageSourceFallbackUri(uri); + if (sourceFallbackUri && sourceFallbackUri !== currentUri && lastAttemptUri.current !== sourceFallbackUri) { + setResolvedUri(sourceFallbackUri); + lastAttemptUri.current = sourceFallbackUri; + return; + } + + // If we get here, either it wasn't a Wikimedia URL, or filename extraction failed, + // or the retry itself failed. + if (fallbackMode === 'none') { + setShowPlaceholder(true); + return; + } + + setResolvedUri((current) => { + if (current === DEFAULT_PLANT_IMAGE_URI) return current; + if (current === selectedFallback) return DEFAULT_PLANT_IMAGE_URI; + return selectedFallback; + }); + + // Prevent infinite loops if fallbacks also fail + setRetryCount(current => current + 1); + }} + /> + ); +}; + +const styles = StyleSheet.create({ + placeholder: { + alignItems: 'center', + justifyContent: 'center', + backgroundColor: '#e7ece8', + }, + placeholderText: { + fontSize: 18, + fontWeight: '700', + color: '#5f6f63', + }, +}); diff --git a/components/SplashScreen.tsx b/components/SplashScreen.tsx new file mode 100644 index 0000000..562cbc9 --- /dev/null +++ b/components/SplashScreen.tsx @@ -0,0 +1,70 @@ +import React, { useEffect, useRef } from 'react'; +import { View, Text, Animated, StyleSheet, Image } from 'react-native'; + +export default function SplashScreen() { + const fadeAnim = useRef(new Animated.Value(0)).current; + + useEffect(() => { + Animated.timing(fadeAnim, { + toValue: 1, + duration: 800, + useNativeDriver: true, + }).start(); + }, []); + + return ( + + + + + + GreenLens + Identify any plant + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#1c1917', + alignItems: 'center', + justifyContent: 'center', + }, + content: { + alignItems: 'center', + }, + iconContainer: { + width: 100, + height: 100, + borderRadius: 24, + backgroundColor: '#ffffff', + elevation: 8, + shadowColor: '#4ade80', + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.2, + shadowRadius: 12, + marginBottom: 8, + overflow: 'hidden', + }, + icon: { + width: '100%', + height: '100%', + }, + title: { + fontSize: 36, + fontWeight: '700', + color: '#fafaf9', + marginTop: 16, + }, + subtitle: { + fontSize: 16, + color: '#a8a29e', + marginTop: 8, + }, +}); diff --git a/components/TabBar.tsx b/components/TabBar.tsx deleted file mode 100644 index d97c588..0000000 --- a/components/TabBar.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react'; -import { Tab } from '../types'; -import { LayoutGrid, Search, User } from 'lucide-react'; - -interface TabBarProps { - currentTab: Tab; - onTabChange: (tab: Tab) => void; - labels: { - home: string; - search: string; - settings: string; - }; -} - -export const TabBar: React.FC = ({ currentTab, onTabChange, labels }) => { - return ( -
-
- - - - - -
-
- ); -}; \ No newline at end of file diff --git a/components/ThemeBackdrop.tsx b/components/ThemeBackdrop.tsx new file mode 100644 index 0000000..f63acef --- /dev/null +++ b/components/ThemeBackdrop.tsx @@ -0,0 +1,108 @@ +import React, { useMemo } from 'react'; +import { StyleSheet, View } from 'react-native'; +import { AppColors } from '../constants/Colors'; + +interface ThemeBackdropProps { + colors: AppColors; +} + +const texturePoints = [ + [4, 6, 2], [12, 14, 1], [20, 9, 2], [26, 19, 1], [34, 8, 2], [42, 16, 1], + [50, 10, 1], [58, 18, 2], [66, 7, 1], [74, 15, 2], [82, 11, 1], [90, 17, 2], + [8, 30, 1], [16, 25, 2], [24, 33, 1], [32, 27, 2], [40, 35, 1], [48, 28, 2], + [56, 36, 1], [64, 26, 2], [72, 34, 1], [80, 29, 2], [88, 37, 1], [94, 31, 2], + [6, 48, 2], [14, 44, 1], [22, 52, 2], [30, 46, 1], [38, 54, 2], [46, 49, 1], + [54, 56, 2], [62, 45, 1], [70, 53, 2], [78, 47, 1], [86, 55, 2], [92, 50, 1], + [10, 70, 1], [18, 64, 2], [26, 72, 1], [34, 67, 2], [42, 74, 1], [50, 68, 2], + [58, 76, 1], [66, 65, 2], [74, 73, 1], [82, 69, 2], [90, 77, 1], [96, 71, 2], +]; + +const parseColor = (value: string) => { + if (value.startsWith('#')) { + const cleaned = value.replace('#', ''); + const normalized = cleaned.length === 3 + ? cleaned.split('').map((c) => `${c}${c}`).join('') + : cleaned; + const int = Number.parseInt(normalized, 16); + return { + r: (int >> 16) & 255, + g: (int >> 8) & 255, + b: int & 255, + a: 1, + }; + } + + const match = value.match(/rgba?\(([^)]+)\)/i); + if (!match) return { r: 0, g: 0, b: 0, a: 0 }; + const parts = match[1].split(',').map((part) => part.trim()); + return { + r: Number.parseFloat(parts[0]) || 0, + g: Number.parseFloat(parts[1]) || 0, + b: Number.parseFloat(parts[2]) || 0, + a: parts.length > 3 ? Number.parseFloat(parts[3]) || 0 : 1, + }; +}; + +const mixColor = (start: string, end: string, ratio: number) => { + const a = parseColor(start); + const b = parseColor(end); + const t = Math.max(0, Math.min(1, ratio)); + const r = Math.round(a.r + (b.r - a.r) * t); + const g = Math.round(a.g + (b.g - a.g) * t); + const bl = Math.round(a.b + (b.b - a.b) * t); + const alpha = a.a + (b.a - a.a) * t; + return `rgba(${r}, ${g}, ${bl}, ${alpha})`; +}; + +const ThemeBackdropInner: React.FC = ({ colors }) => { + const gradientStrips = useMemo(() => + Array.from({ length: 18 }).map((_, index, arr) => { + const ratio = index / (arr.length - 1); + return mixColor(colors.pageGradientStart, colors.pageGradientEnd, ratio); + }), + [colors.pageGradientStart, colors.pageGradientEnd]); + + return ( + + + {gradientStrips.map((stripColor, index) => ( + + ))} + + + {texturePoints.map(([x, y, size], index) => ( + + ))} + + + ); +}; + +export const ThemeBackdrop = React.memo(ThemeBackdropInner); + +const styles = StyleSheet.create({ + gradientLayer: { ...StyleSheet.absoluteFillObject }, + gradientStrip: { flex: 1 }, + textureLayer: { + ...StyleSheet.absoluteFillObject, + }, + noiseDot: { + position: 'absolute', + }, +}); diff --git a/components/Toast.tsx b/components/Toast.tsx index 745ebfe..09bc108 100644 --- a/components/Toast.tsx +++ b/components/Toast.tsx @@ -1,37 +1,79 @@ - -import React, { useEffect, useState } from 'react'; -import { CheckCircle2 } from 'lucide-react'; +import React, { useEffect, useRef } from 'react'; +import { Animated, Text, StyleSheet, View } from 'react-native'; +import { Ionicons } from '@expo/vector-icons'; +import { useColors } from '../constants/Colors'; +import { ColorPalette } from '../types'; interface ToastProps { message: string; isVisible: boolean; onClose: () => void; + isDark?: boolean; + colorPalette?: ColorPalette; } -export const Toast: React.FC = ({ message, isVisible, onClose }) => { - const [show, setShow] = useState(false); +export const Toast: React.FC = ({ + message, + isVisible, + onClose, + isDark = false, + colorPalette = 'forest', +}) => { + const colors = useColors(isDark, colorPalette); + const opacity = useRef(new Animated.Value(0)).current; + const translateY = useRef(new Animated.Value(20)).current; useEffect(() => { if (isVisible) { - setShow(true); - const timer = setTimeout(() => { - setShow(false); - setTimeout(onClose, 300); // Wait for animation - }, 3000); - return () => clearTimeout(timer); - } else { - setShow(false); - } - }, [isVisible, onClose]); + Animated.parallel([ + Animated.timing(opacity, { toValue: 1, duration: 300, useNativeDriver: true }), + Animated.timing(translateY, { toValue: 0, duration: 300, useNativeDriver: true }), + ]).start(); - if (!isVisible && !show) return null; + const timer = setTimeout(() => { + Animated.parallel([ + Animated.timing(opacity, { toValue: 0, duration: 300, useNativeDriver: true }), + Animated.timing(translateY, { toValue: 20, duration: 300, useNativeDriver: true }), + ]).start(() => onClose()); + }, 3000); + + return () => clearTimeout(timer); + } + }, [isVisible]); + + if (!isVisible) return null; return ( -
-
- - {message} -
-
+ + + + {message} + + ); }; + +const styles = StyleSheet.create({ + container: { + position: 'absolute', + bottom: 100, + left: 0, + right: 0, + alignItems: 'center', + zIndex: 70, + pointerEvents: 'none', + }, + toast: { + flexDirection: 'row', + alignItems: 'center', + gap: 8, + paddingHorizontal: 16, + paddingVertical: 12, + borderRadius: 24, + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.2, + shadowRadius: 8, + elevation: 8, + }, + text: { fontSize: 13, fontWeight: '500' }, +}); diff --git a/constants/Colors.ts b/constants/Colors.ts new file mode 100644 index 0000000..82362cd --- /dev/null +++ b/constants/Colors.ts @@ -0,0 +1,354 @@ +import { AppColorScheme, ColorPalette } from '../types'; + +interface SchemeColors { + text: string; + textSecondary: string; + textMuted: string; + textOnImage: string; + background: string; + surface: string; + surfaceMuted: string; + surfaceStrong: string; + border: string; + borderStrong: string; + overlay: string; + overlayStrong: string; + heroButton: string; + heroButtonBorder: string; + tabBarBg: string; + tabBarBorder: string; + inputBg: string; + inputBorder: string; + cardBg: string; + cardBorder: string; + cardShadow: string; + chipBg: string; + chipBorder: string; + pageBase: string; + pageGradientStart: string; + pageGradientEnd: string; + pageTexture: string; +} + +interface PaletteColors { + primary: string; + primaryDark: string; + info: string; + warning: string; + danger: string; + success: string; + accent: string; +} + +interface PaletteSurfaceTone { + background: string; + surface: string; + surfaceMuted: string; + surfaceStrong: string; + border: string; + borderStrong: string; + tabBarBg: string; + tabBarBorder: string; + pageBase: string; + pageGradientStart: string; + pageGradientEnd: string; + pageTexture: string; +} + +interface PaletteThemeTone { + light: PaletteSurfaceTone; + dark: PaletteSurfaceTone; +} + +export interface AppColors extends SchemeColors, PaletteColors { + onPrimary: string; + primarySoft: string; + infoSoft: string; + warningSoft: string; + dangerSoft: string; + successSoft: string; + primaryTint: string; + infoTint: string; + warningTint: string; + dangerTint: string; + successTint: string; + mutedChip: string; + fabBg: string; + fabShadow: string; + iconOnImage: string; +} + +const textByScheme: Record< + AppColorScheme, + Pick +> = { + light: { + text: '#1f2520', + textSecondary: '#4d5650', + textMuted: '#6e7871', + textOnImage: '#f7f8f7', + overlay: 'rgba(16, 20, 17, 0.4)', + overlayStrong: 'rgba(13, 17, 14, 0.78)', + }, + dark: { + text: '#f0f3f1', + textSecondary: '#c9d0cb', + textMuted: '#a1aba4', + textOnImage: '#f5f7f6', + overlay: 'rgba(9, 11, 10, 0.52)', + overlayStrong: 'rgba(8, 10, 9, 0.86)', + }, +}; + +const paletteSurfaces: Record = { + forest: { + light: { + background: '#ecf3ed', + surface: '#f5faf6', + surfaceMuted: '#e4ede6', + surfaceStrong: '#d8e3d9', + border: '#c7d4c8', + borderStrong: '#b3c4b5', + tabBarBg: '#f1f7f2', + tabBarBorder: '#ccd9ce', + pageBase: '#e9f1ea', + pageGradientStart: '#dde9de', + pageGradientEnd: '#f1f5f0', + pageTexture: '#4b6a50', + }, + dark: { + background: '#111813', + surface: '#17211a', + surfaceMuted: '#1d2920', + surfaceStrong: '#243128', + border: '#2b3a2f', + borderStrong: '#394c3d', + tabBarBg: '#141d17', + tabBarBorder: '#2f4033', + pageBase: '#111813', + pageGradientStart: '#15211a', + pageGradientEnd: '#0f1511', + pageTexture: '#91b196', + }, + }, + ocean: { + light: { + background: '#ebf1f8', + surface: '#f4f8fc', + surfaceMuted: '#e1e8f1', + surfaceStrong: '#d4deeb', + border: '#c2cfde', + borderStrong: '#acbdd1', + tabBarBg: '#eef4fa', + tabBarBorder: '#c8d6e6', + pageBase: '#e9f0f7', + pageGradientStart: '#d9e3f0', + pageGradientEnd: '#eef3f8', + pageTexture: '#4c6480', + }, + dark: { + background: '#10171f', + surface: '#16202b', + surfaceMuted: '#1c2734', + surfaceStrong: '#243143', + border: '#2c3b4d', + borderStrong: '#3a4e64', + tabBarBg: '#131c26', + tabBarBorder: '#324357', + pageBase: '#10171f', + pageGradientStart: '#152230', + pageGradientEnd: '#0f151d', + pageTexture: '#96aac2', + }, + }, + sunset: { + light: { + background: '#f7eee8', + surface: '#fdf7f3', + surfaceMuted: '#f2e5da', + surfaceStrong: '#ead8c8', + border: '#dbc4b1', + borderStrong: '#cfb197', + tabBarBg: '#f9f0e8', + tabBarBorder: '#decaB9', + pageBase: '#f6ece4', + pageGradientStart: '#efdccd', + pageGradientEnd: '#f8f1eb', + pageTexture: '#8a644e', + }, + dark: { + background: '#1b1410', + surface: '#271c16', + surfaceMuted: '#31231b', + surfaceStrong: '#3f2d22', + border: '#4a372a', + borderStrong: '#604633', + tabBarBg: '#231913', + tabBarBorder: '#553d2c', + pageBase: '#1a1410', + pageGradientStart: '#2a1d15', + pageGradientEnd: '#16110d', + pageTexture: '#c8a690', + }, + }, + mono: { + light: { + background: '#eff1f3', + surface: '#f7f8fa', + surfaceMuted: '#e5e8ec', + surfaceStrong: '#d8dde3', + border: '#c8ced6', + borderStrong: '#b4bdc8', + tabBarBg: '#f2f4f7', + tabBarBorder: '#cdd3db', + pageBase: '#eceff2', + pageGradientStart: '#dfe4ea', + pageGradientEnd: '#f2f4f6', + pageTexture: '#666f7b', + }, + dark: { + background: '#131518', + surface: '#1b1f24', + surfaceMuted: '#232932', + surfaceStrong: '#2d3540', + border: '#343f4c', + borderStrong: '#455364', + tabBarBg: '#171b20', + tabBarBorder: '#3a4552', + pageBase: '#131518', + pageGradientStart: '#1a2028', + pageGradientEnd: '#111418', + pageTexture: '#a1adbc', + }, + }, +}; + +const palettes: Record = { + forest: { + primary: '#5fa779', + primaryDark: '#3d7f57', + info: '#4e7fb3', + warning: '#bb8a36', + danger: '#be5d5d', + success: '#4f9767', + accent: '#4a8e7f', + }, + ocean: { + primary: '#5a90be', + primaryDark: '#3d6f99', + info: '#4e79b1', + warning: '#bc8b37', + danger: '#be6464', + success: '#4f8b80', + accent: '#4f8fa0', + }, + sunset: { + primary: '#c98965', + primaryDark: '#a36442', + info: '#6c89b4', + warning: '#bd8742', + danger: '#b8666d', + success: '#769f6e', + accent: '#b47453', + }, + mono: { + primary: '#7b8796', + primaryDark: '#5b6574', + info: '#748498', + warning: '#9d8b5a', + danger: '#a86868', + success: '#6f8b75', + accent: '#6c7785', + }, +}; + +const hexToRgb = (hex: string) => { + const cleaned = hex.replace('#', ''); + const normalized = + cleaned.length === 3 + ? cleaned + .split('') + .map((char) => `${char}${char}`) + .join('') + : cleaned; + const int = Number.parseInt(normalized, 16); + return { + r: (int >> 16) & 255, + g: (int >> 8) & 255, + b: int & 255, + }; +}; + +const withOpacity = (hex: string, opacity: number) => { + const { r, g, b } = hexToRgb(hex); + return `rgba(${r}, ${g}, ${b}, ${opacity})`; +}; + +const mixColors = (baseHex: string, tintHex: string, tintWeight: number) => { + const base = hexToRgb(baseHex); + const tint = hexToRgb(tintHex); + const weight = Math.max(0, Math.min(1, tintWeight)); + const r = Math.round(base.r + (tint.r - base.r) * weight); + const g = Math.round(base.g + (tint.g - base.g) * weight); + const b = Math.round(base.b + (tint.b - base.b) * weight); + return `rgb(${r}, ${g}, ${b})`; +}; + +const getOnColor = (hex: string) => { + const { r, g, b } = hexToRgb(hex); + const luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255; + return luminance > 0.58 ? '#111111' : '#ffffff'; +}; + +export const useColors = ( + isDark: boolean, + palette: ColorPalette = 'forest' +): AppColors => { + const schemeKey: AppColorScheme = isDark ? 'dark' : 'light'; + const textColors = textByScheme[schemeKey]; + const paletteColors = palettes[palette]; + const tone = paletteSurfaces[palette][schemeKey]; + + return { + ...textColors, + ...paletteColors, + background: tone.background, + surface: tone.surface, + surfaceMuted: tone.surfaceMuted, + surfaceStrong: tone.surfaceStrong, + border: tone.border, + borderStrong: tone.borderStrong, + tabBarBg: tone.tabBarBg, + tabBarBorder: tone.tabBarBorder, + inputBg: tone.surfaceMuted, + inputBorder: tone.borderStrong, + cardBg: withOpacity(tone.surface, isDark ? 0.9 : 0.92), + cardBorder: withOpacity(tone.borderStrong, isDark ? 0.7 : 0.82), + cardShadow: withOpacity('#000000', isDark ? 0.26 : 0.12), + chipBg: tone.surfaceStrong, + chipBorder: tone.border, + pageBase: tone.pageBase, + pageGradientStart: withOpacity(tone.pageGradientStart, isDark ? 0.44 : 0.52), + pageGradientEnd: withOpacity(tone.pageGradientEnd, isDark ? 0.34 : 0.44), + pageTexture: withOpacity(tone.pageTexture, isDark ? 0.09 : 0.07), + overlay: textColors.overlay, + overlayStrong: textColors.overlayStrong, + heroButton: withOpacity(tone.surface, isDark ? 0.9 : 0.94), + heroButtonBorder: withOpacity(tone.borderStrong, isDark ? 0.7 : 0.8), + onPrimary: getOnColor(paletteColors.primary), + primarySoft: withOpacity(paletteColors.primary, isDark ? 0.26 : 0.18), + infoSoft: withOpacity(paletteColors.info, isDark ? 0.24 : 0.16), + warningSoft: withOpacity(paletteColors.warning, isDark ? 0.24 : 0.18), + dangerSoft: withOpacity(paletteColors.danger, isDark ? 0.2 : 0.14), + successSoft: withOpacity(paletteColors.success, isDark ? 0.2 : 0.14), + primaryTint: mixColors(tone.surfaceStrong, paletteColors.primary, isDark ? 0.22 : 0.2), + infoTint: mixColors(tone.surfaceStrong, paletteColors.info, isDark ? 0.2 : 0.18), + warningTint: mixColors(tone.surfaceStrong, paletteColors.warning, isDark ? 0.22 : 0.2), + dangerTint: mixColors(tone.surfaceStrong, paletteColors.danger, isDark ? 0.2 : 0.18), + successTint: mixColors(tone.surfaceStrong, paletteColors.success, isDark ? 0.2 : 0.18), + mutedChip: tone.surfaceStrong, + fabBg: paletteColors.primary, + fabShadow: withOpacity(paletteColors.primaryDark, 0.75), + iconOnImage: '#ffffff', + }; +}; diff --git a/constants/lexiconBatch1.ts b/constants/lexiconBatch1.ts new file mode 100644 index 0000000..d4a7e6f --- /dev/null +++ b/constants/lexiconBatch1.ts @@ -0,0 +1,1006 @@ +export interface LexiconBatchEntry { + name: string; + botanicalName: string; + confidence: number; + careInfo: { + waterIntervalDays: number; + light: string; + temp: string; + }; + description?: string; + imageUri: string; + categories: string[]; +} + +export const LEXICON_BATCH_1_ENTRIES: LexiconBatchEntry[] = [ + { + name: 'Birkenfeige', + botanicalName: 'Ficus benjamina', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '16-24 °C' }, + description: 'Die Birkenfeige ist ein eleganter Zimmerstrauch mit haengenden Aesten und kleinen, glaenzenden Blaettern.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Starr-080608-7576-Ficus_benjamina-habit_with_Laysan_albatross-Gym_Sand_Island-Midway_Atoll_%2824823189861%29.jpg/500px-Starr-080608-7576-Ficus_benjamina-habit_with_Laysan_albatross-Gym_Sand_Island-Midway_Atoll_%2824823189861%29.jpg', + categories: ['tree', 'air_purifier'], + }, + { + name: 'Ufopflanze', + botanicalName: 'Pilea peperomioides', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '13-30 °C' }, + description: 'Die Ufopflanze hat unverwechselbare, runde Blaetter auf langen Stielen. Bildet leicht Ableger zum Verschenken.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Pilea_peperomioides_Chinese_money_plant.jpg/500px-Pilea_peperomioides_Chinese_money_plant.jpg', + categories: ['easy', 'pet_friendly'], + }, + { + name: 'Paradiesvogelblume', + botanicalName: 'Strelitzia reginae', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '18-26 °C' }, + description: 'Die Paradiesvogelblume beeindruckt mit leuchtend orangefarbenen und blauen Blueten, die einem Vogel aehneln.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Bird_of_Paradise_flower.JPG/500px-Bird_of_Paradise_flower.JPG', + categories: ['flowering', 'sun', 'large'], + }, + { + name: 'Echeverie', + botanicalName: 'Echeveria elegans', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Volles Sonnenlicht', temp: '15-25 °C' }, + description: 'Die Echeverie bildet symmetrische, rosettenfoermige Sukkulenten mit blaugruenen Blaettern. Pflegeleicht.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/5d/Echeveria_elegans_-_1.png/500px-Echeveria_elegans_-_1.png', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Jadepflanze', + botanicalName: 'Crassula ovata', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Helles bis volles Licht', temp: '15-24 °C' }, + description: 'Die Jadepflanze ist eine langlebige Sukkulente mit dicken, ovalen Blaettern. In Japan gilt sie als Gluecksbringer.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Crassula_ovata_700.jpg/500px-Crassula_ovata_700.jpg', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Zebra-Haworthie', + botanicalName: 'Haworthia fasciata', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Helles indirektes Licht', temp: '15-25 °C' }, + description: 'Die Zebra-Haworthie ist eine kompakte Sukkulente mit weissen Querstreifen auf dunkelgruenen Blaettern.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/1_Haworthia_fasciata_-MBB_Kabeljouws_River.jpg/500px-1_Haworthia_fasciata_-MBB_Kabeljouws_River.jpg', + categories: ['easy', 'succulent', 'low_light'], + }, + { + name: 'Eselschwanz', + botanicalName: 'Sedum morganianum', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Volles Sonnenlicht', temp: '15-25 °C' }, + description: 'Der Eselschwanz ist eine haengende Sukkulente mit langen Trieben aus dichten, blaugruenen Blaettchen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e5/Donkey%27s_tail_in_bloom_March_06.jpg/500px-Donkey%27s_tail_in_bloom_March_06.jpg', + categories: ['easy', 'succulent', 'hanging', 'sun'], + }, + { + name: 'Weihnachtskaktus', + botanicalName: 'Schlumbergera truncata', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '15-21 °C' }, + description: 'Der Weihnachtskaktus erfreut zur Weihnachtszeit mit leuchtenden Blueten in Rosa, Rot oder Weiss.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/f1/Schlumbergera_truncata_%28Exotic_Flora_Plate_20%29.jpg/500px-Schlumbergera_truncata_%28Exotic_Flora_Plate_20%29.jpg', + categories: ['easy', 'succulent', 'flowering'], + }, + { + name: 'Kalanchoe', + botanicalName: 'Kalanchoe blossfeldiana', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Die Kalanchoe ist eine beliebte Bluehpflanze mit leuchtenden Blueten in Rot, Orange, Gelb oder Rosa.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Kalanchoe_blossfeldiana_3.jpg/500px-Kalanchoe_blossfeldiana_3.jpg', + categories: ['easy', 'succulent', 'flowering', 'sun'], + }, + { + name: 'Schwarze Rose (Aeonium)', + botanicalName: 'Aeonium arboreum', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Volles Sonnenlicht', temp: '10-25 °C' }, + description: 'Das Aeonium bildet dekorative, rosettenfoermige Sukkulenten an verzweigten Stielen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/28/Madeira%2C_Palheiro_Gardens_-_Aeonium_arboreum_%28Marokko%29_IMG_2310.JPG/500px-Madeira%2C_Palheiro_Gardens_-_Aeonium_arboreum_%28Marokko%29_IMG_2310.JPG', + categories: ['succulent', 'sun'], + }, + { + name: 'Agave', + botanicalName: 'Agave americana', + confidence: 1.0, + careInfo: { waterIntervalDays: 21, light: 'Volles Sonnenlicht', temp: '10-35 °C' }, + description: 'Die Agave ist eine imposante Sukkulente mit steifen, blaugruenen Blaettern mit Stacheln. Sie bluet nur einmal.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Agave_July_2011-1.jpg/500px-Agave_July_2011-1.jpg', + categories: ['succulent', 'sun', 'large'], + }, + { + name: 'Bleistiftkaktus', + botanicalName: 'Euphorbia tirucalli', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Volles Sonnenlicht', temp: '18-30 °C' }, + description: 'Der Bleistiftkaktus ist eine sukkulente Wolfsmilch mit duennen, zylindrischen Zweigen ohne Blaetter.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Euphorbia_tirucalli_in_the_wild_by_tonrulkens.jpg/500px-Euphorbia_tirucalli_in_the_wild_by_tonrulkens.jpg', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Drachenbaum', + botanicalName: 'Dracaena marginata', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Helles indirektes Licht', temp: '15-25 °C' }, + description: 'Der Drachenbaum ist eine schlanke Zimmerpflanze mit roten, schmalen Blaettern auf langen Staemmen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/61/Dracaena_reflexa.JPG/500px-Dracaena_reflexa.JPG', + categories: ['easy', 'air_purifier', 'tree'], + }, + { + name: 'Maisstrauch', + botanicalName: 'Dracaena fragrans', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Helles indirektes Licht', temp: '15-25 °C' }, + description: 'Der Maisstrauch ist eine robuste Zimmerpflanze mit breiten, gestreiften Blaettern. Gedeiht auch bei wenig Licht.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/db/Dracaena_fragrans_%282%29.jpg/500px-Dracaena_fragrans_%282%29.jpg', + categories: ['easy', 'low_light', 'air_purifier', 'tree'], + }, + { + name: 'Herzblatt-Philodendron', + botanicalName: 'Philodendron hederaceum', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Indirektes Licht', temp: '18-28 °C' }, + description: 'Der Herzblatt-Philodendron ist eine pflegeleichte Kletter- oder Haengepflanze mit herzfoermigen Blaettern.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Philodendron_scandens_subsp_oxycardium2.jpg/500px-Philodendron_scandens_subsp_oxycardium2.jpg', + categories: ['easy', 'low_light', 'hanging'], + }, + { + name: 'Marmor-Efeutute', + botanicalName: 'Epipremnum aureum Marble Queen', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '15-30 °C' }, + description: 'Die Marmor-Efeutute hat cremeweiss-gruen marmorierte Blaetter. Eine dekorative Variante der klassischen Efeutute.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/ca/Epipremnum_aureum_Marble_Queen.jpg/500px-Epipremnum_aureum_Marble_Queen.jpg', + categories: ['easy', 'hanging', 'air_purifier'], + }, + { + name: 'Zebrakraut', + botanicalName: 'Tradescantia zebrina', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '15-25 °C' }, + description: 'Das Zebrakraut faellt durch seine silbrig-lila gestreiften Blaetter auf. Schnellwachsende Haengepflanze.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/Zebrina_pendula_20060521_2_closer.jpg/500px-Zebrina_pendula_20060521_2_closer.jpg', + categories: ['easy', 'hanging', 'patterned'], + }, + { + name: 'Koenigsbegonie', + botanicalName: 'Begonia rex', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Indirektes Licht', temp: '18-25 °C' }, + description: 'Die Koenigsbegonie beeindruckt mit prachtvoll gemusterten Blaettern in Silber, Rot und Gruen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Painted_Leaved_Begonia._Begonia_rex_Putz._Flore_des_serres_et_des_jardins_de_l%27Europe_v.12_%281857%29.jpg/500px-Painted_Leaved_Begonia._Begonia_rex_Putz._Flore_des_serres_et_des_jardins_de_l%27Europe_v.12_%281857%29.jpg', + categories: ['patterned', 'high_humidity'], + }, + { + name: 'Alpenveilchen', + botanicalName: 'Cyclamen persicum', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '12-18 °C' }, + description: 'Das Alpenveilchen bluet im Herbst und Winter mit eleganten Blueten in Rosa, Rot oder Weiss.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Yagur_%E2%80%93_Nesher%2C_the_Green_Path_%E2%80%93_Mount_Carmel_016.JPG/500px-Yagur_%E2%80%93_Nesher%2C_the_Green_Path_%E2%80%93_Mount_Carmel_016.JPG', + categories: ['flowering'], + }, + { + name: 'Fleissiges Lieschen', + botanicalName: 'Impatiens walleriana', + confidence: 1.0, + careInfo: { waterIntervalDays: 2, light: 'Helles indirektes Licht', temp: '16-24 °C' }, + description: 'Das Fleissige Lieschen bluet von Fruehling bis Herbst unermudlich in vielen Farben.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/28/Impatienswalleriana.jpg/500px-Impatienswalleriana.jpg', + categories: ['easy', 'flowering'], + }, + { + name: 'Hibiskus', + botanicalName: 'Hibiscus rosa-sinensis', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Volles Sonnenlicht', temp: '18-28 °C' }, + description: 'Der Hibiskus begeistert mit grossen, trompetenfoermigen Blueten in Rot, Orange und Rosa.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/21/Hibiscus_Brilliant.jpg/500px-Hibiscus_Brilliant.jpg', + categories: ['flowering', 'sun', 'bright_light'], + }, + { + name: 'Gardenie', + botanicalName: 'Gardenia jasminoides', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '18-23 °C' }, + description: 'Die Gardenie fasziniert mit cremefarbenen, intensiv duftenden Blueten. Anspruchsvoll in der Pflege.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/54/Gardenia_jasminoides_flower_Argentina.jpg/500px-Gardenia_jasminoides_flower_Argentina.jpg', + categories: ['flowering', 'high_humidity'], + }, + { + name: 'Echter Lavendel', + botanicalName: 'Lavandula angustifolia', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Volles Sonnenlicht', temp: '10-25 °C' }, + description: 'Der Echte Lavendel ist ein aromatischer Halbstrauch mit lilafarbenen Bluetenaehren. Herrlicher Duft.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/4/40/Lavandula_angustifolia_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-087.jpg', + categories: ['medicinal', 'sun', 'bright_light'], + }, + { + name: 'Rosmarin', + botanicalName: 'Rosmarinus officinalis', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '10-25 °C' }, + description: 'Rosmarin ist ein aromatisches Kraut mit nadelartigen Blaettern und blauen Blueten. In der Kueche unverzichtbar.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a3/Rosemary_in_bloom.JPG/500px-Rosemary_in_bloom.JPG', + categories: ['easy', 'medicinal', 'sun'], + }, + { + name: 'Basilikum', + botanicalName: 'Ocimum basilicum', + confidence: 1.0, + careInfo: { waterIntervalDays: 2, light: 'Volles Sonnenlicht', temp: '18-30 °C' }, + description: 'Basilikum ist das beliebteste Kuechenkraut mit intensiv aromatischen, gruenen Blaettern. Fuer Pesto verwendet.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/97/Ocimum_basilicum_8zz.jpg/500px-Ocimum_basilicum_8zz.jpg', + categories: ['easy', 'medicinal', 'sun'], + }, + { + name: 'Gruene Minze', + botanicalName: 'Mentha spicata', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Die Gruene Minze ist ein wuchsfreudiges Kuechenkraut mit frischem, minzigem Duft. Fuer Tee und Cocktails.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/Minze.jpg/500px-Minze.jpg', + categories: ['easy'], + }, + { + name: 'Thymian', + botanicalName: 'Thymus vulgaris', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '10-25 °C' }, + description: 'Thymian ist ein kleiner, aromatischer Strauch mit winzigen Blaettern und rosa Blueten. Wichtiges Kuechenkraut.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/4/4f/Thymus_vulgaris1.JPG/500px-Thymus_vulgaris1.JPG', + categories: ['easy', 'medicinal', 'sun'], + }, + { + name: 'Oregano', + botanicalName: 'Origanum vulgare', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '15-25 °C' }, + description: 'Oregano ist ein aromatisches Kuechenkraut mit runden, behaarten Blaettern. In mediterraner Kueche beliebt.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Origanum_vulgare_-_harilik_pune.jpg/500px-Origanum_vulgare_-_harilik_pune.jpg', + categories: ['easy', 'medicinal', 'sun'], + }, + { + name: 'Petersilie', + botanicalName: 'Petroselinum crispum', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles Licht', temp: '10-25 °C' }, + description: 'Petersilie ist eines der meistgenutzten Kuechenkraeuter mit frisch-aromatischem Geschmack. Reich an Vitaminen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Petroselinum.jpg/500px-Petroselinum.jpg', + categories: ['easy'], + }, + { + name: 'Schnittlauch', + botanicalName: 'Allium schoenoprasum', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles bis volles Licht', temp: '10-25 °C' }, + description: 'Schnittlauch ist ein beliebtes Kuechenkraut mit roehrenfoermigen Blaettern und lila Blueten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/4/49/Allium_schoenoprasum_-_Bombus_lapidarius_-_Tootsi.jpg/500px-Allium_schoenoprasum_-_Bombus_lapidarius_-_Tootsi.jpg', + categories: ['easy'], + }, + { + name: 'Rosengeranie', + botanicalName: 'Pelargonium graveolens', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '15-25 °C' }, + description: 'Die Rosengeranie ist eine Duftpflanze mit tief eingeschnittenen Blaettern und rosaenlichem Aroma.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/%28MHNT%29_Pelargonium_graveolens_flower_and_leaves.jpg/500px-%28MHNT%29_Pelargonium_graveolens_flower_and_leaves.jpg', + categories: ['easy', 'medicinal', 'sun'], + }, + { + name: 'Blutroter Storchschnabel', + botanicalName: 'Geranium sanguineum', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '10-25 °C' }, + description: 'Der Blutrote Storchschnabel ist ein zierlicher Storchschnabel mit intensiv magentafarbenen Blueten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8c/2012-07-03_Bloody_Crane%27s-bill%2C_Hauxley%2C_Northumberland_1.jpg/500px-2012-07-03_Bloody_Crane%27s-bill%2C_Hauxley%2C_Northumberland_1.jpg', + categories: ['easy', 'flowering'], + }, + { + name: 'Fuchsie', + botanicalName: 'Fuchsia hybrida', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles indirektes Licht', temp: '14-22 °C' }, + description: 'Die Fuchsie haengt mit eleganten, zweifarbigen Blueten wie kleine Ohrringe herab. Ideal fuer Ampeln.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Brincos_De_Princesa.jpg/500px-Brincos_De_Princesa.jpg', + categories: ['flowering', 'hanging'], + }, + { + name: 'Petunie', + botanicalName: 'Petunia hybrida', + confidence: 1.0, + careInfo: { waterIntervalDays: 2, light: 'Volles Sonnenlicht', temp: '15-25 °C' }, + description: 'Die Petunie ist eine der beliebtesten Balkonpflanzen mit trichterfoermigen Blueten in unzaehligen Farben.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/PetuniaFlower.JPG/500px-PetuniaFlower.JPG', + categories: ['easy', 'flowering', 'sun', 'pet_friendly'], + }, + { + name: 'Stiefmuetterchen', + botanicalName: 'Viola wittrockiana', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles bis volles Licht', temp: '5-18 °C' }, + description: 'Das Stiefmuetterchen ist ein bekannter Fruehjahrsblueher mit charakteristisch gezeichneten Blueten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b8/PansyScan_%28cropped%29.jpg/500px-PansyScan_%28cropped%29.jpg', + categories: ['easy', 'flowering'], + }, + { + name: 'Primel', + botanicalName: 'Primula vulgaris', + confidence: 1.0, + careInfo: { waterIntervalDays: 4, light: 'Helles indirektes Licht', temp: '10-18 °C' }, + description: 'Die Primel ist einer der ersten Fruehjahrs­boten mit lebhaften Blueten in Gelb, Pink, Rot und Lila.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/Prole%C4%87no_cve%C4%87e_3.JPG/500px-Prole%C4%87no_cve%C4%87e_3.JPG', + categories: ['flowering'], + }, + { + name: 'Efeu', + botanicalName: 'Hedera helix', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Wenig bis helles Licht', temp: '10-20 °C' }, + description: 'Efeu ist eine robuste Kletter- und Haengepflanze mit charakteristischen, dreilappigen Blaettern. Sehr langlebig.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Hedera_helix_Dover.jpg/500px-Hedera_helix_Dover.jpg', + categories: ['easy', 'low_light', 'hanging', 'air_purifier'], + }, + { + name: 'Gummibaum', + botanicalName: 'Ficus elastica', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Helles indirektes Licht', temp: '16-24 °C' }, + description: 'Der Gummibaum ist eine imposante Zimmerpflanze mit grossen, glaenzenden, lederartigen Blaettern. Reinigt die Luft.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/Ficus_elastica_leaves_02.JPG/500px-Ficus_elastica_leaves_02.JPG', + categories: ['easy', 'air_purifier', 'tree'], + }, + { + name: 'Geigenfeige', + botanicalName: 'Ficus lyrata', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Die Geigenfeige ist ein Trendbaum mit grossen, geigenfoermigen Blaettern. Benoetigt viel Licht.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Starr_031108-0130_Ficus_lyrata.jpg/500px-Starr_031108-0130_Ficus_lyrata.jpg', + categories: ['tree', 'bright_light', 'large'], + }, + { + name: 'Yucca-Palme', + botanicalName: 'Yucca elephantipes', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Helles bis volles Licht', temp: '15-28 °C' }, + description: 'Die Yucca-Palme ist eine robuste Zimmerpflanze mit starrem, immergruenem Blaetterschopf auf einem dicken Stamm.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/bd/Yucca_gigantea_-_Jard%C3%ADn_Bot%C3%A1nico_Canario_Viera_y_Clavijo_-_Gran_Canaria.jpg/500px-Yucca_gigantea_-_Jard%C3%ADn_Bot%C3%A1nico_Canario_Viera_y_Clavijo_-_Gran_Canaria.jpg', + categories: ['easy', 'tree', 'sun'], + }, + { + name: 'Pferdeschwanzpalme', + botanicalName: 'Beaucarnea recurvata', + confidence: 1.0, + careInfo: { waterIntervalDays: 21, light: 'Volles Sonnenlicht', temp: '15-30 °C' }, + description: 'Die Pferdeschwanzpalme hat einen verdickten Stammbasis als Wasserspeicher und lange, schmale Blaetter.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/7/7e/Beaucarnea_recurvata%2C_Ocampo%2C_Tamaulipas%2C_Mexico_1.jpg/500px-Beaucarnea_recurvata%2C_Ocampo%2C_Tamaulipas%2C_Mexico_1.jpg', + categories: ['easy', 'succulent', 'tree', 'sun'], + }, + { + name: 'Goldfruchtpalme', + botanicalName: 'Dypsis lutescens', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Die Goldfruchtpalme ist eine elegante Zimmerpalme mit gelblich-gruenen Stielen und gefiederten Wedeln.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/22/%E6%95%A3%E5%B0%BE%E8%91%B5Dypsis_lutescens_20210511145013_05.jpg/500px-%E6%95%A3%E5%B0%BE%E8%91%B5Dypsis_lutescens_20210511145013_05.jpg', + categories: ['air_purifier', 'tree', 'pet_friendly'], + }, + { + name: 'Bergpalme', + botanicalName: 'Chamaedorea elegans', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Wenig bis helles Licht', temp: '15-25 °C' }, + description: 'Die Bergpalme ist eine kompakte Zimmerpalme fuer schattigere Standorte. Ideal fuer dunkle Innenraeume.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/64/Chamaedorea_elegans_Mart.JPG/500px-Chamaedorea_elegans_Mart.JPG', + categories: ['easy', 'low_light', 'tree', 'air_purifier', 'pet_friendly'], + }, + { + name: 'Zwergdattelpalme', + botanicalName: 'Phoenix roebelenii', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '18-27 °C' }, + description: 'Die Zwergdattelpalme ist eine zierliche Palme mit eleganten, gebogenen Fiederblaettern. Tropisches Flair.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/1d/Starr_070124-3839_Phoenix_roebelenii.jpg/500px-Starr_070124-3839_Phoenix_roebelenii.jpg', + categories: ['tree', 'bright_light'], + }, + { + name: 'Stab-Palme', + botanicalName: 'Rhapis excelsa', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '15-25 °C' }, + description: 'Die Stab-Palme ist eine elegante Zimmerpalme mit faecher­foermigen Blaettern auf duennen, bambusartigen Staemmen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Arya_-_Rhapis_excelsa_at_hotel_citradream_Cirebon_2019_0.jpg/500px-Arya_-_Rhapis_excelsa_at_hotel_citradream_Cirebon_2019_0.jpg', + categories: ['low_light', 'tree'], + }, + { + name: 'Amazona-Taro', + botanicalName: 'Alocasia amazonica', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Indirektes Licht', temp: '18-27 °C' }, + description: 'Der Amazona-Taro besticht mit dunkelgruenen, pfeilfoermigen Blaettern mit markant weissen Rippen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Alocasia_x_amazonica_a1.jpg/500px-Alocasia_x_amazonica_a1.jpg', + categories: ['patterned', 'high_humidity', 'large'], + }, + { + name: 'Taro', + botanicalName: 'Colocasia esculenta', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles indirektes Licht', temp: '18-30 °C' }, + description: 'Der Taro ist eine tropische Pflanze mit grossen, herzfoermigen Blaettern. Die Knollen sind Nahrungsquelle.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/30/Songe-R%C3%A9union.JPG/500px-Songe-R%C3%A9union.JPG', + categories: ['high_humidity', 'large'], + }, + { + name: 'Dieffenbachie', + botanicalName: 'Dieffenbachia seguine', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-26 °C' }, + description: 'Die Dieffenbachie ist eine tropische Blattschmuckpflanze mit grossen, gruen-weiss gefleckten Blaettern.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Dieffenbachia_seguine1FKST.jpg/500px-Dieffenbachia_seguine1FKST.jpg', + categories: ['easy', 'low_light', 'air_purifier'], + }, + { + name: 'Buntblatt', + botanicalName: 'Caladium bicolor', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Indirektes Licht', temp: '20-30 °C' }, + description: 'Das Buntblatt beeindruckt mit transparenten, bunt gemusterten Blaettern in Pink, Rot, Weiss und Gruen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Caladium_bicolor_2.jpg/500px-Caladium_bicolor_2.jpg', + categories: ['patterned', 'high_humidity'], + }, + { + name: 'Aglaoneme', + botanicalName: 'Aglaonema commutatum', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Wenig bis helles Licht', temp: '15-26 °C' }, + description: 'Die Aglaoneme ist eine dekorative Zimmerpflanze mit silbrig-gruen gemusterten Blaettern. Tolerant gegenueber wenig Licht.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Aglaonema_commutatum_kz1.jpg/500px-Aglaonema_commutatum_kz1.jpg', + categories: ['easy', 'low_light', 'patterned'], + }, + { + name: 'Gebet-Pflanze', + botanicalName: 'Maranta leuconeura', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Indirektes Licht', temp: '18-27 °C' }, + description: 'Die Gebet-Pflanze faltet ihre gemusterten Blaetter nachts wie Haende zusammen. Faszinierende rote und gruene Muster.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/4/4a/Maranta_leuconeura3.jpg/500px-Maranta_leuconeura3.jpg', + categories: ['patterned', 'high_humidity', 'pet_friendly'], + }, + { + name: 'Stromanthe', + botanicalName: 'Stromanthe sanguinea', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '18-25 °C' }, + description: 'Die Stromanthe hat dekorative Blaetter mit weissem Muster und leuchtend roter Unterseite. Familie der Marantaceen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/38/Stromanthe_sanguinea_in_garden_in_Manaus%2C_Brazil.jpg/500px-Stromanthe_sanguinea_in_garden_in_Manaus%2C_Brazil.jpg', + categories: ['patterned', 'high_humidity'], + }, + { + name: 'Ctenanthe', + botanicalName: 'Ctenanthe burle-marxii', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Indirektes Licht', temp: '18-25 °C' }, + description: 'Die Ctenanthe hat faszinierend gemusterte Blaetter mit dunkelgruunem Fischgraetenmuster auf hellgruunem Hintergrund.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/7/7d/Ctenanthe_burle-marxii.jpg/500px-Ctenanthe_burle-marxii.jpg', + categories: ['patterned', 'high_humidity'], + }, + { + name: 'Kleeblume', + botanicalName: 'Oxalis triangularis', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '15-24 °C' }, + description: 'Die Kleeblume hat tiefviolette, dreieckige Blaetter und zarte rosa Blueten. Sie faltet die Blaetter bei Dunkelheit.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Oxalis_triangularis6.jpg/500px-Oxalis_triangularis6.jpg', + categories: ['flowering', 'patterned'], + }, + { + name: 'Satinpothos', + botanicalName: 'Scindapsus pictus', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-28 °C' }, + description: 'Der Satinpothos hat samtig-glaenzende, silbrig gefleckte Blaetter auf langen, haengenden Ranken.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/ca/Scindapsus_pictus_01.jpg/500px-Scindapsus_pictus_01.jpg', + categories: ['easy', 'hanging', 'patterned'], + }, + { + name: 'Pfeilblatt', + botanicalName: 'Syngonium podophyllum', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '16-27 °C' }, + description: 'Das Pfeilblatt hat charakteristisch pfeilfoermige Blaetter, die sich mit dem Alter weiterentwickeln.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Zingiber_malaysianum.jpg/500px-Zingiber_malaysianum.jpg', + categories: ['easy', 'hanging'], + }, + { + name: 'Wachsblume', + botanicalName: 'Hoya carnosa', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Helles indirektes Licht', temp: '16-27 °C' }, + description: 'Die Wachsblume ist eine Kletterpflanze mit dicken, wachsartigen Blaettern und sternfoermigen, duftenden Blueten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/NKN-2007-06-13_114250_Hoya_Carnosa_%28Yvan_Leduc_author_for_Wikipedia%29.jpg/500px-NKN-2007-06-13_114250_Hoya_Carnosa_%28Yvan_Leduc_author_for_Wikipedia%29.jpg', + categories: ['easy', 'flowering', 'hanging', 'succulent'], + }, + { + name: 'Kleine Wachsblume', + botanicalName: 'Hoya bella', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Die Kleine Wachsblume traegt zierliche, sternfoermige weisse Blueten mit rosa Mitte. Haengende Sukkulente.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/%E7%BE%8E%E9%BA%97%E6%AF%AC%E8%98%AD_Hoya_bella_-%E9%A6%99%E6%B8%AF%E5%85%AC%E5%9C%92_Hong_Kong_Park-_%289240227808%29.jpg/500px-%E7%BE%8E%E9%BA%97%E6%AF%AC%E8%98%AD_Hoya_bella_-%E9%A6%99%E6%B8%AF%E5%85%AC%E5%9C%92_Hong_Kong_Park-_%289240227808%29.jpg', + categories: ['flowering', 'hanging', 'succulent'], + }, + { + name: 'Jasmin', + botanicalName: 'Jasminum polyanthum', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '10-22 °C' }, + description: 'Der Jasmin ist eine Kletterpflanze mit intensiv duftenden, weissen Blueten. Er bluet im Winter und Fruehling.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/%28MHNT%29_Jasminum_polyanthum_%E2%80%93_flowers_and_buds.jpg/500px-%28MHNT%29_Jasminum_polyanthum_%E2%80%93_flowers_and_buds.jpg', + categories: ['flowering'], + }, + { + name: 'Madagaskar-Jasmin', + botanicalName: 'Stephanotis floribunda', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-25 °C' }, + description: 'Der Madagaskar-Jasmin hat dicke, glaenzende Blaetter und wachsweisse, intensiv duftende Blueten. Klassische Hochzeitsblume.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Stephanotis_floribunda3L._Marie.jpg/500px-Stephanotis_floribunda3L._Marie.jpg', + categories: ['flowering'], + }, + { + name: 'Bleiwurz', + botanicalName: 'Plumbago auriculata', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Volles Sonnenlicht', temp: '15-27 °C' }, + description: 'Die Bleiwurz ist ein halbimmergruener Strauch mit himmelblauen Blueten, der fast das ganze Jahr bluet.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Plumbago_auriculata_2718.jpg/500px-Plumbago_auriculata_2718.jpg', + categories: ['flowering', 'sun', 'bright_light'], + }, + { + name: 'Bougainvillea', + botanicalName: 'Bougainvillea spectabilis', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Volles Sonnenlicht', temp: '18-30 °C' }, + description: 'Die Bougainvillea ist eine rankenreiche Kletterpflanze mit leuchtend farbigen Hochblaettern in Rot, Orange oder Pink.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/ae/Starr_030418-0061_Bougainvillea_spectabilis.jpg/500px-Starr_030418-0061_Bougainvillea_spectabilis.jpg', + categories: ['flowering', 'sun', 'bright_light'], + }, + { + name: 'Passionsblume', + botanicalName: 'Passiflora caerulea', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '15-27 °C' }, + description: 'Die Passionsblume ist eine faszinierende Kletterpflanze mit komplex strukturierten, blau-weissen Blueten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Passiflora_caerulea_%282019-06-24%29_frontal-view.jpg/500px-Passiflora_caerulea_%282019-06-24%29_frontal-view.jpg', + categories: ['flowering'], + }, + { + name: 'Suesskartoffel', + botanicalName: 'Ipomoea batatas', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Volles Sonnenlicht', temp: '20-30 °C' }, + description: 'Die Suesskartoffel-Zierpflanze hat dekorative, herzfoermige Blaetter in gruen oder dunkelviolett. Ideal als Haengepflanze.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Ipomoea_batatas_006.JPG/500px-Ipomoea_batatas_006.JPG', + categories: ['easy', 'hanging', 'sun'], + }, + { + name: 'Chinesischer Blauregen', + botanicalName: 'Wisteria sinensis', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '10-25 °C' }, + description: 'Der Chinesische Blauregen ist ein ueppiger Kletterkuenstler mit langen, duftenden Bluetentrauben in Lila.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/7/7a/Chinesischer_Blauregen_Detail_Bl%C3%BCtentraube.JPG/500px-Chinesischer_Blauregen_Detail_Bl%C3%BCtentraube.JPG', + categories: ['flowering', 'sun', 'large'], + }, + { + name: 'Chinesische Rose', + botanicalName: 'Rosa chinensis', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Volles Sonnenlicht', temp: '15-25 °C' }, + description: 'Die Chinesische Rose ist eine der Stammarten vieler Gartenrosen und bluet fast ununterbrochen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/Rosa_chinensis.jpg/500px-Rosa_chinensis.jpg', + categories: ['flowering', 'sun'], + }, + { + name: 'Chrysantheme', + botanicalName: 'Chrysanthemum indicum', + confidence: 1.0, + careInfo: { waterIntervalDays: 4, light: 'Helles bis volles Licht', temp: '12-22 °C' }, + description: 'Die Chrysantheme ist die klassische Herbstblume mit ueppigen, dichten Blueten in vielen Farben.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Chrysanthemum_indicum1.jpg/500px-Chrysanthemum_indicum1.jpg', + categories: ['flowering'], + }, + { + name: 'Gerbera', + botanicalName: 'Gerbera jamesonii', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Die Gerbera ist eine farbenfrohe Schnittblume mit grossen, sonnenblumenaehnlichen Blueten. Sehr beliebt.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Gerbera_jamesonii_%28Asteraceae%29.jpg/500px-Gerbera_jamesonii_%28Asteraceae%29.jpg', + categories: ['flowering', 'bright_light', 'air_purifier'], + }, + { + name: 'Schmetterlingsorchidee', + botanicalName: 'Phalaenopsis amabilis', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Helles indirektes Licht', temp: '18-28 °C' }, + description: 'Die Schmetterlingsorchidee ist die bekannteste Zimmerorchidee. Sie bluet bei guter Pflege monatelang.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/59/Phalaenopsis_amabilis_Orchi_198.jpg/500px-Phalaenopsis_amabilis_Orchi_198.jpg', + categories: ['flowering', 'high_humidity'], + }, + { + name: 'Dendrobium', + botanicalName: 'Dendrobium nobile', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Helles indirektes Licht', temp: '15-28 °C' }, + description: 'Das Dendrobium ist eine beliebte Zimmerorchidee mit langen Pseudobulben, die im Winter mit Blueten besetzt werden.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Dendrobium_nobile_-_flower_view_01.jpg/500px-Dendrobium_nobile_-_flower_view_01.jpg', + categories: ['flowering', 'high_humidity'], + }, + { + name: 'Zymbidium', + botanicalName: 'Cymbidium lowianum', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles Licht', temp: '12-24 °C' }, + description: 'Das Zymbidium ist eine robuste Orchidee mit langen, grassartigen Blaettern und eleganten Bluetenrispen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/b/b7/Cymbidium_lowianum_-_Bot-DSCF1035.jpg', + categories: ['flowering'], + }, + { + name: 'Vanda-Orchidee', + botanicalName: 'Vanda coerulea', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles bis volles Licht', temp: '20-30 °C' }, + description: 'Die Vanda-Orchidee ist bekannt fuer ihre seltene blaue Bluetenfarbe. Epiphytische Orchidee mit grossen Blueten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b3/An_orchid_%28Vanda_caerulea%29%3B_flowering_stem._Watercolour._Wellcome_V0043303.jpg/500px-An_orchid_%28Vanda_caerulea%29%3B_flowering_stem._Watercolour._Wellcome_V0043303.jpg', + categories: ['flowering', 'high_humidity', 'bright_light'], + }, + { + name: 'Cattleya-Orchidee', + botanicalName: 'Cattleya labiata', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-28 °C' }, + description: 'Die Cattleya ist die Koenigin der Orchideen mit ueppigen, duftenden Blueten in Lila, Rosa und Weiss.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Labiata.jpg/500px-Labiata.jpg', + categories: ['flowering', 'high_humidity'], + }, + { + name: 'Tanzerinnen-Orchidee', + botanicalName: 'Oncidium sphacelatum', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Die Tanzerinnen-Orchidee traegt lange Rispen mit Hunderten kleiner, gelb-brauner Blueten. Sehr reichliche Bluetracht.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Oncidium_sphacelatum03.jpg/500px-Oncidium_sphacelatum03.jpg', + categories: ['flowering', 'high_humidity'], + }, + { + name: 'Stiefmuetterchen-Orchidee', + botanicalName: 'Miltoniopsis roezlii', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Indirektes Licht', temp: '15-22 °C' }, + description: 'Die Stiefmuetterchen-Orchidee hat grosse, flache Blueten. Bevorzugt kuehle Temperaturen und hohe Luftfeuchtigkeit.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/bd/Miltoniopsis_roezlii_%28as_Odontoglossum_roezlii%29_-_pl._30_-_Bateman%2C_Monogr.Odont.jpg/500px-Miltoniopsis_roezlii_%28as_Odontoglossum_roezlii%29_-_pl._30_-_Bateman%2C_Monogr.Odont.jpg', + categories: ['flowering', 'high_humidity'], + }, + { + name: 'Vanille', + botanicalName: 'Vanilla planifolia', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '20-30 °C' }, + description: 'Die Vanille ist eine kletternde Orchidee, aus deren Fruechten das beliebte Gewuerz gewonnen wird.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Vanilla_planifolia_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-278.jpg/500px-Vanilla_planifolia_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-278.jpg', + categories: ['flowering', 'high_humidity'], + }, + { + name: 'Goldene Tonne', + botanicalName: 'Echinocactus grusonii', + confidence: 1.0, + careInfo: { waterIntervalDays: 21, light: 'Volles Sonnenlicht', temp: '15-35 °C' }, + description: 'Die Goldene Tonne ist ein ikonischer kugelfoermiger Kaktus mit goldgelben Stacheln. Waechst langsam aber imposant.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Echinocactus_grusonii_%28aka%29.jpg/500px-Echinocactus_grusonii_%28aka%29.jpg', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Fass-Kaktus', + botanicalName: 'Ferocactus cylindraceus', + confidence: 1.0, + careInfo: { waterIntervalDays: 21, light: 'Volles Sonnenlicht', temp: '15-35 °C' }, + description: 'Der Fass-Kaktus ist ein zylindrischer Wuestenkaktus mit langen, roten Stacheln. Sehr langlebig.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/Ferocactus-cylindraceus.jpg/500px-Ferocactus-cylindraceus.jpg', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Mammillaria', + botanicalName: 'Mammillaria zeilmanniana', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Volles Sonnenlicht', temp: '15-35 °C' }, + description: 'Die Mammillaria ist ein kompakter, kugelfoermiger Kaktus, der im Fruehling einen Kranz aus rosa Blueten traegt.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/Mammillaria_zeilmanniana.jpg/500px-Mammillaria_zeilmanniana.jpg', + categories: ['easy', 'succulent', 'flowering', 'sun'], + }, + { + name: 'Mond-Kaktus', + botanicalName: 'Gymnocalycium mihanovichii', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Indirektes Licht', temp: '15-30 °C' }, + description: 'Der Mond-Kaktus ist eine farbenfrohe Veredelung eines chlorophylllosen Kaktus auf einem gruenen Unterlagekaktus.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/51/Gymnocalycium_mihanovichii_4.JPG/500px-Gymnocalycium_mihanovichii_4.JPG', + categories: ['easy', 'succulent'], + }, + { + name: 'Peruanischer Fackelkaktus', + botanicalName: 'Cereus peruvianus', + confidence: 1.0, + careInfo: { waterIntervalDays: 21, light: 'Volles Sonnenlicht', temp: '15-35 °C' }, + description: 'Der Peruanische Fackelkaktus ist ein saeulenfoermiger Kaktus, der im Innenraum bis zu 2 m hoch werden kann.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Cereus_repandus_in_Aruba_-_on_the_way_back_from_Altovista_chapel_%282896840490%29.jpg/500px-Cereus_repandus_in_Aruba_-_on_the_way_back_from_Altovista_chapel_%282896840490%29.jpg', + categories: ['easy', 'succulent', 'sun', 'large'], + }, + { + name: 'Hasenohren-Kaktus', + botanicalName: 'Opuntia microdasys', + confidence: 1.0, + careInfo: { waterIntervalDays: 21, light: 'Volles Sonnenlicht', temp: '10-35 °C' }, + description: 'Der Hasenohren-Kaktus hat flache, ovale Triebe mit dichten weissen Glochiden. Klassischer Zimmerkaktus.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/36/Opuntia_microdasys_3.jpg/500px-Opuntia_microdasys_3.jpg', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'San-Pedro-Kaktus', + botanicalName: 'Echinopsis pachanoi', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Volles Sonnenlicht', temp: '10-35 °C' }, + description: 'Der San-Pedro-Kaktus ist ein schnell wachsender, saeulenfoermiger Kaktus aus den Anden.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Starr_070320-5799_Echinopsis_pachanoi.jpg/500px-Starr_070320-5799_Echinopsis_pachanoi.jpg', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Koenigin der Nacht', + botanicalName: 'Epiphyllum oxypetalum', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Indirektes Licht', temp: '18-27 °C' }, + description: 'Die Koenigin der Nacht bluet nur eine einzige Nacht lang mit riesigen, intensiv duftenden weissen Blueten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Epiphyllum_oxypetalum_flower.JPG/500px-Epiphyllum_oxypetalum_flower.JPG', + categories: ['flowering', 'succulent'], + }, + { + name: 'Korallenkaktus', + botanicalName: 'Rhipsalis baccifera', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Indirektes Licht', temp: '18-27 °C' }, + description: 'Der Korallenkaktus ist ein epiphytischer Kaktus mit duennen, haengenden Trieben und kleinen weissen Beeren.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Rhipsalis_baccifera_01_ies.jpg/500px-Rhipsalis_baccifera_01_ies.jpg', + categories: ['succulent', 'hanging'], + }, + { + name: 'Wuestenrose', + botanicalName: 'Adenium obesum', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Volles Sonnenlicht', temp: '20-35 °C' }, + description: 'Die Wuestenrose ist eine sukkulente Zimmerpflanze mit dickem Stamm und leuchtend pinken Blueten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/4/4a/Adenium_Obesum_Flower_Side_Macro_Mar22_D72_23052-58_ZS_P.jpg/500px-Adenium_Obesum_Flower_Side_Macro_Mar22_D72_23052-58_ZS_P.jpg', + categories: ['succulent', 'flowering', 'sun'], + }, + { + name: 'Geisterpflanze', + botanicalName: 'Graptopetalum paraguayense', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Volles Sonnenlicht', temp: '15-25 °C' }, + description: 'Die Geisterpflanze hat zartgraue bis perlmutt-rosafarbene, rosettenfoermige Blaetter. Sehr robuste Sukkulente.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/59/%28MHNT%29_Graptopetalum_paraguayense_-_leaves.jpg/500px-%28MHNT%29_Graptopetalum_paraguayense_-_leaves.jpg', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Mondstein-Pflanze', + botanicalName: 'Pachyphytum oviferum', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Volles Sonnenlicht', temp: '15-25 °C' }, + description: 'Die Mondstein-Pflanze hat dicke, ovale Blaetter mit einem pastellrosafarbenen, mehligen Ueberzug.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8f/%28MHNT%29_Pachyphytum_oviferum_-_Habitus.jpg/500px-%28MHNT%29_Pachyphytum_oviferum_-_Habitus.jpg', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Kap-Aloe', + botanicalName: 'Aloe arborescens', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Volles Sonnenlicht', temp: '10-30 °C' }, + description: 'Die Kap-Aloe ist eine strauchige Aloe mit schmalen, gezaehnten Blaettern und leuchtend roten Bluetenaehren im Winter.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b9/Aloe_arborescens_Compton.JPG/500px-Aloe_arborescens_Compton.JPG', + categories: ['easy', 'succulent', 'medicinal', 'sun'], + }, + { + name: 'Gasteria', + botanicalName: 'Gasteria carinata', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Helles indirektes Licht', temp: '15-25 °C' }, + description: 'Die Gasteria ist eine kleine Sukkulente mit zweireihig angeordneten, zungenfoermigen, gefleckten Blaettern.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/91/2_Gasteria_carinata_var_carinata.jpg/500px-2_Gasteria_carinata_var_carinata.jpg', + categories: ['easy', 'succulent', 'low_light'], + }, + { + name: 'Japanische Azalee', + botanicalName: 'Rhododendron simsii', + confidence: 1.0, + careInfo: { waterIntervalDays: 4, light: 'Helles indirektes Licht', temp: '10-18 °C' }, + description: 'Die Japanische Azalee bluet im Winter und Fruehling ueppig mit leuchtend roten, rosa oder weissen Blueten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Rhododendron_simsii-bunga_2-Lany_pirna.jpg/500px-Rhododendron_simsii-bunga_2-Lany_pirna.jpg', + categories: ['flowering'], + }, + { + name: 'Indische Azalee', + botanicalName: 'Azalea indica', + confidence: 1.0, + careInfo: { waterIntervalDays: 4, light: 'Helles indirektes Licht', temp: '10-20 °C' }, + description: 'Die Indische Azalee ist ein beliebter Zierstrauch mit grossen, auffaelligen Blueten in Rosa- und Rottönen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/de/Rhododendron_indicum1.jpg/500px-Rhododendron_indicum1.jpg', + categories: ['flowering'], + }, + { + name: 'Kamelie', + botanicalName: 'Camellia japonica', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '7-18 °C' }, + description: 'Die Kamelie ist ein eleganter Zierstrauch mit glaenzenden Blaettern und rosenaehnlichen Blueten von Januar bis April.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e9/Camellia_japonica_NBG.jpg/500px-Camellia_japonica_NBG.jpg', + categories: ['flowering'], + }, + { + name: 'Afrikanisches Veilchen', + botanicalName: 'Saintpaulia ionantha', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-25 °C' }, + description: 'Das Afrikanische Veilchen ist eine kleine, kompakte Bluehpflanze mit samtigen Blaettern und violetten Blueten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/57/Streptocarpus_ionanthus_%28as_Saintpaulia_ionantha%29_-_Curtis%27_121_%28Ser._3_no._51%29_pl._7408_%281895%29.jpg/500px-Streptocarpus_ionanthus_%28as_Saintpaulia_ionantha%29_-_Curtis%27_121_%28Ser._3_no._51%29_pl._7408_%281895%29.jpg', + categories: ['easy', 'flowering'], + }, + { + name: 'Drehfrucht', + botanicalName: 'Streptocarpus hybridus', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '15-22 °C' }, + description: 'Die Drehfrucht ist ein Gesneriengewaechs mit langen, gerippten Blaettern und trichterfoermigen Blueten in Lila oder Rosa.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/2007-03-20Streptocarpus03.jpg/500px-2007-03-20Streptocarpus03.jpg', + categories: ['flowering'], + }, + { + name: 'Gloxinie', + botanicalName: 'Gloxinia speciosa', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '18-25 °C' }, + description: 'Die Gloxinie hat grosse, samtartige Blueten in Violett, Rosa oder Weiss mit farbigen Raendern.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/Florada_da_Glox%C3%ADnia.jpg/500px-Florada_da_Glox%C3%ADnia.jpg', + categories: ['flowering', 'high_humidity'], + }, + { + name: 'Columnea', + botanicalName: 'Columnea gloriosa', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-25 °C' }, + description: 'Die Columnea ist eine haengende Zimmerpflanze mit kleinen, behaarten Blaettern und leuchtend roten, roehrenfoermigen Blueten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Columnea_gloriosa_%2849470911201%29.jpg/500px-Columnea_gloriosa_%2849470911201%29.jpg', + categories: ['flowering', 'hanging', 'high_humidity'], + }, + { + name: 'Lippenstiftpflanze', + botanicalName: 'Aeschynanthus radicans', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Die Lippenstiftpflanze hat haengende Triebe mit glaenzenden Blaettern und leuchtend roten Roehrenbluten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/52/Aeschynanthus_radicans.jpg/500px-Aeschynanthus_radicans.jpg', + categories: ['flowering', 'hanging', 'high_humidity'], + }, + { + name: 'Herzkette', + botanicalName: 'Ceropegia woodii', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Helles indirektes Licht', temp: '15-27 °C' }, + description: 'Die Herzkette hat duenne, haengende Ranken mit herzfoermigen, silbergrau gemusterten Blaettchen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/5/55/Ceropegia_linearis_subsp_woodii.jpg', + categories: ['easy', 'succulent', 'hanging', 'patterned'], + }, + { + name: 'Perlenschnur-Pflanze', + botanicalName: 'Senecio rowleyanus', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Helles bis volles Licht', temp: '15-27 °C' }, + description: 'Die Perlenschnur-Pflanze hat haengende Ranken mit kugelfoermigen, perlenaehnlichen Blaettern. Einzigartige Sukkulente.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/Senecio_rowleyanus_leaves.jpg/500px-Senecio_rowleyanus_leaves.jpg', + categories: ['easy', 'succulent', 'hanging'], + }, + { + name: 'Dischidia', + botanicalName: 'Dischidia ruscifolia', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Die Dischidia ist eine epiphytische Haengepflanze mit kleinen, runden Blaettern entlang duenner Ranken.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/%E7%99%BE%E8%90%AC%E5%BF%83_Dischidia_ruscifolia_-%E9%A6%99%E6%B8%AF%E5%8B%95%E6%A4%8D%E7%89%A9%E5%85%AC%E5%9C%92_Hong_Kong_Botanical_Garden-_%289240152650%29.jpg/500px-%E7%99%BE%E8%90%AC%E5%BF%83_Dischidia_ruscifolia_-%E9%A6%99%E6%B8%AF%E5%8B%95%E6%A4%8D%E7%89%A9%E5%85%AC%E5%9C%92_Hong_Kong_Botanical_Garden-_%289240152650%29.jpg', + categories: ['succulent', 'hanging'], + }, + { + name: 'Rippenpeperomie', + botanicalName: 'Peperomia caperata', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Helles indirektes Licht', temp: '18-26 °C' }, + description: 'Die Rippenpeperomie hat tief gerippte, dunkelgruene bis violette Blaetter mit einer samtigen Textur.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Peperomia_caperata_1-OB9.jpg/500px-Peperomia_caperata_1-OB9.jpg', + categories: ['easy', 'pet_friendly'], + }, + { + name: 'Spiegelpeperomie', + botanicalName: 'Peperomia obtusifolia', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Helles indirektes Licht', temp: '16-26 °C' }, + description: 'Die Spiegelpeperomie hat glaenzende, lederartige, oval-runde Blaetter in tiefem Gruen. Sehr robust.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Peperomia_obtusifolia_3-OB9.jpg/500px-Peperomia_obtusifolia_3-OB9.jpg', + categories: ['easy', 'pet_friendly', 'low_light'], + }, + { + name: 'Riemenblatt', + botanicalName: 'Clivia miniata', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Helles indirektes Licht', temp: '15-24 °C' }, + description: 'Das Riemenblatt ist eine dekorative Zimmerpflanze mit leuchtend orangefarbenen Blueten im Fruehling.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c2/Clivia_miniata%2C_blomme_en_vrugte%2C_Manie_van_der_Schijff_BT%2C_a.jpg/500px-Clivia_miniata%2C_blomme_en_vrugte%2C_Manie_van_der_Schijff_BT%2C_a.jpg', + categories: ['flowering'], + }, + { + name: 'Ritterstern', + botanicalName: 'Hippeastrum hybrid', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '18-25 °C' }, + description: 'Der Ritterstern beeindruckt im Winter mit riesigen, trompetenfoermigen Blueten in Rot, Pink oder Weiss.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Hippeastrum_hybrid_1.jpg/500px-Hippeastrum_hybrid_1.jpg', + categories: ['flowering', 'bright_light'], + }, + { + name: 'Osterglocke', + botanicalName: 'Narcissus pseudonarcissus', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '10-18 °C' }, + description: 'Die Osterglocke ist der klassische Fruehjahrsblueher mit leuchtend gelben, trompetenfoermigen Blueten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a4/Narcissus_pseudonarcissus_flower_300303.jpg/500px-Narcissus_pseudonarcissus_flower_300303.jpg', + categories: ['flowering'], + }, + { + name: 'Tulpe', + botanicalName: 'Tulipa gesneriana', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '8-18 °C' }, + description: 'Die Tulpe ist eine der beliebtesten Fruehjahrsblueher mit kelchfoermigen Blueten in unzaehligen Farben.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/%D7%A6%D7%91%D7%A2%D7%95%D7%A0%D7%99%D7%9D.JPG/500px-%D7%A6%D7%91%D7%A2%D7%95%D7%A0%D7%99%D7%9D.JPG', + categories: ['easy', 'flowering'], + }, + { + name: 'Hyazinthe', + botanicalName: 'Hyacinthus orientalis', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '10-18 °C' }, + description: 'Die Hyazinthe bezaubert mit dichten Bluetenrispen und intensivem Duft in Blau, Rosa, Weiss oder Gelb.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Hyacinth_flower.jpg/500px-Hyacinth_flower.jpg', + categories: ['easy', 'flowering'], + }, + { + name: 'Traubenhyazinthe', + botanicalName: 'Muscari armeniacum', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '8-18 °C' }, + description: 'Die Traubenhyazinthe bildet dichte Trauben aus kleinen, blauen bis violetten Gloeckchen. Zuverlaessige Fruejahrszwiebel.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Muscari_armeniacum_4.jpg/500px-Muscari_armeniacum_4.jpg', + categories: ['easy', 'flowering'], + }, + { + name: 'Krokus', + botanicalName: 'Crocus vernus', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '5-15 °C' }, + description: 'Der Krokus ist einer der ersten Fruehjahrs­boten mit kelchfoermigen Blueten in Lila, Weiss und Gelb.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e2/Crocus_vernus_with_bee.jpg/500px-Crocus_vernus_with_bee.jpg', + categories: ['easy', 'flowering'], + } +]; diff --git a/constants/lexiconBatch2.ts b/constants/lexiconBatch2.ts new file mode 100644 index 0000000..c23a43f --- /dev/null +++ b/constants/lexiconBatch2.ts @@ -0,0 +1,1439 @@ +import type { LexiconBatchEntry } from './lexiconBatch1'; + +const BULK_HERB_CARE = { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '12-24 C' }; +const BULK_FLOWER_CARE = { waterIntervalDays: 4, light: 'Volles bis helles Licht', temp: '10-24 C' }; +const BULK_TREE_CARE = { waterIntervalDays: 7, light: 'Volles bis helles Licht', temp: '5-25 C' }; +const BULK_HOUSEPLANT_CARE = { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 C' }; +const BULK_HUMID_HOUSEPLANT_CARE = { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '18-28 C' }; +const BULK_SUCCULENT_HANGING_CARE = { waterIntervalDays: 10, light: 'Helles bis volles Licht', temp: '18-30 C' }; + +const createPendingEntry = ( + entry: Omit, +): LexiconBatchEntry => ({ + ...entry, + confidence: 1.0, + imageUri: `wikimedia-search:${entry.botanicalName}`, +}); + +const createHerbEntry = ( + name: string, + botanicalName: string, + overrides: Partial> = {}, +): LexiconBatchEntry => createPendingEntry({ + name, + botanicalName, + careInfo: overrides.careInfo || BULK_HERB_CARE, + description: overrides.description || `${name} ist ein bekanntes Kuechenkraut mit aromatischem Geschmack und vielseitiger Verwendung.`, + categories: overrides.categories || ['easy', 'sun'], +}); + +const createHerbPinnedEntry = ( + name: string, + botanicalName: string, + imageUri: string, + overrides: Partial> = {}, +): LexiconBatchEntry => ({ + ...createHerbEntry(name, botanicalName, overrides), + imageUri, +}); + +const createFlowerEntry = ( + name: string, + botanicalName: string, + overrides: Partial> = {}, +): LexiconBatchEntry => createPendingEntry({ + name, + botanicalName, + careInfo: overrides.careInfo || BULK_FLOWER_CARE, + description: overrides.description || `${name} ist eine beliebte Bluetenpflanze fuer Beet, Balkon oder Garten.`, + categories: overrides.categories || ['flowering', 'sun'], +}); + +const createTreeEntry = ( + name: string, + botanicalName: string, + overrides: Partial> = {}, +): LexiconBatchEntry => createPendingEntry({ + name, + botanicalName, + careInfo: overrides.careInfo || BULK_TREE_CARE, + description: overrides.description || `${name} ist ein bekanntes Zier- oder Gartengehoelz mit dekorativem Wuchs.`, + categories: overrides.categories || ['tree', 'sun', 'large'], +}); + +const createHouseplantEntry = ( + name: string, + botanicalName: string, + overrides: Partial> = {}, +): LexiconBatchEntry => createPendingEntry({ + name, + botanicalName, + careInfo: overrides.careInfo || BULK_HOUSEPLANT_CARE, + description: overrides.description || `${name} ist eine beliebte Zimmerpflanze mit dekorativem Laub oder markantem Wuchs.`, + categories: overrides.categories || ['bright_light'], +}); + +const createHouseplantSearchEntry = ( + name: string, + botanicalName: string, + searchQuery: string, + overrides: Partial> = {}, +): LexiconBatchEntry => ({ + ...createHouseplantEntry(name, botanicalName, overrides), + imageUri: `wikimedia-search:${searchQuery}`, +}); + +const createHouseplantPinnedEntry = ( + name: string, + botanicalName: string, + imageUri: string, + overrides: Partial> = {}, +): LexiconBatchEntry => ({ + ...createHouseplantEntry(name, botanicalName, overrides), + imageUri, +}); + +export const LEXICON_BATCH_2_ENTRIES: LexiconBatchEntry[] = [ + { + name: 'Weisse Strelitzie', + botanicalName: 'Strelitzia nicolai', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '18-27 °C' }, + description: 'Die Weisse Strelitzie ist ein beeindruckender Zimmerstrauch mit grossen, blaugruenen Blaettern und weiss-blauen Blueten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Strelitzia_nicolai_3.jpg/500px-Strelitzia_nicolai_3.jpg', + categories: ['large', 'tree', 'bright_light'], + }, + { + name: 'Bananenpflanze', + botanicalName: 'Musa acuminata', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '20-30 °C' }, + description: 'Die Bananenpflanze ist eine tropische Staude mit riesigen, glaenzenden Blaettern. Im Zimmer selten fruechttragend.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/7/7d/Musa_acuminata_in_india01.jpg/500px-Musa_acuminata_in_india01.jpg', + categories: ['large', 'high_humidity'], + }, + { + name: 'Kentia-Palme', + botanicalName: 'Howea forsteriana', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-25 °C' }, + description: 'Die Kentia-Palme ist eine der elegantesten Zimmerpalmen mit langen, herabhängenden Fiederblaettern.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/99/Howea_forsteriana_Lord_Howe_Island.jpg/500px-Howea_forsteriana_Lord_Howe_Island.jpg', + categories: ['tree', 'low_light', 'pet_friendly'], + }, + { + name: 'Chinesische Fächerpalme', + botanicalName: 'Livistona chinensis', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Die Chinesische Fächerpalme hat grosse, faecher­foermige Blaetter auf einem einzelnen Stamm. Sehr dekorativ.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/f6/Livistona-chinensis.jpg/500px-Livistona-chinensis.jpg', + categories: ['tree', 'bright_light'], + }, + { + name: 'Mexikanische Fächerpalme', + botanicalName: 'Washingtonia robusta', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Volles Sonnenlicht', temp: '15-35 °C' }, + description: 'Die Mexikanische Fächerpalme ist eine schlanke, hohe Palme mit faecher­foermigen Blaettern. Sehr hitzetolerant.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b8/Arecales_-_Washingtonia_robusta_-_1.jpg/500px-Arecales_-_Washingtonia_robusta_-_1.jpg', + categories: ['tree', 'sun', 'large'], + }, + { + name: 'Schraubenbaum', + botanicalName: 'Pandanus veitchii', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '18-27 °C' }, + description: 'Der Schraubenbaum hat spiralfoermig angeordnete, gruenweiss gestreifte Blaetter. Sehr dekorativ und exotisch.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/Pandanus_tectorius.jpg/500px-Pandanus_tectorius.jpg', + categories: ['patterned', 'bright_light'], + }, + { + name: 'Bambusrohr', + botanicalName: 'Bambusa vulgaris', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '15-30 °C' }, + description: 'Das Bambusrohr ist eine schnell wachsende Bambusart mit gelbgruenen Halmen. Sehr dekorativ und vielseitig nutzbar.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/10/Golden_Bamboo%28Bambusa_vulgaris%29_in_Hong_Kong.jpg/500px-Golden_Bamboo%28Bambusa_vulgaris%29_in_Hong_Kong.jpg', + categories: ['easy', 'large'], + }, + { + name: 'Goldener Bambus', + botanicalName: 'Phyllostachys aurea', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '10-30 °C' }, + description: 'Der Goldene Bambus hat elegante, goldgelbe Halme mit engstehenden Knoten. Sehr dekorativ als Sichtschutz.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Phyllostachys_aurea0.jpg/500px-Phyllostachys_aurea0.jpg', + categories: ['easy', 'large'], + }, + { + name: 'Paragraphenpflanze', + botanicalName: 'Cyperus alternifolius', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles bis volles Licht', temp: '18-27 °C' }, + description: 'Die Paragraphenpflanze hat lange, grasartige Blaetter, die sternfoermig vom Stiel abstehen. Sie liebt viel Wasser.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/7/76/Cyperus_alternifolius_2.jpg', + categories: ['high_humidity'], + }, + { + name: 'Strahlenaralie', + botanicalName: 'Schefflera arboricola', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '15-25 °C' }, + description: 'Die Strahlenaralie hat fingerfoermig angeordnete, glaenzende Blaetter auf langen Stielen. Sehr robuste Zimmerpflanze.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Schefflera_arboricola%2C_vrugte%2C_a%2C_Pretoria.jpg/500px-Schefflera_arboricola%2C_vrugte%2C_a%2C_Pretoria.jpg', + categories: ['easy', 'air_purifier', 'tree'], + }, + { + name: 'Grosse Strahlenaralie', + botanicalName: 'Schefflera actinophylla', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Die Grosse Strahlenaralie kann grosse, handfoermige Blaetter entwickeln. Sie ist ideal als Zimmerstrauch.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/b/bc/Octopus_Tree_%28Schefflera_actinophylla%29_at_Hyderabad%2C_AP_W_283.jpg', + categories: ['easy', 'tree', 'large'], + }, + { + name: 'Fatsia', + botanicalName: 'Fatsia japonica', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '10-20 °C' }, + description: 'Die Fatsia ist ein dekorativer Zimmerstrauch mit grossen, handfoermigen, glaenzenden Blaettern. Sehr robust.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/Old_Fatsia_japonica_with_blosems.jpg/500px-Old_Fatsia_japonica_with_blosems.jpg', + categories: ['easy', 'low_light'], + }, + { + name: 'Japanische Aucube', + botanicalName: 'Aucuba japonica', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Wenig bis helles Licht', temp: '10-20 °C' }, + description: 'Die Japanische Aucube hat glaenzende, gruene oder gelbgefleckte Blaetter. Sehr schattenvertraeglich.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c6/Aucuba_japonica_Gold_Dust_NBG_LR.jpg/500px-Aucuba_japonica_Gold_Dust_NBG_LR.jpg', + categories: ['easy', 'low_light'], + }, + { + name: 'Keulenlilie', + botanicalName: 'Cordyline australis', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '10-25 °C' }, + description: 'Die Keulenlilie hat lange, schmale, gruene oder rotbraune Blaetter in einem dekorativen Schopf.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/CabbageTreeKaihoka.jpg/500px-CabbageTreeKaihoka.jpg', + categories: ['easy', 'tree', 'sun'], + }, + { + name: 'Tiroler Keulenlilie', + botanicalName: 'Cordyline fruticosa', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Die Tiroler Keulenlilie hat leuchtend rote, gruene oder buntlaubige Blaetter. Eine exotische Zimmerpflanze.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Cordyline_fruticosa_%2820262433874%29.jpg/500px-Cordyline_fruticosa_%2820262433874%29.jpg', + categories: ['easy'], + }, + { + name: 'Schusterpflanze', + botanicalName: 'Aspidistra elatior', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Wenig bis helles Licht', temp: '10-20 °C' }, + description: 'Die Schusterpflanze ist eine extrem robuste Zimmerpflanze mit langen, dunkelgruenen Blaettern. Vertraegt tiefe Temperaturen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Aspidistra_elatior1.jpg/500px-Aspidistra_elatior1.jpg', + categories: ['easy', 'low_light'], + }, + { + name: 'Zylindrischer Bogenhanf', + botanicalName: 'Sansevieria cylindrica', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Helles bis volles Licht', temp: '15-27 °C' }, + description: 'Der Zylindrische Bogenhanf hat zylindrische, aufrechte Blaetter, die sich nach oben verjuengen. Sehr pflegeleicht.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c8/Sansevieria_cylindrica_flowers_7.jpg/500px-Sansevieria_cylindrica_flowers_7.jpg', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Kap-Aloe (ferox)', + botanicalName: 'Aloe ferox', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Volles Sonnenlicht', temp: '10-30 °C' }, + description: 'Aloe ferox ist eine grosse, imposante Aloe mit stachligen, blaugruenen Blaettern und leuchtend roten Bluetenaehren.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/9/9e/Aloe_Ferox_between_Cofimvaba_and_Ngcobo.jpg', + categories: ['succulent', 'medicinal', 'sun', 'large'], + }, + { + name: 'Christusdorn', + botanicalName: 'Euphorbia milii', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Helles bis volles Licht', temp: '15-28 °C' }, + description: 'Der Christusdorn ist eine sukkulente Wolfsmilch mit stacheligen Zweigen und kleinen roten oder gelben Hochblaettern.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/7/77/Euphorbia_Milii_flowers.jpg/500px-Euphorbia_Milii_flowers.jpg', + categories: ['easy', 'succulent', 'flowering', 'sun'], + }, + { + name: 'Weihnachtsstern', + botanicalName: 'Euphorbia pulcherrima', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '15-22 °C' }, + description: 'Der Weihnachtsstern ist die klassische Winterpflanze mit leuchtend roten Hochblaettern. Er steht symbolisch fuer Weihnachten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Weihnachtsstern_-_gro%C3%9F.jpg/500px-Weihnachtsstern_-_gro%C3%9F.jpg', + categories: ['flowering'], + }, + { + name: 'Kaninchen-Ohren', + botanicalName: 'Kalanchoe tomentosa', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Kaninchen-Ohren haben weisslich-filzige Blaetter mit braunen Raendern, die Kaninchen­ohren aehneln. Sehr dekorativ.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/04/Kalanchoe_tomentosa_01.jpg/500px-Kalanchoe_tomentosa_01.jpg', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Brutblatt', + botanicalName: 'Kalanchoe daigremontiana', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Das Brutblatt bildet entlang des Blattrandes zahlreiche kleine Jungpflanzen. Eine faszinierende Sukkulente.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Vivipary_in_Kalanchoe_daigremontiana.jpg/500px-Vivipary_in_Kalanchoe_daigremontiana.jpg', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Lebende Steine', + botanicalName: 'Lithops julii', + confidence: 1.0, + careInfo: { waterIntervalDays: 21, light: 'Volles Sonnenlicht', temp: '10-30 °C' }, + description: 'Lebende Steine sind faszinierende Mimikry-Sukkulenten, die Kieselsteinen taeuschen aehnlich sehen. Sehr trockenheitsresistent.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Lithops_julii_fulleri.jpg/500px-Lithops_julii_fulleri.jpg', + categories: ['succulent', 'sun'], + }, + { + name: 'Konophytum', + botanicalName: 'Conophytum calculus', + confidence: 1.0, + careInfo: { waterIntervalDays: 21, light: 'Volles Sonnenlicht', temp: '10-25 °C' }, + description: 'Das Konophytum ist eine sehr kompakte Sukkulente, die zwei Blaetter zu einer kugelfoermigen Form verschmilzt.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/1_Conophytum_calculus_-_RSA_3.jpg/500px-1_Conophytum_calculus_-_RSA_3.jpg', + categories: ['succulent', 'sun'], + }, + { + name: 'Aasblume', + botanicalName: 'Stapelia grandiflora', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Helles bis volles Licht', temp: '18-30 °C' }, + description: 'Die Aasblume hat fleischige, gruene Staengel und riesige, sternfoermige Blueten mit aasartigem Duft.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/98/Stapelia_grandiflora_22102013_1_%2810606394434%29.jpg/500px-Stapelia_grandiflora_22102013_1_%2810606394434%29.jpg', + categories: ['succulent', 'flowering', 'sun'], + }, + { + name: 'Moos-Crassula', + botanicalName: 'Crassula muscosa', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Die Moos-Crassula hat dicht aneinandergereihte, winzige gruene Blaetter auf unverzweigten Trieben. Sieht aus wie Moos.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/5e/Crassula_muscosa_Grubosz_2006-05-03_01.jpg/500px-Crassula_muscosa_Grubosz_2006-05-03_01.jpg', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Speckbaum', + botanicalName: 'Portulacaria afra', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Helles bis volles Licht', temp: '15-30 °C' }, + description: 'Der Speckbaum ist eine sukkulente Pflanze mit roten Stielen und kleinen, runden, glaenzenden Blaettern.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Portulacaria_afra_02.JPG/500px-Portulacaria_afra_02.JPG', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Blauer Kreuzkraut', + botanicalName: 'Senecio serpens', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Der Blaue Kreuzkraut hat zylindrische, blaublaugruene Blaetter und einen kriechenden Wuchs. Sehr dekorativ.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/57/Senecio_serpens_04.jpg/500px-Senecio_serpens_04.jpg', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Kotyledon', + botanicalName: 'Cotyledon orbiculata', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Kotyledon hat dickfleischige, runde Blaetter mit einem mehligen, weisslichen Belag. Sehr trockenheitsresistent.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Cotyledon_orbiculata_-_pigs_ear_-_Cape_Point_-_South_Africa_2.JPG/500px-Cotyledon_orbiculata_-_pigs_ear_-_Cape_Point_-_South_Africa_2.JPG', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Dudleya', + botanicalName: 'Dudleya brittonii', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Volles Sonnenlicht', temp: '10-25 °C' }, + description: 'Dudleya ist eine rosetten­bildende Sukkulente mit silbrig-weissen, mehligen Blaettern. Sehr elegant.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/10/Dudleya_Brittonii.jpg/500px-Dudleya_Brittonii.jpg', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Adromischus', + botanicalName: 'Adromischus cristatus', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Adromischus ist eine kompakte Sukkulente mit ungewoehnlich wellenrandigen Blaettern auf kurzen Staengeln.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Adromischus_cristatus_-_Gaiser_Conservatory_%28Manito_Park%29_-_IMG_7008.JPG/500px-Adromischus_cristatus_-_Gaiser_Conservatory_%28Manito_Park%29_-_IMG_7008.JPG', + categories: ['easy', 'succulent', 'sun'], + }, + { + name: 'Spanisches Moos', + botanicalName: 'Tillandsia usneoides', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles bis volles Licht', temp: '15-30 °C' }, + description: 'Das Spanische Moos ist eine epiphytische Bromelie ohne Wurzeln, die in der Luft haengt. Es benoetigt nur Feuchtigkeitsbespruehing.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/Spanish_moss_at_the_Mcbryde_Garden_in_hawaii.jpg/500px-Spanish_moss_at_the_Mcbryde_Garden_in_hawaii.jpg', + categories: ['easy', 'hanging'], + }, + { + name: 'Luftpflanze', + botanicalName: 'Tillandsia ionantha', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles bis volles Licht', temp: '15-30 °C' }, + description: 'Die Luftpflanze ist eine kompakte Bromelie ohne Topferde. Sie nimmt Wasser und Naehrstoffe ueber die Blattschuppen auf.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b5/Purple_sky_plant_-_Andrey_Zharkikh.jpg/500px-Purple_sky_plant_-_Andrey_Zharkikh.jpg', + categories: ['easy'], + }, + { + name: 'Silbervase', + botanicalName: 'Aechmea fasciata', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Helles indirektes Licht', temp: '18-25 °C' }, + description: 'Die Silbervase ist eine Bromelie mit silbrig gebänderten Blaettern und einem rosafarbenen Bluetenstand.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/23/Aechmea_fasciata2.jpg/500px-Aechmea_fasciata2.jpg', + categories: ['flowering', 'patterned'], + }, + { + name: 'Flammen-Bromelie', + botanicalName: 'Vriesea splendens', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-25 °C' }, + description: 'Die Flammen-Bromelie hat gebänderte, dunkelgruene Blaetter und einen spektakulaeren, roten Bluetenstand.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Bromelia1.jpg/500px-Bromelia1.jpg', + categories: ['flowering', 'patterned', 'high_humidity'], + }, + { + name: 'Guzmania', + botanicalName: 'Guzmania lingulata', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Die Guzmania ist eine Bromelie mit glänzenden, gruenen Blaettern und einem leuchtend roten, sternfoermigen Bluetenstand.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Bromeliaceae03.jpg/500px-Bromeliaceae03.jpg', + categories: ['flowering', 'high_humidity'], + }, + { + name: 'Neoregelia', + botanicalName: 'Neoregelia carolinae', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '18-27 °C' }, + description: 'Die Neoregelia ist eine Bromelie, bei der das Herzblatt zur Bluetzeit leuchtend rot wird. Sehr dekorativ.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/27/Neoregelia_carolinae_BotGardBln310505a.jpg/500px-Neoregelia_carolinae_BotGardBln310505a.jpg', + categories: ['flowering', 'patterned', 'bright_light'], + }, + { + name: 'Billbergia', + botanicalName: 'Billbergia nutans', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '15-25 °C' }, + description: 'Die Billbergia ist eine robuste Bromelie mit schmalen, gruenen Blaettern und hängenden, blauen und gruenen Blueten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/9/9e/Billbergia_nutans1SHSU.jpg', + categories: ['easy', 'flowering'], + }, + { + name: 'Cryptanthus', + botanicalName: 'Cryptanthus bivittatus', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Cryptanthus ist eine niedrig wachsende Bromelie mit sternfoermigen Rosetten und gemusterten Blaettern. Fuer Terrarien.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/CryptanthusBivittatus.jpg/500px-CryptanthusBivittatus.jpg', + categories: ['patterned', 'high_humidity'], + }, + { + name: 'Blaues Kanaelfarn', + botanicalName: 'Phlebodium aureum', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Der Blaue Kanaelfarn hat wachsartige, blaugruene Wedel und glaenzende Wurzelstaemme. Sehr dekorativ.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Starr_050107-2831_Phlebodium_aureum.jpg/500px-Starr_050107-2831_Phlebodium_aureum.jpg', + categories: ['high_humidity'], + }, + { + name: 'Geweihfarn', + botanicalName: 'Platycerium bifurcatum', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '15-25 °C' }, + description: 'Der Geweihfarn hat gespaltene Wedel, die einem Hirschgeweih aehneln. Er ist ein epiphytischer Farn fuer Holz.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Platycerium_bifurcatum_kz01.jpg/500px-Platycerium_bifurcatum_kz01.jpg', + categories: ['hanging', 'high_humidity'], + }, + { + name: 'Frauenhaarfarn', + botanicalName: 'Adiantum raddianum', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Der Frauenhaarfarn hat zarte, feingliedrige Wedel auf schwarzen, draht­aehnlichen Stielen. Liebt Feuchtigkeit.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/4/45/Starr_030807-0143_Adiantum_raddianum.jpg/500px-Starr_030807-0143_Adiantum_raddianum.jpg', + categories: ['high_humidity'], + }, + { + name: 'Vogelnest-Farn', + botanicalName: 'Asplenium nidus', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Der Vogelnest-Farn hat ganzrandige, glaenzende Wedel, die eine Nestform bilden. Sehr dekorativ und robust.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Asplenium_nidus_%28Bukidnon%2C_Philippines%29_02.jpg/500px-Asplenium_nidus_%28Bukidnon%2C_Philippines%29_02.jpg', + categories: ['easy', 'high_humidity', 'low_light'], + }, + { + name: 'Tueipelfarn', + botanicalName: 'Polypodium vulgare', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '10-20 °C' }, + description: 'Der Tueipelfarn ist ein heimischer Farn mit gelappten Wedeln und runden Sporenhaeufchen auf der Unterseite.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/T%C3%BCpfelfarn_%28Polypodium_vulgare%29.jpg/500px-T%C3%BCpfelfarn_%28Polypodium_vulgare%29.jpg', + categories: ['easy'], + }, + { + name: 'Regenbogenmoos', + botanicalName: 'Selaginella uncinata', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Das Regenbogenmoos hat schuppenfoermige Blaetter, die im Licht schillernd irisieren. Dekorativ fuer Terrarien.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Selaginella_uncinata_-_Berlin_Botanical_Garden_-_IMG_8722.JPG/500px-Selaginella_uncinata_-_Berlin_Botanical_Garden_-_IMG_8722.JPG', + categories: ['high_humidity', 'patterned'], + }, + { + name: 'Tueipelfarn (Microsorum)', + botanicalName: 'Microsorum punctatum', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Microsorum punctatum ist ein tropischer Farn mit langen, ungeteilten, glaenzenden Wedeln. Fuer feuchte Standorte.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/9f/Microsorum_punctatum.jpg/500px-Microsorum_punctatum.jpg', + categories: ['high_humidity'], + }, + { + name: 'Monstera adansonii', + botanicalName: 'Monstera adansonii', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Monstera adansonii hat herzfoermige Blaetter mit zahlreichen runden Lochern. Eine rankende Zimmerpflanze.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/Monstera_adansonii_79319231.jpg/500px-Monstera_adansonii_79319231.jpg', + categories: ['easy', 'hanging'], + }, + { + name: 'Monstera obliqua', + botanicalName: 'Monstera obliqua', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Monstera obliqua ist eine seltene Monstera-Art mit filigranen Blaettern, die hauptsaechlich aus Lochern bestehen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/Obiqula.jpg/500px-Obiqula.jpg', + categories: ['hanging', 'patterned'], + }, + { + name: 'Philodendron gloriosum', + botanicalName: 'Philodendron gloriosum', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Philodendron gloriosum hat grosse, samtige, herzfoermige Blaetter mit weissen Rippen. Eine atemberaubende Pflanze.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Philodendron_gloriosum_%2829587099650%29.jpg/500px-Philodendron_gloriosum_%2829587099650%29.jpg', + categories: ['patterned', 'high_humidity', 'large'], + }, + { + name: 'Philodendron bipinnatifidum', + botanicalName: 'Philodendron bipinnatifidum', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Philodendron bipinnatifidum hat grosse, tief gelappte Blaetter. Er entwickelt einen beeindruckenden, baumfoermigen Wuchs.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Tree1.JPG/500px-Tree1.JPG', + categories: ['easy', 'large'], + }, + { + name: 'Roter Philodendron', + botanicalName: 'Philodendron erubescens', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Der Rote Philodendron hat glaenzende, herzfoermige Blaetter, die jung roetrlich erscheinen. Sehr dekorativ.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Philodendron_erubescens_-_Leaves.jpg/500px-Philodendron_erubescens_-_Leaves.jpg', + categories: ['easy', 'hanging'], + }, + { + name: 'Mini-Monstera', + botanicalName: 'Rhaphidophora tetrasperma', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Die Mini-Monstera hat monstera­aehnliche, gelochte Blaetter auf einer kompakten, klettternden Pflanze. Sehr trendig.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/db/Rhaphidophora_tetrasperma.jpg/500px-Rhaphidophora_tetrasperma.jpg', + categories: ['easy', 'hanging'], + }, + { + name: 'Neon-Efeutute', + botanicalName: 'Epipremnum pinnatum Neon', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '15-30 °C' }, + description: 'Die Neon-Efeutute hat leuchtend limonengruene Blaetter. Sehr auffaellig und pflegeleicht.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/de/Epipremnum_pinnatum_%27Neon%27%2C_Longwood_Gardens_01.jpg/500px-Epipremnum_pinnatum_%27Neon%27%2C_Longwood_Gardens_01.jpg', + categories: ['easy', 'hanging', 'air_purifier'], + }, + { + name: 'Lila Tradescantia', + botanicalName: 'Tradescantia pallida', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Die Lila Tradescantia hat leuchtend purpurrote Blaetter und ist sehr auffaellig. Sie liebt viel Licht.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Tradescantia_pallida_kz03.jpg/500px-Tradescantia_pallida_kz03.jpg', + categories: ['easy', 'hanging', 'sun'], + }, + { + name: 'Weisse Tradescantia', + botanicalName: 'Tradescantia fluminensis', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '15-25 °C' }, + description: 'Die Weisse Tradescantia hat gruene Blaetter mit weisslichen Unterseiten. Sehr robust und schnellwachsend.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/Tradescantia_fluminensis_%28Flowers%29.jpg/500px-Tradescantia_fluminensis_%28Flowers%29.jpg', + categories: ['easy', 'hanging'], + }, + { + name: 'Callisia', + botanicalName: 'Callisia repens', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '15-25 °C' }, + description: 'Callisia repens ist ein kleines, kriechendes Kraut mit winzigen, gruenen Blaettern. Ideal fuer haengende Behaelter.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/7/7c/Callisia_repens_starr.jpg/500px-Callisia_repens_starr.jpg', + categories: ['easy', 'hanging'], + }, + { + name: 'Forellen-Begonie', + botanicalName: 'Begonia maculata', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Die Forellen-Begonie hat olivgruene Blaetter mit silbernen Punkten und einer roten Unterseite. Atemberaubend.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/df/Begonia_maculata3073316230.jpg/500px-Begonia_maculata3073316230.jpg', + categories: ['patterned', 'high_humidity'], + }, + { + name: 'Knollen-Begonie', + botanicalName: 'Begonia tuberhybrida', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '15-22 °C' }, + description: 'Die Knollen-Begonie hat riesige, rosenaehnliche Blueten in leuchtendem Rot, Orange, Gelb oder Weiss.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/Begonia-tuberhybride_Red.jpg/500px-Begonia-tuberhybride_Red.jpg', + categories: ['flowering', 'high_humidity'], + }, + { + name: 'Neuguinea-Balsamine', + botanicalName: 'Impatiens hawkeri', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles indirektes Licht', temp: '18-27 °C' }, + description: 'Die Neuguinea-Balsamine hat grosse, leuchtende Blueten und ist sehr bluehfreudig. Ideal fuer Terrassen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Impatiens_hawkeri%2C_beijo-pintado_%28flores_vermelhas%29_07.jpg/500px-Impatiens_hawkeri%2C_beijo-pintado_%28flores_vermelhas%29_07.jpg', + categories: ['easy', 'flowering'], + }, + { + name: 'Triphylla-Fuchsie', + botanicalName: 'Fuchsia triphylla', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles indirektes Licht', temp: '15-22 °C' }, + description: 'Die Triphylla-Fuchsie hat lange, roehrenfoermige, orangefarbe Blueten in haengenden Trauben. Sehr exotisch.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Fuchsia_triphylla_kz01.jpg/500px-Fuchsia_triphylla_kz01.jpg', + categories: ['flowering', 'hanging'], + }, + { + name: 'Efeu-Geranie', + botanicalName: 'Pelargonium peltatum', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Die Efeu-Geranie hat efeufoermige, glaenzende Blaetter und bluet den ganzen Sommer in leuchtenden Farben.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/98/Pelargonium_peltatum_flower.jpg/500px-Pelargonium_peltatum_flower.jpg', + categories: ['easy', 'flowering', 'hanging', 'sun'], + }, + { + name: 'Duftsteinrich', + botanicalName: 'Lobularia maritima', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles bis volles Licht', temp: '10-22 °C' }, + description: 'Der Duftsteinrich ist ein niedrig wachsendes Pflanzchen mit winzigen, weissen oder lilafarbenen Blueten und suessem Duft.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Smagliczka_nadmorska_1.jpg/500px-Smagliczka_nadmorska_1.jpg', + categories: ['easy', 'flowering'], + }, + { + name: 'Calibrachoa', + botanicalName: 'Calibrachoa hybrida', + confidence: 1.0, + careInfo: { waterIntervalDays: 2, light: 'Volles Sonnenlicht', temp: '15-25 °C' }, + description: 'Calibrachoa ist eine petunienaehnliche Haengepflanze mit unzaehligen, kleinen Trichterbluten in allen Farben.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/Calibrachoa_flower_red.jpg/500px-Calibrachoa_flower_red.jpg', + categories: ['easy', 'flowering', 'hanging', 'sun'], + }, + { + name: 'Wandelroeschen', + botanicalName: 'Lantana camara', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Volles Sonnenlicht', temp: '18-28 °C' }, + description: 'Das Wandelroeschen hat kugelige Bluetenkoepfe, die die Farbe von Gelb ueber Orange zu Rot wechseln. Sehr attraktiv.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/52/LantanaFlowerLeaves.jpg/500px-LantanaFlowerLeaves.jpg', + categories: ['flowering', 'sun', 'bright_light'], + }, + { + name: 'Zinnie', + botanicalName: 'Zinnia elegans', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Volles Sonnenlicht', temp: '18-30 °C' }, + description: 'Die Zinnie ist eine leuchtende Sommerblume mit grossen, dahlienaehnlichen Blueten. Sehr robust und hitzetolerant.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Zinnienbl%C3%BCte_Zinnia_elegans_stack15_20190722-RM-7222254.jpg/500px-Zinnienbl%C3%BCte_Zinnia_elegans_stack15_20190722-RM-7222254.jpg', + categories: ['easy', 'flowering', 'sun'], + }, + { + name: 'Studentenblume', + botanicalName: 'Tagetes patula', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Volles Sonnenlicht', temp: '15-28 °C' }, + description: 'Die Studentenblume ist eine robuste Sommerblume mit orangen oder gelben Blueten. Sie haelt Schadlinge fern.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/French_marigold_Tagetes_patula.jpg/500px-French_marigold_Tagetes_patula.jpg', + categories: ['easy', 'flowering', 'sun'], + }, + { + name: 'Blumenschilfrohr', + botanicalName: 'Canna indica', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Volles Sonnenlicht', temp: '18-28 °C' }, + description: 'Das Blumenschilfrohr hat grosse, tropisch wirkende Blaetter und auffaellige Blueten in Rot, Orange oder Gelb.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Cinnamon-bellied_flowerpiercer_%28Diglossa_baritula%29_male_on_Indian_shot_%28Canna_indica%29_Finca_El_Pilar.jpg/500px-Cinnamon-bellied_flowerpiercer_%28Diglossa_baritula%29_male_on_Indian_shot_%28Canna_indica%29_Finca_El_Pilar.jpg', + categories: ['flowering', 'sun', 'large'], + }, + { + name: 'Dahlie', + botanicalName: 'Dahlia pinnata', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Volles Sonnenlicht', temp: '15-25 °C' }, + description: 'Die Dahlie ist eine prachtvolle Sommerblume mit Blueten in allen Groessen und Formen. Sie wird aus Knollen gezogen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/60/Borboletas_em_Mini-D%C3%A1lias.JPG/500px-Borboletas_em_Mini-D%C3%A1lias.JPG', + categories: ['flowering', 'sun'], + }, + { + name: 'Ostertrompete', + botanicalName: 'Lilium longiflorum', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Die Ostertrompete hat grosse, weisse, trichterfoermige Blueten mit intensivem Duft. Klassische Osterblume.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Lilium_longiflorum_%28Easter_Lily%29.JPG/500px-Lilium_longiflorum_%28Easter_Lily%29.JPG', + categories: ['flowering', 'bright_light'], + }, + { + name: 'Calla', + botanicalName: 'Zantedeschia aethiopica', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '15-24 °C' }, + description: 'Die Calla hat elegante, trichterfoermige weisse Hochblaetter und glaenzende, herzfoermige Blaetter. Sehr edel.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Zantedeschia_aethiopica_-1.jpg/500px-Zantedeschia_aethiopica_-1.jpg', + categories: ['flowering', 'high_humidity'], + }, + { + name: 'Koenigs-Protea', + botanicalName: 'Protea cynaroides', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '10-25 °C' }, + description: 'Die Koenigs-Protea ist die Nationalblume Suedafrikas mit riesigen, imposanten Bluetenkoepfen. Eine echte Besonderheit.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/3d/Protea_cynaroides_3.jpg/500px-Protea_cynaroides_3.jpg', + categories: ['flowering', 'sun', 'large'], + }, + { + name: 'Heliconia', + botanicalName: 'Heliconia psittacorum', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '20-30 °C' }, + description: 'Die Heliconia hat leuchtend orangefarbe oder rote, bootsfoermige Hochblaetter. Eine exotische Tropenpflanze.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Parrot_heliconia_%28Heliconia_psittacorum%29.jpg/500px-Parrot_heliconia_%28Heliconia_psittacorum%29.jpg', + categories: ['flowering', 'high_humidity', 'bright_light'], + }, + { + name: 'Muschelingwer', + botanicalName: 'Alpinia zerumbet', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '20-30 °C' }, + description: 'Der Muschelingwer hat lange, elegante Blaetter und haengende Bluetenrispen mit weiss-rosa Bluetchen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/200410_Alpinia_zerumbet_1.JPG/500px-200410_Alpinia_zerumbet_1.JPG', + categories: ['flowering', 'high_humidity', 'large'], + }, + { + name: 'Kurkuma', + botanicalName: 'Curcuma longa', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '20-30 °C' }, + description: 'Kurkuma ist eine tropische Gewuerzpflanze mit breiten Blaettern und leuchtend gelber Wurzel. Wichtiges Heilgewuerz.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/Turmeric_inflorescence.jpg/500px-Turmeric_inflorescence.jpg', + categories: ['medicinal', 'high_humidity'], + }, + { + name: 'Ingwer', + botanicalName: 'Zingiber officinale', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '20-30 °C' }, + description: 'Ingwer ist eine tropische Gewuerzpflanze mit aromatischen Knollen. Die Blaetter sind schilfartig.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Koeh-146-no_text.jpg/500px-Koeh-146-no_text.jpg', + categories: ['medicinal', 'high_humidity'], + }, + { + name: 'Schamkraut', + botanicalName: 'Mimosa pudica', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '20-28 °C' }, + description: 'Das Schamkraut faltet seine Blaettchen blitzschnell zusammen, wenn man sie beruehrt. Ein faszinierendes Erlebnis.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Mimosa_pudica_in_September_month.jpg/500px-Mimosa_pudica_in_September_month.jpg', + categories: ['flowering', 'bright_light'], + }, + { + name: 'Venusfliegenfalle', + botanicalName: 'Dionaea muscipula', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Volles Sonnenlicht', temp: '15-30 °C' }, + description: 'Die Venusfliegenfalle ist eine fleischfressende Pflanze mit klappfallartigen Blaettern. Faengt Insekten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Venus_Flytrap_showing_trigger_hairs.jpg/500px-Venus_Flytrap_showing_trigger_hairs.jpg', + categories: ['sun'], + }, + { + name: 'Purpursonnentau', + botanicalName: 'Sarracenia purpurea', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Volles Sonnenlicht', temp: '5-25 °C' }, + description: 'Der Purpursonnentau ist eine fleischfressende Kannenpflanze mit purpurroten Kannen. Faengt Insekten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/7/7c/Sarracenia_purpurea_Flowers.JPG/500px-Sarracenia_purpurea_Flowers.JPG', + categories: ['sun', 'high_humidity'], + }, + { + name: 'Kannenpflanze', + botanicalName: 'Nepenthes alata', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '20-30 °C' }, + description: 'Die Kannenpflanze bildet grosse, gefuellte Kannen als Insekten­fallen. Eine faszinierende, tropische Pflanze.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/7/77/Nepenthes_alata_ASR_062007_mt_ambucao_luzon.jpg', + categories: ['high_humidity', 'hanging'], + }, + { + name: 'Sonnentau', + botanicalName: 'Drosera capensis', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Volles Sonnenlicht', temp: '15-25 °C' }, + description: 'Der Sonnentau faengt Insekten mit klebrigen Tropfen auf seinen Blaettern. Eine faszinierende fleischfressende Pflanze.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Drosera_capensis_bend.JPG/500px-Drosera_capensis_bend.JPG', + categories: ['sun', 'high_humidity'], + }, + { + name: 'Fettkraut', + botanicalName: 'Pinguicula grandiflora', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '10-20 °C' }, + description: 'Das Fettkraut faengt Insekten mit klebrigen Blaettern. Es bluet mit violetten, sporenartigen Blueten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Pinguicula_grandiflora_001.jpg/500px-Pinguicula_grandiflora_001.jpg', + categories: ['flowering', 'high_humidity'], + }, + { + name: 'Wasserschlauch', + botanicalName: 'Utricularia gibba', + confidence: 1.0, + careInfo: { waterIntervalDays: 2, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Der Wasserschlauch ist eine wasserbewohnende fleischfressende Pflanze mit Schlaeuchen als Insekten­fallen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/bd/Utricularia_gibba_flower_01.jpg/500px-Utricularia_gibba_flower_01.jpg', + categories: ['high_humidity', 'sun'], + }, + { + name: 'Heliamphora', + botanicalName: 'Heliamphora nutans', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles indirektes Licht', temp: '15-25 °C' }, + description: 'Heliamphora ist eine urtuemliche Kannenpflanze aus den Tafelbergen Venezuelas. Sehr dekorativ und selten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/f9/Roraima_Heliamphora_nutans1.JPG/500px-Roraima_Heliamphora_nutans1.JPG', + categories: ['high_humidity'], + }, + { + name: 'Kaffeestrauch', + botanicalName: 'Coffea arabica', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '18-25 °C' }, + description: 'Der Kaffeestrauch hat glaenzende, dunkelgruene Blaetter und entwickelt rote Kaffe­ekirschen. Kann im Topf gehalten werden.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Coffee_Flowers.JPG/500px-Coffee_Flowers.JPG', + categories: ['easy'], + }, + { + name: 'Teestrauch', + botanicalName: 'Camellia sinensis', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '15-22 °C' }, + description: 'Der Teestrauch ist die Pflanze, aus deren Blaettern Tee gewonnen wird. Er hat weisse Blueten und glaenzende Blaetter.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/Csinensis.jpg/500px-Csinensis.jpg', + categories: ['flowering'], + }, + { + name: 'Zitronenbaum', + botanicalName: 'Citrus limon', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Volles Sonnenlicht', temp: '18-28 °C' }, + description: 'Der Zitronenbaum ist ein kleiner, immergruener Baum mit weissen, duftenden Blueten und gelben Fruechten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/P1030323.JPG/500px-P1030323.JPG', + categories: ['sun', 'tree'], + }, + { + name: 'Orangenbaum', + botanicalName: 'Citrus sinensis', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Volles Sonnenlicht', temp: '18-28 °C' }, + description: 'Der Orangenbaum ist ein kleiner, immergruener Baum mit weissen Blueten und orangen Fruechten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/OrangeBloss_wb.jpg/500px-OrangeBloss_wb.jpg', + categories: ['sun', 'tree'], + }, + { + name: 'Granatapfelbaum', + botanicalName: 'Punica granatum', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '15-28 °C' }, + description: 'Der Granatapfelbaum hat leuchtend rote Blueten und rote, essbare Fruechte mit rubinroten Kernen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/Pomegranate_Juice_%282019%29.jpg/500px-Pomegranate_Juice_%282019%29.jpg', + categories: ['flowering', 'sun', 'tree'], + }, + { + name: 'Guave', + botanicalName: 'Psidium guajava', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '18-30 °C' }, + description: 'Die Guave ist ein tropischer Obstbaum mit gelblich-weissen Fruechten. Sie ist reich an Vitamin C.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Psidium_guajava_fruit.jpg/500px-Psidium_guajava_fruit.jpg', + categories: ['sun', 'tree'], + }, + { + name: 'Papaya', + botanicalName: 'Carica papaya', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Volles Sonnenlicht', temp: '20-35 °C' }, + description: 'Die Papaya ist eine tropische Fruchtpflanze mit grossen, gelappten Blaettern und orangen Fruechten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Carica_papaya_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-029.jpg/500px-Carica_papaya_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-029.jpg', + categories: ['sun', 'large'], + }, + { + name: 'Tomate', + botanicalName: 'Solanum lycopersicum', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Volles Sonnenlicht', temp: '18-28 °C' }, + description: 'Die Tomate ist eine beliebte Gemuese- und Balkonpflanze mit roten, saftigen Fruechten. Im Topf kultivierbar.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/89/Tomato_je.jpg/500px-Tomato_je.jpg', + categories: ['easy'], + }, + { + name: 'Chili', + botanicalName: 'Capsicum annuum', + confidence: 1.0, + careInfo: { waterIntervalDays: 4, light: 'Volles Sonnenlicht', temp: '20-30 °C' }, + description: 'Chili ist eine beliebte Gemuese- und Zierpflanze mit leuchtenden, roten oder orangen Fruechten. Im Topf kultivierbar.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/Capsicum_annuum_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-027.jpg/500px-Capsicum_annuum_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-027.jpg', + categories: ['easy', 'sun', 'medicinal'], + }, + { + name: 'Aubergine', + botanicalName: 'Solanum melongena', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Volles Sonnenlicht', temp: '20-30 °C' }, + description: 'Die Aubergine ist eine Gemuese­pflanze mit grossen, violetten Fruechten. Sie benoetigt viel Waerme und Sonne.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/7/76/Solanum_melongena_24_08_2012_%281%29.JPG/500px-Solanum_melongena_24_08_2012_%281%29.JPG', + categories: ['sun', 'bright_light'], + }, + { + name: 'Gurke', + botanicalName: 'Cucumis sativus', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Volles Sonnenlicht', temp: '18-28 °C' }, + description: 'Die Gurke ist eine rankende Gemuese­pflanze mit gruenen, erfrischenden Fruechten. Im Balkonkasten kultivierbar.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/96/ARS_cucumber.jpg/500px-ARS_cucumber.jpg', + categories: ['easy', 'sun'], + }, + { + name: 'Salat', + botanicalName: 'Lactuca sativa', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles bis volles Licht', temp: '10-22 °C' }, + description: 'Salat ist eine schnell wachsende Blattgemuese­pflanze. Im Topf und Balkonkasten sehr gut zu kultivieren.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Iceberg_lettuce_in_SB.jpg/500px-Iceberg_lettuce_in_SB.jpg', + categories: ['easy'], + }, + { + name: 'Spinat', + botanicalName: 'Spinacia oleracea', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles bis volles Licht', temp: '10-20 °C' }, + description: 'Spinat ist ein naehrstoffreiches Blattgemuese mit dunkelgruenen Blaettern. Reich an Eisen und Vitaminen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Spinacia_oleracea_Spinazie_bloeiend.jpg/500px-Spinacia_oleracea_Spinazie_bloeiend.jpg', + categories: ['easy'], + }, + { + name: 'Mangold', + botanicalName: 'Beta vulgaris', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles bis volles Licht', temp: '10-25 °C' }, + description: 'Mangold ist ein farbenfrohes Blattgemuese mit bunten Stielen in Rot, Gelb, Orange und Weiss.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/f/ff/Beta_vulgaris_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-167.jpg', + categories: ['easy'], + }, + { + name: 'Radieschen', + botanicalName: 'Raphanus sativus', + confidence: 1.0, + careInfo: { waterIntervalDays: 2, light: 'Helles bis volles Licht', temp: '10-22 °C' }, + description: 'Das Radieschen ist ein schnellwachsendes Gemuese mit runden, roten Knollen. Es reift in nur 3-4 Wochen.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Radish_3371103037_4ab07db0bf_o.jpg/500px-Radish_3371103037_4ab07db0bf_o.jpg', + categories: ['easy'], + }, + { + name: 'Karotte', + botanicalName: 'Daucus carota', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '15-22 °C' }, + description: 'Die Karotte ist eine beliebte Gemuese­pflanze mit orangefarbenen Wurzeln. Im tiefen Topf kultivierbar.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/23/Daucus_carota_May_2008-1_edit.jpg/500px-Daucus_carota_May_2008-1_edit.jpg', + categories: ['easy'], + }, + { + name: 'Erdbeere', + botanicalName: 'Fragaria ananassa', + confidence: 1.0, + careInfo: { waterIntervalDays: 3, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Die Erdbeere ist ein beliebtes Obst fuer Balkon und Terrasse mit aromatischen, roten Fruechten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Garden_strawberry_%28Fragaria_%C3%97_ananassa%29_single2.jpg/500px-Garden_strawberry_%28Fragaria_%C3%97_ananassa%29_single2.jpg', + categories: ['easy', 'pet_friendly', 'sun'], + }, + { + name: 'Kamille', + botanicalName: 'Chamomilla recutita', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Volles Sonnenlicht', temp: '15-25 °C' }, + description: 'Die Kamille ist ein beliebtes Heilkraut mit kleinen, weiss-gelben Blueten. Das aetherische Oel wirkt beruhigend.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c8/Matricaria_February_2008-1.jpg/500px-Matricaria_February_2008-1.jpg', + categories: ['easy', 'medicinal', 'sun'], + }, + { + name: 'Zitronenmelisse', + botanicalName: 'Melissa officinalis', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Die Zitronenmelisse ist ein zitronig duftendes Heilkraut. Sie beruhigt die Nerven und foerdert den Schlaf.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Lemon_balm_plant.jpg/500px-Lemon_balm_plant.jpg', + categories: ['easy', 'medicinal'], + }, + { + name: 'Salbei', + botanicalName: 'Salvia officinalis', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '10-25 °C' }, + description: 'Salbei ist ein aromatisches Heilkraut mit silbrig-gruenen Blaettern. Er hat antibakterielle und entzuendungshem­mende Wirkung.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Salvia_officinalis0.jpg/500px-Salvia_officinalis0.jpg', + categories: ['easy', 'medicinal', 'sun'], + }, + { + name: 'Baldrian', + botanicalName: 'Valeriana officinalis', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Baldrian ist ein bekanntes Heilkraut mit weissen bis roeslichen Blueten. Die Wurzeln werden zur Schlaffoerderung verwendet.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/Valeriana_officinalis_inflorescence_-_Niitv%C3%A4lja.jpg/500px-Valeriana_officinalis_inflorescence_-_Niitv%C3%A4lja.jpg', + categories: ['medicinal', 'flowering'], + }, + { + name: 'Johanniskraut', + botanicalName: 'Hypericum perforatum', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '10-25 °C' }, + description: 'Das Johanniskraut hat leuchtend gelbe Blueten und ist ein wichtiges Heilkraut gegen Depressionen und Stimmungstiefs.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/%28MHNT%29_Hypericum_perforatum_flower_and_buttons.jpg/500px-%28MHNT%29_Hypericum_perforatum_flower_and_buttons.jpg', + categories: ['medicinal', 'flowering', 'sun'], + }, + { + name: 'Sonnenhut', + botanicalName: 'Echinacea purpurea', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '15-25 °C' }, + description: 'Der Sonnenhut ist eine beliebte Heilpflanze mit grossen, pinkfarbenen Blueten. Er staerkt das Immunsystem.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Echinacea_purpurea_Grandview_Prairie.jpg/500px-Echinacea_purpurea_Grandview_Prairie.jpg', + categories: ['medicinal', 'flowering', 'sun'], + }, + { + name: 'Arnika', + botanicalName: 'Arnica montana', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '10-20 °C' }, + description: 'Arnika ist eine bekannte Heilpflanze aus den Alpen mit goldgelben Korbbluten. Sie wird fuer Muskeln und Gelenke verwendet.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Arnica_montana_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-015.jpg/500px-Arnica_montana_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-015.jpg', + categories: ['medicinal', 'flowering', 'sun'], + }, + { + name: 'Schafgarbe', + botanicalName: 'Achillea millefolium', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '10-25 °C' }, + description: 'Die Schafgarbe hat weisse oder rosafarbene Bluetenschirme und fein gefiederte Blaetter. Wichtige Heilpflanze.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Achillea_millefolium_%28bright%29.jpg/500px-Achillea_millefolium_%28bright%29.jpg', + categories: ['medicinal', 'flowering', 'sun'], + }, + { + name: 'Roter Fingerhut', + botanicalName: 'Digitalis purpurea', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '10-20 °C' }, + description: 'Der Rote Fingerhut hat hohe Bluetenstaende mit roehrenfoermigen, gepunkteten Blueten in Rosa. Wichtige Arzneipflanze.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Digitalis_purpurea_LC0101.jpg/500px-Digitalis_purpurea_LC0101.jpg', + categories: ['medicinal', 'flowering'], + }, + { + name: 'Wermut', + botanicalName: 'Artemisia absinthium', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Volles Sonnenlicht', temp: '10-25 °C' }, + description: 'Wermut ist ein stark aromatisches Heilkraut mit silbrig-gruenen, tief eingeschnittenen Blaettern. Fuer Kraeuterlikoere.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/eb/Artemisia_absinthium_P1210748.jpg/500px-Artemisia_absinthium_P1210748.jpg', + categories: ['medicinal', 'sun'], + }, + { + name: 'Grosse Brennessel', + botanicalName: 'Urtica dioica', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '10-25 °C' }, + description: 'Die Grosse Brennessel ist eine Heilpflanze mit brennenden Haaren. Die Blaetter sind reich an Vitaminen und Mineralien.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Fen_nettle_%28Urtica_dioica_ssp._galeopsifolia%29_-_geograph.org.uk_-_5423125.jpg/500px-Fen_nettle_%28Urtica_dioica_ssp._galeopsifolia%29_-_geograph.org.uk_-_5423125.jpg', + categories: ['medicinal'], + }, + { + name: 'Schwarzer Holunder', + botanicalName: 'Sambucus nigra', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '10-25 °C' }, + description: 'Der Schwarze Holunder hat weisse Doldenbluten und schwarze Beeren. Die Fruechte werden fuer Sirup und Saft verwendet.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/61/Sambucus_nigra_004.jpg/500px-Sambucus_nigra_004.jpg', + categories: ['medicinal', 'tree', 'flowering'], + }, + { + name: 'Silber-Weide', + botanicalName: 'Salix alba', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles bis volles Licht', temp: '10-25 °C' }, + description: 'Die Silber-Weide hat silbrig-glaenzende Blaetter. Weidenrinde enthält Salicylsaeure, die Grundlage von Aspirin.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Salix_alba_leaves.jpg/500px-Salix_alba_leaves.jpg', + categories: ['medicinal', 'tree', 'large'], + }, + { + name: 'Hange-Birke', + botanicalName: 'Betula pendula', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '10-25 °C' }, + description: 'Die Haenge-Birke hat charakteristisch weisse Rinde und haengende Zweige. Die Blaetter werden in der Heilkunde genutzt.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Betula_pendula_Finland.jpg/500px-Betula_pendula_Finland.jpg', + categories: ['medicinal', 'tree', 'large'], + }, + { + name: 'Faecherahorn', + botanicalName: 'Acer palmatum', + confidence: 1.0, + careInfo: { waterIntervalDays: 5, light: 'Helles bis volles Licht', temp: '10-22 °C' }, + description: 'Der Faecherahorn ist ein japanischer Zierahorn mit feingeschnittenen, faecherfoermigen Blaettern in Gruen oder Rot.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Acer_palmatum0.jpg/500px-Acer_palmatum0.jpg', + categories: ['tree'], + }, + { + name: 'Bonsai-Feige', + botanicalName: 'Ficus retusa', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Helles indirektes Licht', temp: '16-24 °C' }, + description: 'Die Bonsai-Feige ist eine klassische Bonsai-Art mit kleinen, elliptischen Blaettern. Sehr formbar.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Ficus_retusa_herbarium_sheet.jpg/500px-Ficus_retusa_herbarium_sheet.jpg', + categories: ['tree'], + }, + { + name: 'Socotra-Wuestenrose', + botanicalName: 'Adenium socotranum', + confidence: 1.0, + careInfo: { waterIntervalDays: 14, light: 'Volles Sonnenlicht', temp: '20-35 °C' }, + description: 'Die Socotra-Wuestenrose ist eine seltene, endemische Art mit einem sehr dicken, knolligen Stamm und rosa Blueten.', + imageUri: 'wikimedia-search:Adenium socotranum', + categories: ['succulent', 'flowering', 'sun'], + }, + { + name: 'Tempel-Baum', + botanicalName: 'Plumeria rubra', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '20-30 °C' }, + description: 'Der Tempel-Baum hat intensiv duftende, sternfoermige Blueten in Weiss, Gelb oder Rosa. Klassische Tropenblume.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Champa_tree_with_pink_flowers_in_Islamabad%2C_Pakistan.jpg/500px-Champa_tree_with_pink_flowers_in_Islamabad%2C_Pakistan.jpg', + categories: ['flowering', 'sun', 'tree'], + }, + { + name: 'Zaubernuss', + botanicalName: 'Hamamelis mollis', + confidence: 1.0, + careInfo: { waterIntervalDays: 10, light: 'Helles bis volles Licht', temp: '10-20 °C' }, + description: 'Die Zaubernuss bluet im Winter mit fadendunnen, gelben Bluetenkranzeln, die bis -10 Grad standhalten.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/ce/Hamamelis_mollis0.jpg/500px-Hamamelis_mollis0.jpg', + categories: ['flowering', 'medicinal'], + }, + { + name: 'Oleander', + botanicalName: 'Nerium oleander', + confidence: 1.0, + careInfo: { waterIntervalDays: 7, light: 'Volles Sonnenlicht', temp: '15-28 °C' }, + description: 'Der Oleander ist ein mediteraner Strauch mit leuchtend roten, rosa oder weissen Blueten. Sehr hitzetolerant.', + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/cc/Nerium_oleander_flowers_leaves.jpg/500px-Nerium_oleander_flowers_leaves.jpg', + categories: ['flowering', 'sun', 'bright_light'], + }, + // User import: Kraeuter + createHerbEntry('Lorbeer', 'Laurus nobilis'), + createHerbEntry('Estragon', 'Artemisia dracunculus'), + createHerbEntry('Bohnenkraut', 'Satureja hortensis'), + createHerbEntry('Majoran', 'Origanum majorana'), + createHerbEntry('Kerbel', 'Anthriscus cerefolium'), + createHerbEntry('Liebstoeckel', 'Levisticum officinale'), + createHerbEntry('Zitronengras', 'Cymbopogon citratus'), + createHerbEntry('Zitronenverbene', 'Aloysia citrodora'), + createHerbEntry('Borretsch', 'Borago officinalis'), + createHerbEntry('Sauerampfer', 'Rumex acetosa'), + createHerbEntry('Stevia', 'Stevia rebaudiana'), + createHerbEntry('Katzenminze', 'Nepeta cataria'), + createHerbEntry('Currykraut', 'Helichrysum italicum'), + createHerbEntry('Shiso', 'Perilla frutescens'), + createHerbEntry('Schnittknoblauch', 'Allium tuberosum'), + createHerbEntry('Ysop', 'Hyssopus officinalis'), + createHerbEntry('Wasabi', 'Eutrema japonicum', { + careInfo: { waterIntervalDays: 4, light: 'Helles indirektes Licht', temp: '8-20 C' }, + categories: ['bright_light', 'high_humidity'], + description: 'Wasabi ist ein seltenes Wuerzkraut, das gleichmaessige Feuchte und eher kuehle Bedingungen bevorzugt.', + }), + createHerbPinnedEntry('Roemische Kamille', 'Chamaemelum nobile', 'https://upload.wikimedia.org/wikipedia/commons/f/f2/Chamaemelum_nobile_kz02.jpg', { + categories: ['easy', 'sun', 'medicinal'], + }), + createHerbEntry('Koriander', 'Coriandrum sativum'), + createHerbEntry('Dill', 'Anethum graveolens'), + + // User import: Blumen + createFlowerEntry('Sonnenblume', 'Helianthus annuus'), + createFlowerEntry('Rose', 'Rosa x hybrida', { + categories: ['flowering', 'sun', 'bright_light'], + }), + createFlowerEntry('Pfingstrose', 'Paeonia lactiflora'), + createFlowerEntry('Bart-Iris', 'Iris germanica'), + createFlowerEntry('Gaensebluemchen', 'Bellis perennis'), + createFlowerEntry('Nelke', 'Dianthus caryophyllus'), + createFlowerEntry('Loewenmaeulchen', 'Antirrhinum majus'), + createFlowerEntry('Hortensie', 'Hydrangea macrophylla', { + categories: ['flowering', 'bright_light'], + careInfo: { waterIntervalDays: 4, light: 'Helles bis halbschattiges Licht', temp: '8-24 C' }, + }), + createFlowerEntry('Flieder', 'Syringa vulgaris', { + categories: ['flowering', 'tree', 'sun'], + }), + createFlowerEntry('Kosmee', 'Cosmos bipinnatus'), + createFlowerEntry('Kapuzinerkresse', 'Tropaeolum majus'), + createFlowerEntry('Buntnessel', 'Plectranthus scutellarioides', { + categories: ['patterned', 'bright_light'], + description: 'Buntnessel ist eine farbstarke Zierpflanze, die vor allem fuer ihr dekoratives Laub beliebt ist.', + }), + createFlowerEntry('Rittersporn', 'Delphinium elatum'), + createFlowerEntry('Lupine', 'Lupinus polyphyllus'), + createFlowerEntry('Stockrose', 'Alcea rosea'), + createFlowerEntry('Prunkwinde', 'Ipomoea purpurea'), + createFlowerEntry('Clematis', 'Clematis viticella', { + categories: ['flowering', 'bright_light'], + }), + createFlowerEntry('Duftwicke', 'Lathyrus odoratus'), + createFlowerEntry('Hasengloeckchen', 'Hyacinthoides non-scripta'), + createFlowerEntry('Maigloeckchen', 'Convallaria majalis', { + categories: ['flowering', 'medicinal'], + }), + createFlowerEntry('Gladiole', 'Gladiolus hortulanus'), + createFlowerEntry('Ranunkel', 'Ranunculus asiaticus'), + createFlowerEntry('Anemone', 'Anemone coronaria'), + createFlowerEntry('Eisenkraut', 'Verbena bonariensis'), + createFlowerEntry('Flammenblume', 'Phlox paniculata'), + createFlowerEntry('Herbstaster', 'Symphyotrichum novi-belgii'), + createFlowerEntry('Rudbeckie', 'Rudbeckia hirta'), + createFlowerEntry('Feuersalbei', 'Salvia splendens'), + createFlowerEntry('Freesie', 'Freesia refracta'), + createFlowerEntry('Rhododendron', 'Rhododendron catawbiense', { + categories: ['flowering', 'tree', 'bright_light'], + }), + createFlowerEntry('Geissblatt', 'Lonicera japonica', { + categories: ['flowering', 'bright_light'], + }), + createFlowerEntry('Arabischer Jasmin', 'Jasminum sambac', { + categories: ['flowering', 'bright_light'], + }), + createFlowerEntry('Margerite', 'Leucanthemum vulgare'), + createFlowerEntry('Stehende Geranie', 'Pelargonium zonale'), + createFlowerEntry('Eisbegonie', 'Begonia semperflorens-cultorum', { + categories: ['flowering', 'bright_light'], + }), + createFlowerEntry('Gartenbalsamine', 'Impatiens balsamina', { + categories: ['flowering', 'bright_light'], + }), + createFlowerEntry('Vergissmeinnicht', 'Myosotis sylvatica'), + createFlowerEntry('Seidenpflanze', 'Asclepias tuberosa'), + createFlowerEntry('Indianernessel', 'Monarda didyma'), + createFlowerEntry('Bechermalve', 'Lavatera trimestris'), + createFlowerEntry('Maedchenauge', 'Coreopsis tinctoria'), + createFlowerEntry('Taglilie', 'Hemerocallis fulva'), + createFlowerEntry('Lenzrose', 'Helleborus orientalis', { + categories: ['flowering'], + }), + createFlowerEntry('Trompetenwinde', 'Campsis radicans', { + categories: ['flowering', 'bright_light'], + }), + createFlowerEntry('Mohn', 'Papaver rhoeas'), + createFlowerEntry('Kalifornischer Mohn', 'Eschscholzia californica'), + createFlowerEntry('Ringelblume', 'Calendula officinalis', { + categories: ['flowering', 'sun', 'medicinal'], + }), + createFlowerEntry('Kornblume', 'Centaurea cyanus'), + createFlowerEntry('Bartnelke', 'Dianthus barbatus'), + createFlowerEntry('Mittagsgold', 'Gazania rigens'), + createFlowerEntry('Heliotrop', 'Heliotropium arborescens'), + createFlowerEntry('Koenigskerze', 'Verbascum thapsus', { + categories: ['flowering', 'sun', 'medicinal'], + }), + createFlowerEntry('Ziertabak', 'Nicotiana alata'), + createFlowerEntry('Fuchsschwanz', 'Amaranthus caudatus'), + createFlowerEntry('Mehlsalbei', 'Salvia farinacea'), + createFlowerEntry('Kokardenblume', 'Gaillardia aristata'), + createFlowerEntry('Traenendes Herz', 'Lamprocapnos spectabilis', { + categories: ['flowering', 'bright_light'], + }), + createFlowerEntry('Hornveilchen', 'Viola cornuta'), + createFlowerEntry('Nemesie', 'Nemesia strumosa'), + createFlowerEntry('Kapmargerite', 'Osteospermum ecklonis'), + createFlowerEntry('Shasta-Margerite', 'Leucanthemum x superbum'), + + // User import: Baeume und Straeucher + createTreeEntry('Buchsbaum', 'Buxus sempervirens', { + categories: ['tree', 'sun'], + }), + createTreeEntry('Stechpalme', 'Ilex aquifolium', { + categories: ['tree', 'sun'], + }), + createTreeEntry('Magnolie', 'Magnolia grandiflora', { + categories: ['flowering', 'tree', 'large'], + }), + createTreeEntry('Eiche', 'Quercus robur'), + createTreeEntry('Kiefer', 'Pinus sylvestris'), + createTreeEntry('Fichte', 'Picea abies'), + createTreeEntry('Zeder', 'Cedrus libani'), + createTreeEntry('Zypresse', 'Cupressus sempervirens'), + createTreeEntry('Eukalyptus', 'Eucalyptus globulus', { + categories: ['tree', 'sun', 'medicinal'], + }), + createTreeEntry('Jacaranda', 'Jacaranda mimosifolia', { + categories: ['flowering', 'tree', 'large'], + }), + createTreeEntry('Spitzahorn', 'Acer platanoides'), + createTreeEntry('Eberesche', 'Sorbus aucuparia'), + createTreeEntry('Robinie', 'Robinia pseudoacacia'), + createTreeEntry('Flammenbaum', 'Delonix regia', { + categories: ['flowering', 'tree', 'large'], + }), + createTreeEntry('Ginkgo', 'Ginkgo biloba', { + categories: ['tree', 'sun', 'medicinal'], + }), + createTreeEntry('Trompetenbaum', 'Catalpa bignonioides'), + createTreeEntry('Kirschlorbeer', 'Prunus laurocerasus', { + categories: ['tree', 'sun'], + }), + createTreeEntry('Forsythie', 'Forsythia x intermedia', { + categories: ['flowering', 'tree', 'sun'], + }), + createTreeEntry('Gartenhibiskus', 'Hibiscus syriacus', { + categories: ['flowering', 'tree', 'sun'], + }), + createTreeEntry('Weigelie', 'Weigela florida', { + categories: ['flowering', 'tree', 'sun'], + }), + createTreeEntry('Spierstrauch', 'Spiraea japonica', { + categories: ['flowering', 'tree', 'sun'], + }), + createTreeEntry('Schmetterlingsflieder', 'Buddleja davidii', { + categories: ['flowering', 'tree', 'sun'], + }), + + // User import: Zimmerpflanzen + createHouseplantSearchEntry('Kroton', 'Codiaeum variegatum', 'Garden croton', { + categories: ['patterned', 'bright_light'], + }), + createHouseplantEntry('Alocasia zebrina', 'Alocasia zebrina', { + careInfo: BULK_HUMID_HOUSEPLANT_CARE, + categories: ['bright_light', 'high_humidity'], + }), + createHouseplantEntry('Nervenpflanze', 'Fittonia albivenis', { + careInfo: BULK_HUMID_HOUSEPLANT_CARE, + categories: ['patterned', 'high_humidity'], + }), + createHouseplantEntry('Punktblatt', 'Hypoestes phyllostachya', { + categories: ['patterned', 'bright_light'], + }), + createHouseplantEntry('Aluminium-Pflanze', 'Pilea cadierei', { + categories: ['patterned', 'easy', 'pet_friendly'], + }), + createHouseplantEntry('Wassermelonen-Peperomie', 'Peperomia argyreia', { + categories: ['patterned', 'pet_friendly'], + }), + createHouseplantEntry('Raindrop-Peperomie', 'Peperomia polybotrya', { + categories: ['easy', 'pet_friendly'], + }), + createHouseplantEntry('Glueckskastanie', 'Pachira aquatica', { + categories: ['tree', 'bright_light', 'easy'], + }), + createHouseplantEntry('Norfolk-Tanne', 'Araucaria heterophylla', { + categories: ['tree', 'bright_light'], + }), + createHouseplantEntry('Samt-Anthurie', 'Anthurium clarinervium', { + careInfo: BULK_HUMID_HOUSEPLANT_CARE, + categories: ['patterned', 'high_humidity'], + }), + createHouseplantEntry('Kristall-Anthurie', 'Anthurium crystallinum', { + careInfo: BULK_HUMID_HOUSEPLANT_CARE, + categories: ['patterned', 'high_humidity'], + }), + createHouseplantEntry('Falsche Aralie', 'Schefflera elegantissima', { + categories: ['tree', 'bright_light'], + }), + createHouseplantEntry('String of Bananas', 'Curio radicans', { + careInfo: BULK_SUCCULENT_HANGING_CARE, + categories: ['hanging', 'succulent', 'sun'], + }), + createHouseplantPinnedEntry('String of Dolphins', 'Curio x peregrinus', 'https://upload.wikimedia.org/wikipedia/commons/0/00/Dolphinplant.jpg', { + careInfo: BULK_SUCCULENT_HANGING_CARE, + categories: ['hanging', 'succulent', 'sun'], + }), + createHouseplantEntry('Bubikopf', 'Soleirolia soleirolii', { + careInfo: { waterIntervalDays: 4, light: 'Helles indirektes Licht', temp: '15-24 C' }, + categories: ['pet_friendly', 'high_humidity'], + }), + createHouseplantEntry('Palmfarn', 'Cycas revoluta', { + careInfo: { waterIntervalDays: 10, light: 'Helles bis volles Licht', temp: '18-30 C' }, + categories: ['tree', 'sun', 'large'], + }), + createHouseplantEntry('Calathea lancifolia', 'Goeppertia insignis', { + careInfo: BULK_HUMID_HOUSEPLANT_CARE, + categories: ['patterned', 'high_humidity', 'pet_friendly'], + }), + createHouseplantEntry('Calathea ornata', 'Goeppertia ornata', { + careInfo: BULK_HUMID_HOUSEPLANT_CARE, + categories: ['patterned', 'high_humidity', 'pet_friendly'], + }), + createHouseplantPinnedEntry('Philodendron Brasil', 'Philodendron hederaceum Brasil', 'https://upload.wikimedia.org/wikipedia/commons/0/0b/Philodendron_hederaceum_hederaceum_Brasil_0zz.jpg', { + categories: ['easy', 'hanging', 'low_light'], + }), + createHouseplantPinnedEntry('Philodendron Pink Princess', 'Philodendron erubescens Pink Princess', 'https://upload.wikimedia.org/wikipedia/commons/8/89/Philodendron_Pink_Princess.jpg', { + categories: ['bright_light', 'patterned'], + }), + createHouseplantEntry('Philodendron Xanadu', 'Thaumatophyllum xanadu', { + categories: ['bright_light'], + }), + createHouseplantPinnedEntry('Kaffeepflanze arabica nana', 'Coffea arabica Nana', 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/Starr-121108-1098-Coffea_arabica-Philippine_dwarf_habit_with_Forest_and_Angela-Pali_o_Waipio-Maui_%2825102146741%29.jpg/1280px-Starr-121108-1098-Coffea_arabica-Philippine_dwarf_habit_with_Forest_and_Angela-Pali_o_Waipio-Maui_%2825102146741%29.jpg', { + categories: ['bright_light'], + }), + createHouseplantEntry('Yucca aloifolia', 'Yucca aloifolia', { + careInfo: { waterIntervalDays: 10, light: 'Volles Sonnenlicht', temp: '18-30 C' }, + categories: ['tree', 'sun', 'easy'], + }), + createHouseplantEntry('Ficus microcarpa', 'Ficus microcarpa', { + categories: ['tree', 'bright_light', 'easy'], + }), + createHouseplantEntry('Ficus altissima', 'Ficus altissima', { + categories: ['tree', 'bright_light'], + }), +]; diff --git a/constants/searchIntentConfig.js b/constants/searchIntentConfig.js new file mode 100644 index 0000000..7c36f60 --- /dev/null +++ b/constants/searchIntentConfig.js @@ -0,0 +1,402 @@ +const SEARCH_INTENT_CONFIG = { + intents: { + easy: { + aliases: [ + 'easy', + 'easy care', + 'easy plant', + 'easy plants', + 'easy to care', + 'beginner', + 'beginner plant', + 'beginner plants', + 'low maintenance', + 'hard to kill', + 'starter plant', + 'starter plants', + 'pflegearm', + 'pflegeleicht', + 'anfanger', + 'anfangerpflanze', + 'anfangerpflanzen', + 'einfach', + 'unkompliziert', + 'facil cuidado', + 'facil', + 'principiante', + 'planta facil', + 'planta resistente', + ], + entryHints: [ + 'easy', + 'pflegeleicht', + 'robust', + 'resilient', + 'hardy', + 'low maintenance', + 'beginner', + 'facil', + 'resistente', + 'uncomplicated', + ], + }, + low_light: { + aliases: [ + 'low light', + 'dark corner', + 'dark room', + 'office plant', + 'office', + 'windowless room', + 'shade', + 'shady', + 'indirect light', + 'little light', + 'wenig licht', + 'dunkle ecke', + 'buero', + 'buro', + 'dunkel', + 'schatten', + 'halbschatten', + 'poca luz', + 'oficina', + 'rincon oscuro', + 'sombra', + ], + lightHints: [ + 'low light', + 'low to full light', + 'shade', + 'partial shade', + 'indirect', + 'indirect bright', + 'bright indirect', + 'wenig licht', + 'schatten', + 'halbschatten', + 'indirekt', + 'poca luz', + 'sombra', + 'luz indirecta', + ], + }, + pet_friendly: { + aliases: [ + 'pet friendly', + 'pet-safe', + 'pet safe', + 'safe for cats', + 'safe for dogs', + 'cat safe', + 'dog safe', + 'non toxic', + 'non-toxic', + 'haustierfreundlich', + 'tierfreundlich', + 'katzensicher', + 'hundefreundlich', + 'mascota', + 'pet friendly plant', + 'segura para gatos', + 'segura para perros', + 'no toxica', + 'no tóxica', + ], + entryHints: [ + 'pet friendly', + 'safe for pets', + 'safe for cats', + 'safe for dogs', + 'tierfreundlich', + 'haustierfreundlich', + 'mascota', + ], + }, + air_purifier: { + aliases: [ + 'air purifier', + 'air purifying', + 'clean air', + 'cleaner air', + 'air cleaning', + 'air freshening', + 'luftreiniger', + 'luftreinigend', + 'reinigt luft', + 'purificador', + 'aire limpio', + 'purifica aire', + ], + entryHints: [ + 'air purifier', + 'air purifying', + 'clean air', + 'luftreiniger', + 'purificador', + ], + }, + flowering: { + aliases: [ + 'flowering', + 'flowers', + 'blooms', + 'in bloom', + 'bluhend', + 'bluht', + 'blumen', + 'con flores', + 'floracion', + ], + entryHints: [ + 'flowering', + 'blooms', + 'flower', + 'bluh', + 'flor', + ], + }, + succulent: { + aliases: [ + 'succulent', + 'succulents', + 'cactus', + 'cactus-like', + 'drought tolerant', + 'sukkulente', + 'sukkulenten', + 'trockenheitsvertraglich', + 'trockenheitsvertraeglich', + 'suculenta', + 'suculentas', + ], + entryHints: [ + 'succulent', + 'cactus', + 'drought tolerant', + 'sukkulent', + 'suculenta', + ], + }, + bright_light: { + aliases: [ + 'bright light', + 'bright room', + 'bright spot', + 'east window', + 'west window', + 'sunny room', + 'helles licht', + 'hell', + 'lichtreich', + 'fensterplatz', + 'mucha luz', + 'luz brillante', + ], + lightHints: [ + 'bright light', + 'bright indirect', + 'bright', + 'helles licht', + 'helles indirektes licht', + 'luz brillante', + ], + }, + sun: { + aliases: [ + 'full sun', + 'sun', + 'sunny window', + 'direct sun', + 'south window', + 'south facing window', + 'volle sonne', + 'sonnig', + 'direkte sonne', + 'fenster sud', + 'fenster sued', + 'fenster süd', + 'ventana soleada', + 'sol directo', + ], + lightHints: [ + 'full sun', + 'sunny', + 'direct sun', + 'volles sonnenlicht', + 'sonnig', + 'sol directo', + ], + }, + high_humidity: { + aliases: [ + 'high humidity', + 'humid', + 'bathroom plant', + 'bathroom', + 'shower room', + 'humid room', + 'tropical humidity', + 'hohe luftfeuchtigkeit', + 'feucht', + 'badezimmer', + 'dusche', + 'luftfeucht', + 'humedad alta', + 'bano', + 'baño', + ], + entryHints: [ + 'high humidity', + 'humidity', + 'humid', + 'hohe luftfeuchtigkeit', + 'luftfeuchtigkeit', + 'humedad alta', + ], + }, + hanging: { + aliases: [ + 'hanging', + 'trailing', + 'hanging basket', + 'shelf plant', + 'vine plant', + 'cascading', + 'hangend', + 'ampel', + 'rankend', + 'colgante', + 'planta colgante', + ], + entryHints: [ + 'hanging', + 'trailing', + 'vine', + 'hang', + 'colgante', + ], + }, + patterned: { + aliases: [ + 'patterned', + 'patterned leaves', + 'striped', + 'variegated', + 'spotted', + 'decorative leaves', + 'fancy leaves', + 'gemustert', + 'muster', + 'gestreift', + 'bunt', + 'variegada', + 'rayada', + ], + entryHints: [ + 'patterned', + 'striped', + 'variegated', + 'spotted', + 'gemustert', + 'gestreift', + ], + }, + tree: { + aliases: [ + 'tree', + 'indoor tree', + 'small tree', + 'floor tree', + 'zimmerbaum', + 'baum', + 'arbol', + 'árbol', + ], + entryHints: [ + 'tree', + 'baum', + 'arbol', + ], + }, + large: { + aliases: [ + 'large', + 'big plant', + 'tall plant', + 'statement plant', + 'floor plant', + 'oversized plant', + 'gross', + 'groß', + 'grosse pflanze', + 'hohe pflanze', + 'planta grande', + 'planta alta', + ], + entryHints: [ + 'large', + 'big', + 'tall', + 'gross', + 'groß', + 'grande', + ], + }, + medicinal: { + aliases: [ + 'medicinal', + 'healing plant', + 'herb', + 'kitchen herb', + 'tea herb', + 'apothecary plant', + 'heilpflanze', + 'heilkraut', + 'kraut', + 'medicinal plant', + 'medicinal herb', + 'medicinales', + 'hierba', + 'hierba medicinal', + ], + entryHints: [ + 'medicinal', + 'herb', + 'heil', + 'kraut', + 'hierba', + ], + }, + }, + noiseTokens: [ + 'plant', + 'plants', + 'pflanze', + 'pflanzen', + 'planta', + 'plantas', + 'for', + 'fur', + 'fuer', + 'para', + 'mit', + 'with', + 'and', + 'und', + 'y', + 'the', + 'der', + 'die', + 'das', + 'el', + 'la', + 'de', + 'a', + 'an', + ], +}; + +module.exports = { + SEARCH_INTENT_CONFIG, +}; diff --git a/context/AppContext.tsx b/context/AppContext.tsx new file mode 100644 index 0000000..a69ff4a --- /dev/null +++ b/context/AppContext.tsx @@ -0,0 +1,476 @@ +import React, { createContext, useContext, useState, useEffect, useCallback } from 'react'; +import { useColorScheme, Appearance } from 'react-native'; +import { + Plant, + IdentificationResult, + Language, + AppearanceMode, + AppColorScheme, + ColorPalette, +} from '../types'; +import { ImageCacheService } from '../services/imageCacheService'; +import { getTranslation } from '../utils/translations'; +import { backendApiClient } from '../services/backend/backendApiClient'; +import { BillingSummary, PurchaseProductId, SimulatedWebhookEvent } from '../services/backend/contracts'; +import { createIdempotencyKey } from '../utils/idempotency'; +import { AuthService, AuthSession } from '../services/authService'; +import { PlantsDb, SettingsDb, LexiconHistoryDb, AppMetaDb } from '../services/database'; + +interface AppState { + session: AuthSession | null; + plants: Plant[]; + language: Language; + appearanceMode: AppearanceMode; + colorPalette: ColorPalette; + profileName: string; + profileImageUri: string | null; + billingSummary: BillingSummary | null; + resolvedScheme: AppColorScheme; + isDarkMode: boolean; + isInitializing: boolean; + isLoadingPlants: boolean; + isLoadingBilling: boolean; + t: ReturnType; + // Actions + setAppearanceMode: (mode: AppearanceMode) => void; + setColorPalette: (palette: ColorPalette) => void; + setProfileName: (name: string) => Promise; + setProfileImage: (imageUri: string | null) => Promise; + changeLanguage: (lang: Language) => void; + savePlant: (result: IdentificationResult, imageUri: string, overrideSession?: AuthSession) => Promise; + deletePlant: (id: string) => Promise; + updatePlant: (plant: Plant) => void; + refreshPlants: () => void; + refreshBillingSummary: () => Promise; + simulatePurchase: (productId: PurchaseProductId) => Promise; + simulateWebhookEvent: (event: SimulatedWebhookEvent, payload?: { credits?: number }) => Promise; + getLexiconSearchHistory: () => string[]; + saveLexiconSearchQuery: (query: string) => void; + clearLexiconSearchHistory: () => void; + hydrateSession: (session: AuthSession) => Promise; + signOut: () => Promise; + setPendingPlant: (result: IdentificationResult, imageUri: string) => void; + getPendingPlant: () => { result: IdentificationResult; imageUri: string } | null; + guestScanCount: number; + incrementGuestScanCount: () => void; +} + +const AppContext = createContext(null); + +const toErrorMessage = (error: unknown): string => { + if (error instanceof Error) return error.message; + return String(error); +}; + +export const useApp = () => { + const ctx = useContext(AppContext); + if (!ctx) throw new Error('useApp must be used within AppProvider'); + return ctx; +}; + +const isAppearanceMode = (v: string): v is AppearanceMode => + v === 'system' || v === 'light' || v === 'dark'; +const isColorPalette = (v: string): v is ColorPalette => + v === 'forest' || v === 'ocean' || v === 'sunset' || v === 'mono'; +const isLanguage = (v: string): v is Language => v === 'de' || v === 'en' || v === 'es'; + +const getDeviceLanguage = (): Language => { + try { + const locale = Intl.DateTimeFormat().resolvedOptions().locale || ''; + const lang = locale.split('-')[0].toLowerCase(); + if (lang === 'de') return 'de'; + if (lang === 'es') return 'es'; + return 'en'; + } catch { + return 'en'; + } +}; + +export const AppProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [systemColorScheme, setSystemColorScheme] = useState(Appearance.getColorScheme()); + + useEffect(() => { + const subscription = Appearance.addChangeListener(({ colorScheme }) => { + setSystemColorScheme(colorScheme); + }); + return () => subscription.remove(); + }, []); + + const [session, setSession] = useState(null); + const [plants, setPlants] = useState([]); + const [language, setLanguage] = useState(getDeviceLanguage()); + const [appearanceMode, setAppearanceModeState] = useState('system'); + const [colorPalette, setColorPaletteState] = useState('forest'); + const [profileName, setProfileNameState] = useState(''); + const [profileImageUri, setProfileImageUri] = useState(null); + const [pendingPlant, setPendingPlantState] = useState<{ result: IdentificationResult; imageUri: string } | null>(null); + const [guestScanCount, setGuestScanCount] = useState(0); + const [isInitializing, setIsInitializing] = useState(true); + const [isLoadingPlants, setIsLoadingPlants] = useState(true); + const [billingSummary, setBillingSummary] = useState(null); + const [isLoadingBilling, setIsLoadingBilling] = useState(true); + + const resolvedScheme: AppColorScheme = + appearanceMode === 'system' + ? (systemColorScheme ?? 'dark') === 'dark' ? 'dark' : 'light' + : appearanceMode; + const isDarkMode = resolvedScheme === 'dark'; + const t = getTranslation(language); + + const refreshBillingSummary = useCallback(async () => { + setIsLoadingBilling(true); + try { + const summary = await backendApiClient.getBillingSummary(); + setBillingSummary(summary); + } catch (e) { + console.error('Failed to refresh billing summary', e); + } finally { + setIsLoadingBilling(false); + } + }, []); + + const resetStateForSignedOutUser = useCallback(() => { + setSession(null); + setPlants([]); + setLanguage(getDeviceLanguage()); + setAppearanceModeState('system'); + setColorPaletteState('forest'); + setProfileNameState(''); + setProfileImageUri(null); + setIsLoadingPlants(false); + // Fetch guest billing summary instead of setting it to null + refreshBillingSummary(); + }, [refreshBillingSummary]); + + const refreshPlants = useCallback(() => { + if (!session) return; + try { + setPlants(PlantsDb.getAll(session.userId)); + } catch (error) { + console.error('Failed to refresh plants list.', { + userId: session.userId, + error: toErrorMessage(error), + }); + } + }, [session]); + + const savePlant = useCallback(async (result: IdentificationResult, imageUri: string, overrideSession?: AuthSession) => { + const activeSession = overrideSession || session; + if (!activeSession) { + console.warn('Ignoring savePlant request: no active user session.'); + return; + } + + const now = new Date().toISOString(); + let finalImageUri = imageUri; + + try { + finalImageUri = await ImageCacheService.cacheImage(imageUri); + } catch (error) { + console.error('Failed to cache plant image before save.', { + userId: activeSession.userId, + error: toErrorMessage(error), + }); + } + + const newPlant: Plant = { + id: Math.random().toString(36).substr(2, 9), + name: result.name, + botanicalName: result.botanicalName, + imageUri: finalImageUri, + dateAdded: now, + careInfo: result.careInfo, + lastWatered: now, + wateringHistory: [now], + description: result.description, + notificationsEnabled: false, + }; + + try { + PlantsDb.insert(activeSession.userId, newPlant); + } catch (error) { + console.error('Failed to insert plant into SQLite.', { + userId: activeSession.userId, + plantId: newPlant.id, + plantName: newPlant.name, + error: toErrorMessage(error), + }); + throw error; + } + + try { + const reloadedPlants = PlantsDb.getAll(activeSession.userId); + const insertedPlantExists = reloadedPlants.some((plant) => plant.id === newPlant.id); + + if (!insertedPlantExists) { + console.warn('Plant was inserted but not found in immediate reload. Applying optimistic list update.', { + userId: activeSession.userId, + plantId: newPlant.id, + }); + setPlants(prev => [newPlant, ...prev.filter((plant) => plant.id !== newPlant.id)]); + return; + } + + setPlants(reloadedPlants); + } catch (error) { + console.error('Failed to refresh plants after insert. Applying optimistic fallback.', { + userId: activeSession.userId, + plantId: newPlant.id, + error: toErrorMessage(error), + }); + setPlants(prev => [newPlant, ...prev.filter((plant) => plant.id !== newPlant.id)]); + } + }, [session]); + + const deletePlant = useCallback(async (id: string) => { + if (!session) return; + const plant = plants.find(p => p.id === id); + if (plant?.imageUri) { + await ImageCacheService.deleteCachedImage(plant.imageUri); + } + PlantsDb.delete(session.userId, id); + setPlants(prev => prev.filter(p => p.id !== id)); + }, [session, plants]); + + const updatePlant = useCallback((updatedPlant: Plant) => { + if (!session) return; + PlantsDb.update(session.userId, updatedPlant); + setPlants(prev => prev.map(p => p.id === updatedPlant.id ? updatedPlant : p)); + }, [session]); + + const hydrateSession = useCallback(async (nextSession: AuthSession) => { + setSession(nextSession); + setProfileNameState(nextSession.name); + setIsLoadingPlants(true); + setIsLoadingBilling(true); + + // Settings aus SQLite + try { + const settings = SettingsDb.get(nextSession.userId); + if (settings.language_set === 1 && isLanguage(settings.language)) setLanguage(settings.language as Language); + if (isAppearanceMode(settings.appearance_mode)) setAppearanceModeState(settings.appearance_mode as AppearanceMode); + if (isColorPalette(settings.color_palette)) setColorPaletteState(settings.color_palette as ColorPalette); + setProfileImageUri(settings.profile_image); + } catch (e) { + console.error('Failed to load settings from SQLite', e); + } + + // Pflanzen laden + try { + setPlants(PlantsDb.getAll(nextSession.userId)); + } catch (error) { + console.error('Failed to load plants during app bootstrap.', { + userId: nextSession.userId, + error: toErrorMessage(error), + }); + setPlants([]); + } finally { + setIsLoadingPlants(false); + } + + // Billing laden + try { + await refreshBillingSummary(); + } catch (e) { + console.error('Initial billing summary check failed', e); + setIsLoadingBilling(false); + // Einmaliger Retry nach 2s + setTimeout(async () => { + try { + await refreshBillingSummary(); + } catch { + // silent — user can retry manually + } + }, 2000); + } + + // Check for pending plant to save after login/signup + if (pendingPlant) { + setTimeout(async () => { + try { + // Inside hydrateSession, the state 'session' might not be updated yet + // but we can pass nextSession to savePlant if we modify it, + // but savePlant uses the 'session' from the outer scope. + // However, by the time this timeout runs, the session state SHOULD be set. + await savePlant(pendingPlant.result, pendingPlant.imageUri, nextSession); + setPendingPlantState(null); + } catch (e) { + console.error('Failed to save pending plant after hydration', e); + } + }, 800); + } + }, [refreshBillingSummary, pendingPlant, savePlant]); + + const signOut = useCallback(async () => { + await AuthService.logout(); + resetStateForSignedOutUser(); + }, [resetStateForSignedOutUser]); + + // Session + Settings laden (inkl. Server-Validierung) + useEffect(() => { + (async () => { + try { + // Load guest scan count from DB + const savedCount = AppMetaDb.get('guest_scan_count'); + if (savedCount) { + setGuestScanCount(parseInt(savedCount, 10) || 0); + } + + const s = await AuthService.getSession(); + if (!s) { + resetStateForSignedOutUser(); + return; + } + // Token validieren bevor Session gesetzt wird — verhindert kurzes Dashboard-Flash + const validity = await AuthService.validateWithServer(); + if (validity === 'invalid') { + await AuthService.logout(); + resetStateForSignedOutUser(); + return; + } + await hydrateSession(s); + } catch (error) { + console.error('Critical failure during AppContext initialization', error); + resetStateForSignedOutUser(); + } finally { + setIsInitializing(false); + } + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const simulatePurchase = useCallback(async (productId: PurchaseProductId) => { + const response = await backendApiClient.simulatePurchase({ + idempotencyKey: createIdempotencyKey('purchase', productId), + productId, + }); + setBillingSummary(response.billing); + }, []); + + const simulateWebhookEvent = useCallback(async ( + event: SimulatedWebhookEvent, + payload?: { credits?: number }, + ) => { + const response = await backendApiClient.simulateWebhook({ + idempotencyKey: createIdempotencyKey('webhook', event), + event, + payload, + }); + setBillingSummary(response.billing); + }, []); + + const setAppearanceMode = useCallback((mode: AppearanceMode) => { + setAppearanceModeState(mode); + if (session) SettingsDb.setAppearanceMode(session.userId, mode); + }, [session]); + + const setColorPalette = useCallback((palette: ColorPalette) => { + setColorPaletteState(palette); + if (session) SettingsDb.setColorPalette(session.userId, palette); + }, [session]); + + const setProfileName = useCallback(async (name: string) => { + const normalized = name.trim() || session?.name || 'GreenLens User'; + setProfileNameState(normalized); + if (session) { + SettingsDb.setName(session.userId, normalized); + await AuthService.updateSessionName(normalized); + } + }, [session]); + + const setProfileImage = useCallback(async (imageUri: string | null) => { + let nextUri = imageUri; + if (imageUri) { + try { + nextUri = await ImageCacheService.cacheImage(imageUri); + } catch (e) { + console.error('Failed to cache profile image', e); + } + } + if (profileImageUri && profileImageUri !== nextUri) { + await ImageCacheService.deleteCachedImage(profileImageUri); + } + setProfileImageUri(nextUri); + if (session) SettingsDb.setProfileImage(session.userId, nextUri); + }, [session, profileImageUri]); + + const changeLanguage = useCallback((lang: Language) => { + setLanguage(lang); + if (session) SettingsDb.setLanguage(session.userId, lang); + }, [session]); + + + // Lexicon history — synchron (SQLite sync API) + const getLexiconSearchHistory = useCallback((): string[] => { + if (!session) return []; + return LexiconHistoryDb.getAll(session.userId); + }, [session]); + + const saveLexiconSearchQuery = useCallback((query: string) => { + if (!session) return; + LexiconHistoryDb.add(session.userId, query); + }, [session]); + + const clearLexiconSearchHistory = useCallback(() => { + if (!session) return; + LexiconHistoryDb.clear(session.userId); + }, [session]); + + const setPendingPlant = useCallback((result: IdentificationResult, imageUri: string) => { + setPendingPlantState({ result, imageUri }); + }, []); + + const getPendingPlant = useCallback(() => { + return pendingPlant; + }, [pendingPlant]); + + const incrementGuestScanCount = useCallback(() => { + setGuestScanCount(prev => { + const next = prev + 1; + AppMetaDb.set('guest_scan_count', next.toString()); + return next; + }); + }, []); + + return ( + + {children} + + ); +}; diff --git a/context/CoachMarksContext.tsx b/context/CoachMarksContext.tsx new file mode 100644 index 0000000..5b9a72c --- /dev/null +++ b/context/CoachMarksContext.tsx @@ -0,0 +1,77 @@ +import React, { createContext, useContext, useState, useCallback, useRef } from 'react'; +import { LayoutRectangle } from 'react-native'; + +export interface CoachStep { + elementKey: string; + title: string; + description: string; + tooltipSide: 'above' | 'below' | 'left' | 'right'; +} + +interface CoachMarksState { + isActive: boolean; + currentStep: number; + steps: CoachStep[]; + layouts: Record; + registerLayout: (key: string, layout: LayoutRectangle) => void; + startTour: (steps: CoachStep[]) => void; + next: () => void; + skip: () => void; +} + +const CoachMarksContext = createContext(null); + +export const useCoachMarks = () => { + const ctx = useContext(CoachMarksContext); + if (!ctx) throw new Error('useCoachMarks must be within CoachMarksProvider'); + return ctx; +}; + +export const CoachMarksProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [isActive, setIsActive] = useState(false); + const [currentStep, setCurrentStep] = useState(0); + const [steps, setSteps] = useState([]); + const layouts = useRef>({}); + const [, forceRender] = useState(0); + + const registerLayout = useCallback((key: string, layout: LayoutRectangle) => { + layouts.current[key] = layout; + forceRender(n => n + 1); + }, []); + + const startTour = useCallback((newSteps: CoachStep[]) => { + setSteps(newSteps); + setCurrentStep(0); + setIsActive(true); + }, []); + + const next = useCallback(() => { + setCurrentStep(prev => { + if (prev + 1 >= steps.length) { + setIsActive(false); + return 0; + } + return prev + 1; + }); + }, [steps.length]); + + const skip = useCallback(() => { + setIsActive(false); + setCurrentStep(0); + }, []); + + return ( + + {children} + + ); +}; diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..6bc8a46 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,54 @@ +version: '3.8' + +services: + server: + build: + context: ./server + ports: + - "${PORT:-3005}:3000" + environment: + PORT: 3000 + PLANT_DB_PATH: /data/greenlns.sqlite + MINIO_ENDPOINT: minio + MINIO_PORT: 9000 + MINIO_USE_SSL: "false" + MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin} + MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin123} + MINIO_BUCKET: ${MINIO_BUCKET:-plant-images} + # Public URL for MinIO — set this to your Railway MinIO public domain + MINIO_PUBLIC_URL: ${MINIO_PUBLIC_URL:-http://localhost:9000} + # App secrets (set via Railway env vars) + OPENAI_API_KEY: ${OPENAI_API_KEY} + STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY} + STRIPE_PUBLISHABLE_KEY: ${STRIPE_PUBLISHABLE_KEY} + STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET} + JWT_SECRET: ${JWT_SECRET} + PLANT_IMPORT_ADMIN_KEY: ${PLANT_IMPORT_ADMIN_KEY} + volumes: + - db_data:/data + depends_on: + minio: + condition: service_healthy + restart: unless-stopped + + minio: + image: minio/minio:latest + ports: + - "9000:9000" + - "9001:9001" + environment: + MINIO_ROOT_USER: ${MINIO_ACCESS_KEY:-minioadmin} + MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY:-minioadmin123} + volumes: + - minio_data:/data + command: server /data --console-address ":9001" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] + interval: 10s + timeout: 5s + retries: 5 + restart: unless-stopped + +volumes: + db_data: + minio_data: diff --git a/doctor_output.txt b/doctor_output.txt new file mode 100644 index 0000000..dc86edb Binary files /dev/null and b/doctor_output.txt differ diff --git a/doctor_output_utf8.txt b/doctor_output_utf8.txt new file mode 100644 index 0000000..c60592d --- /dev/null +++ b/doctor_output_utf8.txt @@ -0,0 +1,48 @@ +env: load .env.local +env: export EXPO_PUBLIC_OPENAI_API_KEY EXPO_PUBLIC_OPENAI_HEALTH_MODEL EXPO_PUBLIC_OPENAI_SCAN_MODEL EXPO_PUBLIC_PAYMENT_SERVER_URL EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY STRIPE_PUBLISHABLE_KEY STRIPE_SECRET_KEY STRIPE_WEBHOOK_SECRET +Running 17 checks on your project... +15/17 checks passed. 2 checks failed. Possible issues detected: +Use the --verbose flag to see more details about passed checks. + +Ô£û Check for common project setup issues +The .expo directory is not ignored by Git. It contains machine-specific device history and development server settings and should not be committed. +Advice: +Add ".expo/" to your .gitignore to avoid committing local Expo state. + +Ô£û Check that packages match versions required by installed Expo SDK + +ÔÜá´©Å Minor version mismatches +package expected found +react-native-worklets 0.5.1 0.7.2 + + + +1 package out of date. +Advice: +Use 'npx expo install --check' to review and upgrade your dependencies. +To ignore specific packages, add them to "expo.install.exclude" in package.json. Learn more: https://expo.fyi/dependency-validation + +node.exe : 2 checks +failed, indicating +possible issues with +the project. +In Zeile:1 Zeichen:1 ++ & "C:\Program +Files\nodejs/node.exe" +"C:\Program +Files\nodejs/node_mo +... ++ ~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~ +~~ + + CategoryInfo + : NotSpecifi + ed: (2 checks fail + ed...th the projec +t.:String) [], Rem +oteException + + FullyQualifiedEr + rorId : NativeComm + andError + diff --git a/eas.json b/eas.json new file mode 100644 index 0000000..dc9ec7c --- /dev/null +++ b/eas.json @@ -0,0 +1,36 @@ +{ + "cli": { + "version": ">= 3.0.0", + "appVersionSource": "remote" + }, + "build": { + "development": { + "developmentClient": true, + "distribution": "internal" + }, + "preview": { + "node": "22.18.0", + "distribution": "internal", + "env": { + "NPM_CONFIG_LEGACY_PEER_DEPS": "true", + "EXPO_PUBLIC_BACKEND_URL": "https://imaginative-abundance-production-f785.up.railway.app", + "EXPO_PUBLIC_PAYMENT_SERVER_URL": "https://imaginative-abundance-production-f785.up.railway.app", + "EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY": "pk_live_51SHpSLJYShvDMH3vXGaCFTgSDBZmjLUuw12rcvZFPwxfdEK1zRGG5mXFTMs6vMkgp7Udj07eZPDTNijhQn29VYpe00gzX8pBKN", + "EXPO_PUBLIC_REVENUECAT_IOS_API_KEY": "appl_hrjmLmIUUTojZygbsisNqQqrHbX" + } + }, + "production": { + "node": "22.18.0", + "env": { + "NPM_CONFIG_LEGACY_PEER_DEPS": "true", + "EXPO_PUBLIC_BACKEND_URL": "https://imaginative-abundance-production-f785.up.railway.app", + "EXPO_PUBLIC_PAYMENT_SERVER_URL": "https://imaginative-abundance-production-f785.up.railway.app", + "EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY": "pk_live_51SHpSLJYShvDMH3vXGaCFTgSDBZmjLUuw12rcvZFPwxfdEK1zRGG5mXFTMs6vMkgp7Udj07eZPDTNijhQn29VYpe00gzX8pBKN", + "EXPO_PUBLIC_REVENUECAT_IOS_API_KEY": "appl_hrjmLmIUUTojZygbsisNqQqrHbX" + } + } + }, + "submit": { + "production": {} + } +} \ No newline at end of file diff --git a/f.txt b/f.txt new file mode 100644 index 0000000..13c1b7b --- /dev/null +++ b/f.txt @@ -0,0 +1,23 @@ + +Googlebot, Bingbot, GPTBot, ClaudeBot, PerplexityBot, Applebot + + + +https://www.qrmaster.net/tools/instagram-qr-code + +https://www.qrmaster.net/tools/teams-qr-code + + +https://www.qrmaster.net/tools/whatsapp-qr-code + + + + + +app\scanner.tsx: const availableCredits = ses... => const availableCredits = ses... │ +│ │ +│ 107 : null; │ +│ 108 const availableCredits = session │ +│ 109 ? (billingSummary?.credits.available ?? 0) │ +│ 110 - : Math.max(0, 5 - guestScanCount); │ +│ 110 + : Math.max(0, 50 - guestScanCount); \ No newline at end of file diff --git a/fetch_plants.js b/fetch_plants.js new file mode 100644 index 0000000..3e936ac --- /dev/null +++ b/fetch_plants.js @@ -0,0 +1,19 @@ + +const { openDatabase, all, closeDatabase, getDefaultDbPath } = require('./server/lib/sqlite'); +const { getPlants } = require('./server/lib/plants'); + +async function main() { + let db; + try { + db = await openDatabase(); + const plants = await getPlants(db, { limit: 500 }); + console.log(JSON.stringify(plants, null, 2)); + } catch (error) { + console.error(error); + process.exit(1); + } finally { + if (db) await closeDatabase(db); + } +} + +main(); diff --git a/format_md.js b/format_md.js new file mode 100644 index 0000000..509ce55 --- /dev/null +++ b/format_md.js @@ -0,0 +1,23 @@ + +const fs = require('fs'); + +function formatPlants(plants) { + let md = '# Alle Pflanzen in der Datenbank\n\n'; + md += '| Name | Botanischer Name | Kategorie | Gie├ƒintervall (Tage) | Licht | Temperatur |\n'; + md += '| :--- | :--- | :--- | :--- | :--- | :--- |\n'; + + for (const plant of plants) { + const categories = plant.categories.join(', '); + const water = plant.careInfo.waterIntervalDays || '-'; + const light = plant.careInfo.light || '-'; + const temp = plant.careInfo.temp || '-'; + md += `| ${plant.name} | *${plant.botanicalName}* | ${categories} | ${water} | ${light} | ${temp} |\n`; + } + + return md; +} + +const plants = JSON.parse(fs.readFileSync('plants_dump_utf8.json', 'utf8')); +const markdown = formatPlants(plants); +fs.writeFileSync('ALLE_PFLANZEN.md', markdown); +console.log('ALLE_PFLANZEN.md created.'); diff --git a/greenlens_90_day_plan.md b/greenlens_90_day_plan.md new file mode 100644 index 0000000..370394a --- /dev/null +++ b/greenlens_90_day_plan.md @@ -0,0 +1,114 @@ +# 🌿 GreenLens: Der 90-Tage Masterplan + +**Mission:** Einen verlässlichen, wiederholbaren Funnel für urbane Pflanzen-Anfänger aufbauen, deren Pflanzen gerade sterben (Der "Plant ER" Wedge). +**Ziel nach 90 Tagen:** Messbare Verbesserungen bei der Aktivierung, der Paid-Conversion und dem ROI aus organischem Short-Form-Content (UGC). + +--- + +## 🎯 1. Die Strategie (Der "Wedge") + +Anstatt eine generische Pflege-App zu sein, positioniert sich GreenLens als **Notaufnahme für Pflanzen (Plant ER)**. + +* **Zielgruppe (ICP):** Urbane Anfänger, die ihre Pflanzen lieben, aber nicht verstehen. +* **Der Schmerz (Buying Trigger):** Akute Panik. Gelbe Blätter, hängende Köpfe, Schädlinge. Die Angst, die Pflanze zu verlieren. +* **Die Lösung:** Schnelle Diagnose + Klarer, sofort umsetzbarer Aktionsplan. + +--- + +## 📱 2. Die User Journey (App Funnel) + +Der Weg des Nutzers vom Problem bis zur Heilung – und wie wir damit Geld verdienen. + +| Schritt | Was passiert? | Monetarisierung | Wichtigste Metrik (KPI) | +| :--- | :--- | :--- | :--- | +| **1. Panik!** | User bemerkt Symptom & öffnet App | - | % Installs zum 1. Scan (< 10 Min) | +| **2. Diagnose** | Foto + Kontext (Licht, Wasser) erfassen | - | Scan-Abschlussrate | +| **3. Ergebnis** | AI-Diagnose (Vertrauen & Ursache) | 💰 **Ja (Credit-Verbrauch)** | Diagnose-Erfolgsrate | +| **4. Action Plan** | 7-Tage Rettungsplan starten | 💎 **Value (Aha-Moment)** | % User, die Plan starten | +| **5. Follow-Up** | 24h/72h Check-in & Re-Scan | 💰 **Ja (Credits)** | 7-Tage Re-Scan Rate | +| **6. Heilung** | Erfolg wird dokumentiert (Proof) | *Indirekt* | % gerettete Pflanzen | +| **7. Upgrade** | Paywall am perfekten Moment | 💳 **Conversion** | Kauf-Rate, ARPPU | + +> [!IMPORTANT] +> **Die goldene Regel:** Die Paywall (für Abos oder Top-Ups) erscheint erst, *nachdem* der echte Wert (die fertige Diagnose) gezeigt wurde, oder bevor der Follow-up Plan startet. + +--- + +## 🚀 3. Die Wachstums-Maschine (Instagram) + +Organisches Wachstum durch Content, der gespeichert und geteilt wird. +**Fokus:** Saves, Replies und DMs. (3 Posts / Woche, Deutsch & Englisch) + +### Die 3 Content-Pfeiler (Pillars) +1. **Plant Problems & Fixes:** Diagnose ➔ Ursache ➔ Lösung. +2. **Plant Care Basics:** Checklisten und Guides. +3. **Community / Rescue Stories:** Vorher/Nachher Rettungsaktionen (Emotionen). + +### Die stärksten Formate +* **Carousel:** "Gelbe Blätter? Die 5 Gründe & Lösungen" ➔ *Call-to-Action (CTA): Speichern (Save).* +* **Story-Quiz:** "Woran leidet diese Monstera?" ➔ *CTA: Auf Story antworten (Reply).* +* **Reel (Kurz):** Vorher/Nachher Rettung in 7 Tagen ➔ *CTA: An Freund senden (Share).* + +### Der DM-Funnel (Der Lead-Turbo) +1. **Post:** "Kommentiere GUIDE für die Notfall-Checkliste." +2. **DM 1 (Sofort):** Link zur Checkliste (Teaser!) ➔ "Mache den Pilz-Check hier: [App-Link]". +3. **DM 2 (24h später):** "Hat es deiner Pflanze geholfen?" (Feedback & Conversion). + +--- + +## 🛠️ 4. Der 90-Tage Umsetzungsplan + +Eine klare Roadmap von der Basis bis zur Skalierung. + +### Tag 0-30: Basis & Tracking (Build) +* **App:** "Meine Pflanze ist krank" Fast-Path bauen. Diagnose-Output standardisieren (Confidence Score, Schweregrad). +* **Tracking:** Den gesamten Funnel sauber in PostHog tracken. +* **Marketing:** Instagram-Engine starten (3 Pillars, 12 Posts). Lead Magnet ("Emergency Checklist") live schalten. +* **Metriken:** First-Diagnosis Rate, 7-Tage Re-Scan, Upgrade-Rate messen. + +### Tag 31-60: Onboarding & Aktivierung optimieren +* **App:** Follow-up Reminder (Push-Benachrichtigungen!) & Vorher/Nachher-Logging einbauen. +* **Testing:** Wöchentliche A/B-Tests für Paywalls (Wert-basiert) und Onboarding-Geschwindigkeit. +* **Marketing:** Gewinner-Formate auf IG identifizieren und verdoppeln. Erfolgsgeschichten (% gerettet) veröffentlichen. + +### Tag 61-90: Monetarisierung & Skalierung +* **App:** Pricing anpassen (z.B. "Plant ER Case Bundles" im Pro-Abo). +* **Marketing:** Top-UGC-Reels als Paid Ads mit Budget bewerben. +* **Ziele:** Bezahl-Conversion steigern, Churn in den ersten 30 Tagen senken, ROI der Ads belegen. + +--- + +## ⚙️ 5. Wichtige technische Änderungen + +Das muss ins Backend und Frontend eingebaut werden: + +1. **Einheitliches Tracking:** Events wie `plant_er_started`, `scan_submitted`, `paywall_shown`, `upgrade_purchased` müssen strikt implementiert werden. +2. **Erweitertes AI-Modell:** Die Antwort der OpenAI muss klare Felder liefern: + * `confidence_score`: Wie sicher ist die AI? + * `primary_cause`: Hauptursache. + * `severity`: Schweregrad (z.B. kritisch, mittel). + * `recommended_actions`: Konkrete Schritte in einem Array. + * `followup_due_at`: Wann soll der nächste Scan passieren? +3. **Outcome Tracking:** Speichern, wie viele Tage es zur Verbesserung gebraucht hat. + +--- + +## ⚠️ 6. Risiken & Lösungen + +Was den Erfolg gefährden kann – und wie wir es verhindern. + +> [!WARNING] +> **Risiko:** Die KI-Diagnose wirkt unglaubwürdig (User kündigen). +> **Lösung:** Confidence-Score transparent anzeigen + ehrliche Begründungen liefern + Follow-ups erzwingen. + +> [!WARNING] +> **Risiko:** Die frühe Paywall blockiert User beim Onboarding. +> **Lösung:** Erst Value (Diagnosen-Ergebnis), dann Monetarisierung (Behandlungsplan/Top-ups). + +> [!WARNING] +> **Risiko:** Push-Notifications kommen nicht an, Follow-ups sterben. +> **Lösung:** Opt-In für News *nicht* beim App-Start abfragen, sondern exakt dann, wenn der Behandlungsplan erstellt wird ("Sollen wir dich in 24h ans Gießen erinnern?"). + +> [!WARNING] +> **Risiko:** Die "GUIDE" DM-Strategie generiert Traffic, aber keine Installs. +> **Lösung:** Die Checkliste darf kein fertiges PDF sein, sondern ein Teaser, der den Nutzer für die finale Lösung in den Web-Scanner oder die App zieht. diff --git a/greenlns-landing/.dockerignore b/greenlns-landing/.dockerignore new file mode 100644 index 0000000..7b54516 --- /dev/null +++ b/greenlns-landing/.dockerignore @@ -0,0 +1,7 @@ +node_modules +.next +.git +.env* +*.md +nginx +docker-compose.yml diff --git a/greenlns-landing/.gitignore b/greenlns-landing/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/greenlns-landing/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/greenlns-landing/Dockerfile b/greenlns-landing/Dockerfile new file mode 100644 index 0000000..f2efa3a --- /dev/null +++ b/greenlns-landing/Dockerfile @@ -0,0 +1,33 @@ +FROM node:20-alpine AS base + +# ── Dependencies ──────────────────────────────────────────────────────────── +FROM base AS deps +WORKDIR /app +COPY package*.json ./ +RUN npm ci + +# ── Builder ───────────────────────────────────────────────────────────────── +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . +RUN npm run build + +# ── Runner ────────────────────────────────────────────────────────────────── +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV=production + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +CMD ["node", "server.js"] diff --git a/greenlns-landing/README.md b/greenlns-landing/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/greenlns-landing/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/greenlns-landing/app/favicon.ico b/greenlns-landing/app/favicon.ico new file mode 100644 index 0000000..718d6fe Binary files /dev/null and b/greenlns-landing/app/favicon.ico differ diff --git a/greenlns-landing/app/globals.css b/greenlns-landing/app/globals.css new file mode 100644 index 0000000..eac6330 --- /dev/null +++ b/greenlns-landing/app/globals.css @@ -0,0 +1,1322 @@ +@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;0,900;1,400;1,700;1,900&family=Inter:wght@300;400;500;600;700;800&display=swap'); + +/* ============================================ + GreenLens Design System — Premium Landing + ============================================ */ + +:root { + /* Palette */ + --dark: #131f16; + --dark-alt: #1c2e21; + --green: #2a5c3f; + --green-mid: #3d7a56; + --green-light: #56a074; + --accent: #e07a50; + --accent-h: #c96840; + --cream: #f4f1e8; + --cream-alt: #eae6d8; + --white: #ffffff; + --muted: #7a8c7d; + --text-light: rgba(244, 241, 232, 0.72); + + /* Typography */ + --display: 'Playfair Display', Georgia, serif; + --body: 'Inter', -apple-system, sans-serif; + + /* Spacing */ + --s1: 0.5rem; + --s2: 1rem; + --s3: 1.5rem; + --s4: 2rem; + --s6: 3rem; + --s8: 4rem; + --s12: 6rem; + --s16: 8rem; + + /* Radii */ + --r-sm: 8px; + --r-md: 14px; + --r-lg: 24px; + --r-xl: 36px; + --r-pill: 999px; + + /* Easing */ + --ease: cubic-bezier(0.4, 0, 0.2, 1); + --ease-out: cubic-bezier(0, 0, 0.2, 1); + --t: 0.3s var(--ease); + --t-slow: 0.7s var(--ease); +} + +/* ===== RESET ===== */ +*, +*::before, +*::after { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; + font-size: 16px; +} + +body { + font-family: var(--body); + color: var(--dark); + background: var(--cream); + -webkit-font-smoothing: antialiased; + overflow-x: hidden; + line-height: 1.6; +} + +a { + text-decoration: none; + color: inherit; +} + +img, +video { + display: block; + max-width: 100%; +} + +ul { + list-style: none; +} + +button { + cursor: pointer; + font-family: inherit; +} + +/* ===== TYPOGRAPHY ===== */ +h1, +h2, +h3, +h4 { + font-family: var(--display); + line-height: 1.04; + font-weight: 900; +} + +h1 { + font-size: clamp(2.8rem, 6vw, 5.5rem); +} + +h2 { + font-size: clamp(2.2rem, 4.5vw, 4.2rem); +} + +h3 { + font-size: clamp(1.5rem, 2.5vw, 2.2rem); +} + +/* ===== UTILITY ===== */ +.container { + width: 100%; + max-width: 1320px; + margin: 0 auto; + padding: 0 var(--s4); +} + +.tag { + display: inline-block; + font-family: var(--body); + font-size: 0.7rem; + font-weight: 700; + letter-spacing: 0.18em; + text-transform: uppercase; + color: var(--accent); + margin-bottom: var(--s2); +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} + +/* ===== REVEAL ANIMATIONS ===== */ +.reveal { + opacity: 0; + transform: translateY(36px); + transition: opacity 0.9s var(--ease-out), transform 0.9s var(--ease-out); +} + +.reveal.active { + opacity: 1; + transform: translateY(0); +} + +.reveal-fade { + opacity: 0; + transition: opacity 1s var(--ease-out); +} + +.reveal-fade.active { + opacity: 1; +} + +.delay-1 { + transition-delay: 0.12s; +} + +.delay-2 { + transition-delay: 0.24s; +} + +.delay-3 { + transition-delay: 0.36s; +} + +.delay-4 { + transition-delay: 0.48s; +} + +.delay-5 { + transition-delay: 0.60s; +} + +/* ============================================= + NAVBAR + ============================================= */ +.navbar { + position: fixed; + inset: 0 0 auto 0; + z-index: 999; + padding: var(--s2) 0; + transition: background var(--t), padding var(--t), box-shadow var(--t); +} + +.navbar.scrolled { + background: rgba(19, 31, 22, 0.93); + backdrop-filter: blur(18px) saturate(160%); + -webkit-backdrop-filter: blur(18px) saturate(160%); + padding: 0.65rem 0; + box-shadow: 0 2px 40px rgba(0, 0, 0, 0.25); +} + +.navbar .container { + display: flex; + align-items: center; + justify-content: space-between; +} + +.nav-logo { + font-family: var(--display); + font-size: 1.3rem; + font-weight: 900; + color: var(--cream); + letter-spacing: 0.08em; +} + +.nav-links { + display: flex; + align-items: center; + gap: var(--s4); +} + +.nav-links a { + font-size: 0.8rem; + font-weight: 500; + color: var(--text-light); + letter-spacing: 0.04em; + transition: color var(--t); +} + +.nav-links a:hover { + color: var(--cream); +} + +.nav-cta { + background: var(--accent) !important; + color: #fff !important; + padding: 0.6rem 1.4rem; + border-radius: var(--r-pill); + font-weight: 600 !important; + font-size: 0.8rem !important; + transition: background var(--t), transform var(--t), box-shadow var(--t) !important; +} + +.nav-cta:hover { + background: var(--accent-h) !important; + transform: scale(1.04); + box-shadow: 0 6px 24px rgba(224, 122, 80, 0.35); +} + +.nav-hamburger { + display: none; + flex-direction: column; + gap: 5px; + background: none; + border: none; + padding: 4px; +} + +.nav-hamburger span { + display: block; + width: 22px; + height: 2px; + background: var(--cream); + border-radius: 2px; + transition: var(--t); +} + +/* ============================================= + HERO + ============================================= */ +.hero { + position: relative; + min-height: 100vh; + background: var(--dark); + overflow: hidden; + display: flex; + align-items: center; + padding: var(--s16) 0 var(--s12); +} + +.hero-bg-image { + position: absolute; + inset: 0; + background-size: cover; + background-position: center 20%; + opacity: 0.25; + transform: scale(1.05); + transition: transform 8s ease; +} + +.hero-bg-image.loaded { + transform: scale(1); +} + +.hero-bg-overlay { + position: absolute; + inset: 0; + background: linear-gradient(105deg, + rgba(13, 22, 15, 0.92) 0%, + rgba(19, 31, 22, 0.75) 45%, + rgba(19, 31, 22, 0.3) 100%); +} + +.hero .container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--s8); + align-items: center; + position: relative; + z-index: 2; +} + + +.hero-eyebrow { + display: flex; + align-items: center; + gap: var(--s2); + margin-bottom: var(--s3); +} + +.hero-eyebrow-dot { + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--accent); +} + +.hero-eyebrow-text { + font-size: 0.72rem; + font-weight: 600; + letter-spacing: 0.2em; + text-transform: uppercase; + color: var(--accent); +} + +.hero h1 { + color: var(--cream); + margin-bottom: var(--s4); +} + +.hero h1 em { + display: block; + font-style: italic; + background: linear-gradient(135deg, var(--green-light), var(--green-mid)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.hero-desc { + font-size: 1.08rem; + color: var(--text-light); + max-width: 400px; + line-height: 1.75; + margin-bottom: var(--s4); +} + +.hero-actions { + display: flex; + gap: var(--s2); + align-items: center; + flex-wrap: wrap; +} + +.btn-primary { + display: inline-flex; + align-items: center; + gap: 0.5rem; + background: var(--accent); + color: #fff; + padding: 1rem 2.2rem; + border-radius: var(--r-pill); + font-size: 0.9rem; + font-weight: 700; + border: none; + transition: background var(--t), transform var(--t), box-shadow var(--t); +} + +.btn-primary:hover { + background: var(--accent-h); + transform: translateY(-3px); + box-shadow: 0 12px 36px rgba(224, 122, 80, 0.4); +} + +.btn-outline { + display: inline-flex; + align-items: center; + gap: 0.5rem; + background: transparent; + color: var(--cream); + padding: 1rem 2rem; + border-radius: var(--r-pill); + font-size: 0.9rem; + font-weight: 500; + border: 1.5px solid rgba(244, 241, 232, 0.28); + transition: border-color var(--t), background var(--t); +} + +.btn-outline:hover { + border-color: rgba(244, 241, 232, 0.6); + background: rgba(244, 241, 232, 0.07); +} + + +/* Hero visual */ +.hero-visual { + position: relative; + display: flex; + justify-content: center; +} + +.hero-video-card { + position: relative; + border-radius: var(--r-xl); + overflow: hidden; + width: 100%; + max-width: 560px; + aspect-ratio: 9/11; + box-shadow: + 0 40px 100px rgba(0, 0, 0, 0.5), + 0 0 0 1px rgba(244, 241, 232, 0.06); +} + +.hero-video-16-9 { + aspect-ratio: 16/9; + max-width: 800px; +} + +.hero-video-card video { + width: 100%; + height: 100%; + object-fit: cover; +} + +.hero-video-card-overlay { + position: absolute; + inset: 0; + background: linear-gradient(to bottom, transparent 50%, rgba(13, 22, 15, 0.6) 100%); +} + +.hero-video-badge { + position: absolute; + bottom: var(--s3); + left: var(--s3); + background: rgba(19, 31, 22, 0.8); + backdrop-filter: blur(12px); + border: 1px solid rgba(244, 241, 232, 0.12); + border-radius: var(--r-md); + padding: var(--s2) var(--s3); + color: var(--cream); + font-size: 0.78rem; + font-weight: 600; + display: flex; + align-items: center; + gap: var(--s1); +} + +.hero-video-badge-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: #4ebb6c; + animation: pulse-dot 2s ease-in-out infinite; +} + +@keyframes pulse-dot { + + 0%, + 100% { + opacity: 1; + transform: scale(1); + } + + 50% { + opacity: 0.6; + transform: scale(1.4); + } +} + + +/* ============================================= + TICKER / MARQUEE + ============================================= */ +.ticker-wrap { + background: var(--dark-alt); + border-top: 1px solid rgba(244, 241, 232, 0.07); + border-bottom: 1px solid rgba(244, 241, 232, 0.07); + overflow: hidden; + padding: var(--s2) 0; + position: relative; +} + +.ticker-track { + display: flex; + gap: 0; + white-space: nowrap; + animation: ticker 22s linear infinite; + will-change: transform; +} + +.ticker-item { + display: inline-flex; + align-items: center; + gap: var(--s3); + font-family: var(--display); + font-size: clamp(1.3rem, 2.5vw, 1.8rem); + font-weight: 700; + font-style: italic; + color: rgba(244, 241, 232, 0.85); + padding-right: var(--s6); +} + +.ticker-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: var(--accent); + flex-shrink: 0; +} + +@keyframes ticker { + from { + transform: translateX(0); + } + + to { + transform: translateX(-50%); + } +} + +/* ============================================= + FEATURES + ============================================= */ +.features { + padding: var(--s16) 0; + background: var(--cream); +} + +.features-header { + text-align: center; + max-width: 620px; + margin: 0 auto var(--s12); +} + +.features-header h2 { + color: var(--dark); + margin-bottom: var(--s2); +} + +.features-header p { + color: var(--muted); + font-size: 1.05rem; + line-height: 1.75; +} + +/* Bento grid */ +.bento-grid { + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-rows: auto auto; + gap: var(--s3); +} + +.bento-grid-right { + display: grid; + grid-template-rows: 1fr 1fr; + gap: var(--s3); +} + +.bento-card { + position: relative; + border-radius: var(--r-xl); + overflow: hidden; + display: flex; + flex-direction: column; + justify-content: flex-end; + transition: transform var(--t-slow), box-shadow var(--t-slow); +} + +.bento-card:hover { + transform: translateY(-6px); + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.18); +} + +.bento-card-img { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + transition: transform var(--t-slow); +} + +.bento-card:hover .bento-card-img { + transform: scale(1.04); +} + +.bento-card-overlay { + position: absolute; + inset: 0; + background: linear-gradient(to top, rgba(13, 22, 15, 0.92) 0%, rgba(13, 22, 15, 0.25) 55%, transparent 100%); +} + +.bento-card-content { + position: relative; + z-index: 2; + padding: var(--s4); +} + +.bento-card h3 { + color: var(--cream); + margin-bottom: var(--s1); +} + +.bento-card p { + color: var(--text-light); + font-size: 0.88rem; + line-height: 1.65; + max-width: 320px; +} + +.bento-large { + min-height: 560px; +} + +.bento-small { + min-height: 260px; +} + +/* feature-chip tag */ +.bento-chip { + display: inline-block; + background: var(--accent); + color: #fff; + font-size: 0.66rem; + font-weight: 800; + letter-spacing: 0.12em; + text-transform: uppercase; + padding: 0.28rem 0.7rem; + border-radius: var(--r-pill); + margin-bottom: var(--s2); +} + +/* small feature bullets below grid */ +.features-pills { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--s3); + margin-top: var(--s3); +} + +.feature-pill { + background: var(--white); + border-radius: var(--r-lg); + padding: var(--s4); + display: flex; + gap: var(--s3); + align-items: flex-start; + border: 1px solid rgba(42, 92, 63, 0.08); + transition: transform var(--t), box-shadow var(--t); +} + +.feature-pill:hover { + transform: translateY(-4px); + box-shadow: 0 10px 40px rgba(42, 92, 63, 0.1); +} + +.feature-pill-icon { + width: 44px; + height: 44px; + min-width: 44px; + border-radius: var(--r-sm); + background: var(--dark); + display: flex; + align-items: center; + justify-content: center; + font-size: 1.2rem; +} + +.feature-pill-text h4 { + font-family: var(--body); + font-size: 0.92rem; + font-weight: 700; + color: var(--dark); + margin-bottom: 2px; +} + +.feature-pill-text p { + font-size: 0.8rem; + color: var(--muted); + line-height: 1.55; +} + +/* ============================================= + BOTANICAL INTELLIGENCE + ============================================= */ +.intelligence { + padding: var(--s16) 0; + background: var(--white); + overflow: hidden; +} + +.intelligence .container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--s12); + align-items: center; +} + +.intelligence-text h2 { + color: var(--dark); + margin-bottom: var(--s4); +} + +.intelligence-text h2 em { + display: block; + font-style: italic; + color: var(--green); +} + +.intelligence-text>p { + font-size: 1.05rem; + color: var(--muted); + line-height: 1.8; + margin-bottom: var(--s6); +} + +.intelligence-list { + display: flex; + flex-direction: column; + gap: var(--s2); +} + +.intelligence-item { + display: grid; + grid-template-columns: 44px 1fr; + gap: var(--s2); + align-items: center; + padding: var(--s2) var(--s3); + border-radius: var(--r-md); + transition: background var(--t); +} + +.intelligence-item:hover { + background: var(--cream); +} + +.intelligence-item-icon { + width: 44px; + height: 44px; + background: var(--dark); + border-radius: var(--r-sm); + display: flex; + align-items: center; + justify-content: center; + font-size: 1.1rem; +} + +.intelligence-item h4 { + font-family: var(--body); + font-size: 0.9rem; + font-weight: 700; + color: var(--dark); +} + +.intelligence-item p { + font-size: 0.8rem; + color: var(--muted); + margin-top: 1px; +} + +/* Visual side */ +.intelligence-visual { + position: relative; +} + +.intelligence-img-frame { + border-radius: var(--r-xl); + overflow: hidden; + aspect-ratio: 4/5; + position: relative; + box-shadow: 0 30px 80px rgba(13, 22, 15, 0.2); +} + +.intelligence-img-frame img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.intelligence-img-overlay { + position: absolute; + inset: 0; + background: linear-gradient(160deg, rgba(13, 22, 15, 0.3) 0%, transparent 60%); +} + +.intelligence-overlay-text { + position: absolute; + top: var(--s4); + left: var(--s4); + right: var(--s4); +} + +.intelligence-overlay-text h3 { + color: var(--cream); + font-size: clamp(1.8rem, 3vw, 2.8rem); + text-shadow: 0 2px 20px rgba(0, 0, 0, 0.4); +} + +.intelligence-overlay-text h3 em { + color: var(--green-light); + font-style: italic; +} + + +/* ============================================= + HOW IT WORKS (steps) + ============================================= */ +.how { + padding: var(--s16) 0; + background: var(--cream-alt); +} + +.how .container { + display: grid; + grid-template-columns: 1fr 1.3fr; + gap: var(--s12); + align-items: center; +} + +.how-text h2 { + color: var(--dark); + margin-bottom: var(--s4); +} + +.how-text h2 em { + font-style: italic; + color: var(--green); +} + +.how-steps { + display: flex; + flex-direction: column; + gap: var(--s4); + margin-top: var(--s6); +} + +.how-step { + display: grid; + grid-template-columns: 52px 1fr; + gap: var(--s3); + align-items: flex-start; +} + +.how-step-num { + font-family: var(--display); + font-size: 2.5rem; + font-weight: 900; + color: rgba(42, 92, 63, 0.15); + line-height: 1; + user-select: none; +} + +.how-step h4 { + font-family: var(--body); + font-size: 0.95rem; + font-weight: 700; + color: var(--dark); + margin-bottom: 4px; +} + +.how-step p { + font-size: 0.85rem; + color: var(--muted); + line-height: 1.65; +} + +.how-visual { + position: relative; +} + +.how-img-wrap { + border-radius: var(--r-xl); + overflow: hidden; + aspect-ratio: 3/4; + box-shadow: 0 30px 80px rgba(0, 0, 0, 0.18); +} + +.how-img-wrap img { + width: 100%; + height: 100%; + object-fit: cover; +} + + +/* ============================================= + CTA – "Join the Jungle" + ============================================= */ +.cta-section { + padding: var(--s8) 0 0; + background: var(--dark); +} + +.cta-card { + background: var(--dark); + border-radius: var(--r-xl); + overflow: hidden; + display: grid; + grid-template-columns: 1fr 1fr; + min-height: 480px; + position: relative; + box-shadow: 0 30px 80px rgba(13, 22, 15, 0.2); +} + +.cta-card-glow { + position: absolute; + width: 500px; + height: 500px; + border-radius: 50%; + background: radial-gradient(circle, rgba(86, 160, 116, 0.2) 0%, transparent 70%); + top: -120px; + right: -100px; + pointer-events: none; + filter: blur(60px); +} + +.cta-content { + padding: var(--s12) var(--s8); + position: relative; + z-index: 2; + display: flex; + flex-direction: column; + justify-content: center; +} + +.cta-content h2 { + color: var(--cream); + margin-bottom: var(--s3); +} + +.cta-content h2 em { + font-style: italic; + color: var(--green-light); +} + +.cta-content p { + color: var(--text-light); + font-size: 1.05rem; + line-height: 1.75; + margin-bottom: var(--s6); + max-width: 400px; +} + + +.store-row { + display: flex; + gap: var(--s2); + flex-wrap: wrap; +} + +.cta-footnote { + margin-top: var(--s3); + color: var(--text-light); + font-size: 0.82rem; +} + +.cta-footnote a { + text-decoration: underline; + text-underline-offset: 3px; +} + +.store-btn { + display: inline-flex; + align-items: center; + gap: 0.65rem; + background: rgba(244, 241, 232, 0.08); + border: 1.5px solid rgba(244, 241, 232, 0.18); + color: var(--cream); + padding: 0.85rem 1.5rem; + border-radius: var(--r-md); + font-size: 0.82rem; + font-weight: 600; + transition: background var(--t), border-color var(--t), transform var(--t); +} + +.store-btn:hover { + background: rgba(244, 241, 232, 0.14); + border-color: rgba(244, 241, 232, 0.35); + transform: translateY(-2px); +} + +.store-btn-icon { + font-size: 1.5rem; +} + +.store-btn-small { + display: block; + font-size: 0.62rem; + opacity: 0.65; + font-weight: 400; +} + +.store-btn-big { + font-size: 0.92rem; +} + +.cta-visual { + position: relative; + overflow: hidden; +} + +.cta-visual img { + width: 100%; + height: 100%; + object-fit: cover; + opacity: 0.5; + filter: saturate(1.3); +} + +.cta-visual-overlay { + position: absolute; + inset: 0; + background: linear-gradient(to right, var(--dark) 0%, transparent 40%); +} + +/* ============================================= + FOOTER + ============================================= */ +.footer { + background: var(--dark); + padding: var(--s12) 0 var(--s4); + color: var(--cream); +} + +.footer-inner { + display: grid; + grid-template-columns: 1.4fr repeat(3, 1fr); + gap: var(--s8); + padding-bottom: var(--s8); + border-bottom: 1px solid rgba(244, 241, 232, 0.08); +} + +.footer-brand-desc { + color: var(--text-light); + font-size: 0.85rem; + line-height: 1.75; + margin-top: var(--s2); + max-width: 260px; +} + +.footer-col-title { + font-family: var(--body); + font-size: 0.7rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--cream); + margin-bottom: var(--s3); +} + +.footer-col a { + display: block; + color: var(--text-light); + font-size: 0.84rem; + padding: 0.2rem 0; + transition: color var(--t); +} + +.footer-col a:hover { + color: var(--cream); +} + +.footer-brand-xl { + font-family: var(--display); + font-size: clamp(5rem, 12vw, 11rem); + font-weight: 900; + color: rgba(244, 241, 232, 0.045); + text-align: center; + line-height: 1; + padding: var(--s8) 0 var(--s4); + user-select: none; + letter-spacing: -0.02em; + overflow: hidden; +} + +.footer-bottom { + display: flex; + justify-content: space-between; + align-items: center; + border-top: 1px solid rgba(244, 241, 232, 0.05); + padding-top: var(--s3); +} + +.footer-bottom p { + font-size: 0.72rem; + color: var(--text-light); +} + +.footer-contact { + color: var(--cream); + font-size: 0.8rem; + font-weight: 600; +} + +.support-page { + background: + radial-gradient(circle at top left, rgba(86, 160, 116, 0.12), transparent 28%), + linear-gradient(180deg, var(--cream) 0%, var(--white) 100%); + min-height: 100vh; +} + +.support-hero { + padding: 11rem 0 4rem; +} + +.support-hero-inner { + max-width: 880px; +} + +.support-hero-inner h1 { + max-width: 900px; + margin-bottom: var(--s3); +} + +.support-lead { + max-width: 680px; + color: var(--muted); + font-size: 1.05rem; +} + +.support-actions { + display: flex; + gap: var(--s2); + flex-wrap: wrap; + margin-top: var(--s4); +} + +.support-outline { + color: var(--dark); + border-color: rgba(19, 31, 22, 0.16); +} + +.support-outline:hover { + background: rgba(19, 31, 22, 0.04); +} + +.support-grid-wrap { + padding: 0 0 var(--s8); +} + +.support-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--s3); +} + +.support-card, +.support-faq-item { + background: rgba(255, 255, 255, 0.75); + border: 1px solid rgba(19, 31, 22, 0.08); + border-radius: var(--r-lg); + box-shadow: 0 24px 60px rgba(19, 31, 22, 0.05); +} + +.support-card { + padding: var(--s4); +} + +.support-card h2 { + font-size: clamp(1.45rem, 2vw, 1.9rem); + margin-bottom: var(--s2); +} + +.support-card p, +.support-card li { + color: var(--muted); +} + +.support-list { + list-style: disc; + padding-left: 1.2rem; +} + +.support-faq { + padding: 0 0 var(--s16); +} + +.support-section-head { + max-width: 760px; + margin-bottom: var(--s4); +} + +.support-faq-list { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--s3); +} + +.support-faq-item { + padding: var(--s4); +} + +.support-faq-item h3 { + font-size: 1.25rem; + margin-bottom: var(--s2); +} + +.support-faq-item p { + color: var(--muted); +} + +/* ============================================= + RESPONSIVE + ============================================= */ +@media (max-width: 1024px) { + .hero .container { + grid-template-columns: 1fr; + } + + .hero-visual { + display: none; + } + + .hero h1 { + text-align: center; + } + + .hero-desc { + text-align: center; + max-width: 100%; + } + + .hero-actions { + justify-content: center; + } + + + .hero-eyebrow { + justify-content: center; + } + + .intelligence .container { + grid-template-columns: 1fr; + } + + .intelligence-visual { + display: none; + } + + .how .container { + grid-template-columns: 1fr; + } + + .how-visual { + display: none; + } + + .cta-card { + grid-template-columns: 1fr; + } + + .cta-visual { + display: none; + } + + .footer-inner { + grid-template-columns: 1fr 1fr; + gap: var(--s6); + } +} + +@media (max-width: 768px) { + .nav-links { + display: none; + } + + .nav-hamburger { + display: flex; + } + + .bento-grid { + grid-template-columns: 1fr; + } + + .bento-grid-right { + grid-template-columns: 1fr 1fr; + grid-template-rows: auto; + } + + .bento-large { + min-height: 400px; + } + + .bento-small { + min-height: 200px; + } + + .features-pills { + grid-template-columns: 1fr; + } + + + + .footer-inner { + grid-template-columns: 1fr; + gap: var(--s4); + } + + .footer-bottom { + flex-direction: column; + gap: var(--s2); + text-align: center; + } + + .support-grid, + .support-faq-list { + grid-template-columns: 1fr; + } +} diff --git a/greenlns-landing/app/imprint/page.tsx b/greenlns-landing/app/imprint/page.tsx new file mode 100644 index 0000000..0c408c9 --- /dev/null +++ b/greenlns-landing/app/imprint/page.tsx @@ -0,0 +1,71 @@ +'use client' + +import { useLang } from '@/context/LangContext' +import { siteConfig } from '@/lib/site' + +const CONTENT = { + de: { + title: 'Impressum', + companyLabel: 'Unternehmen', + addressLabel: 'Adresse', + representativeLabel: 'Vertretungsberechtigt', + contactLabel: 'Kontakt', + registryLabel: 'Register', + vatLabel: 'USt-ID', + note: 'Vor der Veroeffentlichung muessen alle rechtlichen Angaben mit den echten Firmendaten ersetzt werden.', + }, + en: { + title: 'Imprint', + companyLabel: 'Company', + addressLabel: 'Address', + representativeLabel: 'Represented by', + contactLabel: 'Contact', + registryLabel: 'Registry', + vatLabel: 'VAT ID', + note: 'Replace all legal placeholders with your real company details before publishing the site.', + }, + es: { + title: 'Aviso Legal', + companyLabel: 'Empresa', + addressLabel: 'Direccion', + representativeLabel: 'Representante', + contactLabel: 'Contacto', + registryLabel: 'Registro', + vatLabel: 'IVA', + note: 'Sustituye todos los marcadores legales por tus datos reales antes de publicar el sitio.', + }, +} + +export default function ImprintPage() { + const { lang } = useLang() + const c = CONTENT[lang] + + return ( +
+

{c.title}

+
+

+ {c.companyLabel}: {siteConfig.company.legalName} +

+

+ {c.addressLabel}: {siteConfig.company.addressLine1} +

+ {siteConfig.company.addressLine2 ?

{siteConfig.company.addressLine2}

: null} +

{siteConfig.company.country}

+

+ {c.representativeLabel}: {siteConfig.company.representative} +

+

+ {c.contactLabel}: {siteConfig.legalEmail} +

+

+ {c.registryLabel}: {siteConfig.company.registry} +

+

+ {c.vatLabel}: {siteConfig.company.vatId} +

+

{c.note}

+
+
+ ) +} diff --git a/greenlns-landing/app/layout.tsx b/greenlns-landing/app/layout.tsx new file mode 100644 index 0000000..ae424fc --- /dev/null +++ b/greenlns-landing/app/layout.tsx @@ -0,0 +1,76 @@ +import type { Metadata } from 'next' +import './globals.css' +import { LangProvider } from '@/context/LangContext' +import { siteConfig } from '@/lib/site' + +export const metadata: Metadata = { + metadataBase: new URL(siteConfig.domain), + title: { + default: 'GreenLens - Plant Identifier and Care Planner', + template: '%s | GreenLens', + }, + description: + 'GreenLens helps you identify plants, organize your collection, and keep up with care routines in one app.', + keywords: [ + 'plant identifier by picture', + 'plant care app', + 'watering reminders', + 'houseplant tracker', + 'plant identification', + 'plant health check', + 'Pflanzen App', + 'GreenLens', + ], + authors: [{ name: siteConfig.name }], + openGraph: { + title: 'GreenLens - Plant Identifier and Care Planner', + description: 'Identify plants, get care guidance, and manage your collection with GreenLens.', + type: 'website', + url: siteConfig.domain, + }, + alternates: { + canonical: '/', + languages: { + de: '/', + en: '/', + es: '/', + 'x-default': '/', + }, + }, +} + +export default function RootLayout({ children }: { children: React.ReactNode }) { + return ( + + + + + + + + + + + + diff --git a/landing/script.js b/landing/script.js new file mode 100644 index 0000000..9e5510e --- /dev/null +++ b/landing/script.js @@ -0,0 +1,88 @@ +/* ======================================== + GreenLens Landing Page – Interactions + ======================================== */ + +document.addEventListener('DOMContentLoaded', () => { + + // --- Navbar scroll effect --- + const navbar = document.querySelector('.navbar'); + const handleScroll = () => { + navbar.classList.toggle('scrolled', window.scrollY > 60); + }; + window.addEventListener('scroll', handleScroll, { passive: true }); + handleScroll(); + + // --- Mobile hamburger --- + const hamburger = document.querySelector('.nav-hamburger'); + const navLinks = document.querySelector('.nav-links'); + + if (hamburger) { + hamburger.addEventListener('click', () => { + navLinks.classList.toggle('active'); + }); + + // close on link click + navLinks.querySelectorAll('a').forEach(link => { + link.addEventListener('click', () => { + navLinks.classList.remove('active'); + }); + }); + } + + // --- Scroll reveal --- + const revealElements = document.querySelectorAll('.reveal'); + + const revealObserver = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + entry.target.classList.add('active'); + revealObserver.unobserve(entry.target); + } + }); + }, { + threshold: 0.15, + rootMargin: '0px 0px -50px 0px' + }); + + revealElements.forEach(el => revealObserver.observe(el)); + + // --- Counter animation --- + const counters = document.querySelectorAll('[data-count]'); + const counterObserver = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const el = entry.target; + const target = parseFloat(el.dataset.count); + const suffix = el.dataset.suffix || ''; + const isDecimal = target % 1 !== 0; + const duration = 1500; + const start = performance.now(); + + const step = (now) => { + const progress = Math.min((now - start) / duration, 1); + const eased = 1 - Math.pow(1 - progress, 3); // ease-out cubic + const current = eased * target; + el.textContent = (isDecimal ? current.toFixed(1) : Math.floor(current)) + suffix; + if (progress < 1) requestAnimationFrame(step); + }; + + requestAnimationFrame(step); + counterObserver.unobserve(el); + } + }); + }, { threshold: 0.5 }); + + counters.forEach(el => counterObserver.observe(el)); + + // --- Smooth scroll for anchor links --- + document.querySelectorAll('a[href^="#"]').forEach(link => { + link.addEventListener('click', (e) => { + const target = document.querySelector(link.getAttribute('href')); + if (target) { + e.preventDefault(); + target.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + }); + }); + +}); diff --git a/landing/styles.css b/landing/styles.css new file mode 100644 index 0000000..1c09ec6 --- /dev/null +++ b/landing/styles.css @@ -0,0 +1,968 @@ +/* ======================================== + GreenLens Landing Page – Design System + ======================================== */ + +@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;0,900;1,400;1,700;1,900&family=Inter:wght@300;400;500;600;700&display=swap'); + +/* --- CSS Variables --- */ +:root { + --color-dark: #1a2e1f; + --color-dark-alt: #243828; + --color-green: #2d5a3d; + --color-green-light: #4a8c5e; + --color-accent: #e8734a; + --color-accent-hover: #d4623b; + --color-cream: #f5f2eb; + --color-white: #ffffff; + --color-text: #1a2e1f; + --color-text-light: rgba(245, 242, 235, 0.7); + --color-text-muted: #6b7c6f; + + --font-display: 'Playfair Display', Georgia, serif; + --font-body: 'Inter', -apple-system, sans-serif; + + --space-xs: 0.5rem; + --space-sm: 1rem; + --space-md: 2rem; + --space-lg: 4rem; + --space-xl: 6rem; + --space-2xl: 8rem; + + --radius-sm: 8px; + --radius-md: 12px; + --radius-lg: 20px; + --radius-xl: 32px; + + --transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1); + --transition-slow: 0.6s cubic-bezier(0.4, 0, 0.2, 1); +} + +/* --- Reset & Base --- */ +*, +*::before, +*::after { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; + font-size: 16px; +} + +body { + font-family: var(--font-body); + color: var(--color-text); + background: var(--color-cream); + line-height: 1.6; + overflow-x: hidden; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + text-decoration: none; + color: inherit; + transition: color var(--transition); +} + +img, +video { + max-width: 100%; + display: block; +} + +ul { + list-style: none; +} + +/* --- Typography --- */ +h1, +h2, +h3 { + font-family: var(--font-display); + font-weight: 900; + line-height: 1.05; +} + +h1 { + font-size: clamp(3rem, 6vw, 5.5rem); +} + +h2 { + font-size: clamp(2.2rem, 4vw, 4rem); +} + +h3 { + font-size: clamp(1.5rem, 2.5vw, 2rem); +} + +/* --- Utility --- */ +.container { + width: 100%; + max-width: 1280px; + margin: 0 auto; + padding: 0 var(--space-md); +} + +.section-label { + font-family: var(--font-body); + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 3px; + text-transform: uppercase; + color: var(--color-accent); + margin-bottom: var(--space-sm); +} + +/* --- Animations --- */ +.reveal { + opacity: 0; + transform: translateY(40px); + transition: opacity 0.8s ease, transform 0.8s ease; +} + +.reveal.active { + opacity: 1; + transform: translateY(0); +} + +.reveal-delay-1 { + transition-delay: 0.1s; +} + +.reveal-delay-2 { + transition-delay: 0.2s; +} + +.reveal-delay-3 { + transition-delay: 0.3s; +} + +.reveal-delay-4 { + transition-delay: 0.4s; +} + +/* ======================================== + NAVBAR + ======================================== */ +.navbar { + position: fixed; + top: 0; + left: 0; + width: 100%; + z-index: 1000; + padding: var(--space-sm) 0; + transition: background var(--transition), box-shadow var(--transition), padding var(--transition); +} + +.navbar.scrolled { + background: rgba(26, 46, 31, 0.95); + backdrop-filter: blur(20px); + box-shadow: 0 4px 30px rgba(0, 0, 0, 0.15); + padding: 0.6rem 0; +} + +.navbar .container { + display: flex; + justify-content: space-between; + align-items: center; +} + +.nav-logo { + font-family: var(--font-display); + font-size: 1.4rem; + font-weight: 900; + color: var(--color-cream); + letter-spacing: 2px; +} + +.nav-links { + display: flex; + gap: var(--space-md); + align-items: center; +} + +.nav-links a { + font-size: 0.85rem; + font-weight: 500; + color: var(--color-text-light); + letter-spacing: 0.5px; + transition: color var(--transition); +} + +.nav-links a:hover { + color: var(--color-cream); +} + +.nav-cta { + background: var(--color-accent) !important; + color: var(--color-white) !important; + padding: 0.6rem 1.4rem; + border-radius: 100px; + font-weight: 600 !important; + transition: background var(--transition), transform var(--transition) !important; +} + +.nav-cta:hover { + background: var(--color-accent-hover) !important; + transform: scale(1.05); +} + +.nav-hamburger { + display: none; + flex-direction: column; + gap: 5px; + cursor: pointer; + background: none; + border: none; + padding: 4px; +} + +.nav-hamburger span { + width: 24px; + height: 2px; + background: var(--color-cream); + transition: var(--transition); +} + +/* ======================================== + HERO SECTION + ======================================== */ +.hero { + min-height: 100vh; + background: var(--color-dark); + display: flex; + align-items: center; + position: relative; + overflow: hidden; + padding: var(--space-2xl) 0 var(--space-xl); +} + +.hero .container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--space-lg); + align-items: center; +} + +.hero-content { + z-index: 2; +} + +.hero h1 { + color: var(--color-cream); + margin-bottom: var(--space-md); +} + +.hero h1 em { + font-style: italic; + color: var(--color-green-light); +} + +.hero-description { + font-size: 1.1rem; + color: var(--color-text-light); + max-width: 420px; + margin-bottom: var(--space-md); + line-height: 1.7; +} + +.hero-buttons { + display: flex; + gap: var(--space-sm); + align-items: center; +} + +.btn-primary { + display: inline-flex; + align-items: center; + gap: 0.5rem; + background: var(--color-accent); + color: var(--color-white); + padding: 1rem 2rem; + border-radius: 100px; + font-family: var(--font-body); + font-size: 0.95rem; + font-weight: 600; + border: none; + cursor: pointer; + transition: background var(--transition), transform var(--transition), box-shadow var(--transition); +} + +.btn-primary:hover { + background: var(--color-accent-hover); + transform: translateY(-2px); + box-shadow: 0 8px 30px rgba(232, 115, 74, 0.3); +} + +.btn-secondary { + display: inline-flex; + align-items: center; + gap: 0.5rem; + background: transparent; + color: var(--color-cream); + padding: 1rem 2rem; + border-radius: 100px; + font-family: var(--font-body); + font-size: 0.95rem; + font-weight: 500; + border: 1px solid rgba(245, 242, 235, 0.3); + cursor: pointer; + transition: border-color var(--transition), background var(--transition); +} + +.btn-secondary:hover { + border-color: var(--color-cream); + background: rgba(245, 242, 235, 0.08); +} + +.hero-video-wrapper { + position: relative; + border-radius: var(--radius-lg); + overflow: hidden; + box-shadow: 0 30px 80px rgba(0, 0, 0, 0.4); +} + +.hero-video-wrapper video { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: var(--radius-lg); +} + +.hero-video-overlay { + position: absolute; + inset: 0; + background: linear-gradient(135deg, rgba(26, 46, 31, 0.15), transparent); + border-radius: var(--radius-lg); + pointer-events: none; +} + +.hero-stats { + display: flex; + gap: var(--space-lg); + margin-top: var(--space-lg); +} + +.stat { + text-align: left; +} + +.stat-number { + font-family: var(--font-display); + font-size: 2rem; + font-weight: 900; + color: var(--color-cream); +} + +.stat-label { + font-size: 0.8rem; + color: var(--color-text-light); + margin-top: 2px; +} + +/* ======================================== + FEATURES GRID – "Scan it. / Track it." + ======================================== */ +.features { + padding: var(--space-2xl) 0; + background: var(--color-cream); +} + +.features-header { + text-align: center; + max-width: 600px; + margin: 0 auto var(--space-xl); +} + +.features-header h2 { + color: var(--color-dark); +} + +.features-header p { + color: var(--color-text-muted); + font-size: 1.05rem; + margin-top: var(--space-sm); +} + +.features-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: var(--space-md); +} + +.feature-card { + position: relative; + border-radius: var(--radius-lg); + overflow: hidden; + background: var(--color-dark); + min-height: 400px; + display: flex; + flex-direction: column; + justify-content: flex-end; + padding: var(--space-md); + transition: transform var(--transition), box-shadow var(--transition); +} + +.feature-card:hover { + transform: translateY(-8px); + box-shadow: 0 20px 60px rgba(26, 46, 31, 0.2); +} + +.feature-card-bg { + position: absolute; + inset: 0; + background-size: cover; + background-position: center; + transition: transform var(--transition-slow); +} + +.feature-card:hover .feature-card-bg { + transform: scale(1.05); +} + +.feature-card-overlay { + position: absolute; + inset: 0; + background: linear-gradient(to top, rgba(26, 46, 31, 0.9) 0%, rgba(26, 46, 31, 0.2) 60%); +} + +.feature-card-content { + position: relative; + z-index: 2; +} + +.feature-card h3 { + color: var(--color-cream); + margin-bottom: var(--space-xs); +} + +.feature-card p { + color: var(--color-text-light); + font-size: 0.9rem; + line-height: 1.6; +} + +.feature-tag { + display: inline-block; + background: var(--color-accent); + color: var(--color-white); + font-size: 0.7rem; + font-weight: 700; + letter-spacing: 1px; + text-transform: uppercase; + padding: 0.3rem 0.8rem; + border-radius: 100px; + margin-bottom: var(--space-sm); +} + +/* Small feature cards row */ +.features-small { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--space-md); + margin-top: var(--space-md); +} + +.feature-small-card { + background: var(--color-white); + border-radius: var(--radius-md); + padding: var(--space-md); + transition: transform var(--transition), box-shadow var(--transition); +} + +.feature-small-card:hover { + transform: translateY(-4px); + box-shadow: 0 12px 40px rgba(26, 46, 31, 0.1); +} + +.feature-icon { + width: 48px; + height: 48px; + background: var(--color-dark); + border-radius: var(--radius-sm); + display: flex; + align-items: center; + justify-content: center; + margin-bottom: var(--space-sm); + font-size: 1.3rem; +} + +.feature-small-card h3 { + font-family: var(--font-body); + font-size: 1.1rem; + font-weight: 700; + margin-bottom: var(--space-xs); + color: var(--color-dark); +} + +.feature-small-card p { + font-size: 0.85rem; + color: var(--color-text-muted); + line-height: 1.6; +} + +/* ======================================== + BOTANICAL INTELLIGENCE + ======================================== */ +.intelligence { + padding: var(--space-2xl) 0; + background: var(--color-white); + overflow: hidden; +} + +.intelligence .container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--space-xl); + align-items: center; +} + +.intelligence-content h2 em { + font-style: italic; + color: var(--color-green); +} + +.intelligence-content h2 { + margin-bottom: var(--space-md); +} + +.intelligence-content p { + font-size: 1.05rem; + color: var(--color-text-muted); + margin-bottom: var(--space-md); + line-height: 1.8; +} + +.intelligence-features { + display: flex; + flex-direction: column; + gap: var(--space-sm); +} + +.intelligence-feature { + display: flex; + align-items: flex-start; + gap: var(--space-sm); + padding: var(--space-sm); + border-radius: var(--radius-md); + transition: background var(--transition); +} + +.intelligence-feature:hover { + background: var(--color-cream); +} + +.intelligence-feature-icon { + width: 40px; + height: 40px; + min-width: 40px; + background: var(--color-dark); + border-radius: var(--radius-sm); + display: flex; + align-items: center; + justify-content: center; + font-size: 1.1rem; +} + +.intelligence-feature h4 { + font-family: var(--font-body); + font-weight: 700; + font-size: 0.95rem; + color: var(--color-dark); +} + +.intelligence-feature p { + font-size: 0.85rem; + margin-bottom: 0; + margin-top: 2px; +} + +.intelligence-visual { + position: relative; +} + +.intelligence-mockup { + width: 100%; + max-width: 500px; + margin: 0 auto; + background: var(--color-dark); + border-radius: var(--radius-xl); + padding: var(--space-lg); + min-height: 500px; + display: flex; + align-items: center; + justify-content: center; + position: relative; + overflow: hidden; +} + +.intelligence-mockup::before { + content: ''; + position: absolute; + width: 300px; + height: 300px; + background: radial-gradient(circle, var(--color-green) 0%, transparent 70%); + opacity: 0.3; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + filter: blur(60px); +} + +.mockup-text { + font-family: var(--font-display); + font-size: 2rem; + color: var(--color-cream); + text-align: center; + z-index: 1; + position: relative; +} + +.mockup-text em { + color: var(--color-green-light); + font-style: italic; +} + +/* ======================================== + CTA – "Join the Jungle" + ======================================== */ +.cta-section { + padding: var(--space-2xl) 0; + background: var(--color-cream); +} + +.cta-card { + background: var(--color-dark); + border-radius: var(--radius-xl); + padding: var(--space-xl); + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--space-lg); + align-items: center; + overflow: hidden; + position: relative; +} + +.cta-card::before { + content: ''; + position: absolute; + width: 400px; + height: 400px; + background: radial-gradient(circle, var(--color-green) 0%, transparent 70%); + opacity: 0.15; + top: -100px; + right: -100px; + filter: blur(80px); +} + +.cta-content { + position: relative; + z-index: 2; +} + +.cta-content h2 { + color: var(--color-cream); + margin-bottom: var(--space-sm); +} + +.cta-content h2 em { + font-style: italic; + color: var(--color-green-light); +} + +.cta-content p { + color: var(--color-text-light); + font-size: 1.05rem; + margin-bottom: var(--space-md); + line-height: 1.7; + max-width: 440px; +} + +.cta-metrics { + display: flex; + gap: var(--space-md); + margin-top: var(--space-md); +} + +.cta-metric { + text-align: left; +} + +.cta-metric-number { + font-family: var(--font-display); + font-size: 1.6rem; + font-weight: 900; + color: var(--color-accent); +} + +.cta-metric-label { + font-size: 0.75rem; + color: var(--color-text-light); +} + +.cta-actions { + position: relative; + z-index: 2; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: var(--space-md); +} + +.store-buttons { + display: flex; + gap: var(--space-sm); +} + +.store-btn { + display: inline-flex; + align-items: center; + gap: 0.6rem; + background: rgba(245, 242, 235, 0.1); + border: 1px solid rgba(245, 242, 235, 0.2); + color: var(--color-cream); + padding: 0.8rem 1.4rem; + border-radius: var(--radius-md); + font-size: 0.85rem; + font-weight: 500; + transition: background var(--transition), border-color var(--transition); +} + +.store-btn:hover { + background: rgba(245, 242, 235, 0.15); + border-color: rgba(245, 242, 235, 0.4); +} + +.store-btn-icon { + font-size: 1.4rem; +} + +.store-btn-text small { + display: block; + font-size: 0.65rem; + opacity: 0.7; +} + +.store-btn-text strong { + font-size: 0.9rem; +} + +/* ======================================== + FOOTER + ======================================== */ +.footer { + background: var(--color-dark); + padding: var(--space-xl) 0 var(--space-md); + color: var(--color-cream); +} + +.footer-top { + display: grid; + grid-template-columns: 1fr repeat(3, auto); + gap: var(--space-xl); + padding-bottom: var(--space-lg); + border-bottom: 1px solid rgba(245, 242, 235, 0.1); +} + +.footer-brand p { + color: var(--color-text-light); + font-size: 0.9rem; + margin-top: var(--space-sm); + max-width: 280px; + line-height: 1.7; +} + +.footer-col h4 { + font-family: var(--font-body); + font-size: 0.8rem; + font-weight: 700; + letter-spacing: 1px; + text-transform: uppercase; + color: var(--color-cream); + margin-bottom: var(--space-sm); +} + +.footer-col a { + display: block; + color: var(--color-text-light); + font-size: 0.85rem; + padding: 0.25rem 0; + transition: color var(--transition); +} + +.footer-col a:hover { + color: var(--color-cream); +} + +.footer-brand-large { + font-family: var(--font-display); + font-size: clamp(4rem, 10vw, 10rem); + font-weight: 900; + color: rgba(245, 242, 235, 0.06); + text-align: center; + line-height: 1; + padding: var(--space-lg) 0 var(--space-md); + user-select: none; + letter-spacing: -2px; +} + +.footer-bottom { + display: flex; + justify-content: space-between; + align-items: center; + padding-top: var(--space-sm); + border-top: 1px solid rgba(245, 242, 235, 0.06); +} + +.footer-bottom p { + font-size: 0.75rem; + color: var(--color-text-light); +} + +.footer-socials { + display: flex; + gap: var(--space-sm); +} + +.footer-social-link { + width: 36px; + height: 36px; + border-radius: 50%; + background: rgba(245, 242, 235, 0.08); + display: flex; + align-items: center; + justify-content: center; + font-size: 0.85rem; + color: var(--color-text-light); + transition: background var(--transition), color var(--transition); +} + +.footer-social-link:hover { + background: var(--color-accent); + color: var(--color-white); +} + +/* ======================================== + RESPONSIVE + ======================================== */ +@media (max-width: 1024px) { + .hero .container { + grid-template-columns: 1fr; + text-align: center; + } + + .hero-description { + margin: 0 auto var(--space-md); + } + + .hero-buttons { + justify-content: center; + } + + .hero-stats { + justify-content: center; + } + + .hero-video-wrapper { + max-width: 500px; + margin: var(--space-md) auto 0; + } + + .features-grid { + grid-template-columns: 1fr; + } + + .features-small { + grid-template-columns: 1fr; + } + + .intelligence .container { + grid-template-columns: 1fr; + } + + .intelligence-visual { + order: -1; + } + + .intelligence-mockup { + max-width: 350px; + min-height: 350px; + } + + .cta-card { + grid-template-columns: 1fr; + text-align: center; + } + + .cta-content p { + margin: 0 auto var(--space-md); + } + + .cta-metrics { + justify-content: center; + } + + .cta-actions { + align-items: center; + } + + .footer-top { + grid-template-columns: 1fr 1fr; + gap: var(--space-md); + } +} + +@media (max-width: 640px) { + .nav-links { + display: none; + } + + .nav-hamburger { + display: flex; + } + + .nav-links.active { + display: flex; + flex-direction: column; + position: absolute; + top: 100%; + left: 0; + right: 0; + background: rgba(26, 46, 31, 0.98); + backdrop-filter: blur(20px); + padding: var(--space-md); + gap: var(--space-sm); + } + + h1 { + font-size: 2.5rem; + } + + h2 { + font-size: 2rem; + } + + .hero { + padding: var(--space-xl) 0 var(--space-lg); + } + + .hero-stats { + flex-direction: column; + gap: var(--space-sm); + } + + .store-buttons { + flex-direction: column; + } + + .footer-top { + grid-template-columns: 1fr; + } + + .feature-card { + min-height: 300px; + } +} \ No newline at end of file diff --git a/metadata.json b/metadata.json deleted file mode 100644 index 8fbb427..0000000 --- a/metadata.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "GreenLens", - "description": "Eine faire, datenschutzfreundliche Pflanzen-Identifikations-App für den DACH-Markt. Offline-First und ohne Abo-Zwang.", - "requestFramePermissions": [ - "camera" - ] -} \ No newline at end of file diff --git a/metro.config.js b/metro.config.js new file mode 100644 index 0000000..25f43aa --- /dev/null +++ b/metro.config.js @@ -0,0 +1,13 @@ +const { getDefaultConfig } = require('expo/metro-config'); +const path = require('path'); + +const config = getDefaultConfig(__dirname); + +// Exclude server and landing page from the Metro bundle +config.resolver.blockList = [ + /server\/.*/, + /greenlns-landing\/.*/, + /landing\/.*/, +]; + +module.exports = config; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..009750b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,13558 @@ +{ + "name": "greenlens", + "version": "2.1.4", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "greenlens", + "version": "2.1.4", + "dependencies": { + "@expo/vector-icons": "^15.0.3", + "@google/genai": "^1.38.0", + "@react-native-async-storage/async-storage": "2.2.0", + "expo": "^54.0.33", + "expo-application": "~7.0.8", + "expo-asset": "~12.0.12", + "expo-av": "^16.0.8", + "expo-blur": "~15.0.8", + "expo-build-properties": "^55.0.9", + "expo-camera": "~17.0.10", + "expo-constants": "~18.0.13", + "expo-dev-client": "~6.0.20", + "expo-device": "~8.0.10", + "expo-file-system": "~19.0.21", + "expo-font": "~14.0.11", + "expo-haptics": "~15.0.8", + "expo-image-manipulator": "~14.0.8", + "expo-image-picker": "~17.0.10", + "expo-linking": "~8.0.11", + "expo-localization": "~17.0.8", + "expo-notifications": "~0.32.16", + "expo-router": "~6.0.23", + "expo-secure-store": "~15.0.8", + "expo-splash-screen": "~31.0.13", + "expo-sqlite": "~16.0.10", + "expo-status-bar": "~3.0.9", + "expo-updates": "~29.0.16", + "expo-video": "~3.0.16", + "posthog-react-native": "^4.37.1", + "react": "19.1.0", + "react-dom": "19.1.0", + "react-native": "0.81.5", + "react-native-gesture-handler": "~2.28.0", + "react-native-purchases": "^9.10.5", + "react-native-purchases-ui": "^9.10.5", + "react-native-reanimated": "~4.1.1", + "react-native-safe-area-context": "~5.6.0", + "react-native-screens": "~4.16.0", + "react-native-svg": "^15.12.1", + "react-native-web": "^0.21.2", + "react-native-worklets": "0.5.1" + }, + "devDependencies": { + "@babel/core": "^7.25.0", + "@testing-library/jest-native": "^5.4.3", + "@testing-library/react-native": "^13.3.3", + "@types/jest": "^29.5.14", + "@types/react": "~19.1.0", + "jest": "^29.7.0", + "jest-expo": "^54.0.17", + "typescript": "^5.3.0" + } + }, + "node_modules/@0no-co/graphql.web": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@0no-co/graphql.web/-/graphql.web-1.2.0.tgz", + "integrity": "sha512-/1iHy9TTr63gE1YcR5idjx8UREz1s0kFhydf3bBLCXyqjhkIc6igAzTOx3zPifCwFR87tsh/4Pa9cNts6d2otw==", + "license": "MIT", + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" + }, + "peerDependenciesMeta": { + "graphql": { + "optional": true + } + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", + "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", + "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "regexpu-core": "^6.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.6.tgz", + "integrity": "sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.11" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", + "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-wrap-function": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", + "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", + "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz", + "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.29.0.tgz", + "integrity": "sha512-CVBVv3VY/XRMxRYq5dwr2DS7/MvqPm23cOCjbwNnVrfOqcWlnefua1uUs0sjdKOGjvPUG633o07uWzJq4oI6dA==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-syntax-decorators": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-default-from": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.27.1.tgz", + "integrity": "sha512-hjlsMBl1aJc5lp8MoCDEZCiYzlgdRAShOjAfRw6X+GlpLpUPU7c3XNLsKFZbQk/1cRzBlJ7CXg3xJAJMrFa1Uw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.28.6.tgz", + "integrity": "sha512-71EYI0ONURHJBL4rSFXnITXqXrrY8q4P0q006DPfN+Rk+ASM+++IBXem/ruokgBZR8YNEWZ8R6B+rCb8VcUTqA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-default-from": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.28.6.tgz", + "integrity": "sha512-Svlx1fjJFnNz0LZeUaybRukSxZI3KkpApUmIRzEdXC5k8ErTOz0OD0kNrICi5Vc3GlpP5ZCeRyRO+mfWTSz+iQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.28.6.tgz", + "integrity": "sha512-D+OrJumc9McXNEBI/JmFnc/0uCM2/Y3PEBG3gfV3QIYkKv5pvnpzFrl1kYCrcHJP8nOeFB/SHi1IHz29pNGuew==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", + "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.0.tgz", + "integrity": "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-remap-async-to-generator": "^7.27.1", + "@babel/traverse": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", + "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-remap-async-to-generator": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", + "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", + "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", + "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", + "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-globals": "^7.28.0", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-replace-supers": "^7.28.6", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", + "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/template": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", + "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", + "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.27.1.tgz", + "integrity": "sha512-G5eDKsu50udECw7DL2AcsysXiQyB7Nfg521t2OAJ4tbfTJ27doHLeF/vlI1NZGlLdbb/v+ibvtL1YBQqYOwJGg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-flow": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", + "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", + "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", + "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", + "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", + "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.0.tgz", + "integrity": "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", + "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", + "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", + "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", + "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", + "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", + "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", + "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", + "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz", + "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.28.6.tgz", + "integrity": "sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-syntax-jsx": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz", + "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", + "license": "MIT", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz", + "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.0.tgz", + "integrity": "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.29.0.tgz", + "integrity": "sha512-jlaRT5dJtMaMCV6fAuLbsQMSwz/QkvaHOHOSXRitGGwSpR1blCY4KUKoyP2tYO8vJcqYe8cEj96cqSztv3uF9w==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", + "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", + "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", + "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", + "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.6.tgz", + "integrity": "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", + "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.28.5.tgz", + "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-transform-react-display-name": "^7.28.0", + "@babel/plugin-transform-react-jsx": "^7.27.1", + "@babel/plugin-transform-react-jsx-development": "^7.27.1", + "@babel/plugin-transform-react-pure-annotations": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz", + "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse--for-generate-function-map": { + "name": "@babel/traverse", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@egjs/hammerjs": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", + "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", + "license": "MIT", + "dependencies": { + "@types/hammerjs": "^2.0.36" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@expo/cli": { + "version": "54.0.23", + "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-54.0.23.tgz", + "integrity": "sha512-km0h72SFfQCmVycH/JtPFTVy69w6Lx1cHNDmfLfQqgKFYeeHTjx7LVDP4POHCtNxFP2UeRazrygJhlh4zz498g==", + "license": "MIT", + "dependencies": { + "@0no-co/graphql.web": "^1.0.8", + "@expo/code-signing-certificates": "^0.0.6", + "@expo/config": "~12.0.13", + "@expo/config-plugins": "~54.0.4", + "@expo/devcert": "^1.2.1", + "@expo/env": "~2.0.8", + "@expo/image-utils": "^0.8.8", + "@expo/json-file": "^10.0.8", + "@expo/metro": "~54.2.0", + "@expo/metro-config": "~54.0.14", + "@expo/osascript": "^2.3.8", + "@expo/package-manager": "^1.9.10", + "@expo/plist": "^0.4.8", + "@expo/prebuild-config": "^54.0.8", + "@expo/schema-utils": "^0.1.8", + "@expo/spawn-async": "^1.7.2", + "@expo/ws-tunnel": "^1.0.1", + "@expo/xcpretty": "^4.3.0", + "@react-native/dev-middleware": "0.81.5", + "@urql/core": "^5.0.6", + "@urql/exchange-retry": "^1.3.0", + "accepts": "^1.3.8", + "arg": "^5.0.2", + "better-opn": "~3.0.2", + "bplist-creator": "0.1.0", + "bplist-parser": "^0.3.1", + "chalk": "^4.0.0", + "ci-info": "^3.3.0", + "compression": "^1.7.4", + "connect": "^3.7.0", + "debug": "^4.3.4", + "env-editor": "^0.4.1", + "expo-server": "^1.0.5", + "freeport-async": "^2.0.0", + "getenv": "^2.0.0", + "glob": "^13.0.0", + "lan-network": "^0.1.6", + "minimatch": "^9.0.0", + "node-forge": "^1.3.3", + "npm-package-arg": "^11.0.0", + "ora": "^3.4.0", + "picomatch": "^3.0.1", + "pretty-bytes": "^5.6.0", + "pretty-format": "^29.7.0", + "progress": "^2.0.3", + "prompts": "^2.3.2", + "qrcode-terminal": "0.11.0", + "require-from-string": "^2.0.2", + "requireg": "^0.2.2", + "resolve": "^1.22.2", + "resolve-from": "^5.0.0", + "resolve.exports": "^2.0.3", + "semver": "^7.6.0", + "send": "^0.19.0", + "slugify": "^1.3.4", + "source-map-support": "~0.5.21", + "stacktrace-parser": "^0.1.10", + "structured-headers": "^0.4.1", + "tar": "^7.5.2", + "terminal-link": "^2.1.1", + "undici": "^6.18.2", + "wrap-ansi": "^7.0.0", + "ws": "^8.12.1" + }, + "bin": { + "expo-internal": "build/bin/cli" + }, + "peerDependencies": { + "expo": "*", + "expo-router": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "expo-router": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/@expo/cli/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/code-signing-certificates": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@expo/code-signing-certificates/-/code-signing-certificates-0.0.6.tgz", + "integrity": "sha512-iNe0puxwBNEcuua9gmTGzq+SuMDa0iATai1FlFTMHJ/vUmKvN/V//drXoLJkVb5i5H3iE/n/qIJxyoBnXouD0w==", + "license": "MIT", + "dependencies": { + "node-forge": "^1.3.3" + } + }, + "node_modules/@expo/config": { + "version": "12.0.13", + "resolved": "https://registry.npmjs.org/@expo/config/-/config-12.0.13.tgz", + "integrity": "sha512-Cu52arBa4vSaupIWsF0h7F/Cg//N374nYb7HAxV0I4KceKA7x2UXpYaHOL7EEYYvp7tZdThBjvGpVmr8ScIvaQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "~7.10.4", + "@expo/config-plugins": "~54.0.4", + "@expo/config-types": "^54.0.10", + "@expo/json-file": "^10.0.8", + "deepmerge": "^4.3.1", + "getenv": "^2.0.0", + "glob": "^13.0.0", + "require-from-string": "^2.0.2", + "resolve-from": "^5.0.0", + "resolve-workspace-root": "^2.0.0", + "semver": "^7.6.0", + "slugify": "^1.3.4", + "sucrase": "~3.35.1" + } + }, + "node_modules/@expo/config-plugins": { + "version": "54.0.4", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-54.0.4.tgz", + "integrity": "sha512-g2yXGICdoOw5i3LkQSDxl2Q5AlQCrG7oniu0pCPPO+UxGb7He4AFqSvPSy8HpRUj55io17hT62FTjYRD+d6j3Q==", + "license": "MIT", + "dependencies": { + "@expo/config-types": "^54.0.10", + "@expo/json-file": "~10.0.8", + "@expo/plist": "^0.4.8", + "@expo/sdk-runtime-versions": "^1.0.0", + "chalk": "^4.1.2", + "debug": "^4.3.5", + "getenv": "^2.0.0", + "glob": "^13.0.0", + "resolve-from": "^5.0.0", + "semver": "^7.5.4", + "slash": "^3.0.0", + "slugify": "^1.6.6", + "xcode": "^3.0.1", + "xml2js": "0.6.0" + } + }, + "node_modules/@expo/config-plugins/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/config-types": { + "version": "54.0.10", + "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-54.0.10.tgz", + "integrity": "sha512-/J16SC2an1LdtCZ67xhSkGXpALYUVUNyZws7v+PVsFZxClYehDSoKLqyRaGkpHlYrCc08bS0RF5E0JV6g50psA==", + "license": "MIT" + }, + "node_modules/@expo/config/node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@expo/config/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/devcert": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@expo/devcert/-/devcert-1.2.1.tgz", + "integrity": "sha512-qC4eaxmKMTmJC2ahwyui6ud8f3W60Ss7pMkpBq40Hu3zyiAaugPXnZ24145U7K36qO9UHdZUVxsCvIpz2RYYCA==", + "license": "MIT", + "dependencies": { + "@expo/sudo-prompt": "^9.3.1", + "debug": "^3.1.0" + } + }, + "node_modules/@expo/devcert/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@expo/devtools": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@expo/devtools/-/devtools-0.1.8.tgz", + "integrity": "sha512-SVLxbuanDjJPgc0sy3EfXUMLb/tXzp6XIHkhtPVmTWJAp+FOr6+5SeiCfJrCzZFet0Ifyke2vX3sFcKwEvCXwQ==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/@expo/env": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@expo/env/-/env-2.0.8.tgz", + "integrity": "sha512-5VQD6GT8HIMRaSaB5JFtOXuvfDVU80YtZIuUT/GDhUF782usIXY13Tn3IdDz1Tm/lqA9qnRZQ1BF4t7LlvdJPA==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "debug": "^4.3.4", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "getenv": "^2.0.0" + } + }, + "node_modules/@expo/fingerprint": { + "version": "0.15.4", + "resolved": "https://registry.npmjs.org/@expo/fingerprint/-/fingerprint-0.15.4.tgz", + "integrity": "sha512-eYlxcrGdR2/j2M6pEDXo9zU9KXXF1vhP+V+Tl+lyY+bU8lnzrN6c637mz6Ye3em2ANy8hhUR03Raf8VsT9Ogng==", + "license": "MIT", + "dependencies": { + "@expo/spawn-async": "^1.7.2", + "arg": "^5.0.2", + "chalk": "^4.1.2", + "debug": "^4.3.4", + "getenv": "^2.0.0", + "glob": "^13.0.0", + "ignore": "^5.3.1", + "minimatch": "^9.0.0", + "p-limit": "^3.1.0", + "resolve-from": "^5.0.0", + "semver": "^7.6.0" + }, + "bin": { + "fingerprint": "bin/cli.js" + } + }, + "node_modules/@expo/fingerprint/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/image-utils": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.8.8.tgz", + "integrity": "sha512-HHHaG4J4nKjTtVa1GG9PCh763xlETScfEyNxxOvfTRr8IKPJckjTyqSLEtdJoFNJ1vqiABEjW7tqGhqGibZLeA==", + "license": "MIT", + "dependencies": { + "@expo/spawn-async": "^1.7.2", + "chalk": "^4.0.0", + "getenv": "^2.0.0", + "jimp-compact": "0.16.1", + "parse-png": "^2.1.0", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0", + "semver": "^7.6.0", + "temp-dir": "~2.0.0", + "unique-string": "~2.0.0" + } + }, + "node_modules/@expo/image-utils/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/json-file": { + "version": "10.0.8", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-10.0.8.tgz", + "integrity": "sha512-9LOTh1PgKizD1VXfGQ88LtDH0lRwq9lsTb4aichWTWSWqy3Ugfkhfm3BhzBIkJJfQQ5iJu3m/BoRlEIjoCGcnQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "~7.10.4", + "json5": "^2.2.3" + } + }, + "node_modules/@expo/json-file/node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@expo/metro": { + "version": "54.2.0", + "resolved": "https://registry.npmjs.org/@expo/metro/-/metro-54.2.0.tgz", + "integrity": "sha512-h68TNZPGsk6swMmLm9nRSnE2UXm48rWwgcbtAHVMikXvbxdS41NDHHeqg1rcQ9AbznDRp6SQVC2MVpDnsRKU1w==", + "license": "MIT", + "dependencies": { + "metro": "0.83.3", + "metro-babel-transformer": "0.83.3", + "metro-cache": "0.83.3", + "metro-cache-key": "0.83.3", + "metro-config": "0.83.3", + "metro-core": "0.83.3", + "metro-file-map": "0.83.3", + "metro-minify-terser": "0.83.3", + "metro-resolver": "0.83.3", + "metro-runtime": "0.83.3", + "metro-source-map": "0.83.3", + "metro-symbolicate": "0.83.3", + "metro-transform-plugins": "0.83.3", + "metro-transform-worker": "0.83.3" + } + }, + "node_modules/@expo/metro-config": { + "version": "54.0.14", + "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-54.0.14.tgz", + "integrity": "sha512-hxpLyDfOR4L23tJ9W1IbJJsG7k4lv2sotohBm/kTYyiG+pe1SYCAWsRmgk+H42o/wWf/HQjE5k45S5TomGLxNA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.20.0", + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.5", + "@expo/config": "~12.0.13", + "@expo/env": "~2.0.8", + "@expo/json-file": "~10.0.8", + "@expo/metro": "~54.2.0", + "@expo/spawn-async": "^1.7.2", + "browserslist": "^4.25.0", + "chalk": "^4.1.0", + "debug": "^4.3.2", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "getenv": "^2.0.0", + "glob": "^13.0.0", + "hermes-parser": "^0.29.1", + "jsc-safe-url": "^0.2.4", + "lightningcss": "^1.30.1", + "minimatch": "^9.0.0", + "postcss": "~8.4.32", + "resolve-from": "^5.0.0" + }, + "peerDependencies": { + "expo": "*" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true + } + } + }, + "node_modules/@expo/metro-runtime": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@expo/metro-runtime/-/metro-runtime-6.1.2.tgz", + "integrity": "sha512-nvM+Qv45QH7pmYvP8JB1G8JpScrWND3KrMA6ZKe62cwwNiX/BjHU28Ear0v/4bQWXlOY0mv6B8CDIm8JxXde9g==", + "license": "MIT", + "dependencies": { + "anser": "^1.4.9", + "pretty-format": "^29.7.0", + "stacktrace-parser": "^0.1.10", + "whatwg-fetch": "^3.0.0" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-dom": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/@expo/osascript": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.3.8.tgz", + "integrity": "sha512-/TuOZvSG7Nn0I8c+FcEaoHeBO07yu6vwDgk7rZVvAXoeAK5rkA09jRyjYsZo+0tMEFaToBeywA6pj50Mb3ny9w==", + "license": "MIT", + "dependencies": { + "@expo/spawn-async": "^1.7.2", + "exec-async": "^2.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@expo/package-manager": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@expo/package-manager/-/package-manager-1.9.10.tgz", + "integrity": "sha512-axJm+NOj3jVxep49va/+L3KkF3YW/dkV+RwzqUJedZrv4LeTqOG4rhrCaCPXHTvLqCTDKu6j0Xyd28N7mnxsGA==", + "license": "MIT", + "dependencies": { + "@expo/json-file": "^10.0.8", + "@expo/spawn-async": "^1.7.2", + "chalk": "^4.0.0", + "npm-package-arg": "^11.0.0", + "ora": "^3.4.0", + "resolve-workspace-root": "^2.0.0" + } + }, + "node_modules/@expo/plist": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.4.8.tgz", + "integrity": "sha512-pfNtErGGzzRwHP+5+RqswzPDKkZrx+Cli0mzjQaus1ZWFsog5ibL+nVT3NcporW51o8ggnt7x813vtRbPiyOrQ==", + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.8.8", + "base64-js": "^1.2.3", + "xmlbuilder": "^15.1.1" + } + }, + "node_modules/@expo/prebuild-config": { + "version": "54.0.8", + "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-54.0.8.tgz", + "integrity": "sha512-EA7N4dloty2t5Rde+HP0IEE+nkAQiu4A/+QGZGT9mFnZ5KKjPPkqSyYcRvP5bhQE10D+tvz6X0ngZpulbMdbsg==", + "license": "MIT", + "dependencies": { + "@expo/config": "~12.0.13", + "@expo/config-plugins": "~54.0.4", + "@expo/config-types": "^54.0.10", + "@expo/image-utils": "^0.8.8", + "@expo/json-file": "^10.0.8", + "@react-native/normalize-colors": "0.81.5", + "debug": "^4.3.1", + "resolve-from": "^5.0.0", + "semver": "^7.6.0", + "xml2js": "0.6.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/@expo/prebuild-config/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/schema-utils": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@expo/schema-utils/-/schema-utils-0.1.8.tgz", + "integrity": "sha512-9I6ZqvnAvKKDiO+ZF8BpQQFYWXOJvTAL5L/227RUbWG1OVZDInFifzCBiqAZ3b67NRfeAgpgvbA7rejsqhY62A==", + "license": "MIT" + }, + "node_modules/@expo/sdk-runtime-versions": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@expo/sdk-runtime-versions/-/sdk-runtime-versions-1.0.0.tgz", + "integrity": "sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ==", + "license": "MIT" + }, + "node_modules/@expo/spawn-async": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@expo/spawn-async/-/spawn-async-1.7.2.tgz", + "integrity": "sha512-QdWi16+CHB9JYP7gma19OVVg0BFkvU8zNj9GjWorYI8Iv8FUxjOCcYRuAmX4s/h91e4e7BPsskc8cSrZYho9Ew==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@expo/sudo-prompt": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/@expo/sudo-prompt/-/sudo-prompt-9.3.2.tgz", + "integrity": "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==", + "license": "MIT" + }, + "node_modules/@expo/vector-icons": { + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-15.0.3.tgz", + "integrity": "sha512-SBUyYKphmlfUBqxSfDdJ3jAdEVSALS2VUPOUyqn48oZmb2TL/O7t7/PQm5v4NQujYEPLPMTLn9KVw6H7twwbTA==", + "license": "MIT", + "peerDependencies": { + "expo-font": ">=14.0.4", + "react": "*", + "react-native": "*" + } + }, + "node_modules/@expo/ws-tunnel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@expo/ws-tunnel/-/ws-tunnel-1.0.6.tgz", + "integrity": "sha512-nDRbLmSrJar7abvUjp3smDwH8HcbZcoOEa5jVPUv9/9CajgmWw20JNRwTuBRzWIWIkEJDkz20GoNA+tSwUqk0Q==", + "license": "MIT" + }, + "node_modules/@expo/xcpretty": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@expo/xcpretty/-/xcpretty-4.4.0.tgz", + "integrity": "sha512-o2qDlTqJ606h4xR36H2zWTywmZ3v3842K6TU8Ik2n1mfW0S580VHlt3eItVYdLYz+klaPp7CXqanja8eASZjRw==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/code-frame": "^7.20.0", + "chalk": "^4.1.0", + "js-yaml": "^4.1.0" + }, + "bin": { + "excpretty": "build/cli.js" + } + }, + "node_modules/@google/genai": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.40.0.tgz", + "integrity": "sha512-fhIww8smT0QYRX78qWOiz/nIQhHMF5wXOrlXvj33HBrz3vKDBb+wibLcEmTA+L9dmPD4KmfNr7UF3LDQVTXNjA==", + "license": "Apache-2.0", + "dependencies": { + "google-auth-library": "^10.3.0", + "protobufjs": "^7.5.4", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.25.2" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, + "node_modules/@ide/backoff": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@ide/backoff/-/backoff-1.0.0.tgz", + "integrity": "sha512-F0YfUDjvT+Mtt/R4xdl2X0EYCHMMiJqNLdxHD++jDT5ydEFIyqbCHh51Qx2E211dgZprPKhV7sHmnXKpLuvc5g==", + "license": "MIT" + }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz", + "integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==", + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/create-cache-key-function": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", + "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/diff-sequences": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/get-type": { + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", + "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "devOptional": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "devOptional": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@jest/reporters/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/reporters/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@posthog/core": { + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.23.2.tgz", + "integrity": "sha512-zTDdda9NuSHrnwSOfFMxX/pyXiycF4jtU1kTr8DL61dHhV+7LF6XF1ndRZZTuaGGbfbb/GJYkEsjEX9SXfNZeQ==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.6" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", + "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", + "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", + "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", + "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.0.tgz", + "integrity": "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz", + "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@react-native-async-storage/async-storage": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-2.2.0.tgz", + "integrity": "sha512-gvRvjR5JAaUZF8tv2Kcq/Gbt3JHwbKFYfmb445rhOj6NUMx3qPLixmDx5pZAyb9at1bYvJ4/eTUipU5aki45xw==", + "license": "MIT", + "dependencies": { + "merge-options": "^3.0.4" + }, + "peerDependencies": { + "react-native": "^0.0.0-0 || >=0.65 <1.0" + } + }, + "node_modules/@react-native/assets-registry": { + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.81.5.tgz", + "integrity": "sha512-705B6x/5Kxm1RKRvSv0ADYWm5JOnoiQ1ufW7h8uu2E6G9Of/eE6hP/Ivw3U5jI16ERqZxiKQwk34VJbB0niX9w==", + "license": "MIT", + "engines": { + "node": ">= 20.19.4" + } + }, + "node_modules/@react-native/babel-plugin-codegen": { + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.81.5.tgz", + "integrity": "sha512-oF71cIH6je3fSLi6VPjjC3Sgyyn57JLHXs+mHWc9MoCiJJcM4nqsS5J38zv1XQ8d3zOW2JtHro+LF0tagj2bfQ==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.3", + "@react-native/codegen": "0.81.5" + }, + "engines": { + "node": ">= 20.19.4" + } + }, + "node_modules/@react-native/babel-preset": { + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.81.5.tgz", + "integrity": "sha512-UoI/x/5tCmi+pZ3c1+Ypr1DaRMDLI3y+Q70pVLLVgrnC3DHsHRIbHcCHIeG/IJvoeFqFM2sTdhSOLJrf8lOPrA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/plugin-proposal-export-default-from": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-default-from": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.4", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.25.4", + "@babel/plugin-transform-classes": "^7.25.4", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-flow-strip-types": "^7.25.2", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.25.2", + "@babel/plugin-transform-react-jsx-self": "^7.24.7", + "@babel/plugin-transform-react-jsx-source": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-runtime": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.25.2", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/template": "^7.25.0", + "@react-native/babel-plugin-codegen": "0.81.5", + "babel-plugin-syntax-hermes-parser": "0.29.1", + "babel-plugin-transform-flow-enums": "^0.0.2", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": ">= 20.19.4" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/codegen": { + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.81.5.tgz", + "integrity": "sha512-a2TDA03Up8lpSa9sh5VRGCQDXgCTOyDOFH+aqyinxp1HChG8uk89/G+nkJ9FPd0rqgi25eCTR16TWdS3b+fA6g==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/parser": "^7.25.3", + "glob": "^7.1.1", + "hermes-parser": "0.29.1", + "invariant": "^2.2.4", + "nullthrows": "^1.1.1", + "yargs": "^17.6.2" + }, + "engines": { + "node": ">= 20.19.4" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/codegen/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@react-native/codegen/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@react-native/codegen/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@react-native/community-cli-plugin": { + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.81.5.tgz", + "integrity": "sha512-yWRlmEOtcyvSZ4+OvqPabt+NS36vg0K/WADTQLhrYrm9qdZSuXmq8PmdJWz/68wAqKQ+4KTILiq2kjRQwnyhQw==", + "license": "MIT", + "dependencies": { + "@react-native/dev-middleware": "0.81.5", + "debug": "^4.4.0", + "invariant": "^2.2.4", + "metro": "^0.83.1", + "metro-config": "^0.83.1", + "metro-core": "^0.83.1", + "semver": "^7.1.3" + }, + "engines": { + "node": ">= 20.19.4" + }, + "peerDependencies": { + "@react-native-community/cli": "*", + "@react-native/metro-config": "*" + }, + "peerDependenciesMeta": { + "@react-native-community/cli": { + "optional": true + }, + "@react-native/metro-config": { + "optional": true + } + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native/debugger-frontend": { + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.81.5.tgz", + "integrity": "sha512-bnd9FSdWKx2ncklOetCgrlwqSGhMHP2zOxObJbOWXoj7GHEmih4MKarBo5/a8gX8EfA1EwRATdfNBQ81DY+h+w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 20.19.4" + } + }, + "node_modules/@react-native/dev-middleware": { + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.81.5.tgz", + "integrity": "sha512-WfPfZzboYgo/TUtysuD5xyANzzfka8Ebni6RIb2wDxhb56ERi7qDrE4xGhtPsjCL4pQBXSVxyIlCy0d8I6EgGA==", + "license": "MIT", + "dependencies": { + "@isaacs/ttlcache": "^1.4.1", + "@react-native/debugger-frontend": "0.81.5", + "chrome-launcher": "^0.15.2", + "chromium-edge-launcher": "^0.2.0", + "connect": "^3.6.5", + "debug": "^4.4.0", + "invariant": "^2.2.4", + "nullthrows": "^1.1.1", + "open": "^7.0.3", + "serve-static": "^1.16.2", + "ws": "^6.2.3" + }, + "engines": { + "node": ">= 20.19.4" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/@react-native/gradle-plugin": { + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.81.5.tgz", + "integrity": "sha512-hORRlNBj+ReNMLo9jme3yQ6JQf4GZpVEBLxmTXGGlIL78MAezDZr5/uq9dwElSbcGmLEgeiax6e174Fie6qPLg==", + "license": "MIT", + "engines": { + "node": ">= 20.19.4" + } + }, + "node_modules/@react-native/js-polyfills": { + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.81.5.tgz", + "integrity": "sha512-fB7M1CMOCIUudTRuj7kzxIBTVw2KXnsgbQ6+4cbqSxo8NmRRhA0Ul4ZUzZj3rFd3VznTL4Brmocv1oiN0bWZ8w==", + "license": "MIT", + "engines": { + "node": ">= 20.19.4" + } + }, + "node_modules/@react-native/normalize-colors": { + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.81.5.tgz", + "integrity": "sha512-0HuJ8YtqlTVRXGZuGeBejLE04wSQsibpTI+RGOyVqxZvgtlLLC/Ssw0UmbHhT4lYMp2fhdtvKZSs5emWB1zR/g==", + "license": "MIT" + }, + "node_modules/@react-native/virtualized-lists": { + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.81.5.tgz", + "integrity": "sha512-UVXgV/db25OPIvwZySeToXD/9sKKhOdkcWmmf4Jh8iBZuyfML+/5CasaZ1E7Lqg6g3uqVQq75NqIwkYmORJMPw==", + "license": "MIT", + "dependencies": { + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 20.19.4" + }, + "peerDependencies": { + "@types/react": "^19.1.0", + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@react-navigation/bottom-tabs": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-7.12.0.tgz", + "integrity": "sha512-/GtOfVWRligHG0mvX39I1FGdUWeWl0GVF2okEziQSQj0bOTrLIt7y44C3r/aCLkEpTVltCPGM3swqGTH3UfRCw==", + "license": "MIT", + "dependencies": { + "@react-navigation/elements": "^2.9.5", + "color": "^4.2.3", + "sf-symbols-typescript": "^2.1.0" + }, + "peerDependencies": { + "@react-navigation/native": "^7.1.28", + "react": ">= 18.2.0", + "react-native": "*", + "react-native-safe-area-context": ">= 4.0.0", + "react-native-screens": ">= 4.0.0" + } + }, + "node_modules/@react-navigation/core": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-7.14.0.tgz", + "integrity": "sha512-tMpzskBzVp0E7CRNdNtJIdXjk54Kwe/TF9ViXAef+YFM1kSfGv4e/B2ozfXE+YyYgmh4WavTv8fkdJz1CNyu+g==", + "license": "MIT", + "dependencies": { + "@react-navigation/routers": "^7.5.3", + "escape-string-regexp": "^4.0.0", + "fast-deep-equal": "^3.1.3", + "nanoid": "^3.3.11", + "query-string": "^7.1.3", + "react-is": "^19.1.0", + "use-latest-callback": "^0.2.4", + "use-sync-external-store": "^1.5.0" + }, + "peerDependencies": { + "react": ">= 18.2.0" + } + }, + "node_modules/@react-navigation/elements": { + "version": "2.9.5", + "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-2.9.5.tgz", + "integrity": "sha512-iHZU8rRN1014Upz73AqNVXDvSMZDh5/ktQ1CMe21rdgnOY79RWtHHBp9qOS3VtqlUVYGkuX5GEw5mDt4tKdl0g==", + "license": "MIT", + "dependencies": { + "color": "^4.2.3", + "use-latest-callback": "^0.2.4", + "use-sync-external-store": "^1.5.0" + }, + "peerDependencies": { + "@react-native-masked-view/masked-view": ">= 0.2.0", + "@react-navigation/native": "^7.1.28", + "react": ">= 18.2.0", + "react-native": "*", + "react-native-safe-area-context": ">= 4.0.0" + }, + "peerDependenciesMeta": { + "@react-native-masked-view/masked-view": { + "optional": true + } + } + }, + "node_modules/@react-navigation/native": { + "version": "7.1.28", + "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.1.28.tgz", + "integrity": "sha512-d1QDn+KNHfHGt3UIwOZvupvdsDdiHYZBEj7+wL2yDVo3tMezamYy60H9s3EnNVE1Ae1ty0trc7F2OKqo/RmsdQ==", + "license": "MIT", + "dependencies": { + "@react-navigation/core": "^7.14.0", + "escape-string-regexp": "^4.0.0", + "fast-deep-equal": "^3.1.3", + "nanoid": "^3.3.11", + "use-latest-callback": "^0.2.4" + }, + "peerDependencies": { + "react": ">= 18.2.0", + "react-native": "*" + } + }, + "node_modules/@react-navigation/native-stack": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-7.12.0.tgz", + "integrity": "sha512-XmNJsPshjkNsahgbxNgGWQUq4s1l6HqH/Fei4QsjBNn/0mTvVrRVZwJ1XrY9YhWYvyiYkAN6/OmarWQaQJ0otQ==", + "license": "MIT", + "dependencies": { + "@react-navigation/elements": "^2.9.5", + "color": "^4.2.3", + "sf-symbols-typescript": "^2.1.0", + "warn-once": "^0.1.1" + }, + "peerDependencies": { + "@react-navigation/native": "^7.1.28", + "react": ">= 18.2.0", + "react-native": "*", + "react-native-safe-area-context": ">= 4.0.0", + "react-native-screens": ">= 4.0.0" + } + }, + "node_modules/@react-navigation/routers": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-7.5.3.tgz", + "integrity": "sha512-1tJHg4KKRJuQ1/EvJxatrMef3NZXEPzwUIUZ3n1yJ2t7Q97siwRtbynRpQG9/69ebbtiZ8W3ScOZF/OmhvM4Rg==", + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11" + } + }, + "node_modules/@revenuecat/purchases-js": { + "version": "1.26.2", + "resolved": "https://registry.npmjs.org/@revenuecat/purchases-js/-/purchases-js-1.26.2.tgz", + "integrity": "sha512-10k0LL3cmlxe9gN2GfXBLmLR3ZtnQN7wKpDxzJn/JtRSC0Sq12+/msCIuAiBYRP1CKJv8JAVVEyvYufMDqVf9A==", + "license": "MIT" + }, + "node_modules/@revenuecat/purchases-js-hybrid-mappings": { + "version": "17.41.1", + "resolved": "https://registry.npmjs.org/@revenuecat/purchases-js-hybrid-mappings/-/purchases-js-hybrid-mappings-17.41.1.tgz", + "integrity": "sha512-00T+PXH/2S3T8VmdOH1XZeC2OhIYWxw7YCOAssVHxxorU8JExowE7mlDcMOIb6lFCjAXQBj6t65TxmlHlkW3PA==", + "license": "MIT", + "dependencies": { + "@revenuecat/purchases-js": "1.26.2" + } + }, + "node_modules/@revenuecat/purchases-typescript-internal": { + "version": "17.41.1", + "resolved": "https://registry.npmjs.org/@revenuecat/purchases-typescript-internal/-/purchases-typescript-internal-17.41.1.tgz", + "integrity": "sha512-npyMpQPTcGjXpP8n5NQ4W6N0nc+zTXpb0HSQo6HL+3jNj2eH00EgS/Bzm0wOBtvQAjqINjl0q+Dl6ru/PCZxpw==", + "license": "MIT" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@testing-library/jest-native": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@testing-library/jest-native/-/jest-native-5.4.3.tgz", + "integrity": "sha512-/sSDGaOuE+PJ1Z9Kp4u7PQScSVVXGud59I/qsBFFJvIbcn4P6yYw6cBnBmbPF+X9aRIsTJRDl6gzw5ZkJNm66w==", + "deprecated": "DEPRECATED: This package is no longer maintained.\nPlease use the built-in Jest matchers available in @testing-library/react-native v12.4+.\n\nSee migration guide: https://callstack.github.io/react-native-testing-library/docs/migration/jest-matchers", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "jest-diff": "^29.0.1", + "jest-matcher-utils": "^29.0.1", + "pretty-format": "^29.0.3", + "redent": "^3.0.0" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-native": ">=0.59", + "react-test-renderer": ">=16.0.0" + } + }, + "node_modules/@testing-library/react-native": { + "version": "13.3.3", + "resolved": "https://registry.npmjs.org/@testing-library/react-native/-/react-native-13.3.3.tgz", + "integrity": "sha512-k6Mjsd9dbZgvY4Bl7P1NIpePQNi+dfYtlJ5voi9KQlynxSyQkfOgJmYGCYmw/aSgH/rUcFvG8u5gd4npzgRDyg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "jest-matcher-utils": "^30.0.5", + "picocolors": "^1.1.1", + "pretty-format": "^30.0.5", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "jest": ">=29.0.0", + "react": ">=18.2.0", + "react-native": ">=0.71", + "react-test-renderer": ">=18.2.0" + }, + "peerDependenciesMeta": { + "jest": { + "optional": true + } + } + }, + "node_modules/@testing-library/react-native/node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@testing-library/react-native/node_modules/@sinclair/typebox": { + "version": "0.34.48", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.48.tgz", + "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@testing-library/react-native/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/react-native/node_modules/jest-diff": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@testing-library/react-native/node_modules/jest-matcher-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", + "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.2.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@testing-library/react-native/node_modules/pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@testing-library/react-native/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/hammerjs": { + "version": "2.0.46", + "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.46.tgz", + "integrity": "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw==", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/jsdom": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, + "node_modules/@types/node": { + "version": "25.2.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.2.tgz", + "integrity": "sha512-BkmoP5/FhRYek5izySdkOneRyXYN35I860MFAGupTdebyE66uZaR+bXLHq8k4DirE5DwQi3NuhvRU1jqTVwUrQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/react": { + "version": "19.1.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.17.tgz", + "integrity": "sha512-Qec1E3mhALmaspIrhWt9jkQMNdw6bReVu64mjvhbhq2NFPftLPVr+l1SZgmw/66WwBNpDh7ao5AT6gF5v41PFA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "license": "MIT" + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" + }, + "node_modules/@urql/core": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@urql/core/-/core-5.2.0.tgz", + "integrity": "sha512-/n0ieD0mvvDnVAXEQgX/7qJiVcvYvNkOHeBvkwtylfjydar123caCXcl58PXFY11oU1oquJocVXHxLAbtv4x1A==", + "license": "MIT", + "dependencies": { + "@0no-co/graphql.web": "^1.0.13", + "wonka": "^6.3.2" + } + }, + "node_modules/@urql/exchange-retry": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@urql/exchange-retry/-/exchange-retry-1.3.2.tgz", + "integrity": "sha512-TQMCz2pFJMfpNxmSfX1VSfTjwUIFx/mL+p1bnfM1xjjdla7Z+KnGMW/EhFbpckp3LyWAH4PgOsMwOMnIN+MBFg==", + "license": "MIT", + "dependencies": { + "@urql/core": "^5.1.2", + "wonka": "^6.3.2" + }, + "peerDependencies": { + "@urql/core": "^5.0.0" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", + "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/anser": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", + "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==", + "license": "MIT" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" + }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/await-lock": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz", + "integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==", + "license": "MIT" + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.15.tgz", + "integrity": "sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.6", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.6.tgz", + "integrity": "sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.6" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-react-compiler": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-1.0.0.tgz", + "integrity": "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.26.0" + } + }, + "node_modules/babel-plugin-react-native-web": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.21.2.tgz", + "integrity": "sha512-SPD0J6qjJn8231i0HZhlAGH6NORe+QvRSQM2mwQEzJ2Fb3E4ruWTiiicPlHjmeWShDXLcvoorOCXjeR7k/lyWA==", + "license": "MIT" + }, + "node_modules/babel-plugin-syntax-hermes-parser": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.29.1.tgz", + "integrity": "sha512-2WFYnoWGdmih1I1J5eIqxATOeycOqRwYxAQBu3cUu/rhwInwHUg7k60AFNbuGjSDL8tje5GDrAnxzRLcu2pYcA==", + "license": "MIT", + "dependencies": { + "hermes-parser": "0.29.1" + } + }, + "node_modules/babel-plugin-transform-flow-enums": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", + "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-flow": "^7.12.1" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-expo": { + "version": "54.0.10", + "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-54.0.10.tgz", + "integrity": "sha512-wTt7POavLFypLcPW/uC5v8y+mtQKDJiyGLzYCjqr9tx0Qc3vCXcDKk1iCFIj/++Iy5CWhhTflEa7VvVPNWeCfw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/plugin-proposal-decorators": "^7.12.9", + "@babel/plugin-proposal-export-default-from": "^7.24.7", + "@babel/plugin-syntax-export-default-from": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.27.1", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-flow-strip-types": "^7.25.2", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-runtime": "^7.24.7", + "@babel/preset-react": "^7.22.15", + "@babel/preset-typescript": "^7.23.0", + "@react-native/babel-preset": "0.81.5", + "babel-plugin-react-compiler": "^1.0.0", + "babel-plugin-react-native-web": "~0.21.0", + "babel-plugin-syntax-hermes-parser": "^0.29.1", + "babel-plugin-transform-flow-enums": "^0.0.2", + "debug": "^4.3.4", + "resolve-from": "^5.0.0" + }, + "peerDependencies": { + "@babel/runtime": "^7.20.0", + "expo": "*", + "react-refresh": ">=0.14.0 <1.0.0" + }, + "peerDependenciesMeta": { + "@babel/runtime": { + "optional": true + }, + "expo": { + "optional": true + } + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/badgin": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/badgin/-/badgin-1.2.3.tgz", + "integrity": "sha512-NQGA7LcfCpSzIbGRbkgjgdWkjy7HI+Th5VLxTJfW5EeaAf3fnS+xWQaQOCYiny+q6QSvxqoSO04vCx+4u++EJw==", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", + "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/better-opn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz", + "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==", + "license": "MIT", + "dependencies": { + "open": "^8.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/better-opn/node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/bplist-creator": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz", + "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==", + "license": "MIT", + "dependencies": { + "stream-buffers": "2.2.x" + } + }, + "node_modules/bplist-parser": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", + "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001769", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz", + "integrity": "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/chrome-launcher": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", + "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0" + }, + "bin": { + "print-chrome-path": "bin/print-chrome-path.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/chromium-edge-launcher": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz", + "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0", + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/core-js-compat": { + "version": "3.48.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.48.0.tgz", + "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/cross-fetch/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/cross-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/cross-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/cross-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/css-in-js-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz", + "integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==", + "license": "MIT", + "dependencies": { + "hyphenate-style-name": "^1.0.3" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dedent": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz", + "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==", + "devOptional": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", + "dev": true, + "license": "MIT", + "dependencies": { + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-expand": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", + "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", + "license": "BSD-2-Clause", + "dependencies": { + "dotenv": "^16.4.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.286", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", + "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-editor": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/env-editor/-/env-editor-0.4.2.tgz", + "integrity": "sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-ex/node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/exec-async": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/exec-async/-/exec-async-2.2.0.tgz", + "integrity": "sha512-87OpwcEiMia/DeiKFzaQNBNFeN3XkkpYIh9FyOqq5mS2oKv3CBE67PXoEKcr6nodWdXNogTiQ0jE2NGuoffXPw==", + "license": "MIT" + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/execa/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "devOptional": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/expo": { + "version": "54.0.33", + "resolved": "https://registry.npmjs.org/expo/-/expo-54.0.33.tgz", + "integrity": "sha512-3yOEfAKqo+gqHcV8vKcnq0uA5zxlohnhA3fu4G43likN8ct5ZZ3LjAh9wDdKteEkoad3tFPvwxmXW711S5OHUw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.0", + "@expo/cli": "54.0.23", + "@expo/config": "~12.0.13", + "@expo/config-plugins": "~54.0.4", + "@expo/devtools": "0.1.8", + "@expo/fingerprint": "0.15.4", + "@expo/metro": "~54.2.0", + "@expo/metro-config": "54.0.14", + "@expo/vector-icons": "^15.0.3", + "@ungap/structured-clone": "^1.3.0", + "babel-preset-expo": "~54.0.10", + "expo-asset": "~12.0.12", + "expo-constants": "~18.0.13", + "expo-file-system": "~19.0.21", + "expo-font": "~14.0.11", + "expo-keep-awake": "~15.0.8", + "expo-modules-autolinking": "3.0.24", + "expo-modules-core": "3.0.29", + "pretty-format": "^29.7.0", + "react-refresh": "^0.14.2", + "whatwg-url-without-unicode": "8.0.0-3" + }, + "bin": { + "expo": "bin/cli", + "expo-modules-autolinking": "bin/autolinking", + "fingerprint": "bin/fingerprint" + }, + "peerDependencies": { + "@expo/dom-webview": "*", + "@expo/metro-runtime": "*", + "react": "*", + "react-native": "*", + "react-native-webview": "*" + }, + "peerDependenciesMeta": { + "@expo/dom-webview": { + "optional": true + }, + "@expo/metro-runtime": { + "optional": true + }, + "react-native-webview": { + "optional": true + } + } + }, + "node_modules/expo-application": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/expo-application/-/expo-application-7.0.8.tgz", + "integrity": "sha512-qFGyxk7VJbrNOQWBbE09XUuGuvkOgFS9QfToaK2FdagM2aQ+x3CvGV2DuVgl/l4ZxPgIf3b/MNh9xHpwSwn74Q==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-asset": { + "version": "12.0.12", + "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-12.0.12.tgz", + "integrity": "sha512-CsXFCQbx2fElSMn0lyTdRIyKlSXOal6ilLJd+yeZ6xaC7I9AICQgscY5nj0QcwgA+KYYCCEQEBndMsmj7drOWQ==", + "license": "MIT", + "dependencies": { + "@expo/image-utils": "^0.8.8", + "expo-constants": "~18.0.12" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo-av": { + "version": "16.0.8", + "resolved": "https://registry.npmjs.org/expo-av/-/expo-av-16.0.8.tgz", + "integrity": "sha512-cmVPftGR/ca7XBgs7R6ky36lF3OC0/MM/lpgX/yXqfv0jASTsh7AYX9JxHCwFmF+Z6JEB1vne9FDx4GiLcGreQ==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*", + "react-native-web": "*" + }, + "peerDependenciesMeta": { + "react-native-web": { + "optional": true + } + } + }, + "node_modules/expo-blur": { + "version": "15.0.8", + "resolved": "https://registry.npmjs.org/expo-blur/-/expo-blur-15.0.8.tgz", + "integrity": "sha512-rWyE1NBRZEu9WD+X+5l7gyPRszw7n12cW3IRNAb5i6KFzaBp8cxqT5oeaphJapqURvcqhkOZn2k5EtBSbsuU7w==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo-build-properties": { + "version": "55.0.9", + "resolved": "https://registry.npmjs.org/expo-build-properties/-/expo-build-properties-55.0.9.tgz", + "integrity": "sha512-p0rNHW/6ghKsvjlUn2DQfbLYuTB6ba+15SeTPOz5BYbyU1F/0F/YyxBtHdmWitqgDPn6VgXQeKhiNC1fMwYDpg==", + "license": "MIT", + "dependencies": { + "@expo/schema-utils": "^55.0.2", + "resolve-from": "^5.0.0", + "semver": "^7.6.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-build-properties/node_modules/@expo/schema-utils": { + "version": "55.0.2", + "resolved": "https://registry.npmjs.org/@expo/schema-utils/-/schema-utils-55.0.2.tgz", + "integrity": "sha512-QZ5WKbJOWkCrMq0/kfhV9ry8te/OaS34YgLVpG8u9y2gix96TlpRTbxM/YATjNcUR2s4fiQmPCOxkGtog4i37g==", + "license": "MIT" + }, + "node_modules/expo-build-properties/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/expo-camera": { + "version": "17.0.10", + "resolved": "https://registry.npmjs.org/expo-camera/-/expo-camera-17.0.10.tgz", + "integrity": "sha512-w1RBw83mAGVk4BPPwNrCZyFop0VLiVSRE3c2V9onWbdFwonpRhzmB4drygG8YOUTl1H3wQvALJHyMPTbgsK1Jg==", + "license": "MIT", + "dependencies": { + "invariant": "^2.2.4" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*", + "react-native-web": "*" + }, + "peerDependenciesMeta": { + "react-native-web": { + "optional": true + } + } + }, + "node_modules/expo-constants": { + "version": "18.0.13", + "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.13.tgz", + "integrity": "sha512-FnZn12E1dRYKDHlAdIyNFhBurKTS3F9CrfrBDJI5m3D7U17KBHMQ6JEfYlSj7LG7t+Ulr+IKaj58L1k5gBwTcQ==", + "license": "MIT", + "dependencies": { + "@expo/config": "~12.0.13", + "@expo/env": "~2.0.8" + }, + "peerDependencies": { + "expo": "*", + "react-native": "*" + } + }, + "node_modules/expo-dev-client": { + "version": "6.0.20", + "resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-6.0.20.tgz", + "integrity": "sha512-5XjoVlj1OxakNxy55j/AUaGPrDOlQlB6XdHLLWAw61w5ffSpUDHDnuZzKzs9xY1eIaogOqTOQaAzZ2ddBkdXLA==", + "license": "MIT", + "dependencies": { + "expo-dev-launcher": "6.0.20", + "expo-dev-menu": "7.0.18", + "expo-dev-menu-interface": "2.0.0", + "expo-manifests": "~1.0.10", + "expo-updates-interface": "~2.0.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-launcher": { + "version": "6.0.20", + "resolved": "https://registry.npmjs.org/expo-dev-launcher/-/expo-dev-launcher-6.0.20.tgz", + "integrity": "sha512-a04zHEeT9sB0L5EB38fz7sNnUKJ2Ar1pXpcyl60Ki8bXPNCs9rjY7NuYrDkP/irM8+1DklMBqHpyHiLyJ/R+EA==", + "license": "MIT", + "dependencies": { + "ajv": "^8.11.0", + "expo-dev-menu": "7.0.18", + "expo-manifests": "~1.0.10" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-menu": { + "version": "7.0.18", + "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-7.0.18.tgz", + "integrity": "sha512-4kTdlHrnZCAWCT6tZRQHSSjZ7vECFisL4T+nsG/GJDo/jcHNaOVGV5qPV9wzlTxyMk3YOPggRw4+g7Ownrg5eA==", + "license": "MIT", + "dependencies": { + "expo-dev-menu-interface": "2.0.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-menu-interface": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/expo-dev-menu-interface/-/expo-dev-menu-interface-2.0.0.tgz", + "integrity": "sha512-BvAMPt6x+vyXpThsyjjOYyjwfjREV4OOpQkZ0tNl+nGpsPfcY9mc6DRACoWnH9KpLzyIt3BOgh3cuy/h/OxQjw==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-device": { + "version": "8.0.10", + "resolved": "https://registry.npmjs.org/expo-device/-/expo-device-8.0.10.tgz", + "integrity": "sha512-jd5BxjaF7382JkDMaC+P04aXXknB2UhWaVx5WiQKA05ugm/8GH5uaz9P9ckWdMKZGQVVEOC8MHaUADoT26KmFA==", + "license": "MIT", + "dependencies": { + "ua-parser-js": "^0.7.33" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-device/node_modules/ua-parser-js": { + "version": "0.7.41", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.41.tgz", + "integrity": "sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "license": "MIT", + "bin": { + "ua-parser-js": "script/cli.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/expo-eas-client": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/expo-eas-client/-/expo-eas-client-1.0.8.tgz", + "integrity": "sha512-5or11NJhSeDoHHI6zyvQDW2cz/yFyE+1Cz8NTs5NK8JzC7J0JrkUgptWtxyfB6Xs/21YRNifd3qgbBN3hfKVgA==", + "license": "MIT" + }, + "node_modules/expo-file-system": { + "version": "19.0.21", + "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-19.0.21.tgz", + "integrity": "sha512-s3DlrDdiscBHtab/6W1osrjGL+C2bvoInPJD7sOwmxfJ5Woynv2oc+Fz1/xVXaE/V7HE/+xrHC/H45tu6lZzzg==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react-native": "*" + } + }, + "node_modules/expo-font": { + "version": "14.0.11", + "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.11.tgz", + "integrity": "sha512-ga0q61ny4s/kr4k8JX9hVH69exVSIfcIc19+qZ7gt71Mqtm7xy2c6kwsPTCyhBW2Ro5yXTT8EaZOpuRi35rHbg==", + "license": "MIT", + "dependencies": { + "fontfaceobserver": "^2.1.0" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo-haptics": { + "version": "15.0.8", + "resolved": "https://registry.npmjs.org/expo-haptics/-/expo-haptics-15.0.8.tgz", + "integrity": "sha512-lftutojy8Qs8zaDzzjwM3gKHFZ8bOOEZDCkmh2Ddpe95Ra6kt2izeOfOfKuP/QEh0MZ1j9TfqippyHdRd1ZM9g==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-image-loader": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-6.0.0.tgz", + "integrity": "sha512-nKs/xnOGw6ACb4g26xceBD57FKLFkSwEUTDXEDF3Gtcu3MqF3ZIYd3YM+sSb1/z9AKV1dYT7rMSGVNgsveXLIQ==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-image-manipulator": { + "version": "14.0.8", + "resolved": "https://registry.npmjs.org/expo-image-manipulator/-/expo-image-manipulator-14.0.8.tgz", + "integrity": "sha512-sXsXjm7rIxLWZe0j2A41J/Ph53PpFJRdyzJ3EQ/qetxLUvS2m3K1sP5xy37px43qCf0l79N/i6XgFgenFV36/Q==", + "license": "MIT", + "dependencies": { + "expo-image-loader": "~6.0.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-image-picker": { + "version": "17.0.10", + "resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-17.0.10.tgz", + "integrity": "sha512-a2xrowp2trmvXyUWgX3O6Q2rZaa2C59AqivKI7+bm+wLvMfTEbZgldLX4rEJJhM8xtmEDTNU+lzjtObwzBRGaw==", + "license": "MIT", + "dependencies": { + "expo-image-loader": "~6.0.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-json-utils": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-0.15.0.tgz", + "integrity": "sha512-duRT6oGl80IDzH2LD2yEFWNwGIC2WkozsB6HF3cDYNoNNdUvFk6uN3YiwsTsqVM/D0z6LEAQ01/SlYvN+Fw0JQ==", + "license": "MIT" + }, + "node_modules/expo-keep-awake": { + "version": "15.0.8", + "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-15.0.8.tgz", + "integrity": "sha512-YK9M1VrnoH1vLJiQzChZgzDvVimVoriibiDIFLbQMpjYBnvyfUeHJcin/Gx1a+XgupNXy92EQJLgI/9ZuXajYQ==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react": "*" + } + }, + "node_modules/expo-linking": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-8.0.11.tgz", + "integrity": "sha512-+VSaNL5om3kOp/SSKO5qe6cFgfSIWnnQDSbA7XLs3ECkYzXRquk5unxNS3pg7eK5kNUmQ4kgLI7MhTggAEUBLA==", + "license": "MIT", + "dependencies": { + "expo-constants": "~18.0.12", + "invariant": "^2.2.4" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo-localization": { + "version": "17.0.8", + "resolved": "https://registry.npmjs.org/expo-localization/-/expo-localization-17.0.8.tgz", + "integrity": "sha512-UrdwklZBDJ+t+ZszMMiE0SXZ2eJxcquCuQcl6EvGHM9K+e6YqKVRQ+w8qE+iIB3H75v2RJy6MHAaLK+Mqeo04g==", + "license": "MIT", + "dependencies": { + "rtl-detect": "^1.0.2" + }, + "peerDependencies": { + "expo": "*", + "react": "*" + } + }, + "node_modules/expo-manifests": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-1.0.10.tgz", + "integrity": "sha512-oxDUnURPcL4ZsOBY6X1DGWGuoZgVAFzp6PISWV7lPP2J0r8u1/ucuChBgpK7u1eLGFp6sDIPwXyEUCkI386XSQ==", + "license": "MIT", + "dependencies": { + "@expo/config": "~12.0.11", + "expo-json-utils": "~0.15.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-modules-autolinking": { + "version": "3.0.24", + "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-3.0.24.tgz", + "integrity": "sha512-TP+6HTwhL7orDvsz2VzauyQlXJcAWyU3ANsZ7JGL4DQu8XaZv/A41ZchbtAYLfozNA2Ya1Hzmhx65hXryBMjaQ==", + "license": "MIT", + "dependencies": { + "@expo/spawn-async": "^1.7.2", + "chalk": "^4.1.0", + "commander": "^7.2.0", + "require-from-string": "^2.0.2", + "resolve-from": "^5.0.0" + }, + "bin": { + "expo-modules-autolinking": "bin/expo-modules-autolinking.js" + } + }, + "node_modules/expo-modules-core": { + "version": "3.0.29", + "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-3.0.29.tgz", + "integrity": "sha512-LzipcjGqk8gvkrOUf7O2mejNWugPkf3lmd9GkqL9WuNyeN2fRwU0Dn77e3ZUKI3k6sI+DNwjkq4Nu9fNN9WS7Q==", + "license": "MIT", + "dependencies": { + "invariant": "^2.2.4" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo-notifications": { + "version": "0.32.16", + "resolved": "https://registry.npmjs.org/expo-notifications/-/expo-notifications-0.32.16.tgz", + "integrity": "sha512-QQD/UA6v7LgvwIJ+tS7tSvqJZkdp0nCSj9MxsDk/jU1GttYdK49/5L2LvE/4U0H7sNBz1NZAyhDZozg8xgBLXw==", + "license": "MIT", + "dependencies": { + "@expo/image-utils": "^0.8.8", + "@ide/backoff": "^1.0.0", + "abort-controller": "^3.0.0", + "assert": "^2.0.0", + "badgin": "^1.1.5", + "expo-application": "~7.0.8", + "expo-constants": "~18.0.13" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo-router": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/expo-router/-/expo-router-6.0.23.tgz", + "integrity": "sha512-qCxVAiCrCyu0npky6azEZ6dJDMt77OmCzEbpF6RbUTlfkaCA417LvY14SBkk0xyGruSxy/7pvJOI6tuThaUVCA==", + "license": "MIT", + "dependencies": { + "@expo/metro-runtime": "^6.1.2", + "@expo/schema-utils": "^0.1.8", + "@radix-ui/react-slot": "1.2.0", + "@radix-ui/react-tabs": "^1.1.12", + "@react-navigation/bottom-tabs": "^7.4.0", + "@react-navigation/native": "^7.1.8", + "@react-navigation/native-stack": "^7.3.16", + "client-only": "^0.0.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "expo-server": "^1.0.5", + "fast-deep-equal": "^3.1.3", + "invariant": "^2.2.4", + "nanoid": "^3.3.8", + "query-string": "^7.1.3", + "react-fast-compare": "^3.2.2", + "react-native-is-edge-to-edge": "^1.1.6", + "semver": "~7.6.3", + "server-only": "^0.0.1", + "sf-symbols-typescript": "^2.1.0", + "shallowequal": "^1.1.0", + "use-latest-callback": "^0.2.1", + "vaul": "^1.1.2" + }, + "peerDependencies": { + "@expo/metro-runtime": "^6.1.2", + "@react-navigation/drawer": "^7.5.0", + "@testing-library/react-native": ">= 12.0.0", + "expo": "*", + "expo-constants": "^18.0.13", + "expo-linking": "^8.0.11", + "react": "*", + "react-dom": "*", + "react-native": "*", + "react-native-gesture-handler": "*", + "react-native-reanimated": "*", + "react-native-safe-area-context": ">= 5.4.0", + "react-native-screens": "*", + "react-native-web": "*", + "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" + }, + "peerDependenciesMeta": { + "@react-navigation/drawer": { + "optional": true + }, + "@testing-library/react-native": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native-gesture-handler": { + "optional": true + }, + "react-native-reanimated": { + "optional": true + }, + "react-native-web": { + "optional": true + }, + "react-server-dom-webpack": { + "optional": true + } + } + }, + "node_modules/expo-router/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/expo-secure-store": { + "version": "15.0.8", + "resolved": "https://registry.npmjs.org/expo-secure-store/-/expo-secure-store-15.0.8.tgz", + "integrity": "sha512-lHnzvRajBu4u+P99+0GEMijQMFCOYpWRO4dWsXSuMt77+THPIGjzNvVKrGSl6mMrLsfVaKL8BpwYZLGlgA+zAw==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-server": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/expo-server/-/expo-server-1.0.5.tgz", + "integrity": "sha512-IGR++flYH70rhLyeXF0Phle56/k4cee87WeQ4mamS+MkVAVP+dDlOHf2nN06Z9Y2KhU0Gp1k+y61KkghF7HdhA==", + "license": "MIT", + "engines": { + "node": ">=20.16.0" + } + }, + "node_modules/expo-splash-screen": { + "version": "31.0.13", + "resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-31.0.13.tgz", + "integrity": "sha512-1epJLC1cDlwwj089R2h8cxaU5uk4ONVAC+vzGiTZH4YARQhL4Stlz1MbR6yAS173GMosvkE6CAeihR7oIbCkDA==", + "license": "MIT", + "dependencies": { + "@expo/prebuild-config": "^54.0.8" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-sqlite": { + "version": "16.0.10", + "resolved": "https://registry.npmjs.org/expo-sqlite/-/expo-sqlite-16.0.10.tgz", + "integrity": "sha512-tUOKxE9TpfneRG3eOfbNfhN9236SJ7IiUnP8gCqU7umd9DtgDGB/5PhYVVfl+U7KskgolgNoB9v9OZ9iwXN8Eg==", + "license": "MIT", + "dependencies": { + "await-lock": "^2.2.2" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo-status-bar": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-3.0.9.tgz", + "integrity": "sha512-xyYyVg6V1/SSOZWh4Ni3U129XHCnFHBTcUo0dhWtFDrZbNp/duw5AGsQfb2sVeU0gxWHXSY1+5F0jnKYC7WuOw==", + "license": "MIT", + "dependencies": { + "react-native-is-edge-to-edge": "^1.2.1" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo-structured-headers": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/expo-structured-headers/-/expo-structured-headers-5.0.0.tgz", + "integrity": "sha512-RmrBtnSphk5REmZGV+lcdgdpxyzio5rJw8CXviHE6qH5pKQQ83fhMEcigvrkBdsn2Efw2EODp4Yxl1/fqMvOZw==", + "license": "MIT" + }, + "node_modules/expo-updates": { + "version": "29.0.16", + "resolved": "https://registry.npmjs.org/expo-updates/-/expo-updates-29.0.16.tgz", + "integrity": "sha512-E9/fxRz/Eurtc7hxeI/6ZPyHH3To9Xoccm1kXoICZTRojmuTo+dx0Xv53UHyHn4G5zGMezyaKF2Qtj3AKcT93w==", + "license": "MIT", + "dependencies": { + "@expo/code-signing-certificates": "^0.0.6", + "@expo/plist": "^0.4.8", + "@expo/spawn-async": "^1.7.2", + "arg": "4.1.0", + "chalk": "^4.1.2", + "debug": "^4.3.4", + "expo-eas-client": "~1.0.8", + "expo-manifests": "~1.0.10", + "expo-structured-headers": "~5.0.0", + "expo-updates-interface": "~2.0.0", + "getenv": "^2.0.0", + "glob": "^13.0.0", + "ignore": "^5.3.1", + "resolve-from": "^5.0.0" + }, + "bin": { + "expo-updates": "bin/cli.js" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo-updates-interface": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/expo-updates-interface/-/expo-updates-interface-2.0.0.tgz", + "integrity": "sha512-pTzAIufEZdVPKql6iMi5ylVSPqV1qbEopz9G6TSECQmnNde2nwq42PxdFBaUEd8IZJ/fdJLQnOT3m6+XJ5s7jg==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-updates/node_modules/arg": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", + "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==", + "license": "MIT" + }, + "node_modules/expo-video": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/expo-video/-/expo-video-3.0.16.tgz", + "integrity": "sha512-H1HlxcHGomZItqisGfW3YL/G9BHtNBfVSimDJcLuyxyU87wFnV8loO9tCjuhufkfh/aTa2sW5BYAjLjg9DvnBQ==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "license": "Apache-2.0" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fbjs": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz", + "integrity": "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==", + "license": "MIT", + "dependencies": { + "cross-fetch": "^3.1.5", + "fbjs-css-vars": "^1.0.0", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^1.0.35" + } + }, + "node_modules/fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==", + "license": "MIT" + }, + "node_modules/fbjs/node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "license": "MIT", + "dependencies": { + "asap": "~2.0.3" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flow-enums-runtime": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", + "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==", + "license": "MIT" + }, + "node_modules/fontfaceobserver": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz", + "integrity": "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==", + "license": "BSD-2-Clause" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/freeport-async": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/freeport-async/-/freeport-async-2.0.0.tgz", + "integrity": "sha512-K7od3Uw45AJg00XUmy15+Hae2hOcgKcmN3/EF6Y7i01O0gaqiRx8sUSpsb9+BRNL8RPBrhzPsVfy8q9ADlJuWQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gaxios": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz", + "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2", + "rimraf": "^5.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gaxios/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/gaxios/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/gaxios/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/gaxios/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/getenv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/getenv/-/getenv-2.0.0.tgz", + "integrity": "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/glob": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.1.tgz", + "integrity": "sha512-B7U/vJpE3DkJ5WXTgTpTRN63uV42DseiXXKMwG14LQBXmsdeIoHAPbU/MEo6II0k5ED74uc2ZGTC6MwHFQhF6w==", + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.1.2", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.2.tgz", + "integrity": "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", + "license": "MIT", + "dependencies": { + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/google-auth-library": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.5.0.tgz", + "integrity": "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.0.0", + "gcp-metadata": "^8.0.0", + "google-logging-utils": "^1.0.0", + "gtoken": "^8.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/gtoken": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz", + "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==", + "license": "MIT", + "dependencies": { + "gaxios": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz", + "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==", + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz", + "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.29.1" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/hyphenate-style-name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==", + "license": "BSD-3-Clause" + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz", + "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==", + "license": "MIT", + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/inline-style-prefixer": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-7.0.1.tgz", + "integrity": "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==", + "license": "MIT", + "dependencies": { + "css-in-js-utils": "^3.1.0" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "license": "MIT" + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "devOptional": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "devOptional": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "devOptional": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "devOptional": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-config/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", + "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/jsdom": "^20.0.0", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0", + "jsdom": "^20.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-expo": { + "version": "54.0.17", + "resolved": "https://registry.npmjs.org/jest-expo/-/jest-expo-54.0.17.tgz", + "integrity": "sha512-LyIhrsP4xvHEEcR1R024u/LBj3uPpAgB+UljgV+YXWkEHjprnr0KpE4tROsMNYCVTM1pPlAnPuoBmn5gnAN9KA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@expo/config": "~12.0.13", + "@expo/json-file": "^10.0.8", + "@jest/create-cache-key-function": "^29.2.1", + "@jest/globals": "^29.2.1", + "babel-jest": "^29.2.1", + "jest-environment-jsdom": "^29.2.1", + "jest-snapshot": "^29.2.1", + "jest-watch-select-projects": "^2.0.0", + "jest-watch-typeahead": "2.2.1", + "json5": "^2.2.3", + "lodash": "^4.17.19", + "react-test-renderer": "19.1.0", + "server-only": "^0.0.1", + "stacktrace-js": "^2.0.2" + }, + "bin": { + "jest": "bin/jest.js" + }, + "peerDependencies": { + "expo": "*", + "react-native": "*", + "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" + }, + "peerDependenciesMeta": { + "react-server-dom-webpack": { + "optional": true + } + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "devOptional": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watch-select-projects": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jest-watch-select-projects/-/jest-watch-select-projects-2.0.0.tgz", + "integrity": "sha512-j00nW4dXc2NiCW6znXgFLF9g8PJ0zP25cpQ1xRro/HU2GBfZQFZD0SoXnAlaoKkIY4MlfTMkKGbNXFpvCdjl1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.3.0", + "chalk": "^3.0.0", + "prompts": "^2.2.1" + } + }, + "node_modules/jest-watch-select-projects/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-2.2.1.tgz", + "integrity": "sha512-jYpYmUnTzysmVnwq49TAxlmtOAwp8QIqvZyoofQFn8fiWhEDZj33ZXzg3JA4nGnzWFm1hbWf3ADpteUokvXgFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^6.0.0", + "chalk": "^4.0.0", + "jest-regex-util": "^29.0.0", + "jest-watcher": "^29.0.0", + "slash": "^5.0.0", + "string-length": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "jest": "^27.0.0 || ^28.0.0 || ^29.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/ansi-escapes": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watch-typeahead/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watch-typeahead/node_modules/string-length": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", + "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^2.0.0", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watch-typeahead/node_modules/string-length/node_modules/char-regex": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.2.tgz", + "integrity": "sha512-cbGOjAptfM2LVmWhwRFHEKTPkLwNddVmuqYZQt895yXwAsWsXObCG+YN4DGQ/JBtT4GP1a1lPPdio2z413LmTg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/jest-watch-typeahead/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jimp-compact": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/jimp-compact/-/jimp-compact-0.16.1.tgz", + "integrity": "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==", + "license": "MIT" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsc-safe-url": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz", + "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==", + "license": "0BSD" + }, + "node_modules/jsdom": { + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", + "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "abab": "^2.0.6", + "acorn": "^8.8.1", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.2", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.11.0", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lan-network": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/lan-network/-/lan-network-0.1.7.tgz", + "integrity": "sha512-mnIlAEMu4OyEvUNdzco9xpuB9YVcPkQec+QsgycBCtPZvEqWPCDPfbAE4OJMdBBWpZWtpCn1xw9jJYlwjWI5zQ==", + "license": "MIT", + "bin": { + "lan-network": "dist/lan-network-cli.js" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lighthouse-logger": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", + "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^2.6.9", + "marky": "^1.2.2" + } + }, + "node_modules/lighthouse-logger/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/lighthouse-logger/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/lightningcss": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", + "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.31.1", + "lightningcss-darwin-arm64": "1.31.1", + "lightningcss-darwin-x64": "1.31.1", + "lightningcss-freebsd-x64": "1.31.1", + "lightningcss-linux-arm-gnueabihf": "1.31.1", + "lightningcss-linux-arm64-gnu": "1.31.1", + "lightningcss-linux-arm64-musl": "1.31.1", + "lightningcss-linux-x64-gnu": "1.31.1", + "lightningcss-linux-x64-musl": "1.31.1", + "lightningcss-win32-arm64-msvc": "1.31.1", + "lightningcss-win32-x64-msvc": "1.31.1" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz", + "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz", + "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz", + "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz", + "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz", + "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz", + "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz", + "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz", + "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz", + "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz", + "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz", + "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT" + }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "license": "MIT", + "dependencies": { + "chalk": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/log-symbols/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/marky": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz", + "integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==", + "license": "Apache-2.0" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "license": "CC0-1.0" + }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", + "license": "MIT" + }, + "node_modules/merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "license": "MIT", + "dependencies": { + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT" + }, + "node_modules/metro": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.83.3.tgz", + "integrity": "sha512-+rP+/GieOzkt97hSJ0MrPOuAH/jpaS21ZDvL9DJ35QYRDlQcwzcvUlGUf79AnQxq/2NPiS/AULhhM4TKutIt8Q==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/core": "^7.25.2", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.3", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.3", + "@babel/types": "^7.25.2", + "accepts": "^1.3.7", + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "connect": "^3.6.5", + "debug": "^4.4.0", + "error-stack-parser": "^2.0.6", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "hermes-parser": "0.32.0", + "image-size": "^1.0.2", + "invariant": "^2.2.4", + "jest-worker": "^29.7.0", + "jsc-safe-url": "^0.2.2", + "lodash.throttle": "^4.1.1", + "metro-babel-transformer": "0.83.3", + "metro-cache": "0.83.3", + "metro-cache-key": "0.83.3", + "metro-config": "0.83.3", + "metro-core": "0.83.3", + "metro-file-map": "0.83.3", + "metro-resolver": "0.83.3", + "metro-runtime": "0.83.3", + "metro-source-map": "0.83.3", + "metro-symbolicate": "0.83.3", + "metro-transform-plugins": "0.83.3", + "metro-transform-worker": "0.83.3", + "mime-types": "^2.1.27", + "nullthrows": "^1.1.1", + "serialize-error": "^2.1.0", + "source-map": "^0.5.6", + "throat": "^5.0.0", + "ws": "^7.5.10", + "yargs": "^17.6.2" + }, + "bin": { + "metro": "src/cli.js" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-babel-transformer": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.83.3.tgz", + "integrity": "sha512-1vxlvj2yY24ES1O5RsSIvg4a4WeL7PFXgKOHvXTXiW0deLvQr28ExXj6LjwCCDZ4YZLhq6HddLpZnX4dEdSq5g==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "flow-enums-runtime": "^0.0.6", + "hermes-parser": "0.32.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-babel-transformer/node_modules/hermes-estree": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.32.0.tgz", + "integrity": "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ==", + "license": "MIT" + }, + "node_modules/metro-babel-transformer/node_modules/hermes-parser": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.32.0.tgz", + "integrity": "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.32.0" + } + }, + "node_modules/metro-cache": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.83.3.tgz", + "integrity": "sha512-3jo65X515mQJvKqK3vWRblxDEcgY55Sk3w4xa6LlfEXgQ9g1WgMh9m4qVZVwgcHoLy0a2HENTPCCX4Pk6s8c8Q==", + "license": "MIT", + "dependencies": { + "exponential-backoff": "^3.1.1", + "flow-enums-runtime": "^0.0.6", + "https-proxy-agent": "^7.0.5", + "metro-core": "0.83.3" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-cache-key": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.83.3.tgz", + "integrity": "sha512-59ZO049jKzSmvBmG/B5bZ6/dztP0ilp0o988nc6dpaDsU05Cl1c/lRf+yx8m9WW/JVgbmfO5MziBU559XjI5Zw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-config": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.83.3.tgz", + "integrity": "sha512-mTel7ipT0yNjKILIan04bkJkuCzUUkm2SeEaTads8VfEecCh+ltXchdq6DovXJqzQAXuR2P9cxZB47Lg4klriA==", + "license": "MIT", + "dependencies": { + "connect": "^3.6.5", + "flow-enums-runtime": "^0.0.6", + "jest-validate": "^29.7.0", + "metro": "0.83.3", + "metro-cache": "0.83.3", + "metro-core": "0.83.3", + "metro-runtime": "0.83.3", + "yaml": "^2.6.1" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-core": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.83.3.tgz", + "integrity": "sha512-M+X59lm7oBmJZamc96usuF1kusd5YimqG/q97g4Ac7slnJ3YiGglW5CsOlicTR5EWf8MQFxxjDoB6ytTqRe8Hw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "lodash.throttle": "^4.1.1", + "metro-resolver": "0.83.3" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-file-map": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.83.3.tgz", + "integrity": "sha512-jg5AcyE0Q9Xbbu/4NAwwZkmQn7doJCKGW0SLeSJmzNB9Z24jBe0AL2PHNMy4eu0JiKtNWHz9IiONGZWq7hjVTA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "fb-watchman": "^2.0.0", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "invariant": "^2.2.4", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "nullthrows": "^1.1.1", + "walker": "^1.0.7" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-minify-terser": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.83.3.tgz", + "integrity": "sha512-O2BmfWj6FSfzBLrNCXt/rr2VYZdX5i6444QJU0fFoc7Ljg+Q+iqebwE3K0eTvkI6TRjELsXk1cjU+fXwAR4OjQ==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "terser": "^5.15.0" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-resolver": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.83.3.tgz", + "integrity": "sha512-0js+zwI5flFxb1ktmR///bxHYg7OLpRpWZlBBruYG8OKYxeMP7SV0xQ/o/hUelrEMdK4LJzqVtHAhBm25LVfAQ==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-runtime": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.83.3.tgz", + "integrity": "sha512-JHCJb9ebr9rfJ+LcssFYA2x1qPYuSD/bbePupIGhpMrsla7RCwC/VL3yJ9cSU+nUhU4c9Ixxy8tBta+JbDeZWw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-source-map": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.83.3.tgz", + "integrity": "sha512-xkC3qwUBh2psVZgVavo8+r2C9Igkk3DibiOXSAht1aYRRcztEZNFtAMtfSB7sdO2iFMx2Mlyu++cBxz/fhdzQg==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.3", + "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", + "@babel/types": "^7.25.2", + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-symbolicate": "0.83.3", + "nullthrows": "^1.1.1", + "ob1": "0.83.3", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-symbolicate": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.83.3.tgz", + "integrity": "sha512-F/YChgKd6KbFK3eUR5HdUsfBqVsanf5lNTwFd4Ca7uuxnHgBC3kR/Hba/RGkenR3pZaGNp5Bu9ZqqP52Wyhomw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-source-map": "0.83.3", + "nullthrows": "^1.1.1", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "bin": { + "metro-symbolicate": "src/index.js" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-transform-plugins": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.83.3.tgz", + "integrity": "sha512-eRGoKJU6jmqOakBMH5kUB7VitEWiNrDzBHpYbkBXW7C5fUGeOd2CyqrosEzbMK5VMiZYyOcNFEphvxk3OXey2A==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/generator": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.3", + "flow-enums-runtime": "^0.0.6", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro-transform-worker": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.83.3.tgz", + "integrity": "sha512-Ztekew9t/gOIMZX1tvJOgX7KlSLL5kWykl0Iwu2cL2vKMKVALRl1hysyhUw0vjpAvLFx+Kfq9VLjnHIkW32fPA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.3", + "@babel/types": "^7.25.2", + "flow-enums-runtime": "^0.0.6", + "metro": "0.83.3", + "metro-babel-transformer": "0.83.3", + "metro-cache": "0.83.3", + "metro-cache-key": "0.83.3", + "metro-minify-terser": "0.83.3", + "metro-source-map": "0.83.3", + "metro-transform-plugins": "0.83.3", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/metro/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "license": "MIT" + }, + "node_modules/metro/node_modules/hermes-estree": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.32.0.tgz", + "integrity": "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ==", + "license": "MIT" + }, + "node_modules/metro/node_modules/hermes-parser": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.32.0.tgz", + "integrity": "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.32.0" + } + }, + "node_modules/metro/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nested-error-stacks": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.0.1.tgz", + "integrity": "sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==", + "license": "MIT" + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/node-forge": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz", + "integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-package-arg": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.3.tgz", + "integrity": "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==", + "license": "ISC", + "dependencies": { + "hosted-git-info": "^7.0.0", + "proc-log": "^4.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", + "license": "MIT" + }, + "node_modules/nwsapi": { + "version": "2.2.23", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz", + "integrity": "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/ob1": { + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.83.3.tgz", + "integrity": "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", + "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==", + "license": "MIT", + "dependencies": { + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-spinners": "^2.0.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ora/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/ora/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ora/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-png": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-png/-/parse-png-2.1.0.tgz", + "integrity": "sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==", + "license": "MIT", + "dependencies": { + "pngjs": "^3.3.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.2.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz", + "integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-3.0.1.tgz", + "integrity": "sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/plist": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.8.8", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "node_modules/posthog-react-native": { + "version": "4.37.1", + "resolved": "https://registry.npmjs.org/posthog-react-native/-/posthog-react-native-4.37.1.tgz", + "integrity": "sha512-EHgAC6XkYPKGSOYJUgv5WSoNNAiU+dZdwZSiREKy04qqBr/a3o5ByMvkb8TeJcCE6A/ZFD4YPsXf+01VGmWfvA==", + "license": "MIT", + "dependencies": { + "@posthog/core": "1.23.2" + }, + "peerDependencies": { + "@react-native-async-storage/async-storage": ">=1.0.0", + "@react-navigation/native": ">= 5.0.0", + "expo-application": ">= 4.0.0", + "expo-device": ">= 4.0.0", + "expo-file-system": ">= 13.0.0", + "expo-localization": ">= 11.0.0", + "posthog-react-native-session-replay": ">= 1.5.0", + "react-native-device-info": ">= 10.0.0", + "react-native-localize": ">= 3.0.0", + "react-native-navigation": ">= 6.0.0", + "react-native-safe-area-context": ">= 4.0.0", + "react-native-svg": ">= 15.0.0" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + }, + "@react-navigation/native": { + "optional": true + }, + "expo-application": { + "optional": true + }, + "expo-device": { + "optional": true + }, + "expo-file-system": { + "optional": true + }, + "expo-localization": { + "optional": true + }, + "posthog-react-native-session-replay": { + "optional": true + }, + "react-native-device-info": { + "optional": true + }, + "react-native-localize": { + "optional": true + }, + "react-native-navigation": { + "optional": true + }, + "react-native-safe-area-context": { + "optional": true + } + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/proc-log": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", + "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "license": "MIT", + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/protobufjs": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qrcode-terminal": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz", + "integrity": "sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ==", + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, + "node_modules/query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.3" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/react": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-devtools-core": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.1.5.tgz", + "integrity": "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==", + "license": "MIT", + "dependencies": { + "shell-quote": "^1.6.1", + "ws": "^7" + } + }, + "node_modules/react-devtools-core/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/react-dom": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", + "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.0" + } + }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", + "license": "MIT" + }, + "node_modules/react-freeze": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.4.tgz", + "integrity": "sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=17.0.0" + } + }, + "node_modules/react-is": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.4.tgz", + "integrity": "sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA==", + "license": "MIT" + }, + "node_modules/react-native": { + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.81.5.tgz", + "integrity": "sha512-1w+/oSjEXZjMqsIvmkCRsOc8UBYv163bTWKTI8+1mxztvQPhCRYGTvZ/PL1w16xXHneIj/SLGfxWg2GWN2uexw==", + "license": "MIT", + "dependencies": { + "@jest/create-cache-key-function": "^29.7.0", + "@react-native/assets-registry": "0.81.5", + "@react-native/codegen": "0.81.5", + "@react-native/community-cli-plugin": "0.81.5", + "@react-native/gradle-plugin": "0.81.5", + "@react-native/js-polyfills": "0.81.5", + "@react-native/normalize-colors": "0.81.5", + "@react-native/virtualized-lists": "0.81.5", + "abort-controller": "^3.0.0", + "anser": "^1.4.9", + "ansi-regex": "^5.0.0", + "babel-jest": "^29.7.0", + "babel-plugin-syntax-hermes-parser": "0.29.1", + "base64-js": "^1.5.1", + "commander": "^12.0.0", + "flow-enums-runtime": "^0.0.6", + "glob": "^7.1.1", + "invariant": "^2.2.4", + "jest-environment-node": "^29.7.0", + "memoize-one": "^5.0.0", + "metro-runtime": "^0.83.1", + "metro-source-map": "^0.83.1", + "nullthrows": "^1.1.1", + "pretty-format": "^29.7.0", + "promise": "^8.3.0", + "react-devtools-core": "^6.1.5", + "react-refresh": "^0.14.0", + "regenerator-runtime": "^0.13.2", + "scheduler": "0.26.0", + "semver": "^7.1.3", + "stacktrace-parser": "^0.1.10", + "whatwg-fetch": "^3.0.0", + "ws": "^6.2.3", + "yargs": "^17.6.2" + }, + "bin": { + "react-native": "cli.js" + }, + "engines": { + "node": ">= 20.19.4" + }, + "peerDependencies": { + "@types/react": "^19.1.0", + "react": "^19.1.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-native-gesture-handler": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.28.0.tgz", + "integrity": "sha512-0msfJ1vRxXKVgTgvL+1ZOoYw3/0z1R+Ked0+udoJhyplC2jbVKIJ8Z1bzWdpQRCV3QcQ87Op0zJVE5DhKK2A0A==", + "license": "MIT", + "dependencies": { + "@egjs/hammerjs": "^2.0.17", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-is-edge-to-edge": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.2.1.tgz", + "integrity": "sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q==", + "license": "MIT", + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-purchases": { + "version": "9.10.5", + "resolved": "https://registry.npmjs.org/react-native-purchases/-/react-native-purchases-9.10.5.tgz", + "integrity": "sha512-ofs33aTgdjyjUDZgCtCKYfvl4gBtJrOV77/SXyDzSxTttNjg+8BWGckF3ALfBg69uU65xrXsqfyU3U+Cl86IdQ==", + "license": "MIT", + "workspaces": [ + "examples/purchaseTesterTypescript", + "react-native-purchases-ui" + ], + "dependencies": { + "@revenuecat/purchases-js-hybrid-mappings": "17.41.1", + "@revenuecat/purchases-typescript-internal": "17.41.1" + }, + "peerDependencies": { + "react": ">= 16.6.3", + "react-native": ">= 0.73.0", + "react-native-web": "*" + }, + "peerDependenciesMeta": { + "react-native-web": { + "optional": true + } + } + }, + "node_modules/react-native-purchases-ui": { + "version": "9.10.5", + "resolved": "https://registry.npmjs.org/react-native-purchases-ui/-/react-native-purchases-ui-9.10.5.tgz", + "integrity": "sha512-vull2ssjJSfCNQ0zM/KanZXm4RIJB4KfzbAvE2O93dRK/T6yK8ggi403NQcTyM9B6oLI9NPEKBR+sMk5koT/ew==", + "license": "MIT", + "dependencies": { + "@revenuecat/purchases-typescript-internal": "17.41.1" + }, + "peerDependencies": { + "react": "*", + "react-native": ">= 0.73.0", + "react-native-purchases": "9.10.5", + "react-native-web": "*" + }, + "peerDependenciesMeta": { + "react-native-web": { + "optional": true + } + } + }, + "node_modules/react-native-reanimated": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-4.1.6.tgz", + "integrity": "sha512-F+ZJBYiok/6Jzp1re75F/9aLzkgoQCOh4yxrnwATa8392RvM3kx+fiXXFvwcgE59v48lMwd9q0nzF1oJLXpfxQ==", + "license": "MIT", + "dependencies": { + "react-native-is-edge-to-edge": "^1.2.1", + "semver": "7.7.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0", + "react": "*", + "react-native": "*", + "react-native-worklets": ">=0.5.0" + } + }, + "node_modules/react-native-reanimated/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/react-native-safe-area-context": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz", + "integrity": "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg==", + "license": "MIT", + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-screens": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.16.0.tgz", + "integrity": "sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q==", + "license": "MIT", + "dependencies": { + "react-freeze": "^1.0.0", + "react-native-is-edge-to-edge": "^1.2.1", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-svg": { + "version": "15.12.1", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.12.1.tgz", + "integrity": "sha512-vCuZJDf8a5aNC2dlMovEv4Z0jjEUET53lm/iILFnFewa15b4atjVxU6Wirm6O9y6dEsdjDZVD7Q3QM4T1wlI8g==", + "license": "MIT", + "dependencies": { + "css-select": "^5.1.0", + "css-tree": "^1.1.3", + "warn-once": "0.1.1" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-web": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.21.2.tgz", + "integrity": "sha512-SO2t9/17zM4iEnFvlu2DA9jqNbzNhoUP+AItkoCOyFmDMOhUnBBznBDCYN92fGdfAkfQlWzPoez6+zLxFNsZEg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.6", + "@react-native/normalize-colors": "^0.74.1", + "fbjs": "^3.0.4", + "inline-style-prefixer": "^7.0.1", + "memoize-one": "^6.0.0", + "nullthrows": "^1.1.1", + "postcss-value-parser": "^4.2.0", + "styleq": "^0.1.3" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-native-web/node_modules/@react-native/normalize-colors": { + "version": "0.74.89", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.74.89.tgz", + "integrity": "sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg==", + "license": "MIT" + }, + "node_modules/react-native-web/node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, + "node_modules/react-native-worklets": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/react-native-worklets/-/react-native-worklets-0.5.1.tgz", + "integrity": "sha512-lJG6Uk9YuojjEX/tQrCbcbmpdLCSFxDK1rJlkDhgqkVi1KZzG7cdcBFQRqyNOOzR9Y0CXNuldmtWTGOyM0k0+w==", + "license": "MIT", + "dependencies": { + "@babel/plugin-transform-arrow-functions": "^7.0.0-0", + "@babel/plugin-transform-class-properties": "^7.0.0-0", + "@babel/plugin-transform-classes": "^7.0.0-0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.0.0-0", + "@babel/plugin-transform-optional-chaining": "^7.0.0-0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0-0", + "@babel/plugin-transform-template-literals": "^7.0.0-0", + "@babel/plugin-transform-unicode-regex": "^7.0.0-0", + "@babel/preset-typescript": "^7.16.7", + "convert-source-map": "^2.0.0", + "semver": "7.7.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0", + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-worklets/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/react-native/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/react-native/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/react-native/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/react-native/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/react-native/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/react-native/node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-remove-scroll": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-test-renderer": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-19.1.0.tgz", + "integrity": "sha512-jXkSl3CpvPYEF+p/eGDLB4sPoDX8pKkYvRl9+rR8HxLY0X04vW7hCm1/0zHoUSjPZ3bDa+wXWNTDVIw/R8aDVw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "react-is": "^19.1.0", + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", + "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT" + }, + "node_modules/regexpu-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", + "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.2", + "regjsgen": "^0.8.0", + "regjsparser": "^0.13.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.2.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", + "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requireg": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/requireg/-/requireg-0.2.2.tgz", + "integrity": "sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg==", + "dependencies": { + "nested-error-stacks": "~2.0.1", + "rc": "~1.2.7", + "resolve": "~1.7.1" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/requireg/node_modules/resolve": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", + "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "license": "MIT", + "dependencies": { + "path-parse": "^1.0.5" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-global": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", + "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", + "license": "MIT", + "dependencies": { + "global-dirs": "^0.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-workspace-root": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/resolve-workspace-root/-/resolve-workspace-root-2.0.1.tgz", + "integrity": "sha512-nR23LHAvaI6aHtMg6RWoaHpdR4D881Nydkzi2CixINyg9T00KgaJdJI6Vwty+Ps8WLxZHuxsS0BseWjxSA4C+w==", + "license": "MIT" + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", + "license": "MIT", + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/rtl-detect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.1.2.tgz", + "integrity": "sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==", + "license": "BSD-3-Clause" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", + "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", + "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-static/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/server-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", + "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==", + "license": "MIT" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/sf-symbols-typescript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/sf-symbols-typescript/-/sf-symbols-typescript-2.2.0.tgz", + "integrity": "sha512-TPbeg0b7ylrswdGCji8FRGFAKuqbpQlLbL8SOle3j1iHSs5Ob5mhvMAxWN2UItOjgALAB5Zp3fmMfj8mbWvXKw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/simple-plist": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz", + "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==", + "license": "MIT", + "dependencies": { + "bplist-creator": "0.1.0", + "bplist-parser": "0.3.1", + "plist": "^3.0.5" + } + }, + "node_modules/simple-plist/node_modules/bplist-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", + "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slugify": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", + "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "node_modules/stack-generator": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz", + "integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "license": "MIT" + }, + "node_modules/stacktrace-gps": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz", + "integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "source-map": "0.5.6", + "stackframe": "^1.3.4" + } + }, + "node_modules/stacktrace-gps/node_modules/source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stacktrace-js": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz", + "integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "error-stack-parser": "^2.0.6", + "stack-generator": "^2.0.5", + "stacktrace-gps": "^3.0.4" + } + }, + "node_modules/stacktrace-parser": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz", + "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", + "license": "Unlicense", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-length/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/structured-headers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/structured-headers/-/structured-headers-0.4.1.tgz", + "integrity": "sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==", + "license": "MIT" + }, + "node_modules/styleq": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/styleq/-/styleq-0.1.3.tgz", + "integrity": "sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA==", + "license": "MIT" + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tar": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz", + "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.46.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", + "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "license": "Apache-2.0" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ua-parser-js": { + "version": "1.0.41", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.41.tgz", + "integrity": "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "license": "MIT", + "bin": { + "ua-parser-js": "script/cli.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/undici": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz", + "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "license": "MIT" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "license": "MIT", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-latest-callback": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.2.6.tgz", + "integrity": "sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vaul": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vaul/-/vaul-1.1.2.tgz", + "integrity": "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-dialog": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/vlq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", + "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==", + "license": "MIT" + }, + "node_modules/w3c-xmlserializer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/warn-once": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz", + "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==", + "license": "MIT" + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "license": "MIT" + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url-without-unicode": { + "version": "8.0.0-3", + "resolved": "https://registry.npmjs.org/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz", + "integrity": "sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==", + "license": "MIT", + "dependencies": { + "buffer": "^5.4.3", + "punycode": "^2.1.1", + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/whatwg-url/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wonka": { + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/wonka/-/wonka-6.3.5.tgz", + "integrity": "sha512-SSil+ecw6B4/Dm7Pf2sAshKQ5hWFvfyGlfPbEd6A14dOH6VDjrmbY86u6nZvy9omGwwIPFR8V41+of1EezgoUw==", + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xcode": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", + "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "license": "Apache-2.0", + "dependencies": { + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/xml2js": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.0.tgz", + "integrity": "sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json index 3d6e27f..91b4a4e 100644 --- a/package.json +++ b/package.json @@ -1,24 +1,79 @@ { "name": "greenlens", + "version": "2.1.4", + "main": "expo-router/entry", "private": true, - "version": "0.0.0", - "type": "module", "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview" + "start": "expo start --offline", + "android": "expo start --android --offline", + "ios": "expo start --ios --offline", + "web": "expo start --web --offline", + "build:dev": "eas build --profile development --platform android", + "build:preview": "eas build --profile preview --platform android", + "build:prod": "eas build --profile production --platform android", + "test": "jest", + "audit:semantic": "node scripts/generate_semantic_audit.js" + }, + "jest": { + "preset": "jest-expo", + "transformIgnorePatterns": [ + "node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@sentry/react-native|native-base|react-native-svg)" + ], + "setupFiles": [ + "./jest.setup.js" + ] }, "dependencies": { - "react": "^19.2.4", - "react-dom": "^19.2.4", + "@expo/vector-icons": "^15.0.3", "@google/genai": "^1.38.0", - "lucide-react": "^0.563.0", - "uuid": "^13.0.0" + "@react-native-async-storage/async-storage": "2.2.0", + "expo": "^54.0.33", + "expo-application": "~7.0.8", + "expo-asset": "~12.0.12", + "expo-av": "^16.0.8", + "expo-blur": "~15.0.8", + "expo-build-properties": "^55.0.9", + "expo-camera": "~17.0.10", + "expo-constants": "~18.0.13", + "expo-dev-client": "~6.0.20", + "expo-device": "~8.0.10", + "expo-file-system": "~19.0.21", + "expo-font": "~14.0.11", + "expo-haptics": "~15.0.8", + "expo-image-manipulator": "~14.0.8", + "expo-image-picker": "~17.0.10", + "expo-linking": "~8.0.11", + "expo-localization": "~17.0.8", + "expo-notifications": "~0.32.16", + "expo-router": "~6.0.23", + "expo-secure-store": "~15.0.8", + "expo-splash-screen": "~31.0.13", + "expo-sqlite": "~16.0.10", + "expo-status-bar": "~3.0.9", + "expo-updates": "~29.0.16", + "expo-video": "~3.0.16", + "posthog-react-native": "^4.37.1", + "react": "19.1.0", + "react-dom": "19.1.0", + "react-native": "0.81.5", + "react-native-gesture-handler": "~2.28.0", + "react-native-purchases": "^9.10.5", + "react-native-purchases-ui": "^9.10.5", + "react-native-reanimated": "~4.1.1", + "react-native-safe-area-context": "~5.6.0", + "react-native-screens": "~4.16.0", + "react-native-svg": "^15.12.1", + "react-native-web": "^0.21.2", + "react-native-worklets": "0.5.1" }, "devDependencies": { - "@types/node": "^22.14.0", - "@vitejs/plugin-react": "^5.0.0", - "typescript": "~5.8.2", - "vite": "^6.2.0" + "@babel/core": "^7.25.0", + "@testing-library/jest-native": "^5.4.3", + "@testing-library/react-native": "^13.3.3", + "@types/jest": "^29.5.14", + "@types/react": "~19.1.0", + "jest": "^29.7.0", + "jest-expo": "^54.0.17", + "typescript": "^5.3.0" } } diff --git a/plants_dump.json b/plants_dump.json new file mode 100644 index 0000000..414af53 Binary files /dev/null and b/plants_dump.json differ diff --git a/plants_dump_utf8.json b/plants_dump_utf8.json new file mode 100644 index 0000000..6817391 --- /dev/null +++ b/plants_dump_utf8.json @@ -0,0 +1,4444 @@ +[ + { + "id": "plant_8bfe537a28c86289", + "name": "Aasblume", + "botanicalName": "Stapelia grandiflora", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2c/Stapelia_grandiflora_flowers.jpg/330px-Stapelia_grandiflora_flowers.jpg", + "imageStatus": "ok", + "description": "Die Aasblume hat fleischige, gruene Staengel und riesige, sternfoermige Blueten mit aasartigem Duft.", + "categories": [ + "succulent", + "flowering", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Helles bis volles Licht", + "temp": "18-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_3e0a9ac0f2e3487e", + "name": "Adromischus", + "botanicalName": "Adromischus cristatus", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Adromischus_cristatus.jpg/330px-Adromischus_cristatus.jpg", + "imageStatus": "ok", + "description": "Adromischus ist eine kompakte Sukkulente mit ungewoehnlich wellenrandigen Blaettern auf kurzen Staengeln.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_b149587ebd02e88b", + "name": "Afrikanisches Veilchen", + "botanicalName": "Saintpaulia ionantha", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/African_violet_Saintpaulia_ionantha.jpg/330px-African_violet_Saintpaulia_ionantha.jpg", + "imageStatus": "ok", + "description": "Das Afrikanische Veilchen ist eine kleine, kompakte Bluehpflanze mit samtigen Blaettern und violetten Blueten.", + "categories": [ + "easy", + "flowering", + "low_light" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_163ec12a26b24198", + "name": "Agave", + "botanicalName": "Agave americana", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Agave_americana_%28detail%29.jpg/330px-Agave_americana_%28detail%29.jpg", + "imageStatus": "ok", + "description": "Die Agave ist eine imposante Sukkulente mit steifen, blaugruenen Blaettern mit Stacheln. Sie bluet nur einmal.", + "categories": [ + "succulent", + "sun", + "large" + ], + "careInfo": { + "waterIntervalDays": 21, + "light": "Volles Sonnenlicht", + "temp": "10-35 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_f35722f0d85fcbf0", + "name": "Aglaoneme", + "botanicalName": "Aglaonema commutatum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/Aglaonema_commutatum.jpg/330px-Aglaonema_commutatum.jpg", + "imageStatus": "ok", + "description": "Die Aglaoneme ist eine dekorative Zimmerpflanze mit silbrig-gruen gemusterten Blaettern. Tolerant gegenueber wenig Licht.", + "categories": [ + "easy", + "low_light", + "patterned" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Wenig bis helles Licht", + "temp": "15-26 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_929f7f7041e0b030", + "name": "Aloe Vera", + "botanicalName": "Aloe vera", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/Aloe_Vera_houseplant.jpg/330px-Aloe_Vera_houseplant.jpg", + "imageStatus": "ok", + "description": "Aloe Vera ist eine beliebte Heilpflanze. Das Gel wird fuer Haut- und Wundpflege verwendet.", + "categories": [ + "easy", + "succulent", + "medicinal", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Volles Sonnenlicht", + "temp": "18-24 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_521cc31a3ab2a5b1", + "name": "Alpenveilchen", + "botanicalName": "Cyclamen persicum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Cyclamen_persicum.jpg/330px-Cyclamen_persicum.jpg", + "imageStatus": "ok", + "description": "Das Alpenveilchen bluet im Herbst und Winter mit eleganten Blueten in Rosa, Rot oder Weiss.", + "categories": [ + "flowering" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "12-18 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_c623dbd931826123", + "name": "Amazona-Taro", + "botanicalName": "Alocasia amazonica", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7e/Alocasia_%27Polly%27_or_Amazon_Taro.jpg/330px-Alocasia_%27Polly%27_or_Amazon_Taro.jpg", + "imageStatus": "ok", + "description": "Der Amazona-Taro besticht mit dunkelgruenen, pfeilfoermigen Blaettern mit markant weissen Rippen.", + "categories": [ + "patterned", + "high_humidity", + "large" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_c2890f36d8fc9da0", + "name": "Arnika", + "botanicalName": "Arnica montana", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/eb/Arnica_montana_full.jpg/330px-Arnica_montana_full.jpg", + "imageStatus": "ok", + "description": "Arnika ist eine bekannte Heilpflanze aus den Alpen mit goldgelben Korbbluten. Sie wird fuer Muskeln und Gelenke verwendet.", + "categories": [ + "medicinal", + "flowering", + "sun" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "10-20 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_fdadaf062de2c567", + "name": "Aubergine", + "botanicalName": "Solanum melongena", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Aubergine.jpg/330px-Aubergine.jpg", + "imageStatus": "ok", + "description": "Die Aubergine ist eine Gemuese┬¡pflanze mit grossen, violetten Fruechten. Sie benoetigt viel Waerme und Sonne.", + "categories": [ + "sun", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Volles Sonnenlicht", + "temp": "20-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_480619fefb890692", + "name": "Baldrian", + "botanicalName": "Valeriana officinalis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Valeriana_officinalis_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-105.jpg/330px-Valeriana_officinalis_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-105.jpg", + "imageStatus": "ok", + "description": "Baldrian ist ein bekanntes Heilkraut mit weissen bis roeslichen Blueten. Die Wurzeln werden zur Schlaffoerderung verwendet.", + "categories": [ + "medicinal", + "flowering" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_b73b967c062264fa", + "name": "Bambusrohr", + "botanicalName": "Bambusa vulgaris", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/BambusaVulgarisStriata.jpg/330px-BambusaVulgarisStriata.jpg", + "imageStatus": "ok", + "description": "Das Bambusrohr ist eine schnell wachsende Bambusart mit gelbgruenen Halmen. Sehr dekorativ und vielseitig nutzbar.", + "categories": [ + "easy", + "large" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "15-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_1b52f8bc38189420", + "name": "Bananenpflanze", + "botanicalName": "Musa acuminata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Musa_acuminata_1_%28Luc_Viatour%29.jpg/330px-Musa_acuminata_1_%28Luc_Viatour%29.jpg", + "imageStatus": "ok", + "description": "Die Bananenpflanze ist eine tropische Staude mit riesigen, glaenzenden Blaettern. Im Zimmer selten fruechttragend.", + "categories": [ + "large", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "20-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_65672e0cb49ca62d", + "name": "Basilikum", + "botanicalName": "Ocimum basilicum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Basil-Basilico-Ocimum_basilicum-albahaca.jpg/330px-Basil-Basilico-Ocimum_basilicum-albahaca.jpg", + "imageStatus": "ok", + "description": "Basilikum ist das beliebteste Kuechenkraut mit intensiv aromatischen, gruenen Blaettern. Fuer Pesto verwendet.", + "categories": [ + "easy", + "medicinal", + "sun" + ], + "careInfo": { + "waterIntervalDays": 2, + "light": "Volles Sonnenlicht", + "temp": "18-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_11f9d18d047193e4", + "name": "Bergpalme", + "botanicalName": "Chamaedorea elegans", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Chamaedorea_elegans2.jpg/330px-Chamaedorea_elegans2.jpg", + "imageStatus": "ok", + "description": "Die Bergpalme ist eine kompakte Zimmerpalme fuer schattigere Standorte. Ideal fuer dunkle Innenraeume.", + "categories": [ + "easy", + "low_light", + "tree", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Wenig bis helles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_519742b7ea9df158", + "name": "Billbergia", + "botanicalName": "Billbergia nutans", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e8/Billbergia_nutans.jpg/330px-Billbergia_nutans.jpg", + "imageStatus": "ok", + "description": "Die Billbergia ist eine robuste Bromelie mit schmalen, gruenen Blaettern und h├ñngenden, blauen und gruenen Blueten.", + "categories": [ + "easy", + "flowering" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_2347cc2289a2ef8b", + "name": "Birkenfeige", + "botanicalName": "Ficus benjamina", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Ficus_benjamina.jpg/330px-Ficus_benjamina.jpg", + "imageStatus": "ok", + "description": "Die Birkenfeige ist ein eleganter Zimmerstrauch mit haengenden Aesten und kleinen, glaenzenden Blaettern.", + "categories": [ + "tree", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "16-24 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_4be713bff78ae299", + "name": "Blauer Kreuzkraut", + "botanicalName": "Senecio serpens", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/45/Blue_chalk_sticks_%28Senecio_serpens%29.jpg/330px-Blue_chalk_sticks_%28Senecio_serpens%29.jpg", + "imageStatus": "ok", + "description": "Der Blaue Kreuzkraut hat zylindrische, blaublaugruene Blaetter und einen kriechenden Wuchs. Sehr dekorativ.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_51da778adc3d568f", + "name": "Blaues Kanaelfarn", + "botanicalName": "Phlebodium aureum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Phlebodium_aureum_1.jpg/330px-Phlebodium_aureum_1.jpg", + "imageStatus": "ok", + "description": "Der Blaue Kanaelfarn hat wachsartige, blaugruene Wedel und glaenzende Wurzelstaemme. Sehr dekorativ.", + "categories": [ + "high_humidity", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_f696d8640ac1e58b", + "name": "Bleistiftkaktus", + "botanicalName": "Euphorbia tirucalli", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/59/Euphorbia_tirucalli.jpg/330px-Euphorbia_tirucalli.jpg", + "imageStatus": "ok", + "description": "Der Bleistiftkaktus ist eine sukkulente Wolfsmilch mit duennen, zylindrischen Zweigen ohne Blaetter.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Volles Sonnenlicht", + "temp": "18-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_fcfdae786a599215", + "name": "Bleiwurz", + "botanicalName": "Plumbago auriculata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/Plumbago_auriculata.jpg/330px-Plumbago_auriculata.jpg", + "imageStatus": "ok", + "description": "Die Bleiwurz ist ein halbimmergruener Strauch mit himmelblauen Blueten, der fast das ganze Jahr bluet.", + "categories": [ + "flowering", + "sun", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Volles Sonnenlicht", + "temp": "15-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_2778ede47b41928b", + "name": "Blumenschilfrohr", + "botanicalName": "Canna indica", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Canna_indica2.jpg/330px-Canna_indica2.jpg", + "imageStatus": "ok", + "description": "Das Blumenschilfrohr hat grosse, tropisch wirkende Blaetter und auffaellige Blueten in Rot, Orange oder Gelb.", + "categories": [ + "flowering", + "sun", + "large" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Volles Sonnenlicht", + "temp": "18-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_7b30624e5b0b4c89", + "name": "Blutroter Storchschnabel", + "botanicalName": "Geranium sanguineum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Geranium_sanguineum_R01.jpg/330px-Geranium_sanguineum_R01.jpg", + "imageStatus": "ok", + "description": "Der Blutrote Storchschnabel ist ein zierlicher Storchschnabel mit intensiv magentafarbenen Blueten.", + "categories": [ + "easy", + "flowering" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_766e50dd1b0308ae", + "name": "Bogenhanf", + "botanicalName": "Sansevieria trifasciata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/Snake_Plant_%28Sansevieria_trifasciata_%27Laurentii%27%29.jpg/330px-Snake_Plant_%28Sansevieria_trifasciata_%27Laurentii%27%29.jpg", + "imageStatus": "ok", + "description": "Der Bogenhanf ist eine pflegeleichte Sukkulente. Reinigt die Luft und vertraegt Vernachlaessigung.", + "categories": [ + "easy", + "low_light", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Wenig bis helles Licht", + "temp": "15-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_c71619cd9a02cef2", + "name": "Bonsai-Feige", + "botanicalName": "Ficus retusa", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/Ficus_retusa_bonsai_10.jpg/330px-Ficus_retusa_bonsai_10.jpg", + "imageStatus": "ok", + "description": "Die Bonsai-Feige ist eine klassische Bonsai-Art mit kleinen, elliptischen Blaettern. Sehr formbar.", + "categories": [ + "easy", + "tree" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "16-24 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_a65e5c9dedb9cd6f", + "name": "Bougainvillea", + "botanicalName": "Bougainvillea spectabilis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Bougainvillea_spectabilis_Willd.jpg/330px-Bougainvillea_spectabilis_Willd.jpg", + "imageStatus": "ok", + "description": "Die Bougainvillea ist eine rankenreiche Kletterpflanze mit leuchtend farbigen Hochblaettern in Rot, Orange oder Pink.", + "categories": [ + "flowering", + "sun", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Volles Sonnenlicht", + "temp": "18-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_34a9a605f91a0e38", + "name": "Brutblatt", + "botanicalName": "Kalanchoe daigremontiana", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Kalanchoe_daigremontiana.jpg/330px-Kalanchoe_daigremontiana.jpg", + "imageStatus": "ok", + "description": "Das Brutblatt bildet entlang des Blattrandes zahlreiche kleine Jungpflanzen. Eine faszinierende Sukkulente.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_ca3703f121432723", + "name": "Buntblatt", + "botanicalName": "Caladium bicolor", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cd/Caladium_bicolor_002.JPG/330px-Caladium_bicolor_002.JPG", + "imageStatus": "ok", + "description": "Das Buntblatt beeindruckt mit transparenten, bunt gemusterten Blaettern in Pink, Rot, Weiss und Gruen.", + "categories": [ + "patterned", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Indirektes Licht", + "temp": "20-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_de32e74f5d2e4f07", + "name": "Calibrachoa", + "botanicalName": "Calibrachoa hybrida", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0a/Calibrachoa_hybrid_2.jpg/330px-Calibrachoa_hybrid_2.jpg", + "imageStatus": "ok", + "description": "Calibrachoa ist eine petunienaehnliche Haengepflanze mit unzaehligen, kleinen Trichterbluten in allen Farben.", + "categories": [ + "easy", + "flowering", + "hanging", + "sun" + ], + "careInfo": { + "waterIntervalDays": 2, + "light": "Volles Sonnenlicht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_df8b72684a52d16d", + "name": "Calla", + "botanicalName": "Zantedeschia aethiopica", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Zantedeschia_aethiopica_2.jpg/330px-Zantedeschia_aethiopica_2.jpg", + "imageStatus": "ok", + "description": "Die Calla hat elegante, trichterfoermige weisse Hochblaetter und glaenzende, herzfoermige Blaetter. Sehr edel.", + "categories": [ + "flowering", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "15-24 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_c1e5518101af0660", + "name": "Callisia", + "botanicalName": "Callisia repens", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/09/Callisia_repens2.jpg/330px-Callisia_repens2.jpg", + "imageStatus": "ok", + "description": "Callisia repens ist ein kleines, kriechendes Kraut mit winzigen, gruenen Blaettern. Ideal fuer haengende Behaelter.", + "categories": [ + "easy", + "hanging", + "pet_friendly" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_e98319d5942ee47b", + "name": "Cattleya-Orchidee", + "botanicalName": "Cattleya labiata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Cattleya_labiata_var_autumnalis.jpg/330px-Cattleya_labiata_var_autumnalis.jpg", + "imageStatus": "ok", + "description": "Die Cattleya ist die Koenigin der Orchideen mit ueppigen, duftenden Blueten in Lila, Rosa und Weiss.", + "categories": [ + "flowering", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_f5fef1b22db032e8", + "name": "Chili", + "botanicalName": "Capsicum annuum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f9/Chili_pepper_red.jpg/330px-Chili_pepper_red.jpg", + "imageStatus": "ok", + "description": "Chili ist eine beliebte Gemuese- und Zierpflanze mit leuchtenden, roten oder orangen Fruechten. Im Topf kultivierbar.", + "categories": [ + "easy", + "sun", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 4, + "light": "Volles Sonnenlicht", + "temp": "20-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_282d1b42588a5121", + "name": "Chinesische F├ñcherpalme", + "botanicalName": "Livistona chinensis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/81/Livistona_chinensis_1.jpg/330px-Livistona_chinensis_1.jpg", + "imageStatus": "ok", + "description": "Die Chinesische F├ñcherpalme hat grosse, faecher┬¡foermige Blaetter auf einem einzelnen Stamm. Sehr dekorativ.", + "categories": [ + "tree", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_beef88438a4a5a77", + "name": "Chinesische Rose", + "botanicalName": "Rosa chinensis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/Rosa_chinensis_at_Dunedin_Botanic_Garden_1.jpg/330px-Rosa_chinensis_at_Dunedin_Botanic_Garden_1.jpg", + "imageStatus": "ok", + "description": "Die Chinesische Rose ist eine der Stammarten vieler Gartenrosen und bluet fast ununterbrochen.", + "categories": [ + "flowering", + "sun" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Volles Sonnenlicht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_3062bd4ee2363d81", + "name": "Chinesischer Blauregen", + "botanicalName": "Wisteria sinensis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/92/Wisteria_sinensis.jpg/330px-Wisteria_sinensis.jpg", + "imageStatus": "ok", + "description": "Der Chinesische Blauregen ist ein ueppiger Kletterkuenstler mit langen, duftenden Bluetentrauben in Lila.", + "categories": [ + "flowering", + "sun", + "large" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_552c1df47769e60a", + "name": "Christusdorn", + "botanicalName": "Euphorbia milii", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Euphorbia_milii.jpg/330px-Euphorbia_milii.jpg", + "imageStatus": "ok", + "description": "Der Christusdorn ist eine sukkulente Wolfsmilch mit stacheligen Zweigen und kleinen roten oder gelben Hochblaettern.", + "categories": [ + "easy", + "succulent", + "flowering", + "sun" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Helles bis volles Licht", + "temp": "15-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_d726e9204f2d2353", + "name": "Chrysantheme", + "botanicalName": "Chrysanthemum indicum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/65/Chrysanthemum_indicum1.jpg/330px-Chrysanthemum_indicum1.jpg", + "imageStatus": "ok", + "description": "Die Chrysantheme ist die klassische Herbstblume mit ueppigen, dichten Blueten in vielen Farben.", + "categories": [ + "flowering" + ], + "careInfo": { + "waterIntervalDays": 4, + "light": "Helles bis volles Licht", + "temp": "12-22 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_79e87c68ecaf5082", + "name": "Columnea", + "botanicalName": "Columnea gloriosa", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/27/Columnea_gloriosa1.jpg/330px-Columnea_gloriosa1.jpg", + "imageStatus": "ok", + "description": "Die Columnea ist eine haengende Zimmerpflanze mit kleinen, behaarten Blaettern und leuchtend roten, roehrenfoermigen Blueten.", + "categories": [ + "flowering", + "hanging", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_5136b27d56c24f26", + "name": "Cryptanthus", + "botanicalName": "Cryptanthus bivittatus", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cd/Cryptanthus_bivittatus.jpg/330px-Cryptanthus_bivittatus.jpg", + "imageStatus": "ok", + "description": "Cryptanthus ist eine niedrig wachsende Bromelie mit sternfoermigen Rosetten und gemusterten Blaettern. Fuer Terrarien.", + "categories": [ + "patterned", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_177a5dd7d3237533", + "name": "Ctenanthe", + "botanicalName": "Ctenanthe burle-marxii", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/39/Ctenanthe_burle-marxii.jpg/330px-Ctenanthe_burle-marxii.jpg", + "imageStatus": "ok", + "description": "Die Ctenanthe hat faszinierend gemusterte Blaetter mit dunkelgruunem Fischgraetenmuster auf hellgruunem Hintergrund.", + "categories": [ + "patterned", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Indirektes Licht", + "temp": "18-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_d38f9fdbd2fc0128", + "name": "Dahlie", + "botanicalName": "Dahlia pinnata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Dahlia_x_hybrida.jpg/330px-Dahlia_x_hybrida.jpg", + "imageStatus": "ok", + "description": "Die Dahlie ist eine prachtvolle Sommerblume mit Blueten in allen Groessen und Formen. Sie wird aus Knollen gezogen.", + "categories": [ + "flowering", + "sun" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Volles Sonnenlicht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_0f54f9b5c4726b7c", + "name": "Dendrobium", + "botanicalName": "Dendrobium nobile", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Dendrobium_nobile1.jpg/330px-Dendrobium_nobile1.jpg", + "imageStatus": "ok", + "description": "Das Dendrobium ist eine beliebte Zimmerorchidee mit langen Pseudobulben, die im Winter mit Blueten besetzt werden.", + "categories": [ + "flowering", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Helles indirektes Licht", + "temp": "15-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_4a40e184dc1158af", + "name": "Dieffenbachie", + "botanicalName": "Dieffenbachia seguine", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b3/Dieffenbachia_seguine_1.jpg/330px-Dieffenbachia_seguine_1.jpg", + "imageStatus": "ok", + "description": "Die Dieffenbachie ist eine tropische Blattschmuckpflanze mit grossen, gruen-weiss gefleckten Blaettern.", + "categories": [ + "easy", + "low_light", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-26 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_5a0f781f2fbe33a1", + "name": "Dischidia", + "botanicalName": "Dischidia ruscifolia", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Dischidia_ruscifolia.jpg/330px-Dischidia_ruscifolia.jpg", + "imageStatus": "ok", + "description": "Die Dischidia ist eine epiphytische Haengepflanze mit kleinen, runden Blaettern entlang duenner Ranken.", + "categories": [ + "succulent", + "hanging" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_d888afa045930bba", + "name": "Drachenbaum", + "botanicalName": "Dracaena marginata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Dracaena_marginata_2.jpg/330px-Dracaena_marginata_2.jpg", + "imageStatus": "ok", + "description": "Der Drachenbaum ist eine schlanke Zimmerpflanze mit roten, schmalen Blaettern auf langen Staemmen.", + "categories": [ + "easy", + "air_purifier", + "tree" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Helles indirektes Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_03f2e14e6adb42c5", + "name": "Drehfrucht", + "botanicalName": "Streptocarpus hybridus", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/07/Streptocarpus_saxorum.jpg/330px-Streptocarpus_saxorum.jpg", + "imageStatus": "ok", + "description": "Die Drehfrucht ist ein Gesneriengewaechs mit langen, gerippten Blaettern und trichterfoermigen Blueten in Lila oder Rosa.", + "categories": [ + "flowering" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "15-22 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_3c9b2546fb073192", + "name": "Dudleya", + "botanicalName": "Dudleya brittonii", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Dudleya_brittonii_01.jpg/330px-Dudleya_brittonii_01.jpg", + "imageStatus": "ok", + "description": "Dudleya ist eine rosetten┬¡bildende Sukkulente mit silbrig-weissen, mehligen Blaettern. Sehr elegant.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Volles Sonnenlicht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_db00b284aaf5553b", + "name": "Duftsteinrich", + "botanicalName": "Lobularia maritima", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Lobularia_maritima.jpg/330px-Lobularia_maritima.jpg", + "imageStatus": "ok", + "description": "Der Duftsteinrich ist ein niedrig wachsendes Pflanzchen mit winzigen, weissen oder lilafarbenen Blueten und suessem Duft.", + "categories": [ + "easy", + "flowering" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles bis volles Licht", + "temp": "10-22 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_19ba49fd14de0fd2", + "name": "Echeverie", + "botanicalName": "Echeveria elegans", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Echeveria_elegans_-_1.jpg/330px-Echeveria_elegans_-_1.jpg", + "imageStatus": "ok", + "description": "Die Echeverie bildet symmetrische, rosettenfoermige Sukkulenten mit blaugruenen Blaettern. Pflegeleicht.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Volles Sonnenlicht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_adc9e050aeb462c7", + "name": "Echter Lavendel", + "botanicalName": "Lavandula angustifolia", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Lavandula_angustifolia_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-087.jpg/330px-Lavandula_angustifolia_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-087.jpg", + "imageStatus": "ok", + "description": "Der Echte Lavendel ist ein aromatischer Halbstrauch mit lilafarbenen Bluetenaehren. Herrlicher Duft.", + "categories": [ + "medicinal", + "sun", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Volles Sonnenlicht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_2f9ab7e162ca10e4", + "name": "Efeu", + "botanicalName": "Hedera helix", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/51/Hedera_helix_-_leaves.jpg/330px-Hedera_helix_-_leaves.jpg", + "imageStatus": "ok", + "description": "Efeu ist eine robuste Kletter- und Haengepflanze mit charakteristischen, dreilappigen Blaettern. Sehr langlebig.", + "categories": [ + "easy", + "low_light", + "hanging", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Wenig bis helles Licht", + "temp": "10-20 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_81cfa08a34c49816", + "name": "Efeu-Geranie", + "botanicalName": "Pelargonium peltatum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/Pelargonium_peltatum.jpg/330px-Pelargonium_peltatum.jpg", + "imageStatus": "ok", + "description": "Die Efeu-Geranie hat efeufoermige, glaenzende Blaetter und bluet den ganzen Sommer in leuchtenden Farben.", + "categories": [ + "easy", + "flowering", + "hanging", + "sun" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_797b7521a46e11b0", + "name": "Efeutute", + "botanicalName": "Epipremnum aureum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Money_Plant_%28Epipremnum_aureum%29_4.jpg/330px-Money_Plant_%28Epipremnum_aureum%29_4.jpg", + "imageStatus": "ok", + "description": "Die Efeutute ist eine robuste Haengepflanze. Ideal fuer Anfaenger und reinigt die Raumluft.", + "categories": [ + "easy", + "low_light", + "hanging", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Wenig bis helles Licht", + "temp": "15-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_13694071ae9ffebd", + "name": "Einblatt", + "botanicalName": "Spathiphyllum wallisii", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bd/Spathiphyllum_cochlearispathum_RTBG.jpg/330px-Spathiphyllum_cochlearispathum_RTBG.jpg", + "imageStatus": "ok", + "description": "Das Einblatt besticht durch elegante weisse Blueten. Eine der besten luftreinigenden Zimmerpflanzen.", + "categories": [ + "easy", + "low_light", + "flowering", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_dc1a3a410bf856da", + "name": "Erdbeere", + "botanicalName": "Fragaria ananassa", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/29/PerfectStrawberry.jpg/330px-PerfectStrawberry.jpg", + "imageStatus": "ok", + "description": "Die Erdbeere ist ein beliebtes Obst fuer Balkon und Terrasse mit aromatischen, roten Fruechten.", + "categories": [ + "easy", + "pet_friendly", + "sun" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_3900a4af2d8f685c", + "name": "Eselschwanz", + "botanicalName": "Sedum morganianum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Sedum_morganianum.jpg/330px-Sedum_morganianum.jpg", + "imageStatus": "ok", + "description": "Der Eselschwanz ist eine haengende Sukkulente mit langen Trieben aus dichten, blaugruenen Blaettchen.", + "categories": [ + "easy", + "succulent", + "hanging", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Volles Sonnenlicht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_bcda607d5ebeba6e", + "name": "Faecherahorn", + "botanicalName": "Acer palmatum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5e/Acer_palmatum_in_Prospect_Park_edit.jpg/330px-Acer_palmatum_in_Prospect_Park_edit.jpg", + "imageStatus": "ok", + "description": "Der Faecherahorn ist ein japanischer Zierahorn mit feingeschnittenen, faecherfoermigen Blaettern in Gruen oder Rot.", + "categories": [ + "tree", + "patterned" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "10-22 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_f8e84be57621f80c", + "name": "Fass-Kaktus", + "botanicalName": "Ferocactus cylindraceus", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c3/Ferocactus_cylindraceus.jpg/330px-Ferocactus_cylindraceus.jpg", + "imageStatus": "ok", + "description": "Der Fass-Kaktus ist ein zylindrischer Wuestenkaktus mit langen, roten Stacheln. Sehr langlebig.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 21, + "light": "Volles Sonnenlicht", + "temp": "15-35 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_502fa49e2138d4e5", + "name": "Fatsia", + "botanicalName": "Fatsia japonica", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/60/Fatsia_japonica_02.jpg/330px-Fatsia_japonica_02.jpg", + "imageStatus": "ok", + "description": "Die Fatsia ist ein dekorativer Zimmerstrauch mit grossen, handfoermigen, glaenzenden Blaettern. Sehr robust.", + "categories": [ + "easy", + "low_light" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "10-20 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_4d2d5509b4c55176", + "name": "Fettkraut", + "botanicalName": "Pinguicula grandiflora", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Pinguicula_grandiflora.jpg/330px-Pinguicula_grandiflora.jpg", + "imageStatus": "ok", + "description": "Das Fettkraut faengt Insekten mit klebrigen Blaettern. Es bluet mit violetten, sporenartigen Blueten.", + "categories": [ + "flowering", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "10-20 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_321162597569e247", + "name": "Flamingoblume", + "botanicalName": "Anthurium andraeanum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/AnthuriumAndraenum.jpg/330px-AnthuriumAndraenum.jpg", + "imageStatus": "ok", + "description": "Die Flamingoblume faellt durch leuchtend rote, wachsartige Hochblaetter auf. Bluet fast das ganze Jahr.", + "categories": [ + "flowering", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_a45983ad9bacfbd3", + "name": "Flammen-Bromelie", + "botanicalName": "Vriesea splendens", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Vriesea_splendens2.jpg/330px-Vriesea_splendens2.jpg", + "imageStatus": "ok", + "description": "Die Flammen-Bromelie hat geb├ñnderte, dunkelgruene Blaetter und einen spektakulaeren, roten Bluetenstand.", + "categories": [ + "flowering", + "patterned", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_4385d6c520bf6b30", + "name": "Fleissiges Lieschen", + "botanicalName": "Impatiens walleriana", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/Impatiens_walleriana_-_Flei%C3%9Figes_Lieschen.jpg/330px-Impatiens_walleriana_-_Flei%C3%9Figes_Lieschen.jpg", + "imageStatus": "ok", + "description": "Das Fleissige Lieschen bluet von Fruehling bis Herbst unermudlich in vielen Farben.", + "categories": [ + "easy", + "flowering" + ], + "careInfo": { + "waterIntervalDays": 2, + "light": "Helles indirektes Licht", + "temp": "16-24 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_a1224f40826b5089", + "name": "Forellen-Begonie", + "botanicalName": "Begonia maculata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e5/Begonia_maculata_wightii.jpg/330px-Begonia_maculata_wightii.jpg", + "imageStatus": "ok", + "description": "Die Forellen-Begonie hat olivgruene Blaetter mit silbernen Punkten und einer roten Unterseite. Atemberaubend.", + "categories": [ + "patterned", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_fbe673c97a27643c", + "name": "Frauenhaarfarn", + "botanicalName": "Adiantum raddianum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5d/Adiantum_raddianum_2.jpg/330px-Adiantum_raddianum_2.jpg", + "imageStatus": "ok", + "description": "Der Frauenhaarfarn hat zarte, feingliedrige Wedel auf schwarzen, draht┬¡aehnlichen Stielen. Liebt Feuchtigkeit.", + "categories": [ + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_253febdb6b4c4860", + "name": "Fuchsie", + "botanicalName": "Fuchsia hybrida", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/Fuchsia_with_bee.jpg/330px-Fuchsia_with_bee.jpg", + "imageStatus": "ok", + "description": "Die Fuchsie haengt mit eleganten, zweifarbigen Blueten wie kleine Ohrringe herab. Ideal fuer Ampeln.", + "categories": [ + "flowering", + "hanging" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles indirektes Licht", + "temp": "14-22 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_7e81c1b15627e3d7", + "name": "Gardenie", + "botanicalName": "Gardenia jasminoides", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a4/Gardenia_jasminoides.jpg/330px-Gardenia_jasminoides.jpg", + "imageStatus": "ok", + "description": "Die Gardenie fasziniert mit cremefarbenen, intensiv duftenden Blueten. Anspruchsvoll in der Pflege.", + "categories": [ + "flowering", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "18-23 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_c63e701e278fa8ae", + "name": "Gasteria", + "botanicalName": "Gasteria carinata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Gasteria_bicolor_var._liliputana.jpg/330px-Gasteria_bicolor_var._liliputana.jpg", + "imageStatus": "ok", + "description": "Die Gasteria ist eine kleine Sukkulente mit zweireihig angeordneten, zungenfoermigen, gefleckten Blaettern.", + "categories": [ + "easy", + "succulent", + "low_light" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Helles indirektes Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_fa2afbb2eb4500a7", + "name": "Gebet-Pflanze", + "botanicalName": "Maranta leuconeura", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Maranta_leuconeura.jpg/330px-Maranta_leuconeura.jpg", + "imageStatus": "ok", + "description": "Die Gebet-Pflanze faltet ihre gemusterten Blaetter nachts wie Haende zusammen. Faszinierende rote und gruene Muster.", + "categories": [ + "patterned", + "high_humidity", + "pet_friendly" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_16c869313cd292ca", + "name": "Geigenfeige", + "botanicalName": "Ficus lyrata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Ficus_lyrata_%28Fiddle_leaf_Fig%29_%282939566785%29.jpg/330px-Ficus_lyrata_%28Fiddle_leaf_Fig%29_%282939566785%29.jpg", + "imageStatus": "ok", + "description": "Die Geigenfeige ist ein Trendbaum mit grossen, geigenfoermigen Blaettern. Benoetigt viel Licht.", + "categories": [ + "tree", + "bright_light", + "large" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_25cb30720168c488", + "name": "Geisterpflanze", + "botanicalName": "Graptopetalum paraguayense", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Graptopetalum_paraguayense_-_ghost_plant.jpg/330px-Graptopetalum_paraguayense_-_ghost_plant.jpg", + "imageStatus": "ok", + "description": "Die Geisterpflanze hat zartgraue bis perlmutt-rosafarbene, rosettenfoermige Blaetter. Sehr robuste Sukkulente.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Volles Sonnenlicht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_87b1168e48dec833", + "name": "Gerbera", + "botanicalName": "Gerbera jamesonii", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Gerbera_jamesonii.jpg/330px-Gerbera_jamesonii.jpg", + "imageStatus": "ok", + "description": "Die Gerbera ist eine farbenfrohe Schnittblume mit grossen, sonnenblumenaehnlichen Blueten. Sehr beliebt.", + "categories": [ + "flowering", + "bright_light", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_b93632ad7bfff83a", + "name": "Geweihfarn", + "botanicalName": "Platycerium bifurcatum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Staghorn_Fern_Platycerium_bifurcatum.jpg/330px-Staghorn_Fern_Platycerium_bifurcatum.jpg", + "imageStatus": "ok", + "description": "Der Geweihfarn hat gespaltene Wedel, die einem Hirschgeweih aehneln. Er ist ein epiphytischer Farn fuer Holz.", + "categories": [ + "hanging", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_7e449dc7aefa50dc", + "name": "Gloxinie", + "botanicalName": "Gloxinia speciosa", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Gloxinia_tubiflora.jpg/330px-Gloxinia_tubiflora.jpg", + "imageStatus": "ok", + "description": "Die Gloxinie hat grosse, samtartige Blueten in Violett, Rosa oder Weiss mit farbigen Raendern.", + "categories": [ + "flowering", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "18-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_d77c5e78b5a6cd52", + "name": "Goldene Tonne", + "botanicalName": "Echinocactus grusonii", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Echinocactus_grusonii_Hildm.jpg/330px-Echinocactus_grusonii_Hildm.jpg", + "imageStatus": "ok", + "description": "Die Goldene Tonne ist ein ikonischer kugelfoermiger Kaktus mit goldgelben Stacheln. Waechst langsam aber imposant.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 21, + "light": "Volles Sonnenlicht", + "temp": "15-35 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_86b6774738a97ccf", + "name": "Goldener Bambus", + "botanicalName": "Phyllostachys aurea", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Phyllostachys_aurea_4.jpg/330px-Phyllostachys_aurea_4.jpg", + "imageStatus": "ok", + "description": "Der Goldene Bambus hat elegante, goldgelbe Halme mit engstehenden Knoten. Sehr dekorativ als Sichtschutz.", + "categories": [ + "easy", + "large" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "10-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_cd5e679bdf1106fa", + "name": "Goldfruchtpalme", + "botanicalName": "Dypsis lutescens", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c2/Dypsis_lutescens1.jpg/330px-Dypsis_lutescens1.jpg", + "imageStatus": "ok", + "description": "Die Goldfruchtpalme ist eine elegante Zimmerpalme mit gelblich-gruenen Stielen und gefiederten Wedeln.", + "categories": [ + "air_purifier", + "tree" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_64ff12d55ec3e694", + "name": "Granatapfelbaum", + "botanicalName": "Punica granatum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9f/Garnet_Pomegranate.jpg/330px-Garnet_Pomegranate.jpg", + "imageStatus": "ok", + "description": "Der Granatapfelbaum hat leuchtend rote Blueten und rote, essbare Fruechte mit rubinroten Kernen.", + "categories": [ + "flowering", + "sun", + "tree", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "15-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_6979e7e4cf35ae8e", + "name": "Grosse Brennessel", + "botanicalName": "Urtica dioica", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ae/Urtica_dioica.jpg/330px-Urtica_dioica.jpg", + "imageStatus": "ok", + "description": "Die Grosse Brennessel ist eine Heilpflanze mit brennenden Haaren. Die Blaetter sind reich an Vitaminen und Mineralien.", + "categories": [ + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_e4804808615a29be", + "name": "Grosse Strahlenaralie", + "botanicalName": "Schefflera actinophylla", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8c/Brassaia_actinophylla_large.jpg/330px-Brassaia_actinophylla_large.jpg", + "imageStatus": "ok", + "description": "Die Grosse Strahlenaralie kann grosse, handfoermige Blaetter entwickeln. Sie ist ideal als Zimmerstrauch.", + "categories": [ + "easy", + "tree", + "large" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_0ee7b22313a79a28", + "name": "Gruene Minze", + "botanicalName": "Mentha spicata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ae/Mint-leaves-2007.jpg/330px-Mint-leaves-2007.jpg", + "imageStatus": "ok", + "description": "Die Gruene Minze ist ein wuchsfreudiges Kuechenkraut mit frischem, minzigem Duft. Fuer Tee und Cocktails.", + "categories": [ + "easy", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_52fa97990402f644", + "name": "Gruenlilie", + "botanicalName": "Chlorophytum comosum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Chlorophytum_comosum_01.jpg/330px-Chlorophytum_comosum_01.jpg", + "imageStatus": "ok", + "description": "Die Gruenlilie ist eine klassische Haengepflanze mit langen, gruen-weissen Blaettern. Sehr pflegeleicht.", + "categories": [ + "easy", + "hanging", + "pet_friendly", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_730c6fc12cf97511", + "name": "Guave", + "botanicalName": "Psidium guajava", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Guava_ID.jpg/330px-Guava_ID.jpg", + "imageStatus": "ok", + "description": "Die Guave ist ein tropischer Obstbaum mit gelblich-weissen Fruechten. Sie ist reich an Vitamin C.", + "categories": [ + "sun", + "tree", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "18-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_39c58604790693b9", + "name": "Gummibaum", + "botanicalName": "Ficus elastica", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Ficus_elastica_India_Ink_%28Rubberplant%29.jpg/330px-Ficus_elastica_India_Ink_%28Rubberplant%29.jpg", + "imageStatus": "ok", + "description": "Der Gummibaum ist eine imposante Zimmerpflanze mit grossen, glaenzenden, lederartigen Blaettern. Reinigt die Luft.", + "categories": [ + "easy", + "air_purifier", + "tree" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Helles indirektes Licht", + "temp": "16-24 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_aa6664ed7adebcb5", + "name": "Gurke", + "botanicalName": "Cucumis sativus", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/12/Cucumbers_-_whole_and_slice.jpg/330px-Cucumbers_-_whole_and_slice.jpg", + "imageStatus": "ok", + "description": "Die Gurke ist eine rankende Gemuese┬¡pflanze mit gruenen, erfrischenden Fruechten. Im Balkonkasten kultivierbar.", + "categories": [ + "easy", + "sun", + "hanging" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Volles Sonnenlicht", + "temp": "18-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_46b49e1b0e69fa64", + "name": "Guzmania", + "botanicalName": "Guzmania lingulata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Guzmania_lingulata.jpg/330px-Guzmania_lingulata.jpg", + "imageStatus": "ok", + "description": "Die Guzmania ist eine Bromelie mit gl├ñnzenden, gruenen Blaettern und einem leuchtend roten, sternfoermigen Bluetenstand.", + "categories": [ + "flowering", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_81cd86630aca39e5", + "name": "Hange-Birke", + "botanicalName": "Betula pendula", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Betula_pendula_young_leaves.jpg/330px-Betula_pendula_young_leaves.jpg", + "imageStatus": "ok", + "description": "Die Haenge-Birke hat charakteristisch weisse Rinde und haengende Zweige. Die Blaetter werden in der Heilkunde genutzt.", + "categories": [ + "medicinal", + "tree", + "large" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_f94ccafdbc6c519d", + "name": "Hasenohren-Kaktus", + "botanicalName": "Opuntia microdasys", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a3/Opuntia_microdasys_3.jpg/330px-Opuntia_microdasys_3.jpg", + "imageStatus": "ok", + "description": "Der Hasenohren-Kaktus hat flache, ovale Triebe mit dichten weissen Glochiden. Klassischer Zimmerkaktus.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 21, + "light": "Volles Sonnenlicht", + "temp": "10-35 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_f297c0da1221e6d4", + "name": "Heliamphora", + "botanicalName": "Heliamphora nutans", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Heliamphora_nutans.jpg/330px-Heliamphora_nutans.jpg", + "imageStatus": "ok", + "description": "Heliamphora ist eine urtuemliche Kannenpflanze aus den Tafelbergen Venezuelas. Sehr dekorativ und selten.", + "categories": [ + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_39436f8620e13b0e", + "name": "Heliconia", + "botanicalName": "Heliconia psittacorum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/Heliconia_psittacorum.jpg/330px-Heliconia_psittacorum.jpg", + "imageStatus": "ok", + "description": "Die Heliconia hat leuchtend orangefarbe oder rote, bootsfoermige Hochblaetter. Eine exotische Tropenpflanze.", + "categories": [ + "flowering", + "high_humidity", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "20-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_b246d39c63f29a40", + "name": "Herzblatt-Philodendron", + "botanicalName": "Philodendron hederaceum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Philodendron_hederaceum.jpg/330px-Philodendron_hederaceum.jpg", + "imageStatus": "ok", + "description": "Der Herzblatt-Philodendron ist eine pflegeleichte Kletter- oder Haengepflanze mit herzfoermigen Blaettern.", + "categories": [ + "easy", + "low_light", + "hanging" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Indirektes Licht", + "temp": "18-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_3de588912c04dc7f", + "name": "Herzkette", + "botanicalName": "Ceropegia woodii", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5b/Ceropegia_woodii_Kew.jpg/330px-Ceropegia_woodii_Kew.jpg", + "imageStatus": "ok", + "description": "Die Herzkette hat duenne, haengende Ranken mit herzfoermigen, silbergrau gemusterten Blaettchen.", + "categories": [ + "easy", + "succulent", + "hanging", + "patterned" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Helles indirektes Licht", + "temp": "15-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_8b5798718a1dc5c6", + "name": "Hibiskus", + "botanicalName": "Hibiscus rosa-sinensis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Hibiscus_rosa-sinensis_4.jpg/330px-Hibiscus_rosa-sinensis_4.jpg", + "imageStatus": "ok", + "description": "Der Hibiskus begeistert mit grossen, trompetenfoermigen Blueten in Rot, Orange und Rosa.", + "categories": [ + "flowering", + "sun", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Volles Sonnenlicht", + "temp": "18-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_0306abe03e6d7296", + "name": "Hyazinthe", + "botanicalName": "Hyacinthus orientalis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Hyacinth_Hyacinthus_orientalis.jpg/330px-Hyacinth_Hyacinthus_orientalis.jpg", + "imageStatus": "ok", + "description": "Die Hyazinthe bezaubert mit dichten Bluetenrispen und intensivem Duft in Blau, Rosa, Weiss oder Gelb.", + "categories": [ + "easy", + "flowering" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "10-18 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_4e66095e06f32cf4", + "name": "Indische Azalee", + "botanicalName": "Azalea indica", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/Indian_azalea.jpg/330px-Indian_azalea.jpg", + "imageStatus": "ok", + "description": "Die Indische Azalee ist ein beliebter Zierstrauch mit grossen, auffaelligen Blueten in Rosa- und Rott├Ânen.", + "categories": [ + "flowering" + ], + "careInfo": { + "waterIntervalDays": 4, + "light": "Helles indirektes Licht", + "temp": "10-20 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_902876241a0c1f6f", + "name": "Ingwer", + "botanicalName": "Zingiber officinale", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/33/Fresh_ginger_root.jpg/330px-Fresh_ginger_root.jpg", + "imageStatus": "ok", + "description": "Ingwer ist eine tropische Gewuerzpflanze mit aromatischen Knollen. Die Blaetter sind schilfartig.", + "categories": [ + "medicinal", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "20-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_2f9ba405e4cbd7de", + "name": "Jadepflanze", + "botanicalName": "Crassula ovata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/Crassula_ovata_3.jpg/330px-Crassula_ovata_3.jpg", + "imageStatus": "ok", + "description": "Die Jadepflanze ist eine langlebige Sukkulente mit dicken, ovalen Blaettern. In Japan gilt sie als Gluecksbringer.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Helles bis volles Licht", + "temp": "15-24 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_192fc2d6932b5621", + "name": "Japanische Aucube", + "botanicalName": "Aucuba japonica", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f2/Aucuba_japonica.jpg/330px-Aucuba_japonica.jpg", + "imageStatus": "ok", + "description": "Die Japanische Aucube hat glaenzende, gruene oder gelbgefleckte Blaetter. Sehr schattenvertraeglich.", + "categories": [ + "easy", + "low_light" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Wenig bis helles Licht", + "temp": "10-20 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_a0c9b297c07374b5", + "name": "Japanische Azalee", + "botanicalName": "Rhododendron simsii", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Rhododendron_simsii_flowers.jpg/330px-Rhododendron_simsii_flowers.jpg", + "imageStatus": "ok", + "description": "Die Japanische Azalee bluet im Winter und Fruehling ueppig mit leuchtend roten, rosa oder weissen Blueten.", + "categories": [ + "flowering" + ], + "careInfo": { + "waterIntervalDays": 4, + "light": "Helles indirektes Licht", + "temp": "10-18 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_28ae5636958be358", + "name": "Jasmin", + "botanicalName": "Jasminum polyanthum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/Jasminum_polyanthum.jpg/330px-Jasminum_polyanthum.jpg", + "imageStatus": "ok", + "description": "Der Jasmin ist eine Kletterpflanze mit intensiv duftenden, weissen Blueten. Er bluet im Winter und Fruehling.", + "categories": [ + "flowering" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "10-22 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_8fea9248ff0c7bb5", + "name": "Johanniskraut", + "botanicalName": "Hypericum perforatum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2c/Hypericum_perforatum.jpg/330px-Hypericum_perforatum.jpg", + "imageStatus": "ok", + "description": "Das Johanniskraut hat leuchtend gelbe Blueten und ist ein wichtiges Heilkraut gegen Depressionen und Stimmungstiefs.", + "categories": [ + "medicinal", + "flowering", + "sun" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_c2b3a25e00acf3e2", + "name": "Kaffeestrauch", + "botanicalName": "Coffea arabica", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Arabica_Coffee_Beans.jpg/330px-Arabica_Coffee_Beans.jpg", + "imageStatus": "ok", + "description": "Der Kaffeestrauch hat glaenzende, dunkelgruene Blaetter und entwickelt rote Kaffe┬¡ekirschen. Kann im Topf gehalten werden.", + "categories": [ + "easy", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_7597db1c1b395452", + "name": "Kalanchoe", + "botanicalName": "Kalanchoe blossfeldiana", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Kalanchoe_blossfeldiana3.jpg/330px-Kalanchoe_blossfeldiana3.jpg", + "imageStatus": "ok", + "description": "Die Kalanchoe ist eine beliebte Bluehpflanze mit leuchtenden Blueten in Rot, Orange, Gelb oder Rosa.", + "categories": [ + "easy", + "succulent", + "flowering", + "sun" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_735b19d4a6efe5c0", + "name": "Kamelie", + "botanicalName": "Camellia japonica", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Camellia_japonica_cv_Nuccio%27s_Pearl.jpg/330px-Camellia_japonica_cv_Nuccio%27s_Pearl.jpg", + "imageStatus": "ok", + "description": "Die Kamelie ist ein eleganter Zierstrauch mit glaenzenden Blaettern und rosenaehnlichen Blueten von Januar bis April.", + "categories": [ + "flowering" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "7-18 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_e0432335ee4f0033", + "name": "Kamille", + "botanicalName": "Chamomilla recutita", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cc/Chamomile_%40_Oulu.jpg/330px-Chamomile_%40_Oulu.jpg", + "imageStatus": "ok", + "description": "Die Kamille ist ein beliebtes Heilkraut mit kleinen, weiss-gelben Blueten. Das aetherische Oel wirkt beruhigend.", + "categories": [ + "easy", + "medicinal", + "sun" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Volles Sonnenlicht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_de21871ad8dcaefd", + "name": "Kaninchen-Ohren", + "botanicalName": "Kalanchoe tomentosa", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Kalanchoe_tomentosa.jpg/330px-Kalanchoe_tomentosa.jpg", + "imageStatus": "ok", + "description": "Kaninchen-Ohren haben weisslich-filzige Blaetter mit braunen Raendern, die Kaninchen┬¡ohren aehneln. Sehr dekorativ.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_cb7817f551f6c73e", + "name": "Kannenpflanze", + "botanicalName": "Nepenthes alata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c2/Nepenthes_alata_pitchers.jpg/330px-Nepenthes_alata_pitchers.jpg", + "imageStatus": "ok", + "description": "Die Kannenpflanze bildet grosse, gefuellte Kannen als Insekten┬¡fallen. Eine faszinierende, tropische Pflanze.", + "categories": [ + "high_humidity", + "hanging" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "20-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_325a00f384ac1a15", + "name": "Kap-Aloe", + "botanicalName": "Aloe arborescens", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Aloe_arborescens_flower.jpg/330px-Aloe_arborescens_flower.jpg", + "imageStatus": "ok", + "description": "Die Kap-Aloe ist eine strauchige Aloe mit schmalen, gezaehnten Blaettern und leuchtend roten Bluetenaehren im Winter.", + "categories": [ + "easy", + "succulent", + "medicinal", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Volles Sonnenlicht", + "temp": "10-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_bb4dea2113550a88", + "name": "Kap-Aloe (ferox)", + "botanicalName": "Aloe ferox", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Aloe_ferox_%28Kew%29.jpg/330px-Aloe_ferox_%28Kew%29.jpg", + "imageStatus": "ok", + "description": "Aloe ferox ist eine grosse, imposante Aloe mit stachligen, blaugruenen Blaettern und leuchtend roten Bluetenaehren.", + "categories": [ + "succulent", + "medicinal", + "sun", + "large" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Volles Sonnenlicht", + "temp": "10-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_f8c518688fd2d49b", + "name": "Karotte", + "botanicalName": "Daucus carota", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Daucus_carota_subsp._sativus.jpg/330px-Daucus_carota_subsp._sativus.jpg", + "imageStatus": "ok", + "description": "Die Karotte ist eine beliebte Gemuese┬¡pflanze mit orangefarbenen Wurzeln. Im tiefen Topf kultivierbar.", + "categories": [ + "easy", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "15-22 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_c605a83dcbce1a97", + "name": "Kentia-Palme", + "botanicalName": "Howea forsteriana", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Howea_forsteriana.jpg/330px-Howea_forsteriana.jpg", + "imageStatus": "ok", + "description": "Die Kentia-Palme ist eine der elegantesten Zimmerpalmen mit langen, herabh├ñngenden Fiederblaettern.", + "categories": [ + "tree", + "low_light" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_bf13d931fa5427de", + "name": "Keulenlilie", + "botanicalName": "Cordyline australis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/77/Cordyline_australis.jpg/330px-Cordyline_australis.jpg", + "imageStatus": "ok", + "description": "Die Keulenlilie hat lange, schmale, gruene oder rotbraune Blaetter in einem dekorativen Schopf.", + "categories": [ + "easy", + "tree", + "sun" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_205589ef30c6f380", + "name": "Kleeblume", + "botanicalName": "Oxalis triangularis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Oxalis_triangularis_ssp_papilionacea_2.jpg/330px-Oxalis_triangularis_ssp_papilionacea_2.jpg", + "imageStatus": "ok", + "description": "Die Kleeblume hat tiefviolette, dreieckige Blaetter und zarte rosa Blueten. Sie faltet die Blaetter bei Dunkelheit.", + "categories": [ + "flowering", + "patterned", + "pet_friendly" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "15-24 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_e1f0a5c763e6f721", + "name": "Kleine Wachsblume", + "botanicalName": "Hoya bella", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Hoya_bella_close.jpg/330px-Hoya_bella_close.jpg", + "imageStatus": "ok", + "description": "Die Kleine Wachsblume traegt zierliche, sternfoermige weisse Blueten mit rosa Mitte. Haengende Sukkulente.", + "categories": [ + "flowering", + "hanging", + "succulent" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_156a82fb0d4e7201", + "name": "Knollen-Begonie", + "botanicalName": "Begonia tuberhybrida", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Begonia_tuberhybrida.jpg/330px-Begonia_tuberhybrida.jpg", + "imageStatus": "ok", + "description": "Die Knollen-Begonie hat riesige, rosenaehnliche Blueten in leuchtendem Rot, Orange, Gelb oder Weiss.", + "categories": [ + "flowering", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "15-22 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_6fdbc0c3fc6d0820", + "name": "Koenigin der Nacht", + "botanicalName": "Epiphyllum oxypetalum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Epiphyllum_oxypetalum_flower.jpg/330px-Epiphyllum_oxypetalum_flower.jpg", + "imageStatus": "ok", + "description": "Die Koenigin der Nacht bluet nur eine einzige Nacht lang mit riesigen, intensiv duftenden weissen Blueten.", + "categories": [ + "flowering", + "succulent" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_fb262dee6cb22325", + "name": "Koenigs-Protea", + "botanicalName": "Protea cynaroides", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Protea_cynaroides_-_King_Protea.jpg/330px-Protea_cynaroides_-_King_Protea.jpg", + "imageStatus": "ok", + "description": "Die Koenigs-Protea ist die Nationalblume Suedafrikas mit riesigen, imposanten Bluetenkoepfen. Eine echte Besonderheit.", + "categories": [ + "flowering", + "sun", + "large" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_c18b4430b4dfeef8", + "name": "Koenigsbegonie", + "botanicalName": "Begonia rex", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/Begonia_rex_2.jpg/330px-Begonia_rex_2.jpg", + "imageStatus": "ok", + "description": "Die Koenigsbegonie beeindruckt mit prachtvoll gemusterten Blaettern in Silber, Rot und Gruen.", + "categories": [ + "patterned", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Indirektes Licht", + "temp": "18-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_71f244d60e9fb18d", + "name": "Konophytum", + "botanicalName": "Conophytum calculus", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Conophytum_calculus.jpg/330px-Conophytum_calculus.jpg", + "imageStatus": "ok", + "description": "Das Konophytum ist eine sehr kompakte Sukkulente, die zwei Blaetter zu einer kugelfoermigen Form verschmilzt.", + "categories": [ + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 21, + "light": "Volles Sonnenlicht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_5f6dd525e28bd218", + "name": "Korallenkaktus", + "botanicalName": "Rhipsalis baccifera", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a1/Rhipsalis_baccifera0.jpg/330px-Rhipsalis_baccifera0.jpg", + "imageStatus": "ok", + "description": "Der Korallenkaktus ist ein epiphytischer Kaktus mit duennen, haengenden Trieben und kleinen weissen Beeren.", + "categories": [ + "succulent", + "hanging" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_fd037b7881ac3430", + "name": "Korbmarante", + "botanicalName": "Calathea orbifolia", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Starr_080716-9470_Calathea_crotalifera.jpg/330px-Starr_080716-9470_Calathea_crotalifera.jpg", + "imageStatus": "ok", + "description": "Die Korbmarante beeindruckt mit grossen, runden Blaettern mit silbergrunem Muster. Liebt hohe Luftfeuchtigkeit.", + "categories": [ + "patterned", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Indirektes Licht", + "temp": "18-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_612f629e95b2c540", + "name": "Kotyledon", + "botanicalName": "Cotyledon orbiculata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Cotyledon_orbiculata2.jpg/330px-Cotyledon_orbiculata2.jpg", + "imageStatus": "ok", + "description": "Kotyledon hat dickfleischige, runde Blaetter mit einem mehligen, weisslichen Belag. Sehr trockenheitsresistent.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_adce82fe150c9814", + "name": "Krokus", + "botanicalName": "Crocus vernus", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/Crocus_vernus_1.jpg/330px-Crocus_vernus_1.jpg", + "imageStatus": "ok", + "description": "Der Krokus ist einer der ersten Fruehjahrs┬¡boten mit kelchfoermigen Blueten in Lila, Weiss und Gelb.", + "categories": [ + "easy", + "flowering" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "5-15 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_64ba168636b5e8a3", + "name": "Kurkuma", + "botanicalName": "Curcuma longa", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Curcuma_longa_roots.jpg/330px-Curcuma_longa_roots.jpg", + "imageStatus": "ok", + "description": "Kurkuma ist eine tropische Gewuerzpflanze mit breiten Blaettern und leuchtend gelber Wurzel. Wichtiges Heilgewuerz.", + "categories": [ + "medicinal", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "20-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_bb51efcb52023c48", + "name": "Lebende Steine", + "botanicalName": "Lithops julii", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Lithops_julii_ssp_fulleri_vanzylii_cole_no._246.jpg/330px-Lithops_julii_ssp_fulleri_vanzylii_cole_no._246.jpg", + "imageStatus": "ok", + "description": "Lebende Steine sind faszinierende Mimikry-Sukkulenten, die Kieselsteinen taeuschen aehnlich sehen. Sehr trockenheitsresistent.", + "categories": [ + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 21, + "light": "Volles Sonnenlicht", + "temp": "10-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_0a16a89a9de52d5c", + "name": "Lila Tradescantia", + "botanicalName": "Tradescantia pallida", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Purple_tradescantia.jpg/330px-Purple_tradescantia.jpg", + "imageStatus": "ok", + "description": "Die Lila Tradescantia hat leuchtend purpurrote Blaetter und ist sehr auffaellig. Sie liebt viel Licht.", + "categories": [ + "easy", + "hanging", + "sun" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_a34bdd68ffb97e12", + "name": "Lippenstiftpflanze", + "botanicalName": "Aeschynanthus radicans", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Aeschynanthus_lobbianus.jpg/330px-Aeschynanthus_lobbianus.jpg", + "imageStatus": "ok", + "description": "Die Lippenstiftpflanze hat haengende Triebe mit glaenzenden Blaettern und leuchtend roten Roehrenbluten.", + "categories": [ + "flowering", + "hanging", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_db7b7c883a5fb716", + "name": "Luftpflanze", + "botanicalName": "Tillandsia ionantha", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f6/Tillandsia_ionantha.jpg/330px-Tillandsia_ionantha.jpg", + "imageStatus": "ok", + "description": "Die Luftpflanze ist eine kompakte Bromelie ohne Topferde. Sie nimmt Wasser und Naehrstoffe ueber die Blattschuppen auf.", + "categories": [ + "easy", + "sun" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles bis volles Licht", + "temp": "15-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_fafb81415756f893", + "name": "Madagaskar-Jasmin", + "botanicalName": "Stephanotis floribunda", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Stephanotis_floribunda1.jpg/330px-Stephanotis_floribunda1.jpg", + "imageStatus": "ok", + "description": "Der Madagaskar-Jasmin hat dicke, glaenzende Blaetter und wachsweisse, intensiv duftende Blueten. Klassische Hochzeitsblume.", + "categories": [ + "flowering" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_cabb9c3df66307ba", + "name": "Maisstrauch", + "botanicalName": "Dracaena fragrans", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Dracaena_fragrans_-_Corn_Plant_%283622131419%29.jpg/330px-Dracaena_fragrans_-_Corn_Plant_%283622131419%29.jpg", + "imageStatus": "ok", + "description": "Der Maisstrauch ist eine robuste Zimmerpflanze mit breiten, gestreiften Blaettern. Gedeiht auch bei wenig Licht.", + "categories": [ + "easy", + "low_light", + "air_purifier", + "tree" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Helles indirektes Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_d52a80feceba729c", + "name": "Mammillaria", + "botanicalName": "Mammillaria zeilmanniana", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Mammillaria_zeilmanniana_2.jpg/330px-Mammillaria_zeilmanniana_2.jpg", + "imageStatus": "ok", + "description": "Die Mammillaria ist ein kompakter, kugelfoermiger Kaktus, der im Fruehling einen Kranz aus rosa Blueten traegt.", + "categories": [ + "easy", + "succulent", + "flowering", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Volles Sonnenlicht", + "temp": "15-35 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_9406fa4ffbef305b", + "name": "Mangold", + "botanicalName": "Beta vulgaris", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Chard_multicolored.jpg/330px-Chard_multicolored.jpg", + "imageStatus": "ok", + "description": "Mangold ist ein farbenfrohes Blattgemuese mit bunten Stielen in Rot, Gelb, Orange und Weiss.", + "categories": [ + "easy", + "patterned" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles bis volles Licht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_ca9b1576aab12566", + "name": "Marmor-Efeutute", + "botanicalName": "Epipremnum aureum Marble Queen", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Epipremnum_aureum_31082012.jpg/330px-Epipremnum_aureum_31082012.jpg", + "imageStatus": "ok", + "description": "Die Marmor-Efeutute hat cremeweiss-gruen marmorierte Blaetter. Eine dekorative Variante der klassischen Efeutute.", + "categories": [ + "easy", + "hanging", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "15-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_95de7815c2f690ce", + "name": "Mexikanische F├ñcherpalme", + "botanicalName": "Washingtonia robusta", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Washingtonia_robusta_2.jpg/330px-Washingtonia_robusta_2.jpg", + "imageStatus": "ok", + "description": "Die Mexikanische F├ñcherpalme ist eine schlanke, hohe Palme mit faecher┬¡foermigen Blaettern. Sehr hitzetolerant.", + "categories": [ + "tree", + "sun", + "large" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Volles Sonnenlicht", + "temp": "15-35 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_01ed2f643e7d5d8e", + "name": "Mini-Monstera", + "botanicalName": "Rhaphidophora tetrasperma", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Rhaphidophora_tetrasperma_01.jpg/330px-Rhaphidophora_tetrasperma_01.jpg", + "imageStatus": "ok", + "description": "Die Mini-Monstera hat monstera┬¡aehnliche, gelochte Blaetter auf einer kompakten, klettternden Pflanze. Sehr trendig.", + "categories": [ + "easy", + "hanging" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_8e8b8bf4c4f7bdb6", + "name": "Mond-Kaktus", + "botanicalName": "Gymnocalycium mihanovichii", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/Gymnocalycium_mihanovichii.jpg/330px-Gymnocalycium_mihanovichii.jpg", + "imageStatus": "ok", + "description": "Der Mond-Kaktus ist eine farbenfrohe Veredelung eines chlorophylllosen Kaktus auf einem gruenen Unterlagekaktus.", + "categories": [ + "easy", + "succulent" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Indirektes Licht", + "temp": "15-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_e8ab689f2d26d8b2", + "name": "Mondstein-Pflanze", + "botanicalName": "Pachyphytum oviferum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Pachyphytum_oviferum_%28Moonstones%29.jpg/330px-Pachyphytum_oviferum_%28Moonstones%29.jpg", + "imageStatus": "ok", + "description": "Die Mondstein-Pflanze hat dicke, ovale Blaetter mit einem pastellrosafarbenen, mehligen Ueberzug.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Volles Sonnenlicht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_8106ae1b2a8d0a09", + "name": "Monstera", + "botanicalName": "Monstera deliciosa", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Monstera_deliciosa2.jpg/330px-Monstera_deliciosa2.jpg", + "imageStatus": "ok", + "description": "Die Monstera ist eine tropische Kletterpflanze mit charakteristisch gelochten Blaettern. Sehr beliebt weltweit.", + "categories": [ + "easy", + "large", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_b843de18953d2232", + "name": "Monstera adansonii", + "botanicalName": "Monstera adansonii", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bd/Monstera_adansonii_1.jpg/330px-Monstera_adansonii_1.jpg", + "imageStatus": "ok", + "description": "Monstera adansonii hat herzfoermige Blaetter mit zahlreichen runden Lochern. Eine rankende Zimmerpflanze.", + "categories": [ + "easy", + "hanging" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_44c152d886d0b190", + "name": "Monstera obliqua", + "botanicalName": "Monstera obliqua", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/Monstera_obliqua.jpg/330px-Monstera_obliqua.jpg", + "imageStatus": "ok", + "description": "Monstera obliqua ist eine seltene Monstera-Art mit filigranen Blaettern, die hauptsaechlich aus Lochern bestehen.", + "categories": [ + "hanging", + "patterned" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_da8adeffa961a540", + "name": "Moos-Crassula", + "botanicalName": "Crassula muscosa", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ae/Crassula_muscosa.jpg/330px-Crassula_muscosa.jpg", + "imageStatus": "ok", + "description": "Die Moos-Crassula hat dicht aneinandergereihte, winzige gruene Blaetter auf unverzweigten Trieben. Sieht aus wie Moos.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_917a7775d4ada0c1", + "name": "Muschelingwer", + "botanicalName": "Alpinia zerumbet", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c0/Alpinia_zerumbet_3.jpg/330px-Alpinia_zerumbet_3.jpg", + "imageStatus": "ok", + "description": "Der Muschelingwer hat lange, elegante Blaetter und haengende Bluetenrispen mit weiss-rosa Bluetchen.", + "categories": [ + "flowering", + "high_humidity", + "large" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "20-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_de18a22fc81062c9", + "name": "Neon-Efeutute", + "botanicalName": "Epipremnum pinnatum Neon", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/04/Epipremnum_pinnatum_-_neon_pothos.jpg/330px-Epipremnum_pinnatum_-_neon_pothos.jpg", + "imageStatus": "ok", + "description": "Die Neon-Efeutute hat leuchtend limonengruene Blaetter. Sehr auffaellig und pflegeleicht.", + "categories": [ + "easy", + "hanging", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "15-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_3d4bc95e6500e9fc", + "name": "Neoregelia", + "botanicalName": "Neoregelia carolinae", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Neoregelia_carolinae.jpg/330px-Neoregelia_carolinae.jpg", + "imageStatus": "ok", + "description": "Die Neoregelia ist eine Bromelie, bei der das Herzblatt zur Bluetzeit leuchtend rot wird. Sehr dekorativ.", + "categories": [ + "flowering", + "patterned", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_c62ac934518110bb", + "name": "Neuguinea-Balsamine", + "botanicalName": "Impatiens hawkeri", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Impatiens_hawkeri.jpg/330px-Impatiens_hawkeri.jpg", + "imageStatus": "ok", + "description": "Die Neuguinea-Balsamine hat grosse, leuchtende Blueten und ist sehr bluehfreudig. Ideal fuer Terrassen.", + "categories": [ + "easy", + "flowering" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_3dec7298828d7d5b", + "name": "Oleander", + "botanicalName": "Nerium oleander", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Nerium_oleander_flowers_leaves.jpg/330px-Nerium_oleander_flowers_leaves.jpg", + "imageStatus": "ok", + "description": "Der Oleander ist ein mediteraner Strauch mit leuchtend roten, rosa oder weissen Blueten. Sehr hitzetolerant.", + "categories": [ + "flowering", + "sun", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "15-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_8915ad2e41841f3d", + "name": "Orangenbaum", + "botanicalName": "Citrus sinensis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Ambersweet_oranges.jpg/330px-Ambersweet_oranges.jpg", + "imageStatus": "ok", + "description": "Der Orangenbaum ist ein kleiner, immergruener Baum mit weissen Blueten und orangen Fruechten.", + "categories": [ + "sun", + "tree", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Volles Sonnenlicht", + "temp": "18-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_d61f0c50e94b917d", + "name": "Oregano", + "botanicalName": "Origanum vulgare", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Origanum_vulgare_-_harilik_pune.jpg/330px-Origanum_vulgare_-_harilik_pune.jpg", + "imageStatus": "ok", + "description": "Oregano ist ein aromatisches Kuechenkraut mit runden, behaarten Blaettern. In mediterraner Kueche beliebt.", + "categories": [ + "easy", + "medicinal", + "sun" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_a62147e5f0805622", + "name": "Osterglocke", + "botanicalName": "Narcissus pseudonarcissus", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0a/Narcissus_pseudonarcissus.jpg/330px-Narcissus_pseudonarcissus.jpg", + "imageStatus": "ok", + "description": "Die Osterglocke ist der klassische Fruehjahrsblueher mit leuchtend gelben, trompetenfoermigen Blueten.", + "categories": [ + "flowering" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "10-18 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_f66ecda188a5efad", + "name": "Ostertrompete", + "botanicalName": "Lilium longiflorum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Lilium_longiflorum_Ether.jpg/330px-Lilium_longiflorum_Ether.jpg", + "imageStatus": "ok", + "description": "Die Ostertrompete hat grosse, weisse, trichterfoermige Blueten mit intensivem Duft. Klassische Osterblume.", + "categories": [ + "flowering", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_e4f082a4e9f3a8c5", + "name": "Papaya", + "botanicalName": "Carica papaya", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d0/Papaya_cross_section_BNC.jpg/330px-Papaya_cross_section_BNC.jpg", + "imageStatus": "ok", + "description": "Die Papaya ist eine tropische Fruchtpflanze mit grossen, gelappten Blaettern und orangen Fruechten.", + "categories": [ + "sun", + "large", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Volles Sonnenlicht", + "temp": "20-35 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_612cf58237a77a91", + "name": "Paradiesvogelblume", + "botanicalName": "Strelitzia reginae", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a1/24701-nature-natural-beauty.jpg/330px-24701-nature-natural-beauty.jpg", + "imageStatus": "ok", + "description": "Die Paradiesvogelblume beeindruckt mit leuchtend orangefarbenen und blauen Blueten, die einem Vogel aehneln.", + "categories": [ + "flowering", + "sun", + "large" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "18-26 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_61ec02f0a706b922", + "name": "Paragraphenpflanze", + "botanicalName": "Cyperus alternifolius", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Cyperus_alternifolius_2.jpg/330px-Cyperus_alternifolius_2.jpg", + "imageStatus": "ok", + "description": "Die Paragraphenpflanze hat lange, grasartige Blaetter, die sternfoermig vom Stiel abstehen. Sie liebt viel Wasser.", + "categories": [ + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles bis volles Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_13543a8abb8f50c8", + "name": "Passionsblume", + "botanicalName": "Passiflora caerulea", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Passiflora_caerulea.jpg/330px-Passiflora_caerulea.jpg", + "imageStatus": "ok", + "description": "Die Passionsblume ist eine faszinierende Kletterpflanze mit komplex strukturierten, blau-weissen Blueten.", + "categories": [ + "flowering", + "hanging" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "15-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_b9a0c1910297e2cb", + "name": "Perlenschnur-Pflanze", + "botanicalName": "Senecio rowleyanus", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/04/Senecio_rowleyanus_2.jpg/330px-Senecio_rowleyanus_2.jpg", + "imageStatus": "ok", + "description": "Die Perlenschnur-Pflanze hat haengende Ranken mit kugelfoermigen, perlenaehnlichen Blaettern. Einzigartige Sukkulente.", + "categories": [ + "easy", + "succulent", + "hanging" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Helles bis volles Licht", + "temp": "15-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_ab8fc977bd930772", + "name": "Peruanischer Fackelkaktus", + "botanicalName": "Cereus peruvianus", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/79/Cereus_repandus.jpg/330px-Cereus_repandus.jpg", + "imageStatus": "ok", + "description": "Der Peruanische Fackelkaktus ist ein saeulenfoermiger Kaktus, der im Innenraum bis zu 2 m hoch werden kann.", + "categories": [ + "easy", + "succulent", + "sun", + "large" + ], + "careInfo": { + "waterIntervalDays": 21, + "light": "Volles Sonnenlicht", + "temp": "15-35 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_f57319d9209a678f", + "name": "Petersilie", + "botanicalName": "Petroselinum crispum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/39/Petroselinum_crispum.jpg/330px-Petroselinum_crispum.jpg", + "imageStatus": "ok", + "description": "Petersilie ist eines der meistgenutzten Kuechenkraeuter mit frisch-aromatischem Geschmack. Reich an Vitaminen.", + "categories": [ + "easy", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles Licht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_d859b55b599f2742", + "name": "Petunie", + "botanicalName": "Petunia hybrida", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3d/Petunia_hybrida_hort.%2C_flowers.jpg/330px-Petunia_hybrida_hort.%2C_flowers.jpg", + "imageStatus": "ok", + "description": "Die Petunie ist eine der beliebtesten Balkonpflanzen mit trichterfoermigen Blueten in unzaehligen Farben.", + "categories": [ + "easy", + "flowering", + "sun" + ], + "careInfo": { + "waterIntervalDays": 2, + "light": "Volles Sonnenlicht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_9f46ccdc5b9b10f3", + "name": "Pfeilblatt", + "botanicalName": "Syngonium podophyllum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Syngonium_podophyllum_-_Flickr_-_peganum.jpg/330px-Syngonium_podophyllum_-_Flickr_-_peganum.jpg", + "imageStatus": "ok", + "description": "Das Pfeilblatt hat charakteristisch pfeilfoermige Blaetter, die sich mit dem Alter weiterentwickeln.", + "categories": [ + "easy", + "hanging" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "16-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_c7b763cec4d30529", + "name": "Pferdeschwanzpalme", + "botanicalName": "Beaucarnea recurvata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Beaucarnea_recurvata.jpg/330px-Beaucarnea_recurvata.jpg", + "imageStatus": "ok", + "description": "Die Pferdeschwanzpalme hat einen verdickten Stammbasis als Wasserspeicher und lange, schmale Blaetter.", + "categories": [ + "easy", + "succulent", + "tree", + "sun" + ], + "careInfo": { + "waterIntervalDays": 21, + "light": "Volles Sonnenlicht", + "temp": "15-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_418e4442c57e9974", + "name": "Philodendron bipinnatifidum", + "botanicalName": "Philodendron bipinnatifidum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Philodendron_bipinnatifidum_kz01.jpg/330px-Philodendron_bipinnatifidum_kz01.jpg", + "imageStatus": "ok", + "description": "Philodendron bipinnatifidum hat grosse, tief gelappte Blaetter. Er entwickelt einen beeindruckenden, baumfoermigen Wuchs.", + "categories": [ + "easy", + "large" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_64223543ba5ff673", + "name": "Philodendron gloriosum", + "botanicalName": "Philodendron gloriosum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/52/Philodendron_gloriosum1.jpg/330px-Philodendron_gloriosum1.jpg", + "imageStatus": "ok", + "description": "Philodendron gloriosum hat grosse, samtige, herzfoermige Blaetter mit weissen Rippen. Eine atemberaubende Pflanze.", + "categories": [ + "patterned", + "high_humidity", + "large" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_6a5d7ac021669bb4", + "name": "Primel", + "botanicalName": "Primula vulgaris", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Primula_vulgaris_white.jpg/330px-Primula_vulgaris_white.jpg", + "imageStatus": "ok", + "description": "Die Primel ist einer der ersten Fruehjahrs┬¡boten mit lebhaften Blueten in Gelb, Pink, Rot und Lila.", + "categories": [ + "flowering" + ], + "careInfo": { + "waterIntervalDays": 4, + "light": "Helles indirektes Licht", + "temp": "10-18 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_045dd35819e8793f", + "name": "Purpursonnentau", + "botanicalName": "Sarracenia purpurea", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Sarracenia_purpurea.jpg/330px-Sarracenia_purpurea.jpg", + "imageStatus": "ok", + "description": "Der Purpursonnentau ist eine fleischfressende Kannenpflanze mit purpurroten Kannen. Faengt Insekten.", + "categories": [ + "sun", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Volles Sonnenlicht", + "temp": "5-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_1feebf3d053224a9", + "name": "Radieschen", + "botanicalName": "Raphanus sativus", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Radish_ps10.jpg/330px-Radish_ps10.jpg", + "imageStatus": "ok", + "description": "Das Radieschen ist ein schnellwachsendes Gemuese mit runden, roten Knollen. Es reift in nur 3-4 Wochen.", + "categories": [ + "easy" + ], + "careInfo": { + "waterIntervalDays": 2, + "light": "Helles bis volles Licht", + "temp": "10-22 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_563226faba183e0d", + "name": "Regenbogenmoos", + "botanicalName": "Selaginella uncinata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/09/Selaginella_uncinata_at_SBG.jpg/330px-Selaginella_uncinata_at_SBG.jpg", + "imageStatus": "ok", + "description": "Das Regenbogenmoos hat schuppenfoermige Blaetter, die im Licht schillernd irisieren. Dekorativ fuer Terrarien.", + "categories": [ + "high_humidity", + "patterned" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_a6883747d701df71", + "name": "Riemenblatt", + "botanicalName": "Clivia miniata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/21/Clivia_miniata.jpg/330px-Clivia_miniata.jpg", + "imageStatus": "ok", + "description": "Das Riemenblatt ist eine dekorative Zimmerpflanze mit leuchtend orangefarbenen Blueten im Fruehling.", + "categories": [ + "flowering", + "low_light" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Helles indirektes Licht", + "temp": "15-24 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_5e0e0211b3e815d1", + "name": "Rippenpeperomie", + "botanicalName": "Peperomia caperata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Peperomia_caperata_Rosso.jpg/330px-Peperomia_caperata_Rosso.jpg", + "imageStatus": "ok", + "description": "Die Rippenpeperomie hat tief gerippte, dunkelgruene bis violette Blaetter mit einer samtigen Textur.", + "categories": [ + "easy", + "pet_friendly" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Helles indirektes Licht", + "temp": "18-26 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_f3c4aea00446ce7d", + "name": "Ritterstern", + "botanicalName": "Hippeastrum hybrid", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Hippeastrum_%27Red_Lion%27.jpg/330px-Hippeastrum_%27Red_Lion%27.jpg", + "imageStatus": "ok", + "description": "Der Ritterstern beeindruckt im Winter mit riesigen, trompetenfoermigen Blueten in Rot, Pink oder Weiss.", + "categories": [ + "flowering", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "18-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_ce9ff96b95f4fe81", + "name": "Rosengeranie", + "botanicalName": "Pelargonium graveolens", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/81/Pelargonium_graveolens.jpg/330px-Pelargonium_graveolens.jpg", + "imageStatus": "ok", + "description": "Die Rosengeranie ist eine Duftpflanze mit tief eingeschnittenen Blaettern und rosaenlichem Aroma.", + "categories": [ + "easy", + "medicinal", + "sun" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_bc06c3ee948f7ba7", + "name": "Rosmarin", + "botanicalName": "Rosmarinus officinalis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ae/Rosemary_bush.jpg/330px-Rosemary_bush.jpg", + "imageStatus": "ok", + "description": "Rosmarin ist ein aromatisches Kraut mit nadelartigen Blaettern und blauen Blueten. In der Kueche unverzichtbar.", + "categories": [ + "easy", + "medicinal", + "sun" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_a50df676efef7b7d", + "name": "Roter Fingerhut", + "botanicalName": "Digitalis purpurea", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a1/Digitalis_purpurea_Koehler.jpg/330px-Digitalis_purpurea_Koehler.jpg", + "imageStatus": "ok", + "description": "Der Rote Fingerhut hat hohe Bluetenstaende mit roehrenfoermigen, gepunkteten Blueten in Rosa. Wichtige Arzneipflanze.", + "categories": [ + "medicinal", + "flowering" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "10-20 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_4f9c3ae955d4b1b0", + "name": "Roter Philodendron", + "botanicalName": "Philodendron erubescens", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Philodendron_erubescens.jpg/330px-Philodendron_erubescens.jpg", + "imageStatus": "ok", + "description": "Der Rote Philodendron hat glaenzende, herzfoermige Blaetter, die jung roetrlich erscheinen. Sehr dekorativ.", + "categories": [ + "easy", + "hanging" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_b6887f02c51a178f", + "name": "Salat", + "botanicalName": "Lactuca sativa", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/Lettuce_in_garden.jpg/330px-Lettuce_in_garden.jpg", + "imageStatus": "ok", + "description": "Salat ist eine schnell wachsende Blattgemuese┬¡pflanze. Im Topf und Balkonkasten sehr gut zu kultivieren.", + "categories": [ + "easy" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles bis volles Licht", + "temp": "10-22 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_e3f7fa02342527b0", + "name": "Salbei", + "botanicalName": "Salvia officinalis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Salvia_officinalis_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-118.jpg/330px-Salvia_officinalis_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-118.jpg", + "imageStatus": "ok", + "description": "Salbei ist ein aromatisches Heilkraut mit silbrig-gruenen Blaettern. Er hat antibakterielle und entzuendungshem┬¡mende Wirkung.", + "categories": [ + "easy", + "medicinal", + "sun" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_5ce8d8944fd3edc3", + "name": "San-Pedro-Kaktus", + "botanicalName": "Echinopsis pachanoi", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3d/Echinopsis_pachanoi.jpg/330px-Echinopsis_pachanoi.jpg", + "imageStatus": "ok", + "description": "Der San-Pedro-Kaktus ist ein schnell wachsender, saeulenfoermiger Kaktus aus den Anden.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Volles Sonnenlicht", + "temp": "10-35 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_d30b54367d7c0ccc", + "name": "Satinpothos", + "botanicalName": "Scindapsus pictus", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/65/Scindapsus_pictus.jpg/330px-Scindapsus_pictus.jpg", + "imageStatus": "ok", + "description": "Der Satinpothos hat samtig-glaenzende, silbrig gefleckte Blaetter auf langen, haengenden Ranken.", + "categories": [ + "easy", + "hanging", + "patterned" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_cbc9b35001d4f2fa", + "name": "Schafgarbe", + "botanicalName": "Achillea millefolium", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Achillea_millefolium.jpg/330px-Achillea_millefolium.jpg", + "imageStatus": "ok", + "description": "Die Schafgarbe hat weisse oder rosafarbene Bluetenschirme und fein gefiederte Blaetter. Wichtige Heilpflanze.", + "categories": [ + "medicinal", + "flowering", + "sun" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_ceea5c9d9b527cea", + "name": "Schamkraut", + "botanicalName": "Mimosa pudica", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Mimosa_pudica_touch.jpg/330px-Mimosa_pudica_touch.jpg", + "imageStatus": "ok", + "description": "Das Schamkraut faltet seine Blaettchen blitzschnell zusammen, wenn man sie beruehrt. Ein faszinierendes Erlebnis.", + "categories": [ + "easy", + "pet_friendly" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "20-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_f02576d98e962040", + "name": "Schmetterlingsorchidee", + "botanicalName": "Phalaenopsis amabilis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Phalaenopsis_amabilis_Orchi_054.jpg/330px-Phalaenopsis_amabilis_Orchi_054.jpg", + "imageStatus": "ok", + "description": "Die Schmetterlingsorchidee ist die bekannteste Zimmerorchidee. Sie bluet bei guter Pflege monatelang.", + "categories": [ + "flowering", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Helles indirektes Licht", + "temp": "18-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_1b8072d12aee4246", + "name": "Schnittlauch", + "botanicalName": "Allium schoenoprasum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Allium_schoenoprasum_close_up.jpg/330px-Allium_schoenoprasum_close_up.jpg", + "imageStatus": "ok", + "description": "Schnittlauch ist ein beliebtes Kuechenkraut mit roehrenfoermigen Blaettern und lila Blueten.", + "categories": [ + "easy", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles bis volles Licht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_2dcb1ec9ac8b968f", + "name": "Schraubenbaum", + "botanicalName": "Pandanus veitchii", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7e/Pandanus_utilis_Reunion.jpg/330px-Pandanus_utilis_Reunion.jpg", + "imageStatus": "ok", + "description": "Der Schraubenbaum hat spiralfoermig angeordnete, gruenweiss gestreifte Blaetter. Sehr dekorativ und exotisch.", + "categories": [ + "patterned", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_40f7fbbd6ef0e3ba", + "name": "Schusterpflanze", + "botanicalName": "Aspidistra elatior", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Aspidistra_elatior1.jpg/330px-Aspidistra_elatior1.jpg", + "imageStatus": "ok", + "description": "Die Schusterpflanze ist eine extrem robuste Zimmerpflanze mit langen, dunkelgruenen Blaettern. Vertraegt tiefe Temperaturen.", + "categories": [ + "easy", + "low_light" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Wenig bis helles Licht", + "temp": "10-20 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_fb7db49b3c127f71", + "name": "Schwarze Rose (Aeonium)", + "botanicalName": "Aeonium arboreum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e2/Aeonium_arboreum_-_Schwarze_Rose_-_2009-03-14_-_Jardim_Botanico_Madeira_3.jpg/330px-Aeonium_arboreum_-_Schwarze_Rose_-_2009-03-14_-_Jardim_Botanico_Madeira_3.jpg", + "imageStatus": "ok", + "description": "Das Aeonium bildet dekorative, rosettenfoermige Sukkulenten an verzweigten Stielen.", + "categories": [ + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Volles Sonnenlicht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_183e544c5601be51", + "name": "Schwarzer Holunder", + "botanicalName": "Sambucus nigra", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Sambucus_nigra_2.jpg/330px-Sambucus_nigra_2.jpg", + "imageStatus": "ok", + "description": "Der Schwarze Holunder hat weisse Doldenbluten und schwarze Beeren. Die Fruechte werden fuer Sirup und Saft verwendet.", + "categories": [ + "medicinal", + "tree", + "flowering" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_fc5f536d0b2ff76e", + "name": "Schwertfarn", + "botanicalName": "Nephrolepis exaltata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/30/Boston_Fern_%282873392811%29.png/330px-Boston_Fern_%282873392811%29.png", + "imageStatus": "ok", + "description": "Der Schwertfarn ist ein klassischer Zimmerfarn mit eleganten, herabh├ñngenden Wedeln. Liebt Feuchtigkeit.", + "categories": [ + "hanging", + "high_humidity", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles indirektes Licht", + "temp": "16-24 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_3c6961985d686c33", + "name": "Silber-Weide", + "botanicalName": "Salix alba", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/42/Salix_alba_Morton.jpg/330px-Salix_alba_Morton.jpg", + "imageStatus": "ok", + "description": "Die Silber-Weide hat silbrig-glaenzende Blaetter. Weidenrinde enth├ñlt Salicylsaeure, die Grundlage von Aspirin.", + "categories": [ + "medicinal", + "tree", + "large" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_4d4483c9e8f98e94", + "name": "Silbervase", + "botanicalName": "Aechmea fasciata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Aechmea_fasciata1.jpg/330px-Aechmea_fasciata1.jpg", + "imageStatus": "ok", + "description": "Die Silbervase ist eine Bromelie mit silbrig geb├ñnderten Blaettern und einem rosafarbenen Bluetenstand.", + "categories": [ + "flowering", + "patterned" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Helles indirektes Licht", + "temp": "18-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_24c71b67fe2ed42a", + "name": "Socotra-Wuestenrose", + "botanicalName": "Adenium socotranum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/88/Adenium_socotranum_2.jpg/330px-Adenium_socotranum_2.jpg", + "imageStatus": "ok", + "description": "Die Socotra-Wuestenrose ist eine seltene, endemische Art mit einem sehr dicken, knolligen Stamm und rosa Blueten.", + "categories": [ + "succulent", + "flowering", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Volles Sonnenlicht", + "temp": "20-35 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_a91db7a3318f3302", + "name": "Sonnenhut", + "botanicalName": "Echinacea purpurea", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/Purple_coneflower_Echinacea_purpurea.jpg/330px-Purple_coneflower_Echinacea_purpurea.jpg", + "imageStatus": "ok", + "description": "Der Sonnenhut ist eine beliebte Heilpflanze mit grossen, pinkfarbenen Blueten. Er staerkt das Immunsystem.", + "categories": [ + "medicinal", + "flowering", + "sun" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_0aa802b967afc69a", + "name": "Sonnentau", + "botanicalName": "Drosera capensis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Drosera_capensis.jpg/330px-Drosera_capensis.jpg", + "imageStatus": "ok", + "description": "Der Sonnentau faengt Insekten mit klebrigen Tropfen auf seinen Blaettern. Eine faszinierende fleischfressende Pflanze.", + "categories": [ + "sun", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Volles Sonnenlicht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_db7dd5c2bff6c42d", + "name": "Spanisches Moos", + "botanicalName": "Tillandsia usneoides", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Tillandsia_usneoides_0002.jpg/330px-Tillandsia_usneoides_0002.jpg", + "imageStatus": "ok", + "description": "Das Spanische Moos ist eine epiphytische Bromelie ohne Wurzeln, die in der Luft haengt. Es benoetigt nur Feuchtigkeitsbespruehing.", + "categories": [ + "easy", + "hanging", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles bis volles Licht", + "temp": "15-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_ac11d9bd0c391e9d", + "name": "Speckbaum", + "botanicalName": "Portulacaria afra", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Portulacaria_afra_2.jpg/330px-Portulacaria_afra_2.jpg", + "imageStatus": "ok", + "description": "Der Speckbaum ist eine sukkulente Pflanze mit roten Stielen und kleinen, runden, glaenzenden Blaettern.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Helles bis volles Licht", + "temp": "15-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_477dc83da2cd56cb", + "name": "Spiegelpeperomie", + "botanicalName": "Peperomia obtusifolia", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7c/Peperomia_obtusifolia1.jpg/330px-Peperomia_obtusifolia1.jpg", + "imageStatus": "ok", + "description": "Die Spiegelpeperomie hat glaenzende, lederartige, oval-runde Blaetter in tiefem Gruen. Sehr robust.", + "categories": [ + "easy", + "pet_friendly", + "low_light" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Helles indirektes Licht", + "temp": "16-26 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_4f624a47f15a976c", + "name": "Spinat", + "botanicalName": "Spinacia oleracea", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Spinach_leaves.jpg/330px-Spinach_leaves.jpg", + "imageStatus": "ok", + "description": "Spinat ist ein naehrstoffreiches Blattgemuese mit dunkelgruenen Blaettern. Reich an Eisen und Vitaminen.", + "categories": [ + "easy", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles bis volles Licht", + "temp": "10-20 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_c3b438f135460578", + "name": "Stab-Palme", + "botanicalName": "Rhapis excelsa", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/65/Rhapis_excelsa_02.jpg/330px-Rhapis_excelsa_02.jpg", + "imageStatus": "ok", + "description": "Die Stab-Palme ist eine elegante Zimmerpalme mit faecher┬¡foermigen Blaettern auf duennen, bambusartigen Staemmen.", + "categories": [ + "low_light", + "tree" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_e6998b94b6aa9483", + "name": "Stiefmuetterchen", + "botanicalName": "Viola wittrockiana", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/Violas_at_Butchart_Gardens.jpg/330px-Violas_at_Butchart_Gardens.jpg", + "imageStatus": "ok", + "description": "Das Stiefmuetterchen ist ein bekannter Fruehjahrsblueher mit charakteristisch gezeichneten Blueten.", + "categories": [ + "easy", + "flowering" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles bis volles Licht", + "temp": "5-18 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_4e7aa106c2e0dbed", + "name": "Stiefmuetterchen-Orchidee", + "botanicalName": "Miltoniopsis roezlii", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Miltoniopsis_roezlii.jpg/330px-Miltoniopsis_roezlii.jpg", + "imageStatus": "ok", + "description": "Die Stiefmuetterchen-Orchidee hat grosse, flache Blueten. Bevorzugt kuehle Temperaturen und hohe Luftfeuchtigkeit.", + "categories": [ + "flowering", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Indirektes Licht", + "temp": "15-22 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_67521f8578f80480", + "name": "Strahlenaralie", + "botanicalName": "Schefflera arboricola", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/30/Schefflera_arboricola_3.jpg/330px-Schefflera_arboricola_3.jpg", + "imageStatus": "ok", + "description": "Die Strahlenaralie hat fingerfoermig angeordnete, glaenzende Blaetter auf langen Stielen. Sehr robuste Zimmerpflanze.", + "categories": [ + "easy", + "air_purifier", + "tree" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_15d0205868b79470", + "name": "Stromanthe", + "botanicalName": "Stromanthe sanguinea", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Stromanthe_sanguinea.jpg/330px-Stromanthe_sanguinea.jpg", + "imageStatus": "ok", + "description": "Die Stromanthe hat dekorative Blaetter mit weissem Muster und leuchtend roter Unterseite. Familie der Marantaceen.", + "categories": [ + "patterned", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "18-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_9d6e62be0b1cb281", + "name": "Studentenblume", + "botanicalName": "Tagetes patula", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/63/Marigold_Tagetes.jpg/330px-Marigold_Tagetes.jpg", + "imageStatus": "ok", + "description": "Die Studentenblume ist eine robuste Sommerblume mit orangen oder gelben Blueten. Sie haelt Schadlinge fern.", + "categories": [ + "easy", + "flowering", + "medicinal", + "sun" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Volles Sonnenlicht", + "temp": "15-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_4b198e1fefa08544", + "name": "Suesskartoffel", + "botanicalName": "Ipomoea batatas", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/Ipomoea_batatas_006.JPG/330px-Ipomoea_batatas_006.JPG", + "imageStatus": "ok", + "description": "Die Suesskartoffel-Zierpflanze hat dekorative, herzfoermige Blaetter in gruen oder dunkelviolett. Ideal als Haengepflanze.", + "categories": [ + "easy", + "hanging", + "sun" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Volles Sonnenlicht", + "temp": "20-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_876974955b59c59e", + "name": "Tanzerinnen-Orchidee", + "botanicalName": "Oncidium sphacelatum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/Oncidium_sphacelatum_-_Flickr_002.jpg/330px-Oncidium_sphacelatum_-_Flickr_002.jpg", + "imageStatus": "ok", + "description": "Die Tanzerinnen-Orchidee traegt lange Rispen mit Hunderten kleiner, gelb-brauner Blueten. Sehr reichliche Bluetracht.", + "categories": [ + "flowering", + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_2ee0814c52ec43e5", + "name": "Taro", + "botanicalName": "Colocasia esculenta", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/Colocasia_esculenta_-_Kalo_lo%27i_%28taro%29.jpg/330px-Colocasia_esculenta_-_Kalo_lo%27i_%28taro%29.jpg", + "imageStatus": "ok", + "description": "Der Taro ist eine tropische Pflanze mit grossen, herzfoermigen Blaettern. Die Knollen sind Nahrungsquelle.", + "categories": [ + "high_humidity", + "large" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles indirektes Licht", + "temp": "18-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_8860c603977b7048", + "name": "Teestrauch", + "botanicalName": "Camellia sinensis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/04/TeaPlantation.jpg/330px-TeaPlantation.jpg", + "imageStatus": "ok", + "description": "Der Teestrauch ist die Pflanze, aus deren Blaettern Tee gewonnen wird. Er hat weisse Blueten und glaenzende Blaetter.", + "categories": [ + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "15-22 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_716160bf88dd9d13", + "name": "Tempel-Baum", + "botanicalName": "Plumeria rubra", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/27/Plumeria_rubra_Puu_Waawaa.jpg/330px-Plumeria_rubra_Puu_Waawaa.jpg", + "imageStatus": "ok", + "description": "Der Tempel-Baum hat intensiv duftende, sternfoermige Blueten in Weiss, Gelb oder Rosa. Klassische Tropenblume.", + "categories": [ + "flowering", + "sun", + "tree" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "20-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_9b35df06e64f0898", + "name": "Thymian", + "botanicalName": "Thymus vulgaris", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Thymus_vulgaris_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-274.jpg/330px-Thymus_vulgaris_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-274.jpg", + "imageStatus": "ok", + "description": "Thymian ist ein kleiner, aromatischer Strauch mit winzigen Blaettern und rosa Blueten. Wichtiges Kuechenkraut.", + "categories": [ + "easy", + "medicinal", + "sun" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Volles Sonnenlicht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_4318ad8d02f7a1e3", + "name": "Tiroler Keulenlilie", + "botanicalName": "Cordyline fruticosa", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Cordyline_fruticosa1.jpg/330px-Cordyline_fruticosa1.jpg", + "imageStatus": "ok", + "description": "Die Tiroler Keulenlilie hat leuchtend rote, gruene oder buntlaubige Blaetter. Eine exotische Zimmerpflanze.", + "categories": [ + "easy", + "patterned" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_6209cff29d20de9d", + "name": "Tomate", + "botanicalName": "Solanum lycopersicum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/88/Salad_garden_cherry_tomatoes_are_picked.jpg/330px-Salad_garden_cherry_tomatoes_are_picked.jpg", + "imageStatus": "ok", + "description": "Die Tomate ist eine beliebte Gemuese- und Balkonpflanze mit roten, saftigen Fruechten. Im Topf kultivierbar.", + "categories": [ + "easy", + "sun", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Volles Sonnenlicht", + "temp": "18-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_5b5d63d3d16734c3", + "name": "Traubenhyazinthe", + "botanicalName": "Muscari armeniacum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Muscari_armeniacum_1.jpg/330px-Muscari_armeniacum_1.jpg", + "imageStatus": "ok", + "description": "Die Traubenhyazinthe bildet dichte Trauben aus kleinen, blauen bis violetten Gloeckchen. Zuverlaessige Fruejahrszwiebel.", + "categories": [ + "easy", + "flowering" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "8-18 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_79692a800f05a5e6", + "name": "Triphylla-Fuchsie", + "botanicalName": "Fuchsia triphylla", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Fuchsia_triphylla.jpg/330px-Fuchsia_triphylla.jpg", + "imageStatus": "ok", + "description": "Die Triphylla-Fuchsie hat lange, roehrenfoermige, orangefarbe Blueten in haengenden Trauben. Sehr exotisch.", + "categories": [ + "flowering", + "hanging" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles indirektes Licht", + "temp": "15-22 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_6ad4ada285b323dd", + "name": "Tueipelfarn", + "botanicalName": "Polypodium vulgare", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Polypodium_vulgare_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-106.jpg/330px-Polypodium_vulgare_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-106.jpg", + "imageStatus": "ok", + "description": "Der Tueipelfarn ist ein heimischer Farn mit gelappten Wedeln und runden Sporenhaeufchen auf der Unterseite.", + "categories": [ + "easy", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "10-20 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_f03bc24e17022dd9", + "name": "Tueipelfarn (Microsorum)", + "botanicalName": "Microsorum punctatum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/06/Microsorum_punctatum_0002.JPG/330px-Microsorum_punctatum_0002.JPG", + "imageStatus": "ok", + "description": "Microsorum punctatum ist ein tropischer Farn mit langen, ungeteilten, glaenzenden Wedeln. Fuer feuchte Standorte.", + "categories": [ + "high_humidity" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_a90c8b9c4cddc806", + "name": "Tulpe", + "botanicalName": "Tulipa gesneriana", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Beautiful_red_and_yellow_tulips.jpg/330px-Beautiful_red_and_yellow_tulips.jpg", + "imageStatus": "ok", + "description": "Die Tulpe ist eine der beliebtesten Fruehjahrsblueher mit kelchfoermigen Blueten in unzaehligen Farben.", + "categories": [ + "easy", + "flowering" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "8-18 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_ea198ff58c8805c6", + "name": "Ufopflanze", + "botanicalName": "Pilea peperomioides", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Pilea_peperomioides_Chinese_money_plant.jpg/330px-Pilea_peperomioides_Chinese_money_plant.jpg", + "imageStatus": "ok", + "description": "Die Ufopflanze hat unverwechselbare, runde Blaetter auf langen Stielen. Bildet leicht Ableger zum Verschenken.", + "categories": [ + "easy", + "pet_friendly" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "13-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_40fc59a7783f4dbd", + "name": "Vanda-Orchidee", + "botanicalName": "Vanda coerulea", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Vanda_coerulea.jpg/330px-Vanda_coerulea.jpg", + "imageStatus": "ok", + "description": "Die Vanda-Orchidee ist bekannt fuer ihre seltene blaue Bluetenfarbe. Epiphytische Orchidee mit grossen Blueten.", + "categories": [ + "flowering", + "high_humidity", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Helles bis volles Licht", + "temp": "20-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_ec96801b21f4b888", + "name": "Vanille", + "botanicalName": "Vanilla planifolia", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Vanilla_planifolia_flowers.jpg/330px-Vanilla_planifolia_flowers.jpg", + "imageStatus": "ok", + "description": "Die Vanille ist eine kletternde Orchidee, aus deren Fruechten das beliebte Gewuerz gewonnen wird.", + "categories": [ + "flowering", + "high_humidity", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "20-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_e0c02d30e9553083", + "name": "Venusfliegenfalle", + "botanicalName": "Dionaea muscipula", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Dionaea_muscipula.jpg/330px-Dionaea_muscipula.jpg", + "imageStatus": "ok", + "description": "Die Venusfliegenfalle ist eine fleischfressende Pflanze mit klappfallartigen Blaettern. Faengt Insekten.", + "categories": [ + "sun" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Volles Sonnenlicht", + "temp": "15-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_621534b573f3fbd1", + "name": "Vogelnest-Farn", + "botanicalName": "Asplenium nidus", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Asplenium_nidus_at_Palmengarten_Frankfurt.jpg/330px-Asplenium_nidus_at_Palmengarten_Frankfurt.jpg", + "imageStatus": "ok", + "description": "Der Vogelnest-Farn hat ganzrandige, glaenzende Wedel, die eine Nestform bilden. Sehr dekorativ und robust.", + "categories": [ + "easy", + "high_humidity", + "low_light" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_b109c47be52f9ec8", + "name": "Wachsblume", + "botanicalName": "Hoya carnosa", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Hoya_carnosa.jpg/330px-Hoya_carnosa.jpg", + "imageStatus": "ok", + "description": "Die Wachsblume ist eine Kletterpflanze mit dicken, wachsartigen Blaettern und sternfoermigen, duftenden Blueten.", + "categories": [ + "easy", + "flowering", + "hanging" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Helles indirektes Licht", + "temp": "16-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_632f108725deeafe", + "name": "Wandelroeschen", + "botanicalName": "Lantana camara", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/Lantana_camara_-_flowers.jpg/330px-Lantana_camara_-_flowers.jpg", + "imageStatus": "ok", + "description": "Das Wandelroeschen hat kugelige Bluetenkoepfe, die die Farbe von Gelb ueber Orange zu Rot wechseln. Sehr attraktiv.", + "categories": [ + "flowering", + "sun", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Volles Sonnenlicht", + "temp": "18-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_c64390ca3c3743fe", + "name": "Wasserschlauch", + "botanicalName": "Utricularia gibba", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9d/Utricularia_gibba.jpg/330px-Utricularia_gibba.jpg", + "imageStatus": "ok", + "description": "Der Wasserschlauch ist eine wasserbewohnende fleischfressende Pflanze mit Schlaeuchen als Insekten┬¡fallen.", + "categories": [ + "high_humidity", + "sun" + ], + "careInfo": { + "waterIntervalDays": 2, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_33f62ca8680da000", + "name": "Weihnachtskaktus", + "botanicalName": "Schlumbergera truncata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/Schlumbergera_truncatus.jpg/330px-Schlumbergera_truncatus.jpg", + "imageStatus": "ok", + "description": "Der Weihnachtskaktus erfreut zur Weihnachtszeit mit leuchtenden Blueten in Rosa, Rot oder Weiss.", + "categories": [ + "easy", + "succulent", + "flowering" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "15-21 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_8218a6240dd4a406", + "name": "Weihnachtsstern", + "botanicalName": "Euphorbia pulcherrima", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5b/Poinsettia_Euphorbia_pulcherrima_Red_Christmas.jpg/330px-Poinsettia_Euphorbia_pulcherrima_Red_Christmas.jpg", + "imageStatus": "ok", + "description": "Der Weihnachtsstern ist die klassische Winterpflanze mit leuchtend roten Hochblaettern. Er steht symbolisch fuer Weihnachten.", + "categories": [ + "flowering" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles indirektes Licht", + "temp": "15-22 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_4275140824142c04", + "name": "Weisse Strelitzie", + "botanicalName": "Strelitzia nicolai", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Strelitzia_nicolai_3.jpg/330px-Strelitzia_nicolai_3.jpg", + "imageStatus": "ok", + "description": "Die Weisse Strelitzie ist ein beeindruckender Zimmerstrauch mit grossen, blaugruenen Blaettern und weiss-blauen Blueten.", + "categories": [ + "large", + "tree", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_0a06480067428b83", + "name": "Weisse Tradescantia", + "botanicalName": "Tradescantia fluminensis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Tradescantia_fluminensis_2.jpg/330px-Tradescantia_fluminensis_2.jpg", + "imageStatus": "ok", + "description": "Die Weisse Tradescantia hat gruene Blaetter mit weisslichen Unterseiten. Sehr robust und schnellwachsend.", + "categories": [ + "easy", + "hanging" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_316228d023b525c1", + "name": "Wermut", + "botanicalName": "Artemisia absinthium", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Artemisia_absinthium.jpg/330px-Artemisia_absinthium.jpg", + "imageStatus": "ok", + "description": "Wermut ist ein stark aromatisches Heilkraut mit silbrig-gruenen, tief eingeschnittenen Blaettern. Fuer Kraeuterlikoere.", + "categories": [ + "medicinal", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Volles Sonnenlicht", + "temp": "10-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_77608bbef47bdc04", + "name": "Wuestenrose", + "botanicalName": "Adenium obesum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Adenium_obesum.jpg/330px-Adenium_obesum.jpg", + "imageStatus": "ok", + "description": "Die Wuestenrose ist eine sukkulente Zimmerpflanze mit dickem Stamm und leuchtend pinken Blueten.", + "categories": [ + "succulent", + "flowering", + "sun" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Volles Sonnenlicht", + "temp": "20-35 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_a0e4e7fa68bbad41", + "name": "Yucca-Palme", + "botanicalName": "Yucca elephantipes", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Yucca_elephantipes_2012.jpg/330px-Yucca_elephantipes_2012.jpg", + "imageStatus": "ok", + "description": "Die Yucca-Palme ist eine robuste Zimmerpflanze mit starrem, immergruenem Blaetterschopf auf einem dicken Stamm.", + "categories": [ + "easy", + "tree", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Helles bis volles Licht", + "temp": "15-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_49c4a36c24338324", + "name": "Zamioculcas", + "botanicalName": "Zamioculcas zamiifolia", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Zamioculcas_zamiifolia_1.jpg/330px-Zamioculcas_zamiifolia_1.jpg", + "imageStatus": "ok", + "description": "Die Zamioculcas ist eine ausdauernde Zimmerpflanze mit glaenzenden Fiederbl├ñttern. Sehr trockenheitstolerant.", + "categories": [ + "easy", + "low_light", + "air_purifier" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Wenig bis helles Licht", + "temp": "15-26 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_28107fe5558dfaa3", + "name": "Zaubernuss", + "botanicalName": "Hamamelis mollis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/79/Hamamelis_mollis_J2.jpg/330px-Hamamelis_mollis_J2.jpg", + "imageStatus": "ok", + "description": "Die Zaubernuss bluet im Winter mit fadendunnen, gelben Bluetenkranzeln, die bis -10 Grad standhalten.", + "categories": [ + "flowering", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 10, + "light": "Helles bis volles Licht", + "temp": "10-20 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_75abff461b3d9bf8", + "name": "Zebra-Haworthie", + "botanicalName": "Haworthia fasciata", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Haworthia_fasciata01.jpg/330px-Haworthia_fasciata01.jpg", + "imageStatus": "ok", + "description": "Die Zebra-Haworthie ist eine kompakte Sukkulente mit weissen Querstreifen auf dunkelgruenen Blaettern.", + "categories": [ + "easy", + "succulent", + "low_light" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Helles indirektes Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_f7d0af5f2c284fff", + "name": "Zebrakraut", + "botanicalName": "Tradescantia zebrina", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Tradescantia_zebrina_-_Starr_%28cropped%29.jpg/330px-Tradescantia_zebrina_-_Starr_%28cropped%29.jpg", + "imageStatus": "ok", + "description": "Das Zebrakraut faellt durch seine silbrig-lila gestreiften Blaetter auf. Schnellwachsende Haengepflanze.", + "categories": [ + "easy", + "hanging", + "patterned" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles indirektes Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_ec8a05c334d66976", + "name": "Zinnie", + "botanicalName": "Zinnia elegans", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Zinnia_elegans_cv_Giant_Dahlia_Flowered_Scarlet.jpg/330px-Zinnia_elegans_cv_Giant_Dahlia_Flowered_Scarlet.jpg", + "imageStatus": "ok", + "description": "Die Zinnie ist eine leuchtende Sommerblume mit grossen, dahlienaehnlichen Blueten. Sehr robust und hitzetolerant.", + "categories": [ + "easy", + "flowering", + "sun" + ], + "careInfo": { + "waterIntervalDays": 3, + "light": "Volles Sonnenlicht", + "temp": "18-30 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_29250eba0cf2291f", + "name": "Zitronenbaum", + "botanicalName": "Citrus limon", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Citrus_limon_Lemon_%28Rutaceae%29_Fruit.jpg/330px-Citrus_limon_Lemon_%28Rutaceae%29_Fruit.jpg", + "imageStatus": "ok", + "description": "Der Zitronenbaum ist ein kleiner, immergruener Baum mit weissen, duftenden Blueten und gelben Fruechten.", + "categories": [ + "sun", + "tree", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Volles Sonnenlicht", + "temp": "18-28 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_8febd56fe7368d57", + "name": "Zitronenmelisse", + "botanicalName": "Melissa officinalis", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Melissa_officinalis_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-089.jpg/330px-Melissa_officinalis_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-089.jpg", + "imageStatus": "ok", + "description": "Die Zitronenmelisse ist ein zitronig duftendes Heilkraut. Sie beruhigt die Nerven und foerdert den Schlaf.", + "categories": [ + "easy", + "medicinal" + ], + "careInfo": { + "waterIntervalDays": 5, + "light": "Helles bis volles Licht", + "temp": "15-25 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_3a3d31c9d818021b", + "name": "Zwergdattelpalme", + "botanicalName": "Phoenix roebelenii", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Phoenix_roebelenii0.jpg/330px-Phoenix_roebelenii0.jpg", + "imageStatus": "ok", + "description": "Die Zwergdattelpalme ist eine zierliche Palme mit eleganten, gebogenen Fiederblaettern. Tropisches Flair.", + "categories": [ + "tree", + "bright_light" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles bis volles Licht", + "temp": "18-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_5c8f76b2c7d187f1", + "name": "Zylindrischer Bogenhanf", + "botanicalName": "Sansevieria cylindrica", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Sansevieria_cylindrica.jpg/330px-Sansevieria_cylindrica.jpg", + "imageStatus": "ok", + "description": "Der Zylindrische Bogenhanf hat zylindrische, aufrechte Blaetter, die sich nach oben verjuengen. Sehr pflegeleicht.", + "categories": [ + "easy", + "succulent", + "sun" + ], + "careInfo": { + "waterIntervalDays": 14, + "light": "Helles bis volles Licht", + "temp": "15-27 ┬░C" + }, + "confidence": 1 + }, + { + "id": "plant_7fe204e226887efa", + "name": "Zymbidium", + "botanicalName": "Cymbidium lowianum", + "imageUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/94/Cymbidium_Orchidglade_Davos_Orchid_%28Orchi%29.jpg/330px-Cymbidium_Orchidglade_Davos_Orchid_%28Orchi%29.jpg", + "imageStatus": "ok", + "description": "Das Zymbidium ist eine robuste Orchidee mit langen, grassartigen Blaettern und eleganten Bluetenrispen.", + "categories": [ + "flowering" + ], + "careInfo": { + "waterIntervalDays": 7, + "light": "Helles Licht", + "temp": "12-24 ┬░C" + }, + "confidence": 1 + } +] diff --git a/prototype.html b/prototype.html new file mode 100644 index 0000000..23cd31c --- /dev/null +++ b/prototype.html @@ -0,0 +1,258 @@ + + + + + + GreenLens Premium Prototype + + + +
+
+ +
+ +
+

My Collection

+

12 healthy plants

+
+ +
+
+ + + + +
85%
+
Care Score
+
+ +
+
+
+
+
Hydration
+
72%
+
+
+
+ +
+

Plant List goes here...

+
+
+ + diff --git a/review-change-candidates.md b/review-change-candidates.md new file mode 100644 index 0000000..90d2129 --- /dev/null +++ b/review-change-candidates.md @@ -0,0 +1,98 @@ +# Review Change Candidates + +Date: 2026-03-12 + +Purpose: +- collect the user-provided `AENDERN` review items in one place +- separate already-applied semantic fixes from deferred raw source array reordering + +Status summary: +- semantic fixes: applied +- export ordering: already normalized in `all-plants-categories.csv` +- source-array ordering in the batch files: deferred on purpose + +## Applied Semantic Fixes + +- `Anthurium clarinervium`: `patterned|high_humidity|pet_friendly` -> `patterned|high_humidity` +- `Anthurium crystallinum`: `patterned|high_humidity|pet_friendly` -> `patterned|high_humidity` +- `Camellia sinensis`: `[]` -> `flowering` +- `Mimosa pudica`: `[]` -> `flowering|bright_light` +- `Spinacia oleracea`: `[]` -> `easy` + +## Deferred Raw Source Array Reordering + +These were left out of the source files because the export generator now canonicalizes category order in `all-plants-categories.csv`. If you still want the raw `categories` arrays in the batch files normalized too, these are the deferred candidates from the review list. + +- `Acer platanoides`: `tree|sun|large` -> `tree|large|sun` +- `Achillea millefolium`: `medicinal|flowering|sun` -> `flowering|medicinal|sun` +- `Adenium obesum`: `succulent|flowering|sun` -> `flowering|succulent|sun` +- `Adenium socotranum`: `succulent|flowering|sun` -> `flowering|succulent|sun` +- `Agave americana`: `succulent|sun|large` -> `succulent|large|sun` +- `Aglaonema commutatum`: `easy|low_light|patterned` -> `easy|patterned|low_light` +- `Alocasia amazonica`: `patterned|high_humidity|large` -> `patterned|large|high_humidity` +- `Aloe ferox`: `succulent|medicinal|sun|large` -> `succulent|medicinal|large|sun` +- `Alpinia zerumbet`: `flowering|high_humidity|large` -> `flowering|large|high_humidity` +- `Solanum aviculare`: `medicinal|flowering|sun` -> `flowering|medicinal|sun` +- `Solanum laciniatum`: `medicinal|flowering|sun` -> `flowering|medicinal|sun` +- `Strelitzia reginae`: `flowering|sun|large` -> `flowering|large|sun` +- `Agapanthus africanus`: `flowering|sun|large` -> `flowering|large|sun` +- `Aquilegia vulgaris`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Momordica balsamina`: `flowering|sun|medicinal` -> `flowering|medicinal|sun` +- `Thunbergia alata`: `flowering|sun|hanging` -> `flowering|hanging|sun` +- `Gerbera jamesonii`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Hibiscus rosa-sinensis`: `flowering|sun|large` -> `flowering|large|sun` +- `Bergenia cordifolia`: `flowering|low_light|large` -> `flowering|large|low_light` +- `Photinia serratifolia`: `tree|sun|large` -> `tree|large|sun` +- `Chrysanthemum morifolium`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Galanthus nivalis`: `flowering|low_light|pet_friendly` -> `flowering|pet_friendly|low_light` +- `Leucojum aestivum`: `flowering|low_light|pet_friendly` -> `flowering|pet_friendly|low_light` +- `Cyclamen persicum`: `flowering|low_light|pet_friendly` -> `flowering|pet_friendly|low_light` +- `Narcissus pseudonarcissus`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Dahlia pinnata`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Photinia fraseri`: `tree|sun|large` -> `tree|large|sun` +- `Rosa canina`: `flowering|sun|medicinal` -> `flowering|medicinal|sun` +- `Acer campestre`: `tree|sun|large` -> `tree|large|sun` +- `Amelanchier ovalis`: `flowering|sun|large` -> `flowering|large|sun` +- `Howea forsteriana`: `easy|pet_friendly|large|air_purifier|bright_light` -> `easy|pet_friendly|air_purifier|large|bright_light` +- `Dracaena trifasciata`: `easy|air_purifier|low_light|large` -> `easy|air_purifier|large|low_light` +- `Lobularia maritima`: `flowering|sun|hanging` -> `flowering|hanging|sun` +- `Buxus sempervirens`: `tree|sun|large` -> `tree|large|sun` +- `Cosmos bipinnatus`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Lilium candidum`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Origanum vulgare`: `medicinal|sun|pet_friendly` -> `medicinal|pet_friendly|sun` +- `Rudbeckia hirta`: `flowering|sun|pet_friendly` -> `flowering|pet_friendly|sun` +- `Hibiscus syriacus`: `flowering|sun|large` -> `flowering|large|sun` +- `Sedum acre`: `succulent|sun|pet_friendly` -> `succulent|pet_friendly|sun` +- `Fatsia japonica`: `tree|low_light|large` -> `tree|large|low_light` +- `Ocimum tenuiflorum`: `medicinal|sun|flowering` -> `flowering|medicinal|sun` +- `Ulmus minor`: `tree|sun|large` -> `tree|large|sun` +- `Ulmus americana`: `tree|sun|large` -> `tree|large|sun` +- `Ulmus glabra`: `tree|sun|large` -> `tree|large|sun` +- `Aloysia citrodora`: `medicinal|sun|flowering` -> `flowering|medicinal|sun` +- `Cucumis sativus`: `easy|sun|hanging` -> `easy|hanging|sun` +- `Citrullus lanatus`: `easy|sun|hanging` -> `easy|hanging|sun` +- `Hypoestes phyllostachya`: `patterned|bright_light|pet_friendly` -> `patterned|pet_friendly|bright_light` +- `Nephrolepis exaltata`: `air_purifier|high_humidity|pet_friendly` -> `air_purifier|pet_friendly|high_humidity` +- `Phalaenopsis amabilis`: `flowering|high_humidity|pet_friendly` -> `flowering|pet_friendly|high_humidity` +- `Plantago major`: `medicinal|sun|pet_friendly` -> `medicinal|pet_friendly|sun` +- `Chaenomeles japonica`: `flowering|sun|large` -> `flowering|large|sun` +- `Rhododendron ferrugineum`: `flowering|low_light|large` -> `flowering|large|low_light` +- `Brassica napus napobrassica`: `easy|sun|large` -> `easy|large|sun` +- `Salvia apiana`: `medicinal|sun|flowering` -> `flowering|medicinal|sun` +- `Salvia canariensis`: `medicinal|sun|flowering` -> `flowering|medicinal|sun` +- `Helianthus annuus`: `flowering|sun|large` -> `flowering|large|sun` +- `Syringa vulgaris`: `flowering|sun|large` -> `flowering|large|sun` +- `Calystegia sepium`: `flowering|sun|hanging` -> `flowering|hanging|sun` +- `Vanilla planifolia`: `flowering|high_humidity|hanging` -> `flowering|hanging|high_humidity` +- `Vanda coerulea`: `flowering|high_humidity|bright_light` -> `flowering|bright_light|high_humidity` +- `Verbascum thapsus`: `flowering|sun|medicinal` -> `flowering|medicinal|sun` +- `Washingtonia robusta`: `tree|sun|large` -> `tree|large|sun` +- `Wisteria sinensis`: `flowering|sun|large` -> `flowering|large|sun` +- `Yucca aloifolia`: `tree|sun|easy` -> `easy|tree|sun` + +## Notes + +- Some review items were omitted because they were explicit no-ops, duplicate rows, or already effectively normalized by the export layer. +- The obvious no-op reorder rows were removed from this file during cleanup. +- Some older order proposals may now be stale if a later semantic audit intentionally changed the underlying categories. +- The canonical order visible to QA should be taken from `all-plants-categories.csv`, not from the raw category array order inside the batch source files. diff --git a/scripts/fix_images.js b/scripts/fix_images.js new file mode 100644 index 0000000..b14e735 --- /dev/null +++ b/scripts/fix_images.js @@ -0,0 +1,192 @@ +#!/usr/bin/env node +/** + * fix_images.js + * Finds broken image URLs in lexicon/catalog files and replaces them + * using Wikimedia Commons API. + */ + +const fs = require('fs'); +const https = require('https'); + +const FILES = [ + 'constants/lexiconBatch1.ts', + 'constants/lexiconBatch2.ts', + 'services/backend/mockCatalog.ts', +]; + +// Known manual fixes (botanicalName -> correct Wikimedia filename) +const MANUAL_FIXES = { + 'Chlorophytum comosum': 'Chlorophytum_comosum_01.jpg', + 'Syngonium podophyllum': 'Syngonium_podophyllum1.jpg', + 'Fuchsia hybrida': 'Fuchsia_%27Beacon%27.jpg', + 'Tillandsia usneoides': 'Tillandsia_usneoides_leaves.jpg', + 'Tillandsia ionantha': 'Tillandsia_ionantha0.jpg', +}; + +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +function httpGet(url) { + return new Promise((resolve, reject) => { + const req = https.get(url, { + headers: { + 'User-Agent': 'GreenLens-ImageFixer/1.0 (educational plant app)' + } + }, (res) => { + if (res.statusCode === 301 || res.statusCode === 302) { + resolve(httpGet(res.headers.location)); + return; + } + let data = ''; + res.on('data', chunk => data += chunk); + res.on('end', () => resolve({ status: res.statusCode, body: data })); + }); + req.on('error', reject); + req.setTimeout(10000, () => { + req.destroy(); + reject(new Error('timeout')); + }); + }); +} + +function checkUrl(url) { + return new Promise((resolve) => { + const req = https.get(url, { + headers: { 'User-Agent': 'GreenLens-ImageFixer/1.0' } + }, (res) => { + res.resume(); + resolve(res.statusCode === 200); + }); + req.on('error', () => resolve(false)); + req.setTimeout(8000, () => { req.destroy(); resolve(false); }); + }); +} + +async function searchWikimediaImage(botanicalName) { + const encoded = encodeURIComponent(botanicalName); + const url = `https://commons.wikimedia.org/w/api.php?action=query&generator=search&gsrnamespace=6&gsrsearch=${encoded}&gsrlimit=5&prop=imageinfo&iiprop=url&iiurlwidth=500&format=json`; + + try { + const res = await httpGet(url); + if (res.status !== 200) return null; + const data = JSON.parse(res.body); + const pages = data.query && data.query.pages; + if (!pages) return null; + + for (const page of Object.values(pages)) { + const info = page.imageinfo && page.imageinfo[0]; + if (!info) continue; + const thumbUrl = info.thumburl || info.url; + if (thumbUrl && (thumbUrl.endsWith('.jpg') || thumbUrl.endsWith('.png') || thumbUrl.endsWith('.JPG') || thumbUrl.endsWith('.PNG'))) { + return thumbUrl; + } + } + } catch (e) { + console.error(` API error for "${botanicalName}": ${e.message}`); + } + return null; +} + +function wikimediaThumbUrl(filename) { + // Build a 500px thumb URL from a bare filename + const name = filename.replace(/ /g, '_'); + const hash = require('crypto').createHash('md5').update(name).digest('hex'); + const d1 = hash[0]; + const d2 = hash.substring(0, 2); + const ext = name.split('.').pop().toLowerCase(); + const isJpg = ['jpg', 'jpeg'].includes(ext); + return `https://upload.wikimedia.org/wikipedia/commons/thumb/${d1}/${d2}/${name}/500px-${name}`; +} + +function parseEntries(content) { + // Match blocks: find name, botanicalName, imageUri + const entries = []; + const regex = /name:\s*['"]([^'"]+)['"]\s*,[\s\S]*?botanicalName:\s*['"]([^'"]+)['"]\s*,[\s\S]*?imageUri:\s*['"]([^'"]+)['"]/g; + let m; + while ((m = regex.exec(content)) !== null) { + entries.push({ + name: m[1], + botanicalName: m[2], + imageUri: m[3], + index: m.index, + }); + } + return entries; +} + +async function processFile(filepath) { + console.log(`\n=== Processing ${filepath} ===`); + let content = fs.readFileSync(filepath, 'utf8'); + const entries = parseEntries(content); + console.log(`Found ${entries.length} entries`); + + let fixCount = 0; + + for (const entry of entries) { + const { name, botanicalName, imageUri } = entry; + + // Check if URL is broken + process.stdout.write(` Checking ${botanicalName}... `); + const ok = await checkUrl(imageUri); + if (ok) { + console.log('OK'); + await sleep(100); + continue; + } + console.log('BROKEN'); + + let newUrl = null; + + // Check manual fixes first + if (MANUAL_FIXES[botanicalName]) { + const filename = MANUAL_FIXES[botanicalName]; + const thumb = wikimediaThumbUrl(filename); + console.log(` -> Manual fix: ${thumb}`); + newUrl = thumb; + } else { + // Query Wikimedia Commons API + console.log(` -> Searching Wikimedia for "${botanicalName}"...`); + newUrl = await searchWikimediaImage(botanicalName); + if (newUrl) { + console.log(` -> Found: ${newUrl}`); + } else { + console.log(` -> No result found, skipping`); + } + } + + if (newUrl) { + // Replace the old URL in content (escape for regex) + const escapedOld = imageUri.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + content = content.replace(new RegExp(escapedOld, 'g'), newUrl); + fixCount++; + } + + await sleep(200); + } + + if (fixCount > 0) { + fs.writeFileSync(filepath, content, 'utf8'); + console.log(` => Wrote ${fixCount} fixes to ${filepath}`); + } else { + console.log(` => No changes needed`); + } + + return fixCount; +} + +async function main() { + console.log('GreenLens Image URL Fixer'); + console.log('========================'); + let totalFixes = 0; + for (const file of FILES) { + if (!fs.existsSync(file)) { + console.log(`\nSkipping ${file} (not found)`); + continue; + } + totalFixes += await processFile(file); + } + console.log(`\nDone. Total fixes: ${totalFixes}`); +} + +main().catch(console.error); diff --git a/scripts/generate_semantic_audit.js b/scripts/generate_semantic_audit.js new file mode 100644 index 0000000..af3dc71 --- /dev/null +++ b/scripts/generate_semantic_audit.js @@ -0,0 +1,314 @@ +#!/usr/bin/env node +/* eslint-disable no-console */ +const fs = require('fs'); +const path = require('path'); +const vm = require('vm'); +const ts = require('typescript'); + +const ROOT_DIR = path.resolve(__dirname, '..'); +const OUTPUT_DIR = path.join(ROOT_DIR, 'audits', 'semantic-search'); +const CATEGORY_DIR = path.join(OUTPUT_DIR, 'categories'); +const ROOT_EXPORT_PATH = path.join(ROOT_DIR, 'all-plants-categories.csv'); +const BATCH_1_PATH = path.join(ROOT_DIR, 'constants', 'lexiconBatch1.ts'); +const BATCH_2_PATH = path.join(ROOT_DIR, 'constants', 'lexiconBatch2.ts'); + +const AUDIT_PRIORITY = [ + 'pet_friendly', + 'air_purifier', + 'medicinal', + 'low_light', + 'bright_light', + 'sun', + 'easy', + 'high_humidity', + 'hanging', + 'tree', + 'large', + 'patterned', + 'flowering', + 'succulent', +]; + +const HIGH_CONFIDENCE_MANUAL_REVIEW_CATEGORIES = new Set([ + 'pet_friendly', + 'air_purifier', + 'medicinal', +]); + +const CATEGORY_DISPLAY_ORDER = [ + 'easy', + 'pet_friendly', + 'flowering', + 'succulent', + 'patterned', + 'tree', + 'large', + 'medicinal', + 'hanging', + 'air_purifier', + 'low_light', + 'bright_light', + 'high_humidity', + 'sun', +]; + +const resolveTsFilePath = (fromFile, specifier) => { + if (!specifier.startsWith('.')) return null; + const fromDirectory = path.dirname(fromFile); + const absoluteBase = path.resolve(fromDirectory, specifier); + const candidates = [ + absoluteBase, + `${absoluteBase}.ts`, + `${absoluteBase}.tsx`, + path.join(absoluteBase, 'index.ts'), + ]; + + for (const candidate of candidates) { + if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) { + return candidate; + } + } + + return null; +}; + +const loadTsModule = (absolutePath, cache = new Map()) => { + if (cache.has(absolutePath)) return cache.get(absolutePath); + + const source = fs.readFileSync(absolutePath, 'utf8'); + const transpiled = ts.transpileModule(source, { + compilerOptions: { + module: ts.ModuleKind.CommonJS, + target: ts.ScriptTarget.ES2020, + esModuleInterop: true, + jsx: ts.JsxEmit.ReactJSX, + }, + fileName: absolutePath, + reportDiagnostics: false, + }).outputText; + + const module = { exports: {} }; + cache.set(absolutePath, module.exports); + + const localRequire = (specifier) => { + const resolvedTsPath = resolveTsFilePath(absolutePath, specifier); + if (resolvedTsPath) return loadTsModule(resolvedTsPath, cache); + return require(specifier); + }; + + const sandbox = { + module, + exports: module.exports, + require: localRequire, + __dirname: path.dirname(absolutePath), + __filename: absolutePath, + console, + process, + Buffer, + setTimeout, + clearTimeout, + }; + + vm.runInNewContext(transpiled, sandbox, { filename: absolutePath }); + cache.set(absolutePath, module.exports); + return module.exports; +}; + +const ensureDir = (directoryPath) => { + fs.mkdirSync(directoryPath, { recursive: true }); +}; + +const csvEscape = (value) => { + const stringValue = String(value ?? ''); + if (/[",\n]/.test(stringValue)) { + return `"${stringValue.replace(/"/g, '""')}"`; + } + return stringValue; +}; + +const writeCsv = (filePath, rows) => { + if (!rows.length) { + fs.writeFileSync(filePath, '', 'utf8'); + return; + } + + const headers = Object.keys(rows[0]); + const lines = [headers.join(',')]; + rows.forEach((row) => { + lines.push(headers.map((header) => csvEscape(row[header])).join(',')); + }); + fs.writeFileSync(filePath, `${lines.join('\n')}\n`, 'utf8'); +}; + +const normalizeCategoryFilename = (category) => category.replace(/[^a-z0-9_-]+/gi, '-').toLowerCase(); + +const sortCategories = (categories = []) => ( + [...categories].sort((left, right) => { + const leftIndex = CATEGORY_DISPLAY_ORDER.indexOf(left); + const rightIndex = CATEGORY_DISPLAY_ORDER.indexOf(right); + const normalizedLeft = leftIndex === -1 ? Number.MAX_SAFE_INTEGER : leftIndex; + const normalizedRight = rightIndex === -1 ? Number.MAX_SAFE_INTEGER : rightIndex; + return normalizedLeft - normalizedRight || left.localeCompare(right); + }) +); + +const buildRiskFlags = (entry) => { + const categories = new Set(entry.categories || []); + const flags = []; + + if (categories.has('low_light') && categories.has('sun')) { + flags.push('light_conflict_low_light_and_sun'); + } + if (categories.has('low_light') && categories.has('bright_light')) { + flags.push('light_conflict_low_light_and_bright_light'); + } + if (categories.has('succulent') && categories.has('high_humidity')) { + flags.push('succulent_high_humidity_combo_review'); + } + + (entry.categories || []).forEach((category) => { + if (HIGH_CONFIDENCE_MANUAL_REVIEW_CATEGORIES.has(category)) { + flags.push(`${category}_requires_external_evidence`); + } + }); + + return [...new Set(flags)]; +}; + +const toAuditRow = (entry, category) => ({ + category, + source_file: entry.sourceFile, + source_index: entry.sourceIndex, + name: entry.name, + botanical_name: entry.botanicalName, + description: entry.description || '', + light: entry.careInfo?.light || '', + temp: entry.careInfo?.temp || '', + water_interval_days: entry.careInfo?.waterIntervalDays ?? '', + all_categories: sortCategories(entry.categories || []).join('|'), + risk_flags: buildRiskFlags(entry).join('|'), + audit_status: '', + evidence_source: '', + evidence_url: '', + notes: '', +}); + +const toPlantCategoryRow = (entry) => ({ + source_file: entry.sourceFile, + source_index: entry.sourceIndex, + name: entry.name, + botanical_name: entry.botanicalName, + all_categories: sortCategories(entry.categories || []).join('|'), + category_count: (entry.categories || []).length, + description: entry.description || '', + light: entry.careInfo?.light || '', + temp: entry.careInfo?.temp || '', + water_interval_days: entry.careInfo?.waterIntervalDays ?? '', +}); + +const loadBatchEntries = () => { + const batch1Entries = loadTsModule(BATCH_1_PATH).LEXICON_BATCH_1_ENTRIES; + const batch2Entries = loadTsModule(BATCH_2_PATH).LEXICON_BATCH_2_ENTRIES; + + if (!Array.isArray(batch1Entries) || !Array.isArray(batch2Entries)) { + throw new Error('Could not load lexicon batch entries.'); + } + + return [ + ...batch1Entries.map((entry, index) => ({ ...entry, sourceFile: 'constants/lexiconBatch1.ts', sourceIndex: index + 1 })), + ...batch2Entries.map((entry, index) => ({ ...entry, sourceFile: 'constants/lexiconBatch2.ts', sourceIndex: index + 1 })), + ]; +}; + +const main = () => { + ensureDir(CATEGORY_DIR); + const entries = loadBatchEntries(); + const categories = [...new Set(entries.flatMap((entry) => entry.categories || []))].sort(); + + const summary = { + generatedAt: new Date().toISOString(), + totalEntries: entries.length, + categories: categories.map((category) => ({ + category, + count: entries.filter((entry) => (entry.categories || []).includes(category)).length, + priority: AUDIT_PRIORITY.indexOf(category) >= 0 ? AUDIT_PRIORITY.indexOf(category) + 1 : 999, + })).sort((left, right) => + left.priority - right.priority || + right.count - left.count || + left.category.localeCompare(right.category)), + }; + + const plantCategoryRows = [...entries] + .sort((left, right) => + left.botanicalName.localeCompare(right.botanicalName) || + left.name.localeCompare(right.name)) + .map((entry) => toPlantCategoryRow(entry)); + + const masterRows = []; + const suspiciousRows = []; + + categories.forEach((category) => { + const categoryEntries = entries + .filter((entry) => (entry.categories || []).includes(category)) + .sort((left, right) => + left.botanicalName.localeCompare(right.botanicalName) || + left.name.localeCompare(right.name)); + + const rows = categoryEntries.map((entry) => { + const row = toAuditRow(entry, category); + masterRows.push(row); + + const riskFlags = row.risk_flags ? row.risk_flags.split('|').filter(Boolean) : []; + if (riskFlags.length > 0) { + suspiciousRows.push({ + category, + source_file: entry.sourceFile, + source_index: entry.sourceIndex, + name: entry.name, + botanical_name: entry.botanicalName, + risk_flags: riskFlags.join('|'), + }); + } + + return row; + }); + + writeCsv(path.join(CATEGORY_DIR, `${normalizeCategoryFilename(category)}.csv`), rows); + }); + + writeCsv(path.join(OUTPUT_DIR, 'all-plants-categories.csv'), plantCategoryRows); + writeCsv(ROOT_EXPORT_PATH, plantCategoryRows); + writeCsv(path.join(OUTPUT_DIR, 'master.csv'), masterRows); + writeCsv(path.join(OUTPUT_DIR, 'suspicious.csv'), suspiciousRows); + fs.writeFileSync(path.join(OUTPUT_DIR, 'summary.json'), `${JSON.stringify(summary, null, 2)}\n`, 'utf8'); + fs.writeFileSync(path.join(OUTPUT_DIR, 'suspicious.json'), `${JSON.stringify(suspiciousRows, null, 2)}\n`, 'utf8'); + + const readme = `# Semantic Search Audit + +Generated: ${summary.generatedAt} + +Files: +- \`summary.json\`: category counts and suggested audit order +- \`all-plants-categories.csv\`: one row per plant with its full category list +- \`master.csv\`: all category assignments with blank evidence columns +- \`suspicious.csv\`: entries that require elevated review based on rule flags +- \`categories/*.csv\`: per-category audit sheets + +Suggested audit order: +${summary.categories.map((item) => `- ${item.category} (${item.count})`).join('\n')} + +Workflow: +1. Review one category CSV at a time. +2. Fill \`audit_status\`, \`evidence_source\`, \`evidence_url\`, and \`notes\`. +3. Apply only high-confidence source-tag corrections to the lexicon batch files. +4. Rebuild the server catalog from batches after source edits. +`; + + fs.writeFileSync(path.join(OUTPUT_DIR, 'README.md'), readme, 'utf8'); + + console.log(`Audit artifacts written to ${OUTPUT_DIR}`); + console.log(`Categories exported: ${categories.length}`); + console.log(`Suspicious rows flagged: ${suspiciousRows.length}`); +}; + +main(); diff --git a/scripts/validate_all.ts b/scripts/validate_all.ts new file mode 100644 index 0000000..5e0db3d --- /dev/null +++ b/scripts/validate_all.ts @@ -0,0 +1,55 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +// Using exact string parsing since importing the TS files directly in tsx could have issues if the environment isn't fully set up, but tsx should work. Let's just import them. +import { LEXICON_BATCH_1_ENTRIES } from '../constants/lexiconBatch1'; +import { LEXICON_BATCH_2_ENTRIES } from '../constants/lexiconBatch2'; + +const allPlants = [...LEXICON_BATCH_1_ENTRIES, ...LEXICON_BATCH_2_ENTRIES]; + +async function checkUrl(url: string): Promise { + const headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'Accept': 'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8', + 'Referer': 'https://commons.wikimedia.org/' + }; + try { + const response = await fetch(url, { method: 'GET', headers }); + return response.status === 200; + } catch (error) { + return false; + } +} + +async function run() { + console.log(`Checking ${allPlants.length} plants...`); + let failedCount = 0; + const concurrency = 10; + + for (let i = 0; i < allPlants.length; i += concurrency) { + const batch = allPlants.slice(i, i + concurrency); + const results = await Promise.all(batch.map(async p => { + const ok = await checkUrl(p.imageUri); + return { + name: p.name, + url: p.imageUri, + ok + }; + })); + + for (const res of results) { + if (!res.ok) { + console.log(`❌ Failed: ${res.name} -> ${res.url}`); + failedCount++; + } + } + } + + if (failedCount === 0) { + console.log("✅ All image URLs are reachable!"); + } else { + console.log(`❌ ${failedCount} URLs failed.`); + } +} + +run(); diff --git a/server/.dockerignore b/server/.dockerignore new file mode 100644 index 0000000..09e76bc --- /dev/null +++ b/server/.dockerignore @@ -0,0 +1,4 @@ +node_modules +.env +.env.* +npm-debug.log diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 0000000..7acded8 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,12 @@ +FROM node:20-alpine + +WORKDIR /app + +COPY package*.json ./ +RUN npm ci --only=production + +COPY . . + +EXPOSE 3000 + +CMD ["node", "index.js"] diff --git a/server/index.js b/server/index.js index 2337531..88f8d71 100644 --- a/server/index.js +++ b/server/index.js @@ -1,14 +1,30 @@ +const fs = require('fs'); const path = require('path'); const dotenv = require('dotenv'); const express = require('express'); const cors = require('cors'); const Stripe = require('stripe'); -// override: true ensures .env always wins over existing shell env vars -dotenv.config({ path: path.join(__dirname, '.env'), override: true }); -dotenv.config({ path: path.join(__dirname, '.env.local'), override: true }); -dotenv.config({ path: path.join(__dirname, '..', '.env') }); -dotenv.config({ path: path.join(__dirname, '..', '.env.local') }); +const loadEnvFiles = (filePaths) => { + const mergedFileEnv = {}; + for (const filePath of filePaths) { + if (!fs.existsSync(filePath)) continue; + Object.assign(mergedFileEnv, dotenv.parse(fs.readFileSync(filePath))); + } + + for (const [key, value] of Object.entries(mergedFileEnv)) { + if (process.env[key] === undefined) { + process.env[key] = value; + } + } +}; + +loadEnvFiles([ + path.join(__dirname, '..', '.env'), + path.join(__dirname, '.env'), + path.join(__dirname, '..', '.env.local'), + path.join(__dirname, '.env.local'), +]); const { closeDatabase, getDefaultDbPath, openDatabase, get, run } = require('./lib/sqlite'); const { ensureAuthSchema, signUp: authSignUp, login: authLogin, issueToken, verifyJwt } = require('./lib/auth'); @@ -39,9 +55,12 @@ const { identifyPlant, isConfigured: isOpenAiConfigured, } = require('./lib/openai'); +const { applyCatalogGrounding, normalizeText } = require('./lib/scanGrounding'); +const { ensureStorageBucket, uploadImage, isStorageConfigured } = require('./lib/storage'); const app = express(); const port = Number(process.env.PORT || 3000); +const plantsPublicDir = path.join(__dirname, 'public', 'plants'); const stripeSecretKey = (process.env.STRIPE_SECRET_KEY || '').trim(); if (!stripeSecretKey) { console.error('STRIPE_SECRET_KEY is not set. Payment endpoints will fail.'); @@ -112,15 +131,6 @@ const parseBoolean = (value, fallbackValue) => { return fallbackValue; }; -const normalizeText = (value) => { - return String(value || '') - .toLowerCase() - .normalize('NFD') - .replace(/[\u0300-\u036f]/g, '') - .replace(/\s+/g, ' ') - .trim(); -}; - const hashString = (value) => { let hash = 0; for (let i = 0; i < value.length; i += 1) { @@ -151,6 +161,7 @@ const resolveUserId = (request) => { const authHeader = request.header('authorization'); if (authHeader && authHeader.startsWith('Bearer ')) { const token = authHeader.slice(7); + if (token === 'guest') return 'guest'; const payload = verifyJwt(token); if (payload && payload.sub) return String(payload.sub); } @@ -198,59 +209,6 @@ const pickCatalogFallback = (entries, imageUri, preferHighConfidence = false) => return toPlantResult(entries[index], confidence); }; -const findCatalogMatch = (aiResult, entries) => { - if (!aiResult || !Array.isArray(entries) || entries.length === 0) return null; - const aiBotanical = normalizeText(aiResult.botanicalName); - const aiName = normalizeText(aiResult.name); - if (!aiBotanical && !aiName) return null; - - const byExactBotanical = entries.find((entry) => normalizeText(entry.botanicalName) === aiBotanical); - if (byExactBotanical) return byExactBotanical; - - const byExactName = entries.find((entry) => normalizeText(entry.name) === aiName); - if (byExactName) return byExactName; - - if (aiBotanical) { - const aiGenus = aiBotanical.split(' ')[0]; - if (aiGenus) { - const byGenus = entries.find((entry) => normalizeText(entry.botanicalName).startsWith(`${aiGenus} `)); - if (byGenus) return byGenus; - } - } - - const byContains = entries.find((entry) => { - const plantName = normalizeText(entry.name); - const botanical = normalizeText(entry.botanicalName); - return (aiName && (plantName.includes(aiName) || aiName.includes(plantName))) - || (aiBotanical && (botanical.includes(aiBotanical) || aiBotanical.includes(botanical))); - }); - if (byContains) return byContains; - - return null; -}; - -const applyCatalogGrounding = (aiResult, catalogEntries) => { - const matchedEntry = findCatalogMatch(aiResult, catalogEntries); - if (!matchedEntry) { - return { grounded: false, result: aiResult }; - } - - return { - grounded: true, - result: { - name: matchedEntry.name || aiResult.name, - botanicalName: matchedEntry.botanicalName || aiResult.botanicalName, - confidence: clamp(Math.max(aiResult.confidence || 0.6, 0.78), 0.05, 0.99), - description: aiResult.description || matchedEntry.description || '', - careInfo: { - waterIntervalDays: Math.max(1, Number(matchedEntry.careInfo?.waterIntervalDays) || Number(aiResult.careInfo?.waterIntervalDays) || 7), - light: matchedEntry.careInfo?.light || aiResult.careInfo?.light || 'Unknown', - temp: matchedEntry.careInfo?.temp || aiResult.careInfo?.temp || 'Unknown', - }, - }, - }; -}; - const toImportErrorPayload = (error) => { if (error instanceof PlantImportValidationError) { return { @@ -331,6 +289,8 @@ const ensureRequestAuth = (request) => { return userId; }; +const isGuest = (userId) => userId === 'guest'; + const ensureNonEmptyString = (value, fieldName) => { if (typeof value === 'string' && value.trim()) return value.trim(); const error = new Error(`${fieldName} is required.`); @@ -350,6 +310,7 @@ const seedBootstrapCatalogIfNeeded = async () => { }; app.use(cors()); +app.use('/plants', express.static(plantsPublicDir)); // Webhook must be BEFORE express.json() to get the raw body app.post('/api/webhook', express.raw({ type: 'application/json' }), (request, response) => { @@ -399,6 +360,7 @@ app.get('/', (_request, response) => { 'POST /v1/health-check', 'POST /v1/billing/simulate-purchase', 'POST /v1/billing/simulate-webhook', + 'POST /v1/upload/image', ], }); }); @@ -512,9 +474,11 @@ app.post('/api/payment-sheet', async (request, response) => { app.get('/v1/billing/summary', async (request, response) => { try { const userId = ensureRequestAuth(request); - const userExists = await get(db, 'SELECT id FROM auth_users WHERE id = ?', [userId]); - if (!userExists) { - return response.status(401).json({ code: 'UNAUTHORIZED', message: 'User not found.' }); + if (userId !== 'guest') { + const userExists = await get(db, 'SELECT id FROM auth_users WHERE id = ?', [userId]); + if (!userExists) { + return response.status(401).json({ code: 'UNAUTHORIZED', message: 'User not found.' }); + } } const summary = await getBillingSummary(db, userId); response.status(200).json(summary); @@ -543,23 +507,29 @@ app.post('/v1/scan', async (request, response) => { const modelPath = []; let modelUsed = null; let modelFallbackCount = 0; - creditsCharged += await consumeCreditsWithIdempotency( - db, - userId, - chargeKey('scan-primary', userId, idempotencyKey), - SCAN_PRIMARY_COST, - ); + if (!isGuest(userId)) { + creditsCharged += await consumeCreditsWithIdempotency( + db, + userId, + chargeKey('scan-primary', userId, idempotencyKey), + SCAN_PRIMARY_COST, + ); + } + + const accountSnapshot = await getAccountSnapshot(db, userId); + const scanPlan = accountSnapshot.plan === 'pro' ? 'pro' : 'free'; const catalogEntries = await getPlants(db, { limit: 500 }); let result = pickCatalogFallback(catalogEntries, imageUri, false); let usedOpenAi = false; if (isOpenAiConfigured()) { - console.log(`Starting OpenAI identification for user ${userId} using model ${getScanModel()}`); + console.log(`Starting OpenAI identification for user ${userId} using model ${getScanModel(scanPlan)} (plan: ${scanPlan})`); const openAiPrimary = await identifyPlant({ imageUri, language, mode: 'primary', + plan: scanPlan, }); modelFallbackCount = Math.max( modelFallbackCount, @@ -567,7 +537,7 @@ app.post('/v1/scan', async (request, response) => { ); if (openAiPrimary?.result) { console.log(`OpenAI primary identification successful for user ${userId}: ${openAiPrimary.result.name} (${openAiPrimary.result.confidence}) using ${openAiPrimary.modelUsed}`); - const grounded = applyCatalogGrounding(openAiPrimary.result, catalogEntries); + const grounded = applyCatalogGrounding(openAiPrimary.result, catalogEntries, language); result = grounded.result; if (!grounded.grounded) result = { ...result, confidence: clamp(Math.max(result.confidence || 0.6, 0.72), 0.05, 0.99) }; usedOpenAi = true; @@ -592,22 +562,24 @@ app.post('/v1/scan', async (request, response) => { } const shouldReview = result.confidence < LOW_CONFIDENCE_REVIEW_THRESHOLD; - const accountSnapshot = await getAccountSnapshot(db, userId); if (shouldReview && accountSnapshot.plan === 'pro') { console.log(`Starting AI review for user ${userId} (confidence ${result.confidence} < ${LOW_CONFIDENCE_REVIEW_THRESHOLD})`); try { - creditsCharged += await consumeCreditsWithIdempotency( - db, - userId, - chargeKey('scan-review', userId, idempotencyKey), - SCAN_REVIEW_COST, - ); + if (!isGuest(userId)) { + creditsCharged += await consumeCreditsWithIdempotency( + db, + userId, + chargeKey('scan-review', userId, idempotencyKey), + SCAN_REVIEW_COST, + ); + } if (usedOpenAi) { const openAiReview = await identifyPlant({ imageUri, language, mode: 'review', + plan: scanPlan, }); modelFallbackCount = Math.max( modelFallbackCount, @@ -615,7 +587,7 @@ app.post('/v1/scan', async (request, response) => { ); if (openAiReview?.result) { console.log(`OpenAI review identification successful for user ${userId}: ${openAiReview.result.name} (${openAiReview.result.confidence}) using ${openAiReview.modelUsed}`); - const grounded = applyCatalogGrounding(openAiReview.result, catalogEntries); + const grounded = applyCatalogGrounding(openAiReview.result, catalogEntries, language); result = grounded.result; if (!grounded.grounded) result = { ...result, confidence: clamp(Math.max(result.confidence || 0.6, 0.72), 0.05, 0.99) }; modelUsed = openAiReview.modelUsed || modelUsed; @@ -743,12 +715,15 @@ app.post('/v1/health-check', async (request, response) => { throw error; } - const creditsCharged = await consumeCreditsWithIdempotency( - db, - userId, - chargeKey('health-check', userId, idempotencyKey), - HEALTH_CHECK_COST, - ); + let creditsCharged = 0; + if (!isGuest(userId)) { + creditsCharged = await consumeCreditsWithIdempotency( + db, + userId, + chargeKey('health-check', userId, idempotencyKey), + HEALTH_CHECK_COST, + ); + } const healthCheck = { generatedAt: nowIso(), @@ -803,6 +778,35 @@ app.post('/v1/billing/simulate-webhook', async (request, response) => { } }); +// ─── Image Upload ────────────────────────────────────────────────────────── + +app.post('/v1/upload/image', async (request, response) => { + try { + ensureRequestAuth(request); + + if (!isStorageConfigured()) { + return response.status(503).json({ + code: 'STORAGE_NOT_CONFIGURED', + message: 'Image storage is not configured.', + }); + } + + const { imageBase64, contentType = 'image/jpeg' } = request.body || {}; + if (!imageBase64 || typeof imageBase64 !== 'string') { + return response.status(400).json({ + code: 'BAD_REQUEST', + message: 'imageBase64 is required.', + }); + } + + const { url } = await uploadImage(imageBase64, contentType); + response.status(200).json({ url }); + } catch (error) { + const payload = toApiErrorPayload(error); + response.status(payload.status).json(payload.body); + } +}); + // ─── Auth endpoints ──────────────────────────────────────────────────────── app.post('/auth/signup', async (request, response) => { @@ -843,6 +847,9 @@ const start = async () => { await ensureBillingSchema(db); await ensureAuthSchema(db); await seedBootstrapCatalogIfNeeded(); + if (isStorageConfigured()) { + await ensureStorageBucket().catch((err) => console.warn('MinIO bucket setup failed:', err.message)); + } const stripeMode = getStripeSecretMode(); const stripePublishableMode = getStripePublishableMode(); @@ -855,7 +862,7 @@ const start = async () => { console.log(`Stripe Publishable Mode: ${stripePublishableMode} | Key: ${maskKey(process.env.STRIPE_PUBLISHABLE_KEY || process.env.EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY)}`); const server = app.listen(port, () => { - console.log(`GreenLns server listening at http://localhost:${port}`); + console.log(`GreenLens server listening at http://localhost:${port}`); }); const gracefulShutdown = async () => { @@ -873,6 +880,6 @@ const start = async () => { }; start().catch((error) => { - console.error('Failed to start GreenLns server', error); + console.error('Failed to start GreenLens server', error); process.exit(1); }); diff --git a/server/lib/billing.js b/server/lib/billing.js index 33d3a6a..7b5c680 100644 --- a/server/lib/billing.js +++ b/server/lib/billing.js @@ -1,17 +1,17 @@ const { get, run } = require('./sqlite'); const FREE_MONTHLY_CREDITS = 15; -const PRO_MONTHLY_CREDITS = 50; +const PRO_MONTHLY_CREDITS = 250; const TOPUP_DEFAULT_CREDITS = 60; const TOPUP_CREDITS_BY_PRODUCT = { pro_monthly: 0, - topup_small: 50, + topup_small: 25, topup_medium: 120, topup_large: 300, }; -const AVAILABLE_PRODUCTS = ['pro_monthly', 'topup_small', 'topup_medium', 'topup_large']; +const AVAILABLE_PRODUCTS = ['monthly_pro', 'yearly_pro', 'topup_small', 'topup_medium', 'topup_large']; const nowIso = () => new Date().toISOString(); @@ -68,7 +68,7 @@ const normalizeAccountRow = (row) => { return { userId: String(row.userId), plan: row.plan === 'pro' ? 'pro' : 'free', - provider: typeof row.provider === 'string' && row.provider ? row.provider : 'stripe', + provider: typeof row.provider === 'string' && row.provider ? row.provider : 'revenuecat', cycleStartedAt: String(row.cycleStartedAt), cycleEndsAt: String(row.cycleEndsAt), monthlyAllowance: Number(row.monthlyAllowance) || FREE_MONTHLY_CREDITS, @@ -84,7 +84,7 @@ const buildDefaultAccount = (userId, now) => { return { userId, plan: 'free', - provider: 'stripe', + provider: 'revenuecat', cycleStartedAt: cycleStartedAt.toISOString(), cycleEndsAt: cycleEndsAt.toISOString(), monthlyAllowance: FREE_MONTHLY_CREDITS, @@ -305,6 +305,20 @@ const consumeCreditsWithIdempotency = async (db, userId, key, cost) => { }; const getBillingSummary = async (db, userId) => { + if (userId === 'guest') { + return { + entitlement: { plan: 'free', provider: 'mock', status: 'active', renewsAt: null }, + credits: { + monthlyAllowance: 5, + usedThisCycle: 0, + topupBalance: 0, + available: 5, + cycleStartedAt: nowIso(), + cycleEndsAt: nowIso() + }, + availableProducts: AVAILABLE_PRODUCTS, + }; + } return runInTransaction(db, async () => { const account = await getOrCreateAccount(db, userId); account.updatedAt = nowIso(); @@ -314,6 +328,20 @@ const getBillingSummary = async (db, userId) => { }; const getAccountSnapshot = async (db, userId) => { + if (userId === 'guest') { + return { + userId: 'guest', + plan: 'free', + provider: 'mock', + cycleStartedAt: nowIso(), + cycleEndsAt: nowIso(), + monthlyAllowance: 5, + usedThisCycle: 0, + topupBalance: 0, + renewsAt: null, + updatedAt: nowIso(), + }; + } return runInTransaction(db, async () => { const account = await getOrCreateAccount(db, userId); account.updatedAt = nowIso(); @@ -342,11 +370,11 @@ const simulatePurchase = async (db, userId, idempotencyKey, productId) => { const account = await getOrCreateAccount(db, userId); - if (productId === 'pro_monthly') { + if (productId === 'monthly_pro' || productId === 'yearly_pro') { const now = new Date(); const { cycleStartedAt, cycleEndsAt } = getCycleBounds(now); account.plan = 'pro'; - account.provider = 'stripe'; + account.provider = 'revenuecat'; account.monthlyAllowance = PRO_MONTHLY_CREDITS; account.usedThisCycle = 0; account.cycleStartedAt = cycleStartedAt.toISOString(); @@ -441,7 +469,7 @@ const ensureBillingSchema = async (db) => { `CREATE TABLE IF NOT EXISTS billing_accounts ( userId TEXT PRIMARY KEY, plan TEXT NOT NULL DEFAULT 'free', - provider TEXT NOT NULL DEFAULT 'stripe', + provider TEXT NOT NULL DEFAULT 'revenuecat', cycleStartedAt TEXT NOT NULL, cycleEndsAt TEXT NOT NULL, monthlyAllowance INTEGER NOT NULL DEFAULT 15, diff --git a/server/lib/hybridSearch.js b/server/lib/hybridSearch.js new file mode 100644 index 0000000..2bce8d0 --- /dev/null +++ b/server/lib/hybridSearch.js @@ -0,0 +1,193 @@ +const { SEARCH_INTENT_CONFIG } = require('./searchIntentConfig'); + +const normalizeSearchText = (value) => { + return String(value || '') + .toLowerCase() + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .trim() + .replace(/[^a-z0-9\s_-]+/g, ' ') + .replace(/[_-]+/g, ' ') + .replace(/\s+/g, ' '); +}; + +const tokenize = (normalizedValue) => normalizedValue.split(' ').filter(Boolean); + +const normalizeArray = (values) => { + return [...new Set((values || []).map((value) => normalizeSearchText(value)).filter(Boolean))]; +}; + +const tokenSetFromQuery = (normalizedQuery) => { + const noise = new Set(SEARCH_INTENT_CONFIG.noiseTokens.map((token) => normalizeSearchText(token))); + return new Set(tokenize(normalizedQuery).filter((token) => !noise.has(token))); +}; + +const includesPhrase = (normalizedQuery, normalizedAlias, queryTokens) => { + if (!normalizedAlias) return false; + if (normalizedQuery.includes(normalizedAlias)) return true; + + const aliasTokens = tokenize(normalizedAlias); + if (aliasTokens.length <= 1) return queryTokens.has(normalizedAlias); + return aliasTokens.every((token) => queryTokens.has(token)); +}; + +const detectQueryIntents = (normalizedQuery) => { + const queryTokens = tokenSetFromQuery(normalizedQuery); + return Object.entries(SEARCH_INTENT_CONFIG.intents) + .filter(([, value]) => + (value.aliases || []).some((alias) => includesPhrase(normalizedQuery, normalizeSearchText(alias), queryTokens))) + .map(([intentId]) => intentId); +}; + +const getLevenshteinDistance = (left, right) => { + const rows = left.length + 1; + const cols = right.length + 1; + const matrix = Array.from({ length: rows }, (_, rowIndex) => [rowIndex]); + + for (let col = 0; col < cols; col += 1) { + matrix[0][col] = col; + } + + for (let row = 1; row < rows; row += 1) { + for (let col = 1; col < cols; col += 1) { + const cost = left[row - 1] === right[col - 1] ? 0 : 1; + matrix[row][col] = Math.min( + matrix[row - 1][col] + 1, + matrix[row][col - 1] + 1, + matrix[row - 1][col - 1] + cost, + ); + } + } + + return matrix[left.length][right.length]; +}; + +const fuzzyBonus = (normalizedQuery, candidates) => { + if (normalizedQuery.length < 3 || normalizedQuery.length > 32) return 0; + + let best = Number.POSITIVE_INFINITY; + (candidates || []).forEach((candidate) => { + if (!candidate) return; + tokenize(candidate).forEach((token) => { + best = Math.min(best, getLevenshteinDistance(normalizedQuery, token)); + }); + best = Math.min(best, getLevenshteinDistance(normalizedQuery, candidate)); + }); + + if (best === 1) return 14; + if (best === 2) return 8; + return 0; +}; + +const scoreTextMatch = (normalizedQuery, normalizedTarget, exact, prefix, contains) => { + if (!normalizedQuery || !normalizedTarget) return 0; + if (normalizedTarget === normalizedQuery) return exact; + if (normalizedTarget.startsWith(normalizedQuery)) return prefix; + if (normalizedTarget.includes(normalizedQuery)) return contains; + return 0; +}; + +const buildDerivedIntentSignals = (entry) => { + const normalizedDescription = normalizeSearchText(entry.description || ''); + const normalizedLight = normalizeSearchText(entry.careInfo && entry.careInfo.light ? entry.careInfo.light : ''); + const derivedSignals = new Set((entry.categories || []).map((category) => normalizeSearchText(category))); + + Object.entries(SEARCH_INTENT_CONFIG.intents).forEach(([intentId, intentConfig]) => { + const entryHints = normalizeArray(intentConfig.entryHints || []); + if (entryHints.some((hint) => normalizedDescription.includes(hint))) { + derivedSignals.add(intentId); + } + + const lightHints = normalizeArray(intentConfig.lightHints || []); + if (lightHints.some((hint) => normalizedLight.includes(hint))) { + derivedSignals.add(intentId); + } + }); + + return [...derivedSignals]; +}; + +const scoreHybridEntry = (entry, query) => { + const normalizedQuery = normalizeSearchText(query); + if (!normalizedQuery) return 0; + + const normalizedName = normalizeSearchText(entry.name || ''); + const normalizedBotanical = normalizeSearchText(entry.botanicalName || ''); + const normalizedDescription = normalizeSearchText(entry.description || ''); + const normalizedCategories = (entry.categories || []).map((category) => normalizeSearchText(category)); + const derivedSignals = buildDerivedIntentSignals(entry); + const requestedIntents = detectQueryIntents(normalizedQuery); + + let score = 0; + score += Math.max( + scoreTextMatch(normalizedQuery, normalizedName, 140, 100, 64), + scoreTextMatch(normalizedQuery, normalizedBotanical, 130, 96, 58), + ); + + if (normalizedDescription.includes(normalizedQuery)) { + score += 24; + } + + score += fuzzyBonus(normalizedQuery, [normalizedName, normalizedBotanical, ...normalizedCategories]); + + let matchedIntentCount = 0; + requestedIntents.forEach((intentId) => { + const categoryHit = normalizedCategories.includes(intentId); + const derivedHit = derivedSignals.includes(intentId); + if (categoryHit) { + score += 92; + matchedIntentCount += 1; + return; + } + if (derivedHit) { + score += 56; + matchedIntentCount += 1; + } + }); + + if (matchedIntentCount >= 2) { + score += 38 * matchedIntentCount; + } else if (matchedIntentCount === 1) { + score += 10; + } + + const queryTokens = [...tokenSetFromQuery(normalizedQuery)]; + if (queryTokens.length > 1) { + const searchableText = [ + normalizedName, + normalizedBotanical, + normalizedDescription, + ...normalizedCategories, + ...derivedSignals, + ].join(' '); + const tokenHits = queryTokens.filter((token) => searchableText.includes(token)).length; + score += tokenHits * 8; + if (tokenHits === queryTokens.length) { + score += 16; + } + } + + return score; +}; + +const rankHybridEntries = (entries, query, limit = 30) => { + const normalizedQuery = normalizeSearchText(query); + if (!normalizedQuery) { + return entries.slice(0, limit).map((entry) => ({ entry, score: 0 })); + } + + return entries + .map((entry) => ({ entry, score: scoreHybridEntry(entry, normalizedQuery) })) + .filter((candidate) => candidate.score > 0) + .sort((left, right) => + right.score - left.score || + left.entry.name.length - right.entry.name.length || + left.entry.name.localeCompare(right.entry.name)) + .slice(0, limit); +}; + +module.exports = { + normalizeSearchText, + rankHybridEntries, + scoreHybridEntry, +}; diff --git a/server/lib/openai.js b/server/lib/openai.js index 0e8bfba..cdf563f 100644 --- a/server/lib/openai.js +++ b/server/lib/openai.js @@ -1,7 +1,9 @@ const OPENAI_API_KEY = (process.env.OPENAI_API_KEY || process.env.EXPO_PUBLIC_OPENAI_API_KEY || '').trim(); -const OPENAI_SCAN_MODEL = (process.env.OPENAI_SCAN_MODEL || process.env.EXPO_PUBLIC_OPENAI_SCAN_MODEL || 'gpt-5').trim(); +const OPENAI_SCAN_MODEL = (process.env.OPENAI_SCAN_MODEL || process.env.EXPO_PUBLIC_OPENAI_SCAN_MODEL || 'gpt-5-mini').trim(); +const OPENAI_SCAN_MODEL_PRO = (process.env.OPENAI_SCAN_MODEL_PRO || process.env.EXPO_PUBLIC_OPENAI_SCAN_MODEL_PRO || OPENAI_SCAN_MODEL).trim(); const OPENAI_HEALTH_MODEL = (process.env.OPENAI_HEALTH_MODEL || process.env.EXPO_PUBLIC_OPENAI_HEALTH_MODEL || OPENAI_SCAN_MODEL).trim(); -const OPENAI_SCAN_FALLBACK_MODELS = (process.env.OPENAI_SCAN_FALLBACK_MODELS || process.env.EXPO_PUBLIC_OPENAI_SCAN_FALLBACK_MODELS || 'gpt-5-mini,gpt-4o-mini').trim(); +const OPENAI_SCAN_FALLBACK_MODELS = (process.env.OPENAI_SCAN_FALLBACK_MODELS || process.env.EXPO_PUBLIC_OPENAI_SCAN_FALLBACK_MODELS || 'gpt-5-mini,gpt-4.1-mini').trim(); +const OPENAI_SCAN_FALLBACK_MODELS_PRO = (process.env.OPENAI_SCAN_FALLBACK_MODELS_PRO || process.env.EXPO_PUBLIC_OPENAI_SCAN_FALLBACK_MODELS_PRO || OPENAI_SCAN_FALLBACK_MODELS).trim(); const OPENAI_HEALTH_FALLBACK_MODELS = (process.env.OPENAI_HEALTH_FALLBACK_MODELS || process.env.EXPO_PUBLIC_OPENAI_HEALTH_FALLBACK_MODELS || OPENAI_SCAN_FALLBACK_MODELS).trim(); const OPENAI_CHAT_COMPLETIONS_URL = (process.env.OPENAI_CHAT_COMPLETIONS_URL || 'https://api.openai.com/v1/chat/completions').trim(); const OPENAI_TIMEOUT_MS = (() => { @@ -22,8 +24,13 @@ const parseModelChain = (primaryModel, fallbackModels) => { }; const OPENAI_SCAN_MODEL_CHAIN = parseModelChain(OPENAI_SCAN_MODEL, OPENAI_SCAN_FALLBACK_MODELS); +const OPENAI_SCAN_MODEL_CHAIN_PRO = parseModelChain(OPENAI_SCAN_MODEL_PRO, OPENAI_SCAN_FALLBACK_MODELS_PRO); const OPENAI_HEALTH_MODEL_CHAIN = parseModelChain(OPENAI_HEALTH_MODEL, OPENAI_HEALTH_FALLBACK_MODELS); +const getScanModelChain = (plan) => { + return plan === 'pro' ? OPENAI_SCAN_MODEL_CHAIN_PRO : OPENAI_SCAN_MODEL_CHAIN; +}; + const clamp = (value, min, max) => { return Math.min(max, Math.max(min, value)); }; @@ -197,12 +204,17 @@ const buildIdentifyPrompt = (language, mode) => { ? 'Re-check your first hypothesis with stricter botanical accuracy and correct any mismatch.' : 'Identify the most likely houseplant species from this image with conservative confidence.'; + const nameLanguageInstruction = language === 'en' + ? '- "name" must be an English common name only. Never return a German or other non-English common name. If no reliable English common name is known, use "botanicalName" as "name" instead of inventing or translating.' + : `- "name" must be strictly written in ${getLanguageLabel(language)}. If a reliable common name in that language is not known, use "botanicalName" as "name" instead of inventing a localized name.`; + return [ `${reviewInstruction}`, 'Return strict JSON only in this shape:', '{"name":"...","botanicalName":"...","confidence":0.0,"description":"...","careInfo":{"waterIntervalDays":7,"light":"...","temp":"..."}}', 'Rules:', - `- "name", "description", and "careInfo.light" must be written in ${getLanguageLabel(language)}.`, + nameLanguageInstruction, + `- "description" and "careInfo.light" must be written in ${getLanguageLabel(language)}.`, '- "botanicalName" must use accepted Latin scientific naming and must not be invented or misspelled.', '- If species is uncertain, prefer genus-level naming (for example: "Calathea sp.").', '- "confidence" must be between 0 and 1.', @@ -324,10 +336,11 @@ const postChatCompletion = async ({ modelChain, messages, imageUri, temperature return { payload: null, modelUsed: null, attemptedModels }; }; -const identifyPlant = async ({ imageUri, language, mode = 'primary' }) => { +const identifyPlant = async ({ imageUri, language, mode = 'primary', plan = 'free' }) => { if (!OPENAI_API_KEY) return { result: null, modelUsed: null, attemptedModels: [] }; + const modelChain = getScanModelChain(plan); const completion = await postChatCompletion({ - modelChain: OPENAI_SCAN_MODEL_CHAIN, + modelChain, imageUri, messages: [ { @@ -355,7 +368,7 @@ const identifyPlant = async ({ imageUri, language, mode = 'primary' }) => { const content = extractMessageContent(completion.payload); if (!content) { console.warn('OpenAI identify returned empty content.', { - model: completion.modelUsed || OPENAI_SCAN_MODEL_CHAIN[0], + model: completion.modelUsed || modelChain[0], mode, image: summarizeImageUri(imageUri), }); @@ -365,7 +378,7 @@ const identifyPlant = async ({ imageUri, language, mode = 'primary' }) => { const parsed = parseContentToJson(content); if (!parsed) { console.warn('OpenAI identify returned non-JSON content.', { - model: completion.modelUsed || OPENAI_SCAN_MODEL_CHAIN[0], + model: completion.modelUsed || modelChain[0], mode, preview: content.slice(0, 220), }); @@ -375,7 +388,7 @@ const identifyPlant = async ({ imageUri, language, mode = 'primary' }) => { const normalized = normalizeIdentifyResult(parsed, language); if (!normalized) { console.warn('OpenAI identify JSON did not match schema.', { - model: completion.modelUsed || OPENAI_SCAN_MODEL_CHAIN[0], + model: completion.modelUsed || modelChain[0], mode, keys: Object.keys(parsed), }); @@ -439,8 +452,10 @@ const analyzePlantHealth = async ({ imageUri, language, plantContext }) => { module.exports = { analyzePlantHealth, + buildIdentifyPrompt, getHealthModel: () => OPENAI_HEALTH_MODEL_CHAIN[0], - getScanModel: () => OPENAI_SCAN_MODEL_CHAIN[0], + getScanModel: (plan = 'free') => getScanModelChain(plan)[0], identifyPlant, isConfigured: () => Boolean(OPENAI_API_KEY), + normalizeIdentifyResult, }; diff --git a/server/lib/plants.js b/server/lib/plants.js index 71a1020..d288a48 100644 --- a/server/lib/plants.js +++ b/server/lib/plants.js @@ -1,11 +1,15 @@ const crypto = require('crypto'); const { all, get, run } = require('./sqlite'); +const { normalizeSearchText, rankHybridEntries } = require('./hybridSearch'); const DEFAULT_LIMIT = 60; const MAX_LIMIT = 500; const MAX_AUDIT_DETAILS = 80; const WIKIMEDIA_FILEPATH_SEGMENT = 'Special:FilePath/'; const WIKIMEDIA_REDIRECT_BASE = 'https://commons.wikimedia.org/wiki/Special:FilePath/'; +const WIKIMEDIA_SEARCH_PREFIX = 'wikimedia-search:'; +const LOCAL_PLANT_IMAGE_PREFIX = '/plants/'; +const LOCAL_PLANT_IMAGE_PATH_PATTERN = /^\/plants\/[A-Za-z0-9/_-]+\.[A-Za-z0-9]+$/; class PlantImportValidationError extends Error { constructor(message, details) { @@ -19,12 +23,7 @@ const normalizeWhitespace = (value) => { return value.trim().replace(/\s+/g, ' '); }; -const normalizeKey = (value) => { - return normalizeWhitespace(value) - .toLowerCase() - .normalize('NFD') - .replace(/[\u0300-\u036f]/g, ''); -}; +const normalizeKey = (value) => normalizeSearchText(normalizeWhitespace(value)); const unwrapMarkdownLink = (value) => { const markdownMatch = value.match(/^\[[^\]]+]\((https?:\/\/[^)]+)\)(.*)$/i); @@ -41,6 +40,16 @@ const tryDecode = (value) => { } }; +const decodeRepeatedly = (value, rounds = 3) => { + let current = value; + for (let index = 0; index < rounds; index += 1) { + const decoded = tryDecode(current); + if (decoded === current) break; + current = decoded; + } + return current; +}; + const convertWikimediaFilePathUrl = (value) => { const segmentIndex = value.indexOf(WIKIMEDIA_FILEPATH_SEGMENT); if (segmentIndex < 0) return null; @@ -55,12 +64,75 @@ const convertWikimediaFilePathUrl = (value) => { return `${WIKIMEDIA_REDIRECT_BASE}${encodedFileName}`; }; +const toWikimediaFilePathUrl = (value) => { + if (typeof value !== 'string' || !value.includes('upload.wikimedia.org/wikipedia/commons/')) { + return null; + } + + const cleanUrl = value.split(/[?#]/)[0]; + const parts = cleanUrl.split('/').filter(Boolean); + if (parts.length < 2) return null; + + let fileName = null; + const thumbIndex = parts.indexOf('thumb'); + + if (thumbIndex >= 0 && parts.length >= thumbIndex + 5) { + fileName = parts[parts.length - 2]; + } else { + fileName = parts[parts.length - 1]; + } + + if (!fileName) return null; + + const decoded = tryDecode(fileName).trim(); + if (!decoded) return null; + + return `${WIKIMEDIA_REDIRECT_BASE}${encodeURIComponent(decoded)}`; +}; + +const normalizeLocalImagePath = (value) => { + if (typeof value !== 'string') return null; + + const trimmed = value.trim(); + if (!trimmed) return null; + + const withoutQuery = trimmed.split(/[?#]/)[0].replace(/\\/g, '/'); + const withLeadingSlash = withoutQuery.startsWith('/') ? withoutQuery : `/${withoutQuery}`; + + if (!withLeadingSlash.startsWith(LOCAL_PLANT_IMAGE_PREFIX)) return null; + if (withLeadingSlash.includes('..')) return null; + if (!LOCAL_PLANT_IMAGE_PATH_PATTERN.test(withLeadingSlash)) return null; + + return withLeadingSlash; +}; + +const normalizeWikimediaSearchUri = (value) => { + if (typeof value !== 'string') return null; + + const trimmed = value.trim(); + if (!trimmed.toLowerCase().startsWith(WIKIMEDIA_SEARCH_PREFIX)) return null; + + const rawQuery = trimmed.slice(WIKIMEDIA_SEARCH_PREFIX.length).trim(); + if (!rawQuery) return null; + + const normalizedQuery = normalizeWhitespace(decodeRepeatedly(rawQuery)); + if (!normalizedQuery) return null; + + return `${WIKIMEDIA_SEARCH_PREFIX}${encodeURIComponent(normalizedQuery)}`; +}; + const normalizeImageUri = (rawUri) => { if (typeof rawUri !== 'string') return null; const trimmed = rawUri.trim(); if (!trimmed) return null; + const localPath = normalizeLocalImagePath(trimmed); + if (localPath) return localPath; + + const wikimediaSearchUri = normalizeWikimediaSearchUri(trimmed); + if (wikimediaSearchUri) return wikimediaSearchUri; + const normalized = unwrapMarkdownLink(trimmed); const converted = convertWikimediaFilePathUrl(normalized); const candidate = (converted || normalized).replace(/^http:\/\//i, 'https://'); @@ -142,10 +214,11 @@ const prepareEntry = (rawEntry, index, existingIdMap, preserveExistingIds) => { errors.push({ index, field: 'imageUri', - message: 'imageUri is missing or invalid. A valid http(s) URL is required.', + message: 'imageUri is missing or invalid. Use a valid http(s) URL, a local /plants/... path, or wikimedia-search:.', value: rawEntry?.imageUri ?? null, }); } + const imageStatus = imageUri && imageUri.startsWith(WIKIMEDIA_SEARCH_PREFIX) ? 'pending' : 'ok'; const categories = toArrayOfStrings(rawEntry?.categories); const confidence = parseNumber(rawEntry?.confidence, 1); @@ -168,7 +241,7 @@ const prepareEntry = (rawEntry, index, existingIdMap, preserveExistingIds) => { name, botanicalName, imageUri, - imageStatus: 'ok', + imageStatus, description, categories, careInfo, @@ -335,11 +408,12 @@ const parseJsonObject = (value) => { const toApiPlant = (row) => { const categories = parseJsonArray(row.categories); const careInfo = parseJsonObject(row.careInfo); + const imageUri = toWikimediaFilePathUrl(row.imageUri) || row.imageUri; return { id: row.id, name: row.name, botanicalName: row.botanicalName, - imageUri: row.imageUri, + imageUri, imageStatus: row.imageStatus || 'ok', description: row.description || '', categories, @@ -349,7 +423,7 @@ const toApiPlant = (row) => { }; const getPlants = async (db, options = {}) => { - const query = typeof options.query === 'string' ? options.query.trim().toLowerCase() : ''; + const query = typeof options.query === 'string' ? options.query.trim() : ''; const category = typeof options.category === 'string' ? options.category.trim() : ''; const limitRaw = Number(options.limit); const limit = Number.isFinite(limitRaw) @@ -368,15 +442,6 @@ const getPlants = async (db, options = {}) => { confidence FROM plants`; const params = []; - if (query) { - sql += ` WHERE ( - LOWER(name) LIKE ? - OR LOWER(botanicalName) LIKE ? - OR LOWER(COALESCE(description, '')) LIKE ? - )`; - const likePattern = `%${query}%`; - params.push(likePattern, likePattern, likePattern); - } sql += ' ORDER BY name COLLATE NOCASE ASC'; const rows = await all(db, sql, params); @@ -386,7 +451,12 @@ const getPlants = async (db, options = {}) => { results = results.filter((plant) => plant.categories.includes(category)); } - return results.slice(0, limit); + if (!query) { + return results.slice(0, limit); + } + + return rankHybridEntries(results, query, limit) + .map((candidate) => candidate.entry); }; const getPlantDiagnostics = async (db) => { @@ -565,7 +635,7 @@ const rebuildPlantsCatalog = async (db, rawEntries, options = {}) => { entry.name, entry.botanicalName, entry.imageUri, - 'ok', + entry.imageStatus, entry.description, JSON.stringify(entry.categories), JSON.stringify(entry.careInfo), @@ -647,6 +717,8 @@ module.exports = { ensurePlantSchema, getPlantDiagnostics, getPlants, + normalizeKey, normalizeImageUri, + toWikimediaFilePathUrl, rebuildPlantsCatalog, }; diff --git a/server/lib/scanGrounding.js b/server/lib/scanGrounding.js new file mode 100644 index 0000000..4491ed6 --- /dev/null +++ b/server/lib/scanGrounding.js @@ -0,0 +1,131 @@ +const clamp = (value, min, max) => { + return Math.min(max, Math.max(min, value)); +}; + +const normalizeText = (value) => { + return String(value || '') + .toLowerCase() + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .replace(/\s+/g, ' ') + .trim(); +}; + +const GERMAN_COMMON_NAME_HINTS = [ + 'weihnachtsstern', + 'weinachtsstern', + 'einblatt', + 'fensterblatt', + 'korbmarante', + 'glucksfeder', + 'gluecksfeder', + 'efeutute', + 'drachenbaum', + 'gummibaum', + 'geigenfeige', + 'bogenhanf', + 'yucca palme', + 'gluckskastanie', + 'glueckskastanie', +]; + +const isLikelyGermanCommonName = (value) => { + const raw = String(value || '').trim(); + if (!raw) return false; + if (/[äöüß]/i.test(raw)) return true; + + const normalized = normalizeText(raw).replace(/[^a-z0-9 ]+/g, ' '); + if (!normalized) return false; + if (/\b(der|die|das|ein|eine)\b/.test(normalized)) return true; + + return GERMAN_COMMON_NAME_HINTS.some((hint) => normalized.includes(hint)); +}; + +const isLikelyBotanicalName = (value, botanicalName) => { + const raw = String(value || '').trim(); + const botanicalRaw = String(botanicalName || '').trim(); + if (!raw) return false; + + if (normalizeText(raw) === normalizeText(botanicalRaw)) return true; + + return /^[A-Z][a-z-]+(?:\s[a-z.-]+){1,2}$/.test(raw); +}; + +const findCatalogMatch = (aiResult, entries) => { + if (!aiResult || !Array.isArray(entries) || entries.length === 0) return null; + const aiBotanical = normalizeText(aiResult.botanicalName); + const aiName = normalizeText(aiResult.name); + if (!aiBotanical && !aiName) return null; + + const byExactBotanical = entries.find((entry) => normalizeText(entry.botanicalName) === aiBotanical); + if (byExactBotanical) return byExactBotanical; + + const byExactName = entries.find((entry) => normalizeText(entry.name) === aiName); + if (byExactName) return byExactName; + + if (aiBotanical) { + const aiGenus = aiBotanical.split(' ')[0]; + if (aiGenus) { + const byGenus = entries.find((entry) => normalizeText(entry.botanicalName).startsWith(`${aiGenus} `)); + if (byGenus) return byGenus; + } + } + + const byContains = entries.find((entry) => { + const plantName = normalizeText(entry.name); + const botanical = normalizeText(entry.botanicalName); + return (aiName && (plantName.includes(aiName) || aiName.includes(plantName))) + || (aiBotanical && (botanical.includes(aiBotanical) || aiBotanical.includes(botanical))); + }); + if (byContains) return byContains; + + return null; +}; + +const shouldUseCatalogNameOverride = ({ language, aiResult, matchedEntry }) => { + const catalogName = String(matchedEntry?.name || '').trim(); + if (!catalogName) return false; + if (language !== 'en') return true; + + if (isLikelyBotanicalName(catalogName, matchedEntry?.botanicalName || aiResult?.botanicalName)) { + return true; + } + + if (isLikelyGermanCommonName(catalogName)) { + return false; + } + + return true; +}; + +const applyCatalogGrounding = (aiResult, catalogEntries, language = 'en') => { + const matchedEntry = findCatalogMatch(aiResult, catalogEntries); + if (!matchedEntry) { + return { grounded: false, result: aiResult }; + } + + const useCatalogName = shouldUseCatalogNameOverride({ language, aiResult, matchedEntry }); + + return { + grounded: true, + result: { + name: useCatalogName ? matchedEntry.name || aiResult.name : aiResult.name, + botanicalName: matchedEntry.botanicalName || aiResult.botanicalName, + confidence: clamp(Math.max(aiResult.confidence || 0.6, 0.78), 0.05, 0.99), + description: aiResult.description || matchedEntry.description || '', + careInfo: { + waterIntervalDays: Math.max(1, Number(matchedEntry.careInfo?.waterIntervalDays) || Number(aiResult.careInfo?.waterIntervalDays) || 7), + light: matchedEntry.careInfo?.light || aiResult.careInfo?.light || 'Unknown', + temp: matchedEntry.careInfo?.temp || aiResult.careInfo?.temp || 'Unknown', + }, + }, + }; +}; + +module.exports = { + applyCatalogGrounding, + findCatalogMatch, + isLikelyGermanCommonName, + normalizeText, + shouldUseCatalogNameOverride, +}; diff --git a/server/lib/searchIntentConfig.js b/server/lib/searchIntentConfig.js new file mode 100644 index 0000000..7c36f60 --- /dev/null +++ b/server/lib/searchIntentConfig.js @@ -0,0 +1,402 @@ +const SEARCH_INTENT_CONFIG = { + intents: { + easy: { + aliases: [ + 'easy', + 'easy care', + 'easy plant', + 'easy plants', + 'easy to care', + 'beginner', + 'beginner plant', + 'beginner plants', + 'low maintenance', + 'hard to kill', + 'starter plant', + 'starter plants', + 'pflegearm', + 'pflegeleicht', + 'anfanger', + 'anfangerpflanze', + 'anfangerpflanzen', + 'einfach', + 'unkompliziert', + 'facil cuidado', + 'facil', + 'principiante', + 'planta facil', + 'planta resistente', + ], + entryHints: [ + 'easy', + 'pflegeleicht', + 'robust', + 'resilient', + 'hardy', + 'low maintenance', + 'beginner', + 'facil', + 'resistente', + 'uncomplicated', + ], + }, + low_light: { + aliases: [ + 'low light', + 'dark corner', + 'dark room', + 'office plant', + 'office', + 'windowless room', + 'shade', + 'shady', + 'indirect light', + 'little light', + 'wenig licht', + 'dunkle ecke', + 'buero', + 'buro', + 'dunkel', + 'schatten', + 'halbschatten', + 'poca luz', + 'oficina', + 'rincon oscuro', + 'sombra', + ], + lightHints: [ + 'low light', + 'low to full light', + 'shade', + 'partial shade', + 'indirect', + 'indirect bright', + 'bright indirect', + 'wenig licht', + 'schatten', + 'halbschatten', + 'indirekt', + 'poca luz', + 'sombra', + 'luz indirecta', + ], + }, + pet_friendly: { + aliases: [ + 'pet friendly', + 'pet-safe', + 'pet safe', + 'safe for cats', + 'safe for dogs', + 'cat safe', + 'dog safe', + 'non toxic', + 'non-toxic', + 'haustierfreundlich', + 'tierfreundlich', + 'katzensicher', + 'hundefreundlich', + 'mascota', + 'pet friendly plant', + 'segura para gatos', + 'segura para perros', + 'no toxica', + 'no tóxica', + ], + entryHints: [ + 'pet friendly', + 'safe for pets', + 'safe for cats', + 'safe for dogs', + 'tierfreundlich', + 'haustierfreundlich', + 'mascota', + ], + }, + air_purifier: { + aliases: [ + 'air purifier', + 'air purifying', + 'clean air', + 'cleaner air', + 'air cleaning', + 'air freshening', + 'luftreiniger', + 'luftreinigend', + 'reinigt luft', + 'purificador', + 'aire limpio', + 'purifica aire', + ], + entryHints: [ + 'air purifier', + 'air purifying', + 'clean air', + 'luftreiniger', + 'purificador', + ], + }, + flowering: { + aliases: [ + 'flowering', + 'flowers', + 'blooms', + 'in bloom', + 'bluhend', + 'bluht', + 'blumen', + 'con flores', + 'floracion', + ], + entryHints: [ + 'flowering', + 'blooms', + 'flower', + 'bluh', + 'flor', + ], + }, + succulent: { + aliases: [ + 'succulent', + 'succulents', + 'cactus', + 'cactus-like', + 'drought tolerant', + 'sukkulente', + 'sukkulenten', + 'trockenheitsvertraglich', + 'trockenheitsvertraeglich', + 'suculenta', + 'suculentas', + ], + entryHints: [ + 'succulent', + 'cactus', + 'drought tolerant', + 'sukkulent', + 'suculenta', + ], + }, + bright_light: { + aliases: [ + 'bright light', + 'bright room', + 'bright spot', + 'east window', + 'west window', + 'sunny room', + 'helles licht', + 'hell', + 'lichtreich', + 'fensterplatz', + 'mucha luz', + 'luz brillante', + ], + lightHints: [ + 'bright light', + 'bright indirect', + 'bright', + 'helles licht', + 'helles indirektes licht', + 'luz brillante', + ], + }, + sun: { + aliases: [ + 'full sun', + 'sun', + 'sunny window', + 'direct sun', + 'south window', + 'south facing window', + 'volle sonne', + 'sonnig', + 'direkte sonne', + 'fenster sud', + 'fenster sued', + 'fenster süd', + 'ventana soleada', + 'sol directo', + ], + lightHints: [ + 'full sun', + 'sunny', + 'direct sun', + 'volles sonnenlicht', + 'sonnig', + 'sol directo', + ], + }, + high_humidity: { + aliases: [ + 'high humidity', + 'humid', + 'bathroom plant', + 'bathroom', + 'shower room', + 'humid room', + 'tropical humidity', + 'hohe luftfeuchtigkeit', + 'feucht', + 'badezimmer', + 'dusche', + 'luftfeucht', + 'humedad alta', + 'bano', + 'baño', + ], + entryHints: [ + 'high humidity', + 'humidity', + 'humid', + 'hohe luftfeuchtigkeit', + 'luftfeuchtigkeit', + 'humedad alta', + ], + }, + hanging: { + aliases: [ + 'hanging', + 'trailing', + 'hanging basket', + 'shelf plant', + 'vine plant', + 'cascading', + 'hangend', + 'ampel', + 'rankend', + 'colgante', + 'planta colgante', + ], + entryHints: [ + 'hanging', + 'trailing', + 'vine', + 'hang', + 'colgante', + ], + }, + patterned: { + aliases: [ + 'patterned', + 'patterned leaves', + 'striped', + 'variegated', + 'spotted', + 'decorative leaves', + 'fancy leaves', + 'gemustert', + 'muster', + 'gestreift', + 'bunt', + 'variegada', + 'rayada', + ], + entryHints: [ + 'patterned', + 'striped', + 'variegated', + 'spotted', + 'gemustert', + 'gestreift', + ], + }, + tree: { + aliases: [ + 'tree', + 'indoor tree', + 'small tree', + 'floor tree', + 'zimmerbaum', + 'baum', + 'arbol', + 'árbol', + ], + entryHints: [ + 'tree', + 'baum', + 'arbol', + ], + }, + large: { + aliases: [ + 'large', + 'big plant', + 'tall plant', + 'statement plant', + 'floor plant', + 'oversized plant', + 'gross', + 'groß', + 'grosse pflanze', + 'hohe pflanze', + 'planta grande', + 'planta alta', + ], + entryHints: [ + 'large', + 'big', + 'tall', + 'gross', + 'groß', + 'grande', + ], + }, + medicinal: { + aliases: [ + 'medicinal', + 'healing plant', + 'herb', + 'kitchen herb', + 'tea herb', + 'apothecary plant', + 'heilpflanze', + 'heilkraut', + 'kraut', + 'medicinal plant', + 'medicinal herb', + 'medicinales', + 'hierba', + 'hierba medicinal', + ], + entryHints: [ + 'medicinal', + 'herb', + 'heil', + 'kraut', + 'hierba', + ], + }, + }, + noiseTokens: [ + 'plant', + 'plants', + 'pflanze', + 'pflanzen', + 'planta', + 'plantas', + 'for', + 'fur', + 'fuer', + 'para', + 'mit', + 'with', + 'and', + 'und', + 'y', + 'the', + 'der', + 'die', + 'das', + 'el', + 'la', + 'de', + 'a', + 'an', + ], +}; + +module.exports = { + SEARCH_INTENT_CONFIG, +}; diff --git a/server/lib/storage.js b/server/lib/storage.js new file mode 100644 index 0000000..f8f320a --- /dev/null +++ b/server/lib/storage.js @@ -0,0 +1,72 @@ +const Minio = require('minio'); +const crypto = require('crypto'); + +const getTrimmedEnv = (name, fallback = '') => String(process.env[name] ?? fallback).trim(); + +const MINIO_ENDPOINT = getTrimmedEnv('MINIO_ENDPOINT'); +const MINIO_PORT = Number(process.env.MINIO_PORT || 9000); +const MINIO_USE_SSL = process.env.MINIO_USE_SSL === 'true'; +const MINIO_ACCESS_KEY = getTrimmedEnv('MINIO_ACCESS_KEY'); +const MINIO_SECRET_KEY = getTrimmedEnv('MINIO_SECRET_KEY'); +const MINIO_BUCKET = getTrimmedEnv('MINIO_BUCKET', 'plant-images') || 'plant-images'; + +const isStorageConfigured = () => Boolean(MINIO_ENDPOINT && MINIO_ACCESS_KEY && MINIO_SECRET_KEY); + +const getMinioPublicUrl = () => + getTrimmedEnv('MINIO_PUBLIC_URL', `http://${MINIO_ENDPOINT}:${MINIO_PORT}`).replace(/\/$/, ''); + +const getClient = () => { + if (!isStorageConfigured()) { + throw new Error('Image storage is not configured.'); + } + + return new Minio.Client({ + endPoint: MINIO_ENDPOINT, + port: MINIO_PORT, + useSSL: MINIO_USE_SSL, + accessKey: MINIO_ACCESS_KEY, + secretKey: MINIO_SECRET_KEY, + }); +}; + +const ensureStorageBucket = async () => { + const client = getClient(); + const exists = await client.bucketExists(MINIO_BUCKET); + if (!exists) { + await client.makeBucket(MINIO_BUCKET); + const policy = JSON.stringify({ + Version: '2012-10-17', + Statement: [ + { + Effect: 'Allow', + Principal: { AWS: ['*'] }, + Action: ['s3:GetObject'], + Resource: [`arn:aws:s3:::${MINIO_BUCKET}/*`], + }, + ], + }); + await client.setBucketPolicy(MINIO_BUCKET, policy); + console.log(`MinIO bucket '${MINIO_BUCKET}' created with public read policy.`); + } +}; + +const uploadImage = async (base64Data, contentType = 'image/jpeg') => { + const client = getClient(); + const rawExtension = contentType.split('/')[1] || 'jpg'; + const extension = rawExtension === 'jpeg' ? 'jpg' : rawExtension; + const filename = `${Date.now()}-${crypto.randomBytes(8).toString('hex')}.${extension}`; + const buffer = Buffer.from(base64Data, 'base64'); + + await client.putObject(MINIO_BUCKET, filename, buffer, buffer.length, { + 'Content-Type': contentType, + }); + + const url = `${getMinioPublicUrl()}/${MINIO_BUCKET}/${filename}`; + return { url, filename }; +}; + +module.exports = { + ensureStorageBucket, + uploadImage, + isStorageConfigured, +}; diff --git a/server/package-lock.json b/server/package-lock.json index 1191b3c..043fb07 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -12,10 +12,22 @@ "cors": "^2.8.6", "dotenv": "^17.3.1", "express": "^5.2.1", + "minio": "^8.0.5", + "sharp": "^0.34.5", "sqlite3": "^5.1.7", "stripe": "^20.3.1" } }, + "node_modules/@emnapi/runtime": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", @@ -23,6 +35,471 @@ "license": "MIT", "optional": true }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@npmcli/fs": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", @@ -151,6 +628,12 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -198,6 +681,15 @@ "readable-stream": "^3.4.0" } }, + "node_modules/block-stream2": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/block-stream2/-/block-stream2-2.1.0.tgz", + "integrity": "sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==", + "license": "MIT", + "dependencies": { + "readable-stream": "^3.4.0" + } + }, "node_modules/body-parser": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", @@ -233,6 +725,12 @@ "concat-map": "0.0.1" } }, + "node_modules/browser-or-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-2.1.1.tgz", + "integrity": "sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==", + "license": "MIT" + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -257,6 +755,15 @@ "ieee754": "^1.1.13" } }, + "node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -442,6 +949,15 @@ } } }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -633,6 +1149,12 @@ "node": ">= 0.6" } }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -685,12 +1207,52 @@ "url": "https://opencollective.com/express" } }, + "node_modules/fast-xml-builder": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.0.0.tgz", + "integrity": "sha512-fpZuDogrAgnyt9oDDz+5DBz0zgPdPZz6D4IR7iESxRXElrlGTRkHJ9eEt+SACRJwT0FNFrt71DFQIUFBJfX/uQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/fast-xml-parser": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.4.2.tgz", + "integrity": "sha512-pw/6pIl4k0CSpElPEJhDppLzaixDEuWui2CUQQBH/ECDf7+y6YwA4Gf7Tyb0Rfe4DIMuZipYj4AEL0nACKglvQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "fast-xml-builder": "^1.0.0", + "strnum": "^2.1.2" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "license": "MIT" }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/finalhandler": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", @@ -1102,6 +1664,12 @@ "license": "ISC", "optional": true }, + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "license": "MIT" + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -1242,6 +1810,60 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minio": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/minio/-/minio-8.0.7.tgz", + "integrity": "sha512-E737MgufW8CeQAsTAtnEMrxZ9scMSf29kkhZoXzDTKj/Jszzo2SfeZUH9wbDQH2Rsq6TCtl/yQL0+XdVKZansQ==", + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.4", + "block-stream2": "^2.1.0", + "browser-or-node": "^2.1.1", + "buffer-crc32": "^1.0.0", + "eventemitter3": "^5.0.1", + "fast-xml-parser": "^5.3.4", + "ipaddr.js": "^2.0.1", + "lodash": "^4.17.21", + "mime-types": "^2.1.35", + "query-string": "^7.1.3", + "stream-json": "^1.8.0", + "through2": "^4.0.2", + "xml2js": "^0.5.0 || ^0.6.2" + }, + "engines": { + "node": "^16 || ^18 || >=20" + } + }, + "node_modules/minio/node_modules/ipaddr.js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.3.0.tgz", + "integrity": "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/minio/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minio/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minipass": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", @@ -1625,6 +2247,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -1747,6 +2387,15 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, + "node_modules/sax": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.5.0.tgz", + "integrity": "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, "node_modules/semver": { "version": "7.7.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", @@ -1817,6 +2466,50 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -1982,6 +2675,15 @@ "node": ">= 10" } }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/sqlite3": { "version": "5.1.7", "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", @@ -2028,6 +2730,30 @@ "node": ">= 0.8" } }, + "node_modules/stream-chain": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", + "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", + "license": "BSD-3-Clause" + }, + "node_modules/stream-json": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", + "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==", + "license": "BSD-3-Clause", + "dependencies": { + "stream-chain": "^2.2.5" + } + }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -2091,6 +2817,18 @@ } } }, + "node_modules/strnum": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.0.tgz", + "integrity": "sha512-Y7Bj8XyJxnPAORMZj/xltsfo55uOiyHcU2tnAVzHUnSJR/KsEX+9RoDeXEnsXtl/CX4fAcrt64gZ13aGaWPeBg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", @@ -2152,6 +2890,15 @@ "node": ">=8" } }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -2161,6 +2908,13 @@ "node": ">=0.6" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -2263,6 +3017,28 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/server/package.json b/server/package.json index 25b4040..a0dd331 100644 --- a/server/package.json +++ b/server/package.json @@ -7,6 +7,7 @@ "start": "node index.js", "rebuild:batches": "node scripts/rebuild-from-batches.js", "diagnostics": "node scripts/plant-diagnostics.js", + "images:download": "node scripts/download-plant-images.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], @@ -16,6 +17,8 @@ "cors": "^2.8.6", "dotenv": "^17.3.1", "express": "^5.2.1", + "minio": "^8.0.5", + "sharp": "^0.34.5", "sqlite3": "^5.1.7", "stripe": "^20.3.1" } diff --git a/server/public/plants/.gitkeep b/server/public/plants/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/server/public/plants/.gitkeep @@ -0,0 +1 @@ + diff --git a/server/public/plants/acer-palmatum--faecherahorn--388b6858.webp b/server/public/plants/acer-palmatum--faecherahorn--388b6858.webp new file mode 100644 index 0000000..43e664c Binary files /dev/null and b/server/public/plants/acer-palmatum--faecherahorn--388b6858.webp differ diff --git a/server/public/plants/acer-platanoides--spitzahorn--dc2fbf6a.webp b/server/public/plants/acer-platanoides--spitzahorn--dc2fbf6a.webp new file mode 100644 index 0000000..b714961 Binary files /dev/null and b/server/public/plants/acer-platanoides--spitzahorn--dc2fbf6a.webp differ diff --git a/server/public/plants/achillea-millefolium--schafgarbe--a945b3a0.webp b/server/public/plants/achillea-millefolium--schafgarbe--a945b3a0.webp new file mode 100644 index 0000000..086354d Binary files /dev/null and b/server/public/plants/achillea-millefolium--schafgarbe--a945b3a0.webp differ diff --git a/server/public/plants/adenium-obesum--wuestenrose--18b1b800.webp b/server/public/plants/adenium-obesum--wuestenrose--18b1b800.webp new file mode 100644 index 0000000..4e10447 Binary files /dev/null and b/server/public/plants/adenium-obesum--wuestenrose--18b1b800.webp differ diff --git a/server/public/plants/adenium-socotranum--socotra-wuestenrose--0118195c.webp b/server/public/plants/adenium-socotranum--socotra-wuestenrose--0118195c.webp new file mode 100644 index 0000000..e7c56cb Binary files /dev/null and b/server/public/plants/adenium-socotranum--socotra-wuestenrose--0118195c.webp differ diff --git a/server/public/plants/adiantum-raddianum--frauenhaarfarn--d47cef0b.webp b/server/public/plants/adiantum-raddianum--frauenhaarfarn--d47cef0b.webp new file mode 100644 index 0000000..70c377a Binary files /dev/null and b/server/public/plants/adiantum-raddianum--frauenhaarfarn--d47cef0b.webp differ diff --git a/server/public/plants/adromischus-cristatus--adromischus--9b24b9fc.webp b/server/public/plants/adromischus-cristatus--adromischus--9b24b9fc.webp new file mode 100644 index 0000000..10fe5cd Binary files /dev/null and b/server/public/plants/adromischus-cristatus--adromischus--9b24b9fc.webp differ diff --git a/server/public/plants/aechmea-fasciata--silbervase--04efba01.webp b/server/public/plants/aechmea-fasciata--silbervase--04efba01.webp new file mode 100644 index 0000000..f8c8ba6 Binary files /dev/null and b/server/public/plants/aechmea-fasciata--silbervase--04efba01.webp differ diff --git a/server/public/plants/aeonium-arboreum--schwarze-rose-aeonium--2fa8210f.webp b/server/public/plants/aeonium-arboreum--schwarze-rose-aeonium--2fa8210f.webp new file mode 100644 index 0000000..062d47f Binary files /dev/null and b/server/public/plants/aeonium-arboreum--schwarze-rose-aeonium--2fa8210f.webp differ diff --git a/server/public/plants/aeschynanthus-radicans--lippenstiftpflanze--c0f3a18c.webp b/server/public/plants/aeschynanthus-radicans--lippenstiftpflanze--c0f3a18c.webp new file mode 100644 index 0000000..8dbaaea Binary files /dev/null and b/server/public/plants/aeschynanthus-radicans--lippenstiftpflanze--c0f3a18c.webp differ diff --git a/server/public/plants/agave-americana--agave--3b197a68.webp b/server/public/plants/agave-americana--agave--3b197a68.webp new file mode 100644 index 0000000..08e9777 Binary files /dev/null and b/server/public/plants/agave-americana--agave--3b197a68.webp differ diff --git a/server/public/plants/aglaonema-commutatum--aglaoneme--7928abe4.webp b/server/public/plants/aglaonema-commutatum--aglaoneme--7928abe4.webp new file mode 100644 index 0000000..4cddfcc Binary files /dev/null and b/server/public/plants/aglaonema-commutatum--aglaoneme--7928abe4.webp differ diff --git a/server/public/plants/alcea-rosea--stockrose--4b6ec327.webp b/server/public/plants/alcea-rosea--stockrose--4b6ec327.webp new file mode 100644 index 0000000..f99dced Binary files /dev/null and b/server/public/plants/alcea-rosea--stockrose--4b6ec327.webp differ diff --git a/server/public/plants/allium-schoenoprasum--schnittlauch--d820fe95.webp b/server/public/plants/allium-schoenoprasum--schnittlauch--d820fe95.webp new file mode 100644 index 0000000..df35c45 Binary files /dev/null and b/server/public/plants/allium-schoenoprasum--schnittlauch--d820fe95.webp differ diff --git a/server/public/plants/allium-tuberosum--schnittknoblauch--3904b032.webp b/server/public/plants/allium-tuberosum--schnittknoblauch--3904b032.webp new file mode 100644 index 0000000..2972163 Binary files /dev/null and b/server/public/plants/allium-tuberosum--schnittknoblauch--3904b032.webp differ diff --git a/server/public/plants/alocasia-amazonica--amazona-taro--e1c87d71.webp b/server/public/plants/alocasia-amazonica--amazona-taro--e1c87d71.webp new file mode 100644 index 0000000..8aaee6d Binary files /dev/null and b/server/public/plants/alocasia-amazonica--amazona-taro--e1c87d71.webp differ diff --git a/server/public/plants/alocasia-zebrina--525caa90.webp b/server/public/plants/alocasia-zebrina--525caa90.webp new file mode 100644 index 0000000..b3cece5 Binary files /dev/null and b/server/public/plants/alocasia-zebrina--525caa90.webp differ diff --git a/server/public/plants/aloe-arborescens--kap-aloe--2c4f60ef.webp b/server/public/plants/aloe-arborescens--kap-aloe--2c4f60ef.webp new file mode 100644 index 0000000..b69387d Binary files /dev/null and b/server/public/plants/aloe-arborescens--kap-aloe--2c4f60ef.webp differ diff --git a/server/public/plants/aloe-ferox--kap-aloe-ferox--e78c3f65.webp b/server/public/plants/aloe-ferox--kap-aloe-ferox--e78c3f65.webp new file mode 100644 index 0000000..44b4582 Binary files /dev/null and b/server/public/plants/aloe-ferox--kap-aloe-ferox--e78c3f65.webp differ diff --git a/server/public/plants/aloe-vera--206a00f6.webp b/server/public/plants/aloe-vera--206a00f6.webp new file mode 100644 index 0000000..a3050c8 Binary files /dev/null and b/server/public/plants/aloe-vera--206a00f6.webp differ diff --git a/server/public/plants/aloysia-citrodora--zitronenverbene--92460709.webp b/server/public/plants/aloysia-citrodora--zitronenverbene--92460709.webp new file mode 100644 index 0000000..22d7bee Binary files /dev/null and b/server/public/plants/aloysia-citrodora--zitronenverbene--92460709.webp differ diff --git a/server/public/plants/alpinia-zerumbet--muschelingwer--f0c5c11e.webp b/server/public/plants/alpinia-zerumbet--muschelingwer--f0c5c11e.webp new file mode 100644 index 0000000..4a94f57 Binary files /dev/null and b/server/public/plants/alpinia-zerumbet--muschelingwer--f0c5c11e.webp differ diff --git a/server/public/plants/amaranthus-caudatus--fuchsschwanz--ae0190ae.webp b/server/public/plants/amaranthus-caudatus--fuchsschwanz--ae0190ae.webp new file mode 100644 index 0000000..b559582 Binary files /dev/null and b/server/public/plants/amaranthus-caudatus--fuchsschwanz--ae0190ae.webp differ diff --git a/server/public/plants/anemone-coronaria--anemone--8a7fda1c.webp b/server/public/plants/anemone-coronaria--anemone--8a7fda1c.webp new file mode 100644 index 0000000..fbdea13 Binary files /dev/null and b/server/public/plants/anemone-coronaria--anemone--8a7fda1c.webp differ diff --git a/server/public/plants/anethum-graveolens--dill--b93ab119.webp b/server/public/plants/anethum-graveolens--dill--b93ab119.webp new file mode 100644 index 0000000..7b0d470 Binary files /dev/null and b/server/public/plants/anethum-graveolens--dill--b93ab119.webp differ diff --git a/server/public/plants/anthriscus-cerefolium--kerbel--eb8bf3ab.webp b/server/public/plants/anthriscus-cerefolium--kerbel--eb8bf3ab.webp new file mode 100644 index 0000000..2832606 Binary files /dev/null and b/server/public/plants/anthriscus-cerefolium--kerbel--eb8bf3ab.webp differ diff --git a/server/public/plants/anthurium-andraeanum--flamingoblume--2087000b.webp b/server/public/plants/anthurium-andraeanum--flamingoblume--2087000b.webp new file mode 100644 index 0000000..e9df0ff Binary files /dev/null and b/server/public/plants/anthurium-andraeanum--flamingoblume--2087000b.webp differ diff --git a/server/public/plants/anthurium-clarinervium--samt-anthurie--dd38d7fa.webp b/server/public/plants/anthurium-clarinervium--samt-anthurie--dd38d7fa.webp new file mode 100644 index 0000000..269906c Binary files /dev/null and b/server/public/plants/anthurium-clarinervium--samt-anthurie--dd38d7fa.webp differ diff --git a/server/public/plants/anthurium-crystallinum--kristall-anthurie--2d5ec8d4.webp b/server/public/plants/anthurium-crystallinum--kristall-anthurie--2d5ec8d4.webp new file mode 100644 index 0000000..8236907 Binary files /dev/null and b/server/public/plants/anthurium-crystallinum--kristall-anthurie--2d5ec8d4.webp differ diff --git a/server/public/plants/antirrhinum-majus--loewenmaeulchen--ee99a45e.webp b/server/public/plants/antirrhinum-majus--loewenmaeulchen--ee99a45e.webp new file mode 100644 index 0000000..182d9ff Binary files /dev/null and b/server/public/plants/antirrhinum-majus--loewenmaeulchen--ee99a45e.webp differ diff --git a/server/public/plants/araucaria-heterophylla--norfolk-tanne--56ef2a36.webp b/server/public/plants/araucaria-heterophylla--norfolk-tanne--56ef2a36.webp new file mode 100644 index 0000000..47f23a7 Binary files /dev/null and b/server/public/plants/araucaria-heterophylla--norfolk-tanne--56ef2a36.webp differ diff --git a/server/public/plants/arnica-montana--arnika--285e6ea8.webp b/server/public/plants/arnica-montana--arnika--285e6ea8.webp new file mode 100644 index 0000000..c26da05 Binary files /dev/null and b/server/public/plants/arnica-montana--arnika--285e6ea8.webp differ diff --git a/server/public/plants/artemisia-absinthium--wermut--26709c63.webp b/server/public/plants/artemisia-absinthium--wermut--26709c63.webp new file mode 100644 index 0000000..8bb2122 Binary files /dev/null and b/server/public/plants/artemisia-absinthium--wermut--26709c63.webp differ diff --git a/server/public/plants/artemisia-dracunculus--estragon--68c643ad.webp b/server/public/plants/artemisia-dracunculus--estragon--68c643ad.webp new file mode 100644 index 0000000..b73eb19 Binary files /dev/null and b/server/public/plants/artemisia-dracunculus--estragon--68c643ad.webp differ diff --git a/server/public/plants/asclepias-tuberosa--seidenpflanze--d082aa6e.webp b/server/public/plants/asclepias-tuberosa--seidenpflanze--d082aa6e.webp new file mode 100644 index 0000000..97466a9 Binary files /dev/null and b/server/public/plants/asclepias-tuberosa--seidenpflanze--d082aa6e.webp differ diff --git a/server/public/plants/aspidistra-elatior--schusterpflanze--27471002.webp b/server/public/plants/aspidistra-elatior--schusterpflanze--27471002.webp new file mode 100644 index 0000000..f0bedc8 Binary files /dev/null and b/server/public/plants/aspidistra-elatior--schusterpflanze--27471002.webp differ diff --git a/server/public/plants/asplenium-nidus--vogelnest-farn--c9fbbb3c.webp b/server/public/plants/asplenium-nidus--vogelnest-farn--c9fbbb3c.webp new file mode 100644 index 0000000..4238518 Binary files /dev/null and b/server/public/plants/asplenium-nidus--vogelnest-farn--c9fbbb3c.webp differ diff --git a/server/public/plants/aucuba-japonica--japanische-aucube--c4bcd588.webp b/server/public/plants/aucuba-japonica--japanische-aucube--c4bcd588.webp new file mode 100644 index 0000000..6709a23 Binary files /dev/null and b/server/public/plants/aucuba-japonica--japanische-aucube--c4bcd588.webp differ diff --git a/server/public/plants/azalea-indica--indische-azalee--fe6e49a3.webp b/server/public/plants/azalea-indica--indische-azalee--fe6e49a3.webp new file mode 100644 index 0000000..c983b11 Binary files /dev/null and b/server/public/plants/azalea-indica--indische-azalee--fe6e49a3.webp differ diff --git a/server/public/plants/bambusa-vulgaris--bambusrohr--620e47a2.webp b/server/public/plants/bambusa-vulgaris--bambusrohr--620e47a2.webp new file mode 100644 index 0000000..fe9a3dc Binary files /dev/null and b/server/public/plants/bambusa-vulgaris--bambusrohr--620e47a2.webp differ diff --git a/server/public/plants/beaucarnea-recurvata--pferdeschwanzpalme--31691c81.webp b/server/public/plants/beaucarnea-recurvata--pferdeschwanzpalme--31691c81.webp new file mode 100644 index 0000000..35206ef Binary files /dev/null and b/server/public/plants/beaucarnea-recurvata--pferdeschwanzpalme--31691c81.webp differ diff --git a/server/public/plants/begonia-maculata--forellen-begonie--5cce47c8.webp b/server/public/plants/begonia-maculata--forellen-begonie--5cce47c8.webp new file mode 100644 index 0000000..73435b4 Binary files /dev/null and b/server/public/plants/begonia-maculata--forellen-begonie--5cce47c8.webp differ diff --git a/server/public/plants/begonia-rex--koenigsbegonie--b6083f44.webp b/server/public/plants/begonia-rex--koenigsbegonie--b6083f44.webp new file mode 100644 index 0000000..3d3ef51 Binary files /dev/null and b/server/public/plants/begonia-rex--koenigsbegonie--b6083f44.webp differ diff --git a/server/public/plants/begonia-semperflorens-cultorum--eisbegonie--7d66e22f.webp b/server/public/plants/begonia-semperflorens-cultorum--eisbegonie--7d66e22f.webp new file mode 100644 index 0000000..9de47d3 Binary files /dev/null and b/server/public/plants/begonia-semperflorens-cultorum--eisbegonie--7d66e22f.webp differ diff --git a/server/public/plants/begonia-tuberhybrida--knollen-begonie--7d9dfd00.webp b/server/public/plants/begonia-tuberhybrida--knollen-begonie--7d9dfd00.webp new file mode 100644 index 0000000..4ab83fd Binary files /dev/null and b/server/public/plants/begonia-tuberhybrida--knollen-begonie--7d9dfd00.webp differ diff --git a/server/public/plants/bellis-perennis--gaensebluemchen--324d3eb0.webp b/server/public/plants/bellis-perennis--gaensebluemchen--324d3eb0.webp new file mode 100644 index 0000000..d9806cc Binary files /dev/null and b/server/public/plants/bellis-perennis--gaensebluemchen--324d3eb0.webp differ diff --git a/server/public/plants/beta-vulgaris--mangold--7fb88006.webp b/server/public/plants/beta-vulgaris--mangold--7fb88006.webp new file mode 100644 index 0000000..6aeb6fb Binary files /dev/null and b/server/public/plants/beta-vulgaris--mangold--7fb88006.webp differ diff --git a/server/public/plants/betula-pendula--hange-birke--aff0bb68.webp b/server/public/plants/betula-pendula--hange-birke--aff0bb68.webp new file mode 100644 index 0000000..5eb2303 Binary files /dev/null and b/server/public/plants/betula-pendula--hange-birke--aff0bb68.webp differ diff --git a/server/public/plants/billbergia-nutans--billbergia--a659ab7f.webp b/server/public/plants/billbergia-nutans--billbergia--a659ab7f.webp new file mode 100644 index 0000000..645b143 Binary files /dev/null and b/server/public/plants/billbergia-nutans--billbergia--a659ab7f.webp differ diff --git a/server/public/plants/borago-officinalis--borretsch--0d13299a.webp b/server/public/plants/borago-officinalis--borretsch--0d13299a.webp new file mode 100644 index 0000000..23c4b5c Binary files /dev/null and b/server/public/plants/borago-officinalis--borretsch--0d13299a.webp differ diff --git a/server/public/plants/bougainvillea-spectabilis--bougainvillea--0d84eedd.webp b/server/public/plants/bougainvillea-spectabilis--bougainvillea--0d84eedd.webp new file mode 100644 index 0000000..4f2d99c Binary files /dev/null and b/server/public/plants/bougainvillea-spectabilis--bougainvillea--0d84eedd.webp differ diff --git a/server/public/plants/buddleja-davidii--schmetterlingsflieder--c6785fa7.webp b/server/public/plants/buddleja-davidii--schmetterlingsflieder--c6785fa7.webp new file mode 100644 index 0000000..2279984 Binary files /dev/null and b/server/public/plants/buddleja-davidii--schmetterlingsflieder--c6785fa7.webp differ diff --git a/server/public/plants/buxus-sempervirens--buchsbaum--598f8440.webp b/server/public/plants/buxus-sempervirens--buchsbaum--598f8440.webp new file mode 100644 index 0000000..dae0a5d Binary files /dev/null and b/server/public/plants/buxus-sempervirens--buchsbaum--598f8440.webp differ diff --git a/server/public/plants/caladium-bicolor--buntblatt--d052df1e.webp b/server/public/plants/caladium-bicolor--buntblatt--d052df1e.webp new file mode 100644 index 0000000..6923c40 Binary files /dev/null and b/server/public/plants/caladium-bicolor--buntblatt--d052df1e.webp differ diff --git a/server/public/plants/calathea-orbifolia--korbmarante--fdc40419.webp b/server/public/plants/calathea-orbifolia--korbmarante--fdc40419.webp new file mode 100644 index 0000000..cfddb51 Binary files /dev/null and b/server/public/plants/calathea-orbifolia--korbmarante--fdc40419.webp differ diff --git a/server/public/plants/calendula-officinalis--ringelblume--03f33ce8.webp b/server/public/plants/calendula-officinalis--ringelblume--03f33ce8.webp new file mode 100644 index 0000000..c7ad810 Binary files /dev/null and b/server/public/plants/calendula-officinalis--ringelblume--03f33ce8.webp differ diff --git a/server/public/plants/calibrachoa-hybrida--calibrachoa--18b44d0e.webp b/server/public/plants/calibrachoa-hybrida--calibrachoa--18b44d0e.webp new file mode 100644 index 0000000..454425a Binary files /dev/null and b/server/public/plants/calibrachoa-hybrida--calibrachoa--18b44d0e.webp differ diff --git a/server/public/plants/callisia-repens--callisia--65401a5e.webp b/server/public/plants/callisia-repens--callisia--65401a5e.webp new file mode 100644 index 0000000..c59aab9 Binary files /dev/null and b/server/public/plants/callisia-repens--callisia--65401a5e.webp differ diff --git a/server/public/plants/camellia-japonica--kamelie--6a23eb3f.webp b/server/public/plants/camellia-japonica--kamelie--6a23eb3f.webp new file mode 100644 index 0000000..3b6a45d Binary files /dev/null and b/server/public/plants/camellia-japonica--kamelie--6a23eb3f.webp differ diff --git a/server/public/plants/camellia-sinensis--teestrauch--2c1d14da.webp b/server/public/plants/camellia-sinensis--teestrauch--2c1d14da.webp new file mode 100644 index 0000000..16e9580 Binary files /dev/null and b/server/public/plants/camellia-sinensis--teestrauch--2c1d14da.webp differ diff --git a/server/public/plants/campsis-radicans--trompetenwinde--7ed75a41.webp b/server/public/plants/campsis-radicans--trompetenwinde--7ed75a41.webp new file mode 100644 index 0000000..db9c06d Binary files /dev/null and b/server/public/plants/campsis-radicans--trompetenwinde--7ed75a41.webp differ diff --git a/server/public/plants/canna-indica--blumenschilfrohr--adfa9705.webp b/server/public/plants/canna-indica--blumenschilfrohr--adfa9705.webp new file mode 100644 index 0000000..0c7568b Binary files /dev/null and b/server/public/plants/canna-indica--blumenschilfrohr--adfa9705.webp differ diff --git a/server/public/plants/capsicum-annuum--chili--dabf0f0e.webp b/server/public/plants/capsicum-annuum--chili--dabf0f0e.webp new file mode 100644 index 0000000..c71ebd6 Binary files /dev/null and b/server/public/plants/capsicum-annuum--chili--dabf0f0e.webp differ diff --git a/server/public/plants/carica-papaya--papaya--240dc331.webp b/server/public/plants/carica-papaya--papaya--240dc331.webp new file mode 100644 index 0000000..ad38696 Binary files /dev/null and b/server/public/plants/carica-papaya--papaya--240dc331.webp differ diff --git a/server/public/plants/catalpa-bignonioides--trompetenbaum--b3b0e8b4.webp b/server/public/plants/catalpa-bignonioides--trompetenbaum--b3b0e8b4.webp new file mode 100644 index 0000000..cb04b1b Binary files /dev/null and b/server/public/plants/catalpa-bignonioides--trompetenbaum--b3b0e8b4.webp differ diff --git a/server/public/plants/cattleya-labiata--cattleya-orchidee--91962802.webp b/server/public/plants/cattleya-labiata--cattleya-orchidee--91962802.webp new file mode 100644 index 0000000..04c1022 Binary files /dev/null and b/server/public/plants/cattleya-labiata--cattleya-orchidee--91962802.webp differ diff --git a/server/public/plants/cedrus-libani--zeder--6af4a3dd.webp b/server/public/plants/cedrus-libani--zeder--6af4a3dd.webp new file mode 100644 index 0000000..e3faf85 Binary files /dev/null and b/server/public/plants/cedrus-libani--zeder--6af4a3dd.webp differ diff --git a/server/public/plants/centaurea-cyanus--kornblume--ff8efded.webp b/server/public/plants/centaurea-cyanus--kornblume--ff8efded.webp new file mode 100644 index 0000000..33f88f9 Binary files /dev/null and b/server/public/plants/centaurea-cyanus--kornblume--ff8efded.webp differ diff --git a/server/public/plants/cereus-peruvianus--peruanischer-fackelkaktus--b087b5cf.webp b/server/public/plants/cereus-peruvianus--peruanischer-fackelkaktus--b087b5cf.webp new file mode 100644 index 0000000..00e77d5 Binary files /dev/null and b/server/public/plants/cereus-peruvianus--peruanischer-fackelkaktus--b087b5cf.webp differ diff --git a/server/public/plants/ceropegia-woodii--herzkette--b51fb231.webp b/server/public/plants/ceropegia-woodii--herzkette--b51fb231.webp new file mode 100644 index 0000000..4e76a99 Binary files /dev/null and b/server/public/plants/ceropegia-woodii--herzkette--b51fb231.webp differ diff --git a/server/public/plants/chamaedorea-elegans--bergpalme--05a6cf35.webp b/server/public/plants/chamaedorea-elegans--bergpalme--05a6cf35.webp new file mode 100644 index 0000000..9ff53c2 Binary files /dev/null and b/server/public/plants/chamaedorea-elegans--bergpalme--05a6cf35.webp differ diff --git a/server/public/plants/chamaemelum-nobile--roemische-kamille--9235aca6.webp b/server/public/plants/chamaemelum-nobile--roemische-kamille--9235aca6.webp new file mode 100644 index 0000000..5807506 Binary files /dev/null and b/server/public/plants/chamaemelum-nobile--roemische-kamille--9235aca6.webp differ diff --git a/server/public/plants/chamomilla-recutita--kamille--0bffdb72.webp b/server/public/plants/chamomilla-recutita--kamille--0bffdb72.webp new file mode 100644 index 0000000..bf9ab58 Binary files /dev/null and b/server/public/plants/chamomilla-recutita--kamille--0bffdb72.webp differ diff --git a/server/public/plants/chlorophytum-comosum--gruenlilie--e48be10b.webp b/server/public/plants/chlorophytum-comosum--gruenlilie--e48be10b.webp new file mode 100644 index 0000000..26cd7ba Binary files /dev/null and b/server/public/plants/chlorophytum-comosum--gruenlilie--e48be10b.webp differ diff --git a/server/public/plants/chrysanthemum-indicum--chrysantheme--f3f1b7ad.webp b/server/public/plants/chrysanthemum-indicum--chrysantheme--f3f1b7ad.webp new file mode 100644 index 0000000..d6a3aeb Binary files /dev/null and b/server/public/plants/chrysanthemum-indicum--chrysantheme--f3f1b7ad.webp differ diff --git a/server/public/plants/citrus-limon--zitronenbaum--100d9901.webp b/server/public/plants/citrus-limon--zitronenbaum--100d9901.webp new file mode 100644 index 0000000..121924e Binary files /dev/null and b/server/public/plants/citrus-limon--zitronenbaum--100d9901.webp differ diff --git a/server/public/plants/citrus-sinensis--orangenbaum--294e1722.webp b/server/public/plants/citrus-sinensis--orangenbaum--294e1722.webp new file mode 100644 index 0000000..023fc42 Binary files /dev/null and b/server/public/plants/citrus-sinensis--orangenbaum--294e1722.webp differ diff --git a/server/public/plants/clematis-viticella--clematis--7c06c3b1.webp b/server/public/plants/clematis-viticella--clematis--7c06c3b1.webp new file mode 100644 index 0000000..7fbdd3c Binary files /dev/null and b/server/public/plants/clematis-viticella--clematis--7c06c3b1.webp differ diff --git a/server/public/plants/clivia-miniata--riemenblatt--29bc76f5.webp b/server/public/plants/clivia-miniata--riemenblatt--29bc76f5.webp new file mode 100644 index 0000000..8f709d8 Binary files /dev/null and b/server/public/plants/clivia-miniata--riemenblatt--29bc76f5.webp differ diff --git a/server/public/plants/codiaeum-variegatum--kroton--fceb7491.webp b/server/public/plants/codiaeum-variegatum--kroton--fceb7491.webp new file mode 100644 index 0000000..bc9d059 Binary files /dev/null and b/server/public/plants/codiaeum-variegatum--kroton--fceb7491.webp differ diff --git a/server/public/plants/coffea-arabica--kaffeestrauch--a5ffdda3.webp b/server/public/plants/coffea-arabica--kaffeestrauch--a5ffdda3.webp new file mode 100644 index 0000000..539f68f Binary files /dev/null and b/server/public/plants/coffea-arabica--kaffeestrauch--a5ffdda3.webp differ diff --git a/server/public/plants/coffea-arabica-nana--kaffeepflanze-arabica-nana--3dab6209.webp b/server/public/plants/coffea-arabica-nana--kaffeepflanze-arabica-nana--3dab6209.webp new file mode 100644 index 0000000..1ea4937 Binary files /dev/null and b/server/public/plants/coffea-arabica-nana--kaffeepflanze-arabica-nana--3dab6209.webp differ diff --git a/server/public/plants/colocasia-esculenta--taro--d23c3d35.webp b/server/public/plants/colocasia-esculenta--taro--d23c3d35.webp new file mode 100644 index 0000000..e53eebc Binary files /dev/null and b/server/public/plants/colocasia-esculenta--taro--d23c3d35.webp differ diff --git a/server/public/plants/columnea-gloriosa--columnea--3fd247d6.webp b/server/public/plants/columnea-gloriosa--columnea--3fd247d6.webp new file mode 100644 index 0000000..50acd35 Binary files /dev/null and b/server/public/plants/columnea-gloriosa--columnea--3fd247d6.webp differ diff --git a/server/public/plants/conophytum-calculus--konophytum--4c3a116e.webp b/server/public/plants/conophytum-calculus--konophytum--4c3a116e.webp new file mode 100644 index 0000000..6e38a0c Binary files /dev/null and b/server/public/plants/conophytum-calculus--konophytum--4c3a116e.webp differ diff --git a/server/public/plants/convallaria-majalis--maigloeckchen--d7acb648.webp b/server/public/plants/convallaria-majalis--maigloeckchen--d7acb648.webp new file mode 100644 index 0000000..5b4a8a2 Binary files /dev/null and b/server/public/plants/convallaria-majalis--maigloeckchen--d7acb648.webp differ diff --git a/server/public/plants/cordyline-australis--keulenlilie--31be351b.webp b/server/public/plants/cordyline-australis--keulenlilie--31be351b.webp new file mode 100644 index 0000000..cfd8345 Binary files /dev/null and b/server/public/plants/cordyline-australis--keulenlilie--31be351b.webp differ diff --git a/server/public/plants/cordyline-fruticosa--tiroler-keulenlilie--4a44ec99.webp b/server/public/plants/cordyline-fruticosa--tiroler-keulenlilie--4a44ec99.webp new file mode 100644 index 0000000..87e28fe Binary files /dev/null and b/server/public/plants/cordyline-fruticosa--tiroler-keulenlilie--4a44ec99.webp differ diff --git a/server/public/plants/coreopsis-tinctoria--maedchenauge--64a5d938.webp b/server/public/plants/coreopsis-tinctoria--maedchenauge--64a5d938.webp new file mode 100644 index 0000000..ced388e Binary files /dev/null and b/server/public/plants/coreopsis-tinctoria--maedchenauge--64a5d938.webp differ diff --git a/server/public/plants/coriandrum-sativum--koriander--c1d3ccee.webp b/server/public/plants/coriandrum-sativum--koriander--c1d3ccee.webp new file mode 100644 index 0000000..c92b293 Binary files /dev/null and b/server/public/plants/coriandrum-sativum--koriander--c1d3ccee.webp differ diff --git a/server/public/plants/cosmos-bipinnatus--kosmee--5a231205.webp b/server/public/plants/cosmos-bipinnatus--kosmee--5a231205.webp new file mode 100644 index 0000000..1fb1471 Binary files /dev/null and b/server/public/plants/cosmos-bipinnatus--kosmee--5a231205.webp differ diff --git a/server/public/plants/cotyledon-orbiculata--kotyledon--e61a1c1a.webp b/server/public/plants/cotyledon-orbiculata--kotyledon--e61a1c1a.webp new file mode 100644 index 0000000..87d309a Binary files /dev/null and b/server/public/plants/cotyledon-orbiculata--kotyledon--e61a1c1a.webp differ diff --git a/server/public/plants/crassula-muscosa--moos-crassula--41420e37.webp b/server/public/plants/crassula-muscosa--moos-crassula--41420e37.webp new file mode 100644 index 0000000..c1db837 Binary files /dev/null and b/server/public/plants/crassula-muscosa--moos-crassula--41420e37.webp differ diff --git a/server/public/plants/crassula-ovata--jadepflanze--3ac94122.webp b/server/public/plants/crassula-ovata--jadepflanze--3ac94122.webp new file mode 100644 index 0000000..3c72810 Binary files /dev/null and b/server/public/plants/crassula-ovata--jadepflanze--3ac94122.webp differ diff --git a/server/public/plants/crocus-vernus--krokus--31f51b70.webp b/server/public/plants/crocus-vernus--krokus--31f51b70.webp new file mode 100644 index 0000000..983e75c Binary files /dev/null and b/server/public/plants/crocus-vernus--krokus--31f51b70.webp differ diff --git a/server/public/plants/cryptanthus-bivittatus--cryptanthus--0300865d.webp b/server/public/plants/cryptanthus-bivittatus--cryptanthus--0300865d.webp new file mode 100644 index 0000000..637c1bc Binary files /dev/null and b/server/public/plants/cryptanthus-bivittatus--cryptanthus--0300865d.webp differ diff --git a/server/public/plants/ctenanthe-burle-marxii--ctenanthe--aaacfef1.webp b/server/public/plants/ctenanthe-burle-marxii--ctenanthe--aaacfef1.webp new file mode 100644 index 0000000..e7cba49 Binary files /dev/null and b/server/public/plants/ctenanthe-burle-marxii--ctenanthe--aaacfef1.webp differ diff --git a/server/public/plants/cucumis-sativus--gurke--3b96fd46.webp b/server/public/plants/cucumis-sativus--gurke--3b96fd46.webp new file mode 100644 index 0000000..70c786c Binary files /dev/null and b/server/public/plants/cucumis-sativus--gurke--3b96fd46.webp differ diff --git a/server/public/plants/cupressus-sempervirens--zypresse--fece2137.webp b/server/public/plants/cupressus-sempervirens--zypresse--fece2137.webp new file mode 100644 index 0000000..a2995d8 Binary files /dev/null and b/server/public/plants/cupressus-sempervirens--zypresse--fece2137.webp differ diff --git a/server/public/plants/curcuma-longa--kurkuma--cb270150.webp b/server/public/plants/curcuma-longa--kurkuma--cb270150.webp new file mode 100644 index 0000000..0102407 Binary files /dev/null and b/server/public/plants/curcuma-longa--kurkuma--cb270150.webp differ diff --git a/server/public/plants/curio-radicans--string-of-bananas--cee5c6f3.webp b/server/public/plants/curio-radicans--string-of-bananas--cee5c6f3.webp new file mode 100644 index 0000000..4ec508c Binary files /dev/null and b/server/public/plants/curio-radicans--string-of-bananas--cee5c6f3.webp differ diff --git a/server/public/plants/curio-x-peregrinus--string-of-dolphins--167250ea.webp b/server/public/plants/curio-x-peregrinus--string-of-dolphins--167250ea.webp new file mode 100644 index 0000000..e3caf42 Binary files /dev/null and b/server/public/plants/curio-x-peregrinus--string-of-dolphins--167250ea.webp differ diff --git a/server/public/plants/cycas-revoluta--palmfarn--71371c45.webp b/server/public/plants/cycas-revoluta--palmfarn--71371c45.webp new file mode 100644 index 0000000..09504d2 Binary files /dev/null and b/server/public/plants/cycas-revoluta--palmfarn--71371c45.webp differ diff --git a/server/public/plants/cyclamen-persicum--alpenveilchen--42e9e354.webp b/server/public/plants/cyclamen-persicum--alpenveilchen--42e9e354.webp new file mode 100644 index 0000000..6fdefcb Binary files /dev/null and b/server/public/plants/cyclamen-persicum--alpenveilchen--42e9e354.webp differ diff --git a/server/public/plants/cymbidium-lowianum--zymbidium--3ee7a3d5.webp b/server/public/plants/cymbidium-lowianum--zymbidium--3ee7a3d5.webp new file mode 100644 index 0000000..752598d Binary files /dev/null and b/server/public/plants/cymbidium-lowianum--zymbidium--3ee7a3d5.webp differ diff --git a/server/public/plants/cymbopogon-citratus--zitronengras--671a6414.webp b/server/public/plants/cymbopogon-citratus--zitronengras--671a6414.webp new file mode 100644 index 0000000..d268cd6 Binary files /dev/null and b/server/public/plants/cymbopogon-citratus--zitronengras--671a6414.webp differ diff --git a/server/public/plants/cyperus-alternifolius--paragraphenpflanze--986a54bf.webp b/server/public/plants/cyperus-alternifolius--paragraphenpflanze--986a54bf.webp new file mode 100644 index 0000000..eb74239 Binary files /dev/null and b/server/public/plants/cyperus-alternifolius--paragraphenpflanze--986a54bf.webp differ diff --git a/server/public/plants/dahlia-pinnata--dahlie--34a69e35.webp b/server/public/plants/dahlia-pinnata--dahlie--34a69e35.webp new file mode 100644 index 0000000..1c58e81 Binary files /dev/null and b/server/public/plants/dahlia-pinnata--dahlie--34a69e35.webp differ diff --git a/server/public/plants/daucus-carota--karotte--85d90d33.webp b/server/public/plants/daucus-carota--karotte--85d90d33.webp new file mode 100644 index 0000000..e6c34b2 Binary files /dev/null and b/server/public/plants/daucus-carota--karotte--85d90d33.webp differ diff --git a/server/public/plants/delonix-regia--flammenbaum--efa632a4.webp b/server/public/plants/delonix-regia--flammenbaum--efa632a4.webp new file mode 100644 index 0000000..29d7a1a Binary files /dev/null and b/server/public/plants/delonix-regia--flammenbaum--efa632a4.webp differ diff --git a/server/public/plants/delphinium-elatum--rittersporn--d7df6211.webp b/server/public/plants/delphinium-elatum--rittersporn--d7df6211.webp new file mode 100644 index 0000000..fb4d6df Binary files /dev/null and b/server/public/plants/delphinium-elatum--rittersporn--d7df6211.webp differ diff --git a/server/public/plants/dendrobium-nobile--dendrobium--a29be123.webp b/server/public/plants/dendrobium-nobile--dendrobium--a29be123.webp new file mode 100644 index 0000000..76730be Binary files /dev/null and b/server/public/plants/dendrobium-nobile--dendrobium--a29be123.webp differ diff --git a/server/public/plants/dianthus-barbatus--bartnelke--e1f96804.webp b/server/public/plants/dianthus-barbatus--bartnelke--e1f96804.webp new file mode 100644 index 0000000..9124e2a Binary files /dev/null and b/server/public/plants/dianthus-barbatus--bartnelke--e1f96804.webp differ diff --git a/server/public/plants/dianthus-caryophyllus--nelke--1ccf57de.webp b/server/public/plants/dianthus-caryophyllus--nelke--1ccf57de.webp new file mode 100644 index 0000000..6673ee2 Binary files /dev/null and b/server/public/plants/dianthus-caryophyllus--nelke--1ccf57de.webp differ diff --git a/server/public/plants/dieffenbachia-seguine--dieffenbachie--755822dd.webp b/server/public/plants/dieffenbachia-seguine--dieffenbachie--755822dd.webp new file mode 100644 index 0000000..328f7b0 Binary files /dev/null and b/server/public/plants/dieffenbachia-seguine--dieffenbachie--755822dd.webp differ diff --git a/server/public/plants/digitalis-purpurea--roter-fingerhut--be177092.webp b/server/public/plants/digitalis-purpurea--roter-fingerhut--be177092.webp new file mode 100644 index 0000000..28f2f59 Binary files /dev/null and b/server/public/plants/digitalis-purpurea--roter-fingerhut--be177092.webp differ diff --git a/server/public/plants/dionaea-muscipula--venusfliegenfalle--fbcebf61.webp b/server/public/plants/dionaea-muscipula--venusfliegenfalle--fbcebf61.webp new file mode 100644 index 0000000..b5d3683 Binary files /dev/null and b/server/public/plants/dionaea-muscipula--venusfliegenfalle--fbcebf61.webp differ diff --git a/server/public/plants/dischidia-ruscifolia--dischidia--962061db.webp b/server/public/plants/dischidia-ruscifolia--dischidia--962061db.webp new file mode 100644 index 0000000..438ec3f Binary files /dev/null and b/server/public/plants/dischidia-ruscifolia--dischidia--962061db.webp differ diff --git a/server/public/plants/dracaena-fragrans--maisstrauch--107c7d0f.webp b/server/public/plants/dracaena-fragrans--maisstrauch--107c7d0f.webp new file mode 100644 index 0000000..a67f88b Binary files /dev/null and b/server/public/plants/dracaena-fragrans--maisstrauch--107c7d0f.webp differ diff --git a/server/public/plants/dracaena-marginata--drachenbaum--ae46a13c.webp b/server/public/plants/dracaena-marginata--drachenbaum--ae46a13c.webp new file mode 100644 index 0000000..842ccae Binary files /dev/null and b/server/public/plants/dracaena-marginata--drachenbaum--ae46a13c.webp differ diff --git a/server/public/plants/drosera-capensis--sonnentau--7122f48c.webp b/server/public/plants/drosera-capensis--sonnentau--7122f48c.webp new file mode 100644 index 0000000..d6085fe Binary files /dev/null and b/server/public/plants/drosera-capensis--sonnentau--7122f48c.webp differ diff --git a/server/public/plants/dudleya-brittonii--dudleya--be6042d1.webp b/server/public/plants/dudleya-brittonii--dudleya--be6042d1.webp new file mode 100644 index 0000000..2d5fca0 Binary files /dev/null and b/server/public/plants/dudleya-brittonii--dudleya--be6042d1.webp differ diff --git a/server/public/plants/dypsis-lutescens--goldfruchtpalme--890812c2.webp b/server/public/plants/dypsis-lutescens--goldfruchtpalme--890812c2.webp new file mode 100644 index 0000000..9992ecc Binary files /dev/null and b/server/public/plants/dypsis-lutescens--goldfruchtpalme--890812c2.webp differ diff --git a/server/public/plants/echeveria-elegans--echeverie--71f5556f.webp b/server/public/plants/echeveria-elegans--echeverie--71f5556f.webp new file mode 100644 index 0000000..b46eafa Binary files /dev/null and b/server/public/plants/echeveria-elegans--echeverie--71f5556f.webp differ diff --git a/server/public/plants/echinacea-purpurea--sonnenhut--cd110eab.webp b/server/public/plants/echinacea-purpurea--sonnenhut--cd110eab.webp new file mode 100644 index 0000000..67daf27 Binary files /dev/null and b/server/public/plants/echinacea-purpurea--sonnenhut--cd110eab.webp differ diff --git a/server/public/plants/echinocactus-grusonii--goldene-tonne--d5268f53.webp b/server/public/plants/echinocactus-grusonii--goldene-tonne--d5268f53.webp new file mode 100644 index 0000000..d995fe9 Binary files /dev/null and b/server/public/plants/echinocactus-grusonii--goldene-tonne--d5268f53.webp differ diff --git a/server/public/plants/echinopsis-pachanoi--san-pedro-kaktus--7f1085bc.webp b/server/public/plants/echinopsis-pachanoi--san-pedro-kaktus--7f1085bc.webp new file mode 100644 index 0000000..50ee3cb Binary files /dev/null and b/server/public/plants/echinopsis-pachanoi--san-pedro-kaktus--7f1085bc.webp differ diff --git a/server/public/plants/epiphyllum-oxypetalum--koenigin-der-nacht--7ecd1979.webp b/server/public/plants/epiphyllum-oxypetalum--koenigin-der-nacht--7ecd1979.webp new file mode 100644 index 0000000..6ff5fd2 Binary files /dev/null and b/server/public/plants/epiphyllum-oxypetalum--koenigin-der-nacht--7ecd1979.webp differ diff --git a/server/public/plants/epipremnum-aureum--efeutute--29871648.webp b/server/public/plants/epipremnum-aureum--efeutute--29871648.webp new file mode 100644 index 0000000..22630d2 Binary files /dev/null and b/server/public/plants/epipremnum-aureum--efeutute--29871648.webp differ diff --git a/server/public/plants/epipremnum-aureum-marble-queen--marmor-efeutute--1d6745d9.webp b/server/public/plants/epipremnum-aureum-marble-queen--marmor-efeutute--1d6745d9.webp new file mode 100644 index 0000000..3736b8c Binary files /dev/null and b/server/public/plants/epipremnum-aureum-marble-queen--marmor-efeutute--1d6745d9.webp differ diff --git a/server/public/plants/epipremnum-pinnatum-neon--neon-efeutute--3e91b575.webp b/server/public/plants/epipremnum-pinnatum-neon--neon-efeutute--3e91b575.webp new file mode 100644 index 0000000..c883110 Binary files /dev/null and b/server/public/plants/epipremnum-pinnatum-neon--neon-efeutute--3e91b575.webp differ diff --git a/server/public/plants/eschscholzia-californica--kalifornischer-mohn--da7d0f79.webp b/server/public/plants/eschscholzia-californica--kalifornischer-mohn--da7d0f79.webp new file mode 100644 index 0000000..be96572 Binary files /dev/null and b/server/public/plants/eschscholzia-californica--kalifornischer-mohn--da7d0f79.webp differ diff --git a/server/public/plants/eucalyptus-globulus--eukalyptus--48f49df6.webp b/server/public/plants/eucalyptus-globulus--eukalyptus--48f49df6.webp new file mode 100644 index 0000000..49784a7 Binary files /dev/null and b/server/public/plants/eucalyptus-globulus--eukalyptus--48f49df6.webp differ diff --git a/server/public/plants/euphorbia-milii--christusdorn--f647812e.webp b/server/public/plants/euphorbia-milii--christusdorn--f647812e.webp new file mode 100644 index 0000000..fe064e6 Binary files /dev/null and b/server/public/plants/euphorbia-milii--christusdorn--f647812e.webp differ diff --git a/server/public/plants/euphorbia-pulcherrima--weihnachtsstern--ce82aeac.webp b/server/public/plants/euphorbia-pulcherrima--weihnachtsstern--ce82aeac.webp new file mode 100644 index 0000000..9a297d0 Binary files /dev/null and b/server/public/plants/euphorbia-pulcherrima--weihnachtsstern--ce82aeac.webp differ diff --git a/server/public/plants/euphorbia-tirucalli--bleistiftkaktus--2760cacf.webp b/server/public/plants/euphorbia-tirucalli--bleistiftkaktus--2760cacf.webp new file mode 100644 index 0000000..1a1e61c Binary files /dev/null and b/server/public/plants/euphorbia-tirucalli--bleistiftkaktus--2760cacf.webp differ diff --git a/server/public/plants/eutrema-japonicum--wasabi--0ea8f701.webp b/server/public/plants/eutrema-japonicum--wasabi--0ea8f701.webp new file mode 100644 index 0000000..c228f67 Binary files /dev/null and b/server/public/plants/eutrema-japonicum--wasabi--0ea8f701.webp differ diff --git a/server/public/plants/fatsia-japonica--fatsia--425270ac.webp b/server/public/plants/fatsia-japonica--fatsia--425270ac.webp new file mode 100644 index 0000000..e25f43b Binary files /dev/null and b/server/public/plants/fatsia-japonica--fatsia--425270ac.webp differ diff --git a/server/public/plants/ferocactus-cylindraceus--fass-kaktus--ef5c90b1.webp b/server/public/plants/ferocactus-cylindraceus--fass-kaktus--ef5c90b1.webp new file mode 100644 index 0000000..e92dffa Binary files /dev/null and b/server/public/plants/ferocactus-cylindraceus--fass-kaktus--ef5c90b1.webp differ diff --git a/server/public/plants/ficus-altissima--76a13dda.webp b/server/public/plants/ficus-altissima--76a13dda.webp new file mode 100644 index 0000000..2d69be2 Binary files /dev/null and b/server/public/plants/ficus-altissima--76a13dda.webp differ diff --git a/server/public/plants/ficus-benjamina--birkenfeige--399b661c.webp b/server/public/plants/ficus-benjamina--birkenfeige--399b661c.webp new file mode 100644 index 0000000..aba08f5 Binary files /dev/null and b/server/public/plants/ficus-benjamina--birkenfeige--399b661c.webp differ diff --git a/server/public/plants/ficus-elastica--gummibaum--925b35e7.webp b/server/public/plants/ficus-elastica--gummibaum--925b35e7.webp new file mode 100644 index 0000000..069f18a Binary files /dev/null and b/server/public/plants/ficus-elastica--gummibaum--925b35e7.webp differ diff --git a/server/public/plants/ficus-lyrata--geigenfeige--c025bb04.webp b/server/public/plants/ficus-lyrata--geigenfeige--c025bb04.webp new file mode 100644 index 0000000..ee25e1b Binary files /dev/null and b/server/public/plants/ficus-lyrata--geigenfeige--c025bb04.webp differ diff --git a/server/public/plants/ficus-microcarpa--ca033402.webp b/server/public/plants/ficus-microcarpa--ca033402.webp new file mode 100644 index 0000000..05c0fa8 Binary files /dev/null and b/server/public/plants/ficus-microcarpa--ca033402.webp differ diff --git a/server/public/plants/ficus-retusa--bonsai-feige--dff4fbd3.webp b/server/public/plants/ficus-retusa--bonsai-feige--dff4fbd3.webp new file mode 100644 index 0000000..52fa901 Binary files /dev/null and b/server/public/plants/ficus-retusa--bonsai-feige--dff4fbd3.webp differ diff --git a/server/public/plants/fittonia-albivenis--nervenpflanze--b674f5e6.webp b/server/public/plants/fittonia-albivenis--nervenpflanze--b674f5e6.webp new file mode 100644 index 0000000..c892b3c Binary files /dev/null and b/server/public/plants/fittonia-albivenis--nervenpflanze--b674f5e6.webp differ diff --git a/server/public/plants/forsythia-x-intermedia--forsythie--390c28f1.webp b/server/public/plants/forsythia-x-intermedia--forsythie--390c28f1.webp new file mode 100644 index 0000000..e827ff9 Binary files /dev/null and b/server/public/plants/forsythia-x-intermedia--forsythie--390c28f1.webp differ diff --git a/server/public/plants/fragaria-ananassa--erdbeere--4a97a911.webp b/server/public/plants/fragaria-ananassa--erdbeere--4a97a911.webp new file mode 100644 index 0000000..b4b898e Binary files /dev/null and b/server/public/plants/fragaria-ananassa--erdbeere--4a97a911.webp differ diff --git a/server/public/plants/freesia-refracta--freesie--9dafaec2.webp b/server/public/plants/freesia-refracta--freesie--9dafaec2.webp new file mode 100644 index 0000000..33d16e7 Binary files /dev/null and b/server/public/plants/freesia-refracta--freesie--9dafaec2.webp differ diff --git a/server/public/plants/fuchsia-hybrida--fuchsie--93ef43c2.webp b/server/public/plants/fuchsia-hybrida--fuchsie--93ef43c2.webp new file mode 100644 index 0000000..9c567f2 Binary files /dev/null and b/server/public/plants/fuchsia-hybrida--fuchsie--93ef43c2.webp differ diff --git a/server/public/plants/fuchsia-triphylla--triphylla-fuchsie--822e8e3b.webp b/server/public/plants/fuchsia-triphylla--triphylla-fuchsie--822e8e3b.webp new file mode 100644 index 0000000..09d4715 Binary files /dev/null and b/server/public/plants/fuchsia-triphylla--triphylla-fuchsie--822e8e3b.webp differ diff --git a/server/public/plants/gaillardia-aristata--kokardenblume--050cf2e5.webp b/server/public/plants/gaillardia-aristata--kokardenblume--050cf2e5.webp new file mode 100644 index 0000000..376bd8b Binary files /dev/null and b/server/public/plants/gaillardia-aristata--kokardenblume--050cf2e5.webp differ diff --git a/server/public/plants/gardenia-jasminoides--gardenie--f8284265.webp b/server/public/plants/gardenia-jasminoides--gardenie--f8284265.webp new file mode 100644 index 0000000..2988404 Binary files /dev/null and b/server/public/plants/gardenia-jasminoides--gardenie--f8284265.webp differ diff --git a/server/public/plants/gasteria-carinata--gasteria--b27de8c8.webp b/server/public/plants/gasteria-carinata--gasteria--b27de8c8.webp new file mode 100644 index 0000000..544aa47 Binary files /dev/null and b/server/public/plants/gasteria-carinata--gasteria--b27de8c8.webp differ diff --git a/server/public/plants/gazania-rigens--mittagsgold--cc595e45.webp b/server/public/plants/gazania-rigens--mittagsgold--cc595e45.webp new file mode 100644 index 0000000..7678f65 Binary files /dev/null and b/server/public/plants/gazania-rigens--mittagsgold--cc595e45.webp differ diff --git a/server/public/plants/geranium-sanguineum--blutroter-storchschnabel--9d8300fb.webp b/server/public/plants/geranium-sanguineum--blutroter-storchschnabel--9d8300fb.webp new file mode 100644 index 0000000..23aba8f Binary files /dev/null and b/server/public/plants/geranium-sanguineum--blutroter-storchschnabel--9d8300fb.webp differ diff --git a/server/public/plants/gerbera-jamesonii--gerbera--f17eec14.webp b/server/public/plants/gerbera-jamesonii--gerbera--f17eec14.webp new file mode 100644 index 0000000..f6e9970 Binary files /dev/null and b/server/public/plants/gerbera-jamesonii--gerbera--f17eec14.webp differ diff --git a/server/public/plants/ginkgo-biloba--ginkgo--8d8c3f3f.webp b/server/public/plants/ginkgo-biloba--ginkgo--8d8c3f3f.webp new file mode 100644 index 0000000..2149ae1 Binary files /dev/null and b/server/public/plants/ginkgo-biloba--ginkgo--8d8c3f3f.webp differ diff --git a/server/public/plants/gladiolus-hortulanus--gladiole--e2a2d34f.webp b/server/public/plants/gladiolus-hortulanus--gladiole--e2a2d34f.webp new file mode 100644 index 0000000..5b6f8a1 Binary files /dev/null and b/server/public/plants/gladiolus-hortulanus--gladiole--e2a2d34f.webp differ diff --git a/server/public/plants/gloxinia-speciosa--gloxinie--8a73752c.webp b/server/public/plants/gloxinia-speciosa--gloxinie--8a73752c.webp new file mode 100644 index 0000000..64d447a Binary files /dev/null and b/server/public/plants/gloxinia-speciosa--gloxinie--8a73752c.webp differ diff --git a/server/public/plants/goeppertia-insignis--calathea-lancifolia--f77abcca.webp b/server/public/plants/goeppertia-insignis--calathea-lancifolia--f77abcca.webp new file mode 100644 index 0000000..9a05ba6 Binary files /dev/null and b/server/public/plants/goeppertia-insignis--calathea-lancifolia--f77abcca.webp differ diff --git a/server/public/plants/goeppertia-ornata--calathea-ornata--e7f67cad.webp b/server/public/plants/goeppertia-ornata--calathea-ornata--e7f67cad.webp new file mode 100644 index 0000000..1e67a5c Binary files /dev/null and b/server/public/plants/goeppertia-ornata--calathea-ornata--e7f67cad.webp differ diff --git a/server/public/plants/graptopetalum-paraguayense--geisterpflanze--9584de97.webp b/server/public/plants/graptopetalum-paraguayense--geisterpflanze--9584de97.webp new file mode 100644 index 0000000..6b37d80 Binary files /dev/null and b/server/public/plants/graptopetalum-paraguayense--geisterpflanze--9584de97.webp differ diff --git a/server/public/plants/guzmania-lingulata--guzmania--63fafdcb.webp b/server/public/plants/guzmania-lingulata--guzmania--63fafdcb.webp new file mode 100644 index 0000000..1ab54c4 Binary files /dev/null and b/server/public/plants/guzmania-lingulata--guzmania--63fafdcb.webp differ diff --git a/server/public/plants/gymnocalycium-mihanovichii--mond-kaktus--c7e6e78b.webp b/server/public/plants/gymnocalycium-mihanovichii--mond-kaktus--c7e6e78b.webp new file mode 100644 index 0000000..36169f2 Binary files /dev/null and b/server/public/plants/gymnocalycium-mihanovichii--mond-kaktus--c7e6e78b.webp differ diff --git a/server/public/plants/hamamelis-mollis--zaubernuss--7ef3c16c.webp b/server/public/plants/hamamelis-mollis--zaubernuss--7ef3c16c.webp new file mode 100644 index 0000000..2eea511 Binary files /dev/null and b/server/public/plants/hamamelis-mollis--zaubernuss--7ef3c16c.webp differ diff --git a/server/public/plants/haworthia-fasciata--zebra-haworthie--e4e7e4db.webp b/server/public/plants/haworthia-fasciata--zebra-haworthie--e4e7e4db.webp new file mode 100644 index 0000000..09b911a Binary files /dev/null and b/server/public/plants/haworthia-fasciata--zebra-haworthie--e4e7e4db.webp differ diff --git a/server/public/plants/hedera-helix--efeu--cebdfbf1.webp b/server/public/plants/hedera-helix--efeu--cebdfbf1.webp new file mode 100644 index 0000000..7526984 Binary files /dev/null and b/server/public/plants/hedera-helix--efeu--cebdfbf1.webp differ diff --git a/server/public/plants/heliamphora-nutans--heliamphora--16977b41.webp b/server/public/plants/heliamphora-nutans--heliamphora--16977b41.webp new file mode 100644 index 0000000..b936109 Binary files /dev/null and b/server/public/plants/heliamphora-nutans--heliamphora--16977b41.webp differ diff --git a/server/public/plants/helianthus-annuus--sonnenblume--d26f9031.webp b/server/public/plants/helianthus-annuus--sonnenblume--d26f9031.webp new file mode 100644 index 0000000..105fa44 Binary files /dev/null and b/server/public/plants/helianthus-annuus--sonnenblume--d26f9031.webp differ diff --git a/server/public/plants/helichrysum-italicum--currykraut--9f84755c.webp b/server/public/plants/helichrysum-italicum--currykraut--9f84755c.webp new file mode 100644 index 0000000..f0b84df Binary files /dev/null and b/server/public/plants/helichrysum-italicum--currykraut--9f84755c.webp differ diff --git a/server/public/plants/heliconia-psittacorum--heliconia--15bad812.webp b/server/public/plants/heliconia-psittacorum--heliconia--15bad812.webp new file mode 100644 index 0000000..7d28deb Binary files /dev/null and b/server/public/plants/heliconia-psittacorum--heliconia--15bad812.webp differ diff --git a/server/public/plants/heliotropium-arborescens--heliotrop--73a11073.webp b/server/public/plants/heliotropium-arborescens--heliotrop--73a11073.webp new file mode 100644 index 0000000..860e254 Binary files /dev/null and b/server/public/plants/heliotropium-arborescens--heliotrop--73a11073.webp differ diff --git a/server/public/plants/helleborus-orientalis--lenzrose--f7df56b8.webp b/server/public/plants/helleborus-orientalis--lenzrose--f7df56b8.webp new file mode 100644 index 0000000..c2ea4f4 Binary files /dev/null and b/server/public/plants/helleborus-orientalis--lenzrose--f7df56b8.webp differ diff --git a/server/public/plants/hemerocallis-fulva--taglilie--de9c4c6c.webp b/server/public/plants/hemerocallis-fulva--taglilie--de9c4c6c.webp new file mode 100644 index 0000000..de3f096 Binary files /dev/null and b/server/public/plants/hemerocallis-fulva--taglilie--de9c4c6c.webp differ diff --git a/server/public/plants/hibiscus-rosa-sinensis--hibiskus--9e6d8b54.webp b/server/public/plants/hibiscus-rosa-sinensis--hibiskus--9e6d8b54.webp new file mode 100644 index 0000000..e435be4 Binary files /dev/null and b/server/public/plants/hibiscus-rosa-sinensis--hibiskus--9e6d8b54.webp differ diff --git a/server/public/plants/hibiscus-syriacus--gartenhibiskus--4701a393.webp b/server/public/plants/hibiscus-syriacus--gartenhibiskus--4701a393.webp new file mode 100644 index 0000000..60c5b14 Binary files /dev/null and b/server/public/plants/hibiscus-syriacus--gartenhibiskus--4701a393.webp differ diff --git a/server/public/plants/hippeastrum-hybrid--ritterstern--82bc6dc8.webp b/server/public/plants/hippeastrum-hybrid--ritterstern--82bc6dc8.webp new file mode 100644 index 0000000..aab1370 Binary files /dev/null and b/server/public/plants/hippeastrum-hybrid--ritterstern--82bc6dc8.webp differ diff --git a/server/public/plants/howea-forsteriana--kentia-palme--f2c205ea.webp b/server/public/plants/howea-forsteriana--kentia-palme--f2c205ea.webp new file mode 100644 index 0000000..7952e3b Binary files /dev/null and b/server/public/plants/howea-forsteriana--kentia-palme--f2c205ea.webp differ diff --git a/server/public/plants/hoya-bella--kleine-wachsblume--db73dcff.webp b/server/public/plants/hoya-bella--kleine-wachsblume--db73dcff.webp new file mode 100644 index 0000000..cc163ac Binary files /dev/null and b/server/public/plants/hoya-bella--kleine-wachsblume--db73dcff.webp differ diff --git a/server/public/plants/hoya-carnosa--wachsblume--4da8fed5.webp b/server/public/plants/hoya-carnosa--wachsblume--4da8fed5.webp new file mode 100644 index 0000000..b685b6c Binary files /dev/null and b/server/public/plants/hoya-carnosa--wachsblume--4da8fed5.webp differ diff --git a/server/public/plants/hyacinthoides-non-scripta--hasengloeckchen--cda24b58.webp b/server/public/plants/hyacinthoides-non-scripta--hasengloeckchen--cda24b58.webp new file mode 100644 index 0000000..386b705 Binary files /dev/null and b/server/public/plants/hyacinthoides-non-scripta--hasengloeckchen--cda24b58.webp differ diff --git a/server/public/plants/hyacinthus-orientalis--hyazinthe--2c07af5d.webp b/server/public/plants/hyacinthus-orientalis--hyazinthe--2c07af5d.webp new file mode 100644 index 0000000..d5c450e Binary files /dev/null and b/server/public/plants/hyacinthus-orientalis--hyazinthe--2c07af5d.webp differ diff --git a/server/public/plants/hydrangea-macrophylla--hortensie--78d76f22.webp b/server/public/plants/hydrangea-macrophylla--hortensie--78d76f22.webp new file mode 100644 index 0000000..863d47e Binary files /dev/null and b/server/public/plants/hydrangea-macrophylla--hortensie--78d76f22.webp differ diff --git a/server/public/plants/hypericum-perforatum--johanniskraut--9bdb2ebc.webp b/server/public/plants/hypericum-perforatum--johanniskraut--9bdb2ebc.webp new file mode 100644 index 0000000..94d17d2 Binary files /dev/null and b/server/public/plants/hypericum-perforatum--johanniskraut--9bdb2ebc.webp differ diff --git a/server/public/plants/hypoestes-phyllostachya--punktblatt--08034897.webp b/server/public/plants/hypoestes-phyllostachya--punktblatt--08034897.webp new file mode 100644 index 0000000..c6dbc6e Binary files /dev/null and b/server/public/plants/hypoestes-phyllostachya--punktblatt--08034897.webp differ diff --git a/server/public/plants/hyssopus-officinalis--ysop--d3df148e.webp b/server/public/plants/hyssopus-officinalis--ysop--d3df148e.webp new file mode 100644 index 0000000..db99a45 Binary files /dev/null and b/server/public/plants/hyssopus-officinalis--ysop--d3df148e.webp differ diff --git a/server/public/plants/ilex-aquifolium--stechpalme--19cff9ae.webp b/server/public/plants/ilex-aquifolium--stechpalme--19cff9ae.webp new file mode 100644 index 0000000..65877c2 Binary files /dev/null and b/server/public/plants/ilex-aquifolium--stechpalme--19cff9ae.webp differ diff --git a/server/public/plants/impatiens-balsamina--gartenbalsamine--4e1447e8.webp b/server/public/plants/impatiens-balsamina--gartenbalsamine--4e1447e8.webp new file mode 100644 index 0000000..f3251c6 Binary files /dev/null and b/server/public/plants/impatiens-balsamina--gartenbalsamine--4e1447e8.webp differ diff --git a/server/public/plants/impatiens-hawkeri--neuguinea-balsamine--4e5c7c8f.webp b/server/public/plants/impatiens-hawkeri--neuguinea-balsamine--4e5c7c8f.webp new file mode 100644 index 0000000..6cd7d1e Binary files /dev/null and b/server/public/plants/impatiens-hawkeri--neuguinea-balsamine--4e5c7c8f.webp differ diff --git a/server/public/plants/impatiens-walleriana--fleissiges-lieschen--5816f930.webp b/server/public/plants/impatiens-walleriana--fleissiges-lieschen--5816f930.webp new file mode 100644 index 0000000..84dc7ce Binary files /dev/null and b/server/public/plants/impatiens-walleriana--fleissiges-lieschen--5816f930.webp differ diff --git a/server/public/plants/ipomoea-batatas--suesskartoffel--09695c9f.webp b/server/public/plants/ipomoea-batatas--suesskartoffel--09695c9f.webp new file mode 100644 index 0000000..3ab7e7f Binary files /dev/null and b/server/public/plants/ipomoea-batatas--suesskartoffel--09695c9f.webp differ diff --git a/server/public/plants/ipomoea-purpurea--prunkwinde--a9c61099.webp b/server/public/plants/ipomoea-purpurea--prunkwinde--a9c61099.webp new file mode 100644 index 0000000..d36aa27 Binary files /dev/null and b/server/public/plants/ipomoea-purpurea--prunkwinde--a9c61099.webp differ diff --git a/server/public/plants/iris-germanica--bart-iris--f0e4d8d1.webp b/server/public/plants/iris-germanica--bart-iris--f0e4d8d1.webp new file mode 100644 index 0000000..98f9aef Binary files /dev/null and b/server/public/plants/iris-germanica--bart-iris--f0e4d8d1.webp differ diff --git a/server/public/plants/jacaranda-mimosifolia--jacaranda--324b12c5.webp b/server/public/plants/jacaranda-mimosifolia--jacaranda--324b12c5.webp new file mode 100644 index 0000000..1401084 Binary files /dev/null and b/server/public/plants/jacaranda-mimosifolia--jacaranda--324b12c5.webp differ diff --git a/server/public/plants/jasminum-polyanthum--jasmin--14162cf1.webp b/server/public/plants/jasminum-polyanthum--jasmin--14162cf1.webp new file mode 100644 index 0000000..02d008a Binary files /dev/null and b/server/public/plants/jasminum-polyanthum--jasmin--14162cf1.webp differ diff --git a/server/public/plants/jasminum-sambac--arabischer-jasmin--5be39aae.webp b/server/public/plants/jasminum-sambac--arabischer-jasmin--5be39aae.webp new file mode 100644 index 0000000..6146a09 Binary files /dev/null and b/server/public/plants/jasminum-sambac--arabischer-jasmin--5be39aae.webp differ diff --git a/server/public/plants/kalanchoe-blossfeldiana--kalanchoe--e040640f.webp b/server/public/plants/kalanchoe-blossfeldiana--kalanchoe--e040640f.webp new file mode 100644 index 0000000..c4666d6 Binary files /dev/null and b/server/public/plants/kalanchoe-blossfeldiana--kalanchoe--e040640f.webp differ diff --git a/server/public/plants/kalanchoe-daigremontiana--brutblatt--5b643bf7.webp b/server/public/plants/kalanchoe-daigremontiana--brutblatt--5b643bf7.webp new file mode 100644 index 0000000..c386abe Binary files /dev/null and b/server/public/plants/kalanchoe-daigremontiana--brutblatt--5b643bf7.webp differ diff --git a/server/public/plants/kalanchoe-tomentosa--kaninchen-ohren--2c3b1e90.webp b/server/public/plants/kalanchoe-tomentosa--kaninchen-ohren--2c3b1e90.webp new file mode 100644 index 0000000..5cf0ee2 Binary files /dev/null and b/server/public/plants/kalanchoe-tomentosa--kaninchen-ohren--2c3b1e90.webp differ diff --git a/server/public/plants/lactuca-sativa--salat--7cd31564.webp b/server/public/plants/lactuca-sativa--salat--7cd31564.webp new file mode 100644 index 0000000..53a9696 Binary files /dev/null and b/server/public/plants/lactuca-sativa--salat--7cd31564.webp differ diff --git a/server/public/plants/lamprocapnos-spectabilis--traenendes-herz--ab9054da.webp b/server/public/plants/lamprocapnos-spectabilis--traenendes-herz--ab9054da.webp new file mode 100644 index 0000000..affa96c Binary files /dev/null and b/server/public/plants/lamprocapnos-spectabilis--traenendes-herz--ab9054da.webp differ diff --git a/server/public/plants/lantana-camara--wandelroeschen--b8fc5640.webp b/server/public/plants/lantana-camara--wandelroeschen--b8fc5640.webp new file mode 100644 index 0000000..77402e4 Binary files /dev/null and b/server/public/plants/lantana-camara--wandelroeschen--b8fc5640.webp differ diff --git a/server/public/plants/lathyrus-odoratus--duftwicke--029de58d.webp b/server/public/plants/lathyrus-odoratus--duftwicke--029de58d.webp new file mode 100644 index 0000000..e7d3282 Binary files /dev/null and b/server/public/plants/lathyrus-odoratus--duftwicke--029de58d.webp differ diff --git a/server/public/plants/laurus-nobilis--lorbeer--7fb425a5.webp b/server/public/plants/laurus-nobilis--lorbeer--7fb425a5.webp new file mode 100644 index 0000000..2d1e23b Binary files /dev/null and b/server/public/plants/laurus-nobilis--lorbeer--7fb425a5.webp differ diff --git a/server/public/plants/lavandula-angustifolia--echter-lavendel--cfd090c5.webp b/server/public/plants/lavandula-angustifolia--echter-lavendel--cfd090c5.webp new file mode 100644 index 0000000..b3800b8 Binary files /dev/null and b/server/public/plants/lavandula-angustifolia--echter-lavendel--cfd090c5.webp differ diff --git a/server/public/plants/lavatera-trimestris--bechermalve--96fa8526.webp b/server/public/plants/lavatera-trimestris--bechermalve--96fa8526.webp new file mode 100644 index 0000000..c7df363 Binary files /dev/null and b/server/public/plants/lavatera-trimestris--bechermalve--96fa8526.webp differ diff --git a/server/public/plants/leucanthemum-vulgare--margerite--f583d6a2.webp b/server/public/plants/leucanthemum-vulgare--margerite--f583d6a2.webp new file mode 100644 index 0000000..12b6dfb Binary files /dev/null and b/server/public/plants/leucanthemum-vulgare--margerite--f583d6a2.webp differ diff --git a/server/public/plants/leucanthemum-x-superbum--shasta-margerite--519d56a9.webp b/server/public/plants/leucanthemum-x-superbum--shasta-margerite--519d56a9.webp new file mode 100644 index 0000000..a019e99 Binary files /dev/null and b/server/public/plants/leucanthemum-x-superbum--shasta-margerite--519d56a9.webp differ diff --git a/server/public/plants/levisticum-officinale--liebstoeckel--649f0af1.webp b/server/public/plants/levisticum-officinale--liebstoeckel--649f0af1.webp new file mode 100644 index 0000000..ec16be2 Binary files /dev/null and b/server/public/plants/levisticum-officinale--liebstoeckel--649f0af1.webp differ diff --git a/server/public/plants/lilium-longiflorum--ostertrompete--4b791484.webp b/server/public/plants/lilium-longiflorum--ostertrompete--4b791484.webp new file mode 100644 index 0000000..b2540a9 Binary files /dev/null and b/server/public/plants/lilium-longiflorum--ostertrompete--4b791484.webp differ diff --git a/server/public/plants/lithops-julii--lebende-steine--939c0d2c.webp b/server/public/plants/lithops-julii--lebende-steine--939c0d2c.webp new file mode 100644 index 0000000..aa961ad Binary files /dev/null and b/server/public/plants/lithops-julii--lebende-steine--939c0d2c.webp differ diff --git a/server/public/plants/livistona-chinensis--chinesische-facherpalme--773e43a2.webp b/server/public/plants/livistona-chinensis--chinesische-facherpalme--773e43a2.webp new file mode 100644 index 0000000..c849a9d Binary files /dev/null and b/server/public/plants/livistona-chinensis--chinesische-facherpalme--773e43a2.webp differ diff --git a/server/public/plants/lobularia-maritima--duftsteinrich--309e832f.webp b/server/public/plants/lobularia-maritima--duftsteinrich--309e832f.webp new file mode 100644 index 0000000..9cb2031 Binary files /dev/null and b/server/public/plants/lobularia-maritima--duftsteinrich--309e832f.webp differ diff --git a/server/public/plants/lonicera-japonica--geissblatt--4b2c6fdb.webp b/server/public/plants/lonicera-japonica--geissblatt--4b2c6fdb.webp new file mode 100644 index 0000000..e25ba5f Binary files /dev/null and b/server/public/plants/lonicera-japonica--geissblatt--4b2c6fdb.webp differ diff --git a/server/public/plants/lupinus-polyphyllus--lupine--d528d819.webp b/server/public/plants/lupinus-polyphyllus--lupine--d528d819.webp new file mode 100644 index 0000000..32b9db0 Binary files /dev/null and b/server/public/plants/lupinus-polyphyllus--lupine--d528d819.webp differ diff --git a/server/public/plants/magnolia-grandiflora--magnolie--5eaff200.webp b/server/public/plants/magnolia-grandiflora--magnolie--5eaff200.webp new file mode 100644 index 0000000..3ac90b6 Binary files /dev/null and b/server/public/plants/magnolia-grandiflora--magnolie--5eaff200.webp differ diff --git a/server/public/plants/mammillaria-zeilmanniana--mammillaria--ee6d834e.webp b/server/public/plants/mammillaria-zeilmanniana--mammillaria--ee6d834e.webp new file mode 100644 index 0000000..a9ad971 Binary files /dev/null and b/server/public/plants/mammillaria-zeilmanniana--mammillaria--ee6d834e.webp differ diff --git a/server/public/plants/manifest.json b/server/public/plants/manifest.json new file mode 100644 index 0000000..9992ad2 --- /dev/null +++ b/server/public/plants/manifest.json @@ -0,0 +1,2877 @@ +{ + "generatedAt": "2026-03-12T09:19:24.727Z", + "summary": { + "totalPlants": 358, + "downloadedCount": 0, + "existingCount": 358, + "skippedCount": 0, + "failureCount": 0 + }, + "failures": [], + "items": [ + { + "id": "plant_8bfe537a28c86289", + "botanicalName": "Stapelia grandiflora", + "name": "Aasblume", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/98/Stapelia_grandiflora_22102013_1_%2810606394434%29.jpg/500px-Stapelia_grandiflora_22102013_1_%2810606394434%29.jpg", + "localImageUri": "/plants/stapelia-grandiflora--aasblume--b87af483.webp", + "status": "existing" + }, + { + "id": "plant_3e0a9ac0f2e3487e", + "botanicalName": "Adromischus cristatus", + "name": "Adromischus", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Adromischus_cristatus_-_Gaiser_Conservatory_%28Manito_Park%29_-_IMG_7008.JPG/500px-Adromischus_cristatus_-_Gaiser_Conservatory_%28Manito_Park%29_-_IMG_7008.JPG", + "localImageUri": "/plants/adromischus-cristatus--adromischus--9b24b9fc.webp", + "status": "existing" + }, + { + "id": "plant_b149587ebd02e88b", + "botanicalName": "Saintpaulia ionantha", + "name": "Afrikanisches Veilchen", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/57/Streptocarpus_ionanthus_%28as_Saintpaulia_ionantha%29_-_Curtis%27_121_%28Ser._3_no._51%29_pl._7408_%281895%29.jpg/500px-Streptocarpus_ionanthus_%28as_Saintpaulia_ionantha%29_-_Curtis%27_121_%28Ser._3_no._51%29_pl._7408_%281895%29.jpg", + "localImageUri": "/plants/saintpaulia-ionantha--afrikanisches-veilchen--bc75f4a8.webp", + "status": "existing" + }, + { + "id": "plant_163ec12a26b24198", + "botanicalName": "Agave americana", + "name": "Agave", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Agave_July_2011-1.jpg/500px-Agave_July_2011-1.jpg", + "localImageUri": "/plants/agave-americana--agave--3b197a68.webp", + "status": "existing" + }, + { + "id": "plant_f35722f0d85fcbf0", + "botanicalName": "Aglaonema commutatum", + "name": "Aglaoneme", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Aglaonema_commutatum_kz1.jpg/500px-Aglaonema_commutatum_kz1.jpg", + "localImageUri": "/plants/aglaonema-commutatum--aglaoneme--7928abe4.webp", + "status": "existing" + }, + { + "id": "plant_480b93349eb97dce", + "botanicalName": "Alocasia zebrina", + "name": "Alocasia zebrina", + "sourceUri": "wikimedia-search:Alocasia%20zebrina", + "localImageUri": "/plants/alocasia-zebrina--525caa90.webp", + "status": "existing" + }, + { + "id": "plant_521cc31a3ab2a5b1", + "botanicalName": "Cyclamen persicum", + "name": "Alpenveilchen", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Yagur_%E2%80%93_Nesher%2C_the_Green_Path_%E2%80%93_Mount_Carmel_016.JPG/500px-Yagur_%E2%80%93_Nesher%2C_the_Green_Path_%E2%80%93_Mount_Carmel_016.JPG", + "localImageUri": "/plants/cyclamen-persicum--alpenveilchen--42e9e354.webp", + "status": "existing" + }, + { + "id": "plant_7a47f2728dced1a4", + "botanicalName": "Pilea cadierei", + "name": "Aluminium-Pflanze", + "sourceUri": "wikimedia-search:Pilea%20cadierei", + "localImageUri": "/plants/pilea-cadierei--aluminium-pflanze--3e1e1bd9.webp", + "status": "existing" + }, + { + "id": "plant_c623dbd931826123", + "botanicalName": "Alocasia amazonica", + "name": "Amazona-Taro", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Alocasia_x_amazonica_a1.jpg/500px-Alocasia_x_amazonica_a1.jpg", + "localImageUri": "/plants/alocasia-amazonica--amazona-taro--e1c87d71.webp", + "status": "existing" + }, + { + "id": "plant_28d349e6f67fe99a", + "botanicalName": "Anemone coronaria", + "name": "Anemone", + "sourceUri": "wikimedia-search:Anemone%20coronaria", + "localImageUri": "/plants/anemone-coronaria--anemone--8a7fda1c.webp", + "status": "existing" + }, + { + "id": "plant_7079ed3283a094f9", + "botanicalName": "Jasminum sambac", + "name": "Arabischer Jasmin", + "sourceUri": "wikimedia-search:Jasminum%20sambac", + "localImageUri": "/plants/jasminum-sambac--arabischer-jasmin--5be39aae.webp", + "status": "existing" + }, + { + "id": "plant_c2890f36d8fc9da0", + "botanicalName": "Arnica montana", + "name": "Arnika", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Arnica_montana_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-015.jpg/500px-Arnica_montana_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-015.jpg", + "localImageUri": "/plants/arnica-montana--arnika--285e6ea8.webp", + "status": "existing" + }, + { + "id": "plant_fdadaf062de2c567", + "botanicalName": "Solanum melongena", + "name": "Aubergine", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/76/Solanum_melongena_24_08_2012_%281%29.JPG/500px-Solanum_melongena_24_08_2012_%281%29.JPG", + "localImageUri": "/plants/solanum-melongena--aubergine--5f3bad2f.webp", + "status": "existing" + }, + { + "id": "plant_480619fefb890692", + "botanicalName": "Valeriana officinalis", + "name": "Baldrian", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/Valeriana_officinalis_inflorescence_-_Niitv%C3%A4lja.jpg/500px-Valeriana_officinalis_inflorescence_-_Niitv%C3%A4lja.jpg", + "localImageUri": "/plants/valeriana-officinalis--baldrian--7bc7a2ae.webp", + "status": "existing" + }, + { + "id": "plant_b73b967c062264fa", + "botanicalName": "Bambusa vulgaris", + "name": "Bambusrohr", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/10/Golden_Bamboo%28Bambusa_vulgaris%29_in_Hong_Kong.jpg/500px-Golden_Bamboo%28Bambusa_vulgaris%29_in_Hong_Kong.jpg", + "localImageUri": "/plants/bambusa-vulgaris--bambusrohr--620e47a2.webp", + "status": "existing" + }, + { + "id": "plant_1b52f8bc38189420", + "botanicalName": "Musa acuminata", + "name": "Bananenpflanze", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7d/Musa_acuminata_in_india01.jpg/500px-Musa_acuminata_in_india01.jpg", + "localImageUri": "/plants/musa-acuminata--bananenpflanze--0a6a2ad8.webp", + "status": "existing" + }, + { + "id": "plant_1f420e53ba82d27e", + "botanicalName": "Iris germanica", + "name": "Bart-Iris", + "sourceUri": "wikimedia-search:Iris%20germanica", + "localImageUri": "/plants/iris-germanica--bart-iris--f0e4d8d1.webp", + "status": "existing" + }, + { + "id": "plant_2c5e541195cb3797", + "botanicalName": "Dianthus barbatus", + "name": "Bartnelke", + "sourceUri": "wikimedia-search:Dianthus%20barbatus", + "localImageUri": "/plants/dianthus-barbatus--bartnelke--e1f96804.webp", + "status": "existing" + }, + { + "id": "plant_65672e0cb49ca62d", + "botanicalName": "Ocimum basilicum", + "name": "Basilikum", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/97/Ocimum_basilicum_8zz.jpg/500px-Ocimum_basilicum_8zz.jpg", + "localImageUri": "/plants/ocimum-basilicum--basilikum--cdc33445.webp", + "status": "existing" + }, + { + "id": "plant_c804e440aeb95635", + "botanicalName": "Lavatera trimestris", + "name": "Bechermalve", + "sourceUri": "wikimedia-search:Lavatera%20trimestris", + "localImageUri": "/plants/lavatera-trimestris--bechermalve--96fa8526.webp", + "status": "existing" + }, + { + "id": "plant_11f9d18d047193e4", + "botanicalName": "Chamaedorea elegans", + "name": "Bergpalme", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/64/Chamaedorea_elegans_Mart.JPG/500px-Chamaedorea_elegans_Mart.JPG", + "localImageUri": "/plants/chamaedorea-elegans--bergpalme--05a6cf35.webp", + "status": "existing" + }, + { + "id": "plant_519742b7ea9df158", + "botanicalName": "Billbergia nutans", + "name": "Billbergia", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/9/9e/Billbergia_nutans1SHSU.jpg", + "localImageUri": "/plants/billbergia-nutans--billbergia--a659ab7f.webp", + "status": "existing" + }, + { + "id": "plant_2347cc2289a2ef8b", + "botanicalName": "Ficus benjamina", + "name": "Birkenfeige", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Starr-080608-7576-Ficus_benjamina-habit_with_Laysan_albatross-Gym_Sand_Island-Midway_Atoll_%2824823189861%29.jpg/500px-Starr-080608-7576-Ficus_benjamina-habit_with_Laysan_albatross-Gym_Sand_Island-Midway_Atoll_%2824823189861%29.jpg", + "localImageUri": "/plants/ficus-benjamina--birkenfeige--399b661c.webp", + "status": "existing" + }, + { + "id": "plant_4be713bff78ae299", + "botanicalName": "Senecio serpens", + "name": "Blauer Kreuzkraut", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/57/Senecio_serpens_04.jpg/500px-Senecio_serpens_04.jpg", + "localImageUri": "/plants/senecio-serpens--blauer-kreuzkraut--4ec1f347.webp", + "status": "existing" + }, + { + "id": "plant_51da778adc3d568f", + "botanicalName": "Phlebodium aureum", + "name": "Blaues Kanaelfarn", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Starr_050107-2831_Phlebodium_aureum.jpg/500px-Starr_050107-2831_Phlebodium_aureum.jpg", + "localImageUri": "/plants/phlebodium-aureum--blaues-kanaelfarn--a630296a.webp", + "status": "existing" + }, + { + "id": "plant_f696d8640ac1e58b", + "botanicalName": "Euphorbia tirucalli", + "name": "Bleistiftkaktus", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Euphorbia_tirucalli_in_the_wild_by_tonrulkens.jpg/500px-Euphorbia_tirucalli_in_the_wild_by_tonrulkens.jpg", + "localImageUri": "/plants/euphorbia-tirucalli--bleistiftkaktus--2760cacf.webp", + "status": "existing" + }, + { + "id": "plant_fcfdae786a599215", + "botanicalName": "Plumbago auriculata", + "name": "Bleiwurz", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Plumbago_auriculata_2718.jpg/500px-Plumbago_auriculata_2718.jpg", + "localImageUri": "/plants/plumbago-auriculata--bleiwurz--a1ea78f5.webp", + "status": "existing" + }, + { + "id": "plant_2778ede47b41928b", + "botanicalName": "Canna indica", + "name": "Blumenschilfrohr", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Cinnamon-bellied_flowerpiercer_%28Diglossa_baritula%29_male_on_Indian_shot_%28Canna_indica%29_Finca_El_Pilar.jpg/500px-Cinnamon-bellied_flowerpiercer_%28Diglossa_baritula%29_male_on_Indian_shot_%28Canna_indica%29_Finca_El_Pilar.jpg", + "localImageUri": "/plants/canna-indica--blumenschilfrohr--adfa9705.webp", + "status": "existing" + }, + { + "id": "plant_7b30624e5b0b4c89", + "botanicalName": "Geranium sanguineum", + "name": "Blutroter Storchschnabel", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8c/2012-07-03_Bloody_Crane%27s-bill%2C_Hauxley%2C_Northumberland_1.jpg/500px-2012-07-03_Bloody_Crane%27s-bill%2C_Hauxley%2C_Northumberland_1.jpg", + "localImageUri": "/plants/geranium-sanguineum--blutroter-storchschnabel--9d8300fb.webp", + "status": "existing" + }, + { + "id": "plant_02e3ea2f54fa9fcb", + "botanicalName": "Satureja hortensis", + "name": "Bohnenkraut", + "sourceUri": "wikimedia-search:Satureja%20hortensis", + "localImageUri": "/plants/satureja-hortensis--bohnenkraut--b5b822ab.webp", + "status": "existing" + }, + { + "id": "plant_c71619cd9a02cef2", + "botanicalName": "Ficus retusa", + "name": "Bonsai-Feige", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Ficus_retusa_herbarium_sheet.jpg/500px-Ficus_retusa_herbarium_sheet.jpg", + "localImageUri": "/plants/ficus-retusa--bonsai-feige--dff4fbd3.webp", + "status": "existing" + }, + { + "id": "plant_fb10011bdfcaeb73", + "botanicalName": "Borago officinalis", + "name": "Borretsch", + "sourceUri": "wikimedia-search:Borago%20officinalis", + "localImageUri": "/plants/borago-officinalis--borretsch--0d13299a.webp", + "status": "existing" + }, + { + "id": "plant_a65e5c9dedb9cd6f", + "botanicalName": "Bougainvillea spectabilis", + "name": "Bougainvillea", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ae/Starr_030418-0061_Bougainvillea_spectabilis.jpg/500px-Starr_030418-0061_Bougainvillea_spectabilis.jpg", + "localImageUri": "/plants/bougainvillea-spectabilis--bougainvillea--0d84eedd.webp", + "status": "existing" + }, + { + "id": "plant_34a9a605f91a0e38", + "botanicalName": "Kalanchoe daigremontiana", + "name": "Brutblatt", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Vivipary_in_Kalanchoe_daigremontiana.jpg/500px-Vivipary_in_Kalanchoe_daigremontiana.jpg", + "localImageUri": "/plants/kalanchoe-daigremontiana--brutblatt--5b643bf7.webp", + "status": "existing" + }, + { + "id": "plant_7d5148b82570ac03", + "botanicalName": "Soleirolia soleirolii", + "name": "Bubikopf", + "sourceUri": "wikimedia-search:Soleirolia%20soleirolii", + "localImageUri": "/plants/soleirolia-soleirolii--bubikopf--b1b13e0f.webp", + "status": "existing" + }, + { + "id": "plant_a4cf51a5e4359d1d", + "botanicalName": "Buxus sempervirens", + "name": "Buchsbaum", + "sourceUri": "wikimedia-search:Buxus%20sempervirens", + "localImageUri": "/plants/buxus-sempervirens--buchsbaum--598f8440.webp", + "status": "existing" + }, + { + "id": "plant_ca3703f121432723", + "botanicalName": "Caladium bicolor", + "name": "Buntblatt", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Caladium_bicolor_2.jpg/500px-Caladium_bicolor_2.jpg", + "localImageUri": "/plants/caladium-bicolor--buntblatt--d052df1e.webp", + "status": "existing" + }, + { + "id": "plant_99ba7fe9e23a07d2", + "botanicalName": "Plectranthus scutellarioides", + "name": "Buntnessel", + "sourceUri": "wikimedia-search:Plectranthus%20scutellarioides", + "localImageUri": "/plants/plectranthus-scutellarioides--buntnessel--7e6c3a78.webp", + "status": "existing" + }, + { + "id": "plant_d13f1280e602ce42", + "botanicalName": "Goeppertia insignis", + "name": "Calathea lancifolia", + "sourceUri": "wikimedia-search:Goeppertia%20insignis", + "localImageUri": "/plants/goeppertia-insignis--calathea-lancifolia--f77abcca.webp", + "status": "existing" + }, + { + "id": "plant_d1a2562fb13fc53a", + "botanicalName": "Goeppertia ornata", + "name": "Calathea ornata", + "sourceUri": "wikimedia-search:Goeppertia%20ornata", + "localImageUri": "/plants/goeppertia-ornata--calathea-ornata--e7f67cad.webp", + "status": "existing" + }, + { + "id": "plant_de32e74f5d2e4f07", + "botanicalName": "Calibrachoa hybrida", + "name": "Calibrachoa", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/Calibrachoa_flower_red.jpg/500px-Calibrachoa_flower_red.jpg", + "localImageUri": "/plants/calibrachoa-hybrida--calibrachoa--18b44d0e.webp", + "status": "existing" + }, + { + "id": "plant_df8b72684a52d16d", + "botanicalName": "Zantedeschia aethiopica", + "name": "Calla", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Zantedeschia_aethiopica_-1.jpg/500px-Zantedeschia_aethiopica_-1.jpg", + "localImageUri": "/plants/zantedeschia-aethiopica--calla--c739da85.webp", + "status": "existing" + }, + { + "id": "plant_c1e5518101af0660", + "botanicalName": "Callisia repens", + "name": "Callisia", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7c/Callisia_repens_starr.jpg/500px-Callisia_repens_starr.jpg", + "localImageUri": "/plants/callisia-repens--callisia--65401a5e.webp", + "status": "existing" + }, + { + "id": "plant_e98319d5942ee47b", + "botanicalName": "Cattleya labiata", + "name": "Cattleya-Orchidee", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Labiata.jpg/500px-Labiata.jpg", + "localImageUri": "/plants/cattleya-labiata--cattleya-orchidee--91962802.webp", + "status": "existing" + }, + { + "id": "plant_f5fef1b22db032e8", + "botanicalName": "Capsicum annuum", + "name": "Chili", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/Capsicum_annuum_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-027.jpg/500px-Capsicum_annuum_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-027.jpg", + "localImageUri": "/plants/capsicum-annuum--chili--dabf0f0e.webp", + "status": "existing" + }, + { + "id": "plant_282d1b42588a5121", + "botanicalName": "Livistona chinensis", + "name": "Chinesische Fächerpalme", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f6/Livistona-chinensis.jpg/500px-Livistona-chinensis.jpg", + "localImageUri": "/plants/livistona-chinensis--chinesische-facherpalme--773e43a2.webp", + "status": "existing" + }, + { + "id": "plant_beef88438a4a5a77", + "botanicalName": "Rosa chinensis", + "name": "Chinesische Rose", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/Rosa_chinensis.jpg/500px-Rosa_chinensis.jpg", + "localImageUri": "/plants/rosa-chinensis--chinesische-rose--2c0514b0.webp", + "status": "existing" + }, + { + "id": "plant_3062bd4ee2363d81", + "botanicalName": "Wisteria sinensis", + "name": "Chinesischer Blauregen", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7a/Chinesischer_Blauregen_Detail_Bl%C3%BCtentraube.JPG/500px-Chinesischer_Blauregen_Detail_Bl%C3%BCtentraube.JPG", + "localImageUri": "/plants/wisteria-sinensis--chinesischer-blauregen--8887793e.webp", + "status": "existing" + }, + { + "id": "plant_552c1df47769e60a", + "botanicalName": "Euphorbia milii", + "name": "Christusdorn", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/77/Euphorbia_Milii_flowers.jpg/500px-Euphorbia_Milii_flowers.jpg", + "localImageUri": "/plants/euphorbia-milii--christusdorn--f647812e.webp", + "status": "existing" + }, + { + "id": "plant_d726e9204f2d2353", + "botanicalName": "Chrysanthemum indicum", + "name": "Chrysantheme", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Chrysanthemum_indicum1.jpg/500px-Chrysanthemum_indicum1.jpg", + "localImageUri": "/plants/chrysanthemum-indicum--chrysantheme--f3f1b7ad.webp", + "status": "existing" + }, + { + "id": "plant_ca9d5a83cf397269", + "botanicalName": "Clematis viticella", + "name": "Clematis", + "sourceUri": "wikimedia-search:Clematis%20viticella", + "localImageUri": "/plants/clematis-viticella--clematis--7c06c3b1.webp", + "status": "existing" + }, + { + "id": "plant_79e87c68ecaf5082", + "botanicalName": "Columnea gloriosa", + "name": "Columnea", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Columnea_gloriosa_%2849470911201%29.jpg/500px-Columnea_gloriosa_%2849470911201%29.jpg", + "localImageUri": "/plants/columnea-gloriosa--columnea--3fd247d6.webp", + "status": "existing" + }, + { + "id": "plant_5136b27d56c24f26", + "botanicalName": "Cryptanthus bivittatus", + "name": "Cryptanthus", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/CryptanthusBivittatus.jpg/500px-CryptanthusBivittatus.jpg", + "localImageUri": "/plants/cryptanthus-bivittatus--cryptanthus--0300865d.webp", + "status": "existing" + }, + { + "id": "plant_177a5dd7d3237533", + "botanicalName": "Ctenanthe burle-marxii", + "name": "Ctenanthe", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7d/Ctenanthe_burle-marxii.jpg/500px-Ctenanthe_burle-marxii.jpg", + "localImageUri": "/plants/ctenanthe-burle-marxii--ctenanthe--aaacfef1.webp", + "status": "existing" + }, + { + "id": "plant_4698cb973868e2ea", + "botanicalName": "Helichrysum italicum", + "name": "Currykraut", + "sourceUri": "wikimedia-search:Helichrysum%20italicum", + "localImageUri": "/plants/helichrysum-italicum--currykraut--9f84755c.webp", + "status": "existing" + }, + { + "id": "plant_d38f9fdbd2fc0128", + "botanicalName": "Dahlia pinnata", + "name": "Dahlie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/60/Borboletas_em_Mini-D%C3%A1lias.JPG/500px-Borboletas_em_Mini-D%C3%A1lias.JPG", + "localImageUri": "/plants/dahlia-pinnata--dahlie--34a69e35.webp", + "status": "existing" + }, + { + "id": "plant_0f54f9b5c4726b7c", + "botanicalName": "Dendrobium nobile", + "name": "Dendrobium", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Dendrobium_nobile_-_flower_view_01.jpg/500px-Dendrobium_nobile_-_flower_view_01.jpg", + "localImageUri": "/plants/dendrobium-nobile--dendrobium--a29be123.webp", + "status": "existing" + }, + { + "id": "plant_4a40e184dc1158af", + "botanicalName": "Dieffenbachia seguine", + "name": "Dieffenbachie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Dieffenbachia_seguine1FKST.jpg/500px-Dieffenbachia_seguine1FKST.jpg", + "localImageUri": "/plants/dieffenbachia-seguine--dieffenbachie--755822dd.webp", + "status": "existing" + }, + { + "id": "plant_e2d789d2529ac262", + "botanicalName": "Anethum graveolens", + "name": "Dill", + "sourceUri": "wikimedia-search:Anethum%20graveolens", + "localImageUri": "/plants/anethum-graveolens--dill--b93ab119.webp", + "status": "existing" + }, + { + "id": "plant_5a0f781f2fbe33a1", + "botanicalName": "Dischidia ruscifolia", + "name": "Dischidia", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/%E7%99%BE%E8%90%AC%E5%BF%83_Dischidia_ruscifolia_-%E9%A6%99%E6%B8%AF%E5%8B%95%E6%A4%8D%E7%89%A9%E5%85%AC%E5%9C%92_Hong_Kong_Botanical_Garden-_%289240152650%29.jpg/500px-%E7%99%BE%E8%90%AC%E5%BF%83_Dischidia_ruscifolia_-%E9%A6%99%E6%B8%AF%E5%8B%95%E6%A4%8D%E7%89%A9%E5%85%AC%E5%9C%92_Hong_Kong_Botanical_Garden-_%289240152650%29.jpg", + "localImageUri": "/plants/dischidia-ruscifolia--dischidia--962061db.webp", + "status": "existing" + }, + { + "id": "plant_d888afa045930bba", + "botanicalName": "Dracaena marginata", + "name": "Drachenbaum", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/61/Dracaena_reflexa.JPG/500px-Dracaena_reflexa.JPG", + "localImageUri": "/plants/dracaena-marginata--drachenbaum--ae46a13c.webp", + "status": "existing" + }, + { + "id": "plant_03f2e14e6adb42c5", + "botanicalName": "Streptocarpus hybridus", + "name": "Drehfrucht", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/2007-03-20Streptocarpus03.jpg/500px-2007-03-20Streptocarpus03.jpg", + "localImageUri": "/plants/streptocarpus-hybridus--drehfrucht--d30e3476.webp", + "status": "existing" + }, + { + "id": "plant_3c9b2546fb073192", + "botanicalName": "Dudleya brittonii", + "name": "Dudleya", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/10/Dudleya_Brittonii.jpg/500px-Dudleya_Brittonii.jpg", + "localImageUri": "/plants/dudleya-brittonii--dudleya--be6042d1.webp", + "status": "existing" + }, + { + "id": "plant_db00b284aaf5553b", + "botanicalName": "Lobularia maritima", + "name": "Duftsteinrich", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Smagliczka_nadmorska_1.jpg/500px-Smagliczka_nadmorska_1.jpg", + "localImageUri": "/plants/lobularia-maritima--duftsteinrich--309e832f.webp", + "status": "existing" + }, + { + "id": "plant_ded5f50a41d943e2", + "botanicalName": "Lathyrus odoratus", + "name": "Duftwicke", + "sourceUri": "wikimedia-search:Lathyrus%20odoratus", + "localImageUri": "/plants/lathyrus-odoratus--duftwicke--029de58d.webp", + "status": "existing" + }, + { + "id": "plant_1c5e1673e5c8084d", + "botanicalName": "Sorbus aucuparia", + "name": "Eberesche", + "sourceUri": "wikimedia-search:Sorbus%20aucuparia", + "localImageUri": "/plants/sorbus-aucuparia--eberesche--8ebfe649.webp", + "status": "existing" + }, + { + "id": "plant_19ba49fd14de0fd2", + "botanicalName": "Echeveria elegans", + "name": "Echeverie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5d/Echeveria_elegans_-_1.png/500px-Echeveria_elegans_-_1.png", + "localImageUri": "/plants/echeveria-elegans--echeverie--71f5556f.webp", + "status": "existing" + }, + { + "id": "plant_adc9e050aeb462c7", + "botanicalName": "Lavandula angustifolia", + "name": "Echter Lavendel", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/4/40/Lavandula_angustifolia_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-087.jpg", + "localImageUri": "/plants/lavandula-angustifolia--echter-lavendel--cfd090c5.webp", + "status": "existing" + }, + { + "id": "plant_2f9ab7e162ca10e4", + "botanicalName": "Hedera helix", + "name": "Efeu", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Hedera_helix_Dover.jpg/500px-Hedera_helix_Dover.jpg", + "localImageUri": "/plants/hedera-helix--efeu--cebdfbf1.webp", + "status": "existing" + }, + { + "id": "plant_81cfa08a34c49816", + "botanicalName": "Pelargonium peltatum", + "name": "Efeu-Geranie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/98/Pelargonium_peltatum_flower.jpg/500px-Pelargonium_peltatum_flower.jpg", + "localImageUri": "/plants/pelargonium-peltatum--efeu-geranie--8cd609cc.webp", + "status": "existing" + }, + { + "id": "plant_1401620498ee85ea", + "botanicalName": "Quercus robur", + "name": "Eiche", + "sourceUri": "wikimedia-search:Quercus%20robur", + "localImageUri": "/plants/quercus-robur--eiche--ea94af29.webp", + "status": "existing" + }, + { + "id": "plant_9c1fe0b19dc69115", + "botanicalName": "Begonia semperflorens-cultorum", + "name": "Eisbegonie", + "sourceUri": "wikimedia-search:Begonia%20semperflorens-cultorum", + "localImageUri": "/plants/begonia-semperflorens-cultorum--eisbegonie--7d66e22f.webp", + "status": "existing" + }, + { + "id": "plant_80dcaefb7e942ba2", + "botanicalName": "Verbena bonariensis", + "name": "Eisenkraut", + "sourceUri": "wikimedia-search:Verbena%20bonariensis", + "localImageUri": "/plants/verbena-bonariensis--eisenkraut--486982ce.webp", + "status": "existing" + }, + { + "id": "plant_dc1a3a410bf856da", + "botanicalName": "Fragaria ananassa", + "name": "Erdbeere", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Garden_strawberry_%28Fragaria_%C3%97_ananassa%29_single2.jpg/500px-Garden_strawberry_%28Fragaria_%C3%97_ananassa%29_single2.jpg", + "localImageUri": "/plants/fragaria-ananassa--erdbeere--4a97a911.webp", + "status": "existing" + }, + { + "id": "plant_3900a4af2d8f685c", + "botanicalName": "Sedum morganianum", + "name": "Eselschwanz", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e5/Donkey%27s_tail_in_bloom_March_06.jpg/500px-Donkey%27s_tail_in_bloom_March_06.jpg", + "localImageUri": "/plants/sedum-morganianum--eselschwanz--f6256abc.webp", + "status": "existing" + }, + { + "id": "plant_441bffa80236bad9", + "botanicalName": "Artemisia dracunculus", + "name": "Estragon", + "sourceUri": "wikimedia-search:Artemisia%20dracunculus", + "localImageUri": "/plants/artemisia-dracunculus--estragon--68c643ad.webp", + "status": "existing" + }, + { + "id": "plant_ef61030c75921bec", + "botanicalName": "Eucalyptus globulus", + "name": "Eukalyptus", + "sourceUri": "wikimedia-search:Eucalyptus%20globulus", + "localImageUri": "/plants/eucalyptus-globulus--eukalyptus--48f49df6.webp", + "status": "existing" + }, + { + "id": "plant_bcda607d5ebeba6e", + "botanicalName": "Acer palmatum", + "name": "Faecherahorn", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Acer_palmatum0.jpg/500px-Acer_palmatum0.jpg", + "localImageUri": "/plants/acer-palmatum--faecherahorn--388b6858.webp", + "status": "existing" + }, + { + "id": "plant_44ed48e3379766d4", + "botanicalName": "Schefflera elegantissima", + "name": "Falsche Aralie", + "sourceUri": "wikimedia-search:Schefflera%20elegantissima", + "localImageUri": "/plants/schefflera-elegantissima--falsche-aralie--ff7f753e.webp", + "status": "existing" + }, + { + "id": "plant_f8e84be57621f80c", + "botanicalName": "Ferocactus cylindraceus", + "name": "Fass-Kaktus", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/Ferocactus-cylindraceus.jpg/500px-Ferocactus-cylindraceus.jpg", + "localImageUri": "/plants/ferocactus-cylindraceus--fass-kaktus--ef5c90b1.webp", + "status": "existing" + }, + { + "id": "plant_502fa49e2138d4e5", + "botanicalName": "Fatsia japonica", + "name": "Fatsia", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/Old_Fatsia_japonica_with_blosems.jpg/500px-Old_Fatsia_japonica_with_blosems.jpg", + "localImageUri": "/plants/fatsia-japonica--fatsia--425270ac.webp", + "status": "existing" + }, + { + "id": "plant_4d2d5509b4c55176", + "botanicalName": "Pinguicula grandiflora", + "name": "Fettkraut", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Pinguicula_grandiflora_001.jpg/500px-Pinguicula_grandiflora_001.jpg", + "localImageUri": "/plants/pinguicula-grandiflora--fettkraut--8ec9dead.webp", + "status": "existing" + }, + { + "id": "plant_133e475a45d4a204", + "botanicalName": "Salvia splendens", + "name": "Feuersalbei", + "sourceUri": "wikimedia-search:Salvia%20splendens", + "localImageUri": "/plants/salvia-splendens--feuersalbei--09913571.webp", + "status": "existing" + }, + { + "id": "plant_982eaf3da780eb59", + "botanicalName": "Picea abies", + "name": "Fichte", + "sourceUri": "wikimedia-search:Picea%20abies", + "localImageUri": "/plants/picea-abies--fichte--400d9dc4.webp", + "status": "existing" + }, + { + "id": "plant_04676d4c182b8d1f", + "botanicalName": "Ficus altissima", + "name": "Ficus altissima", + "sourceUri": "wikimedia-search:Ficus%20altissima", + "localImageUri": "/plants/ficus-altissima--76a13dda.webp", + "status": "existing" + }, + { + "id": "plant_ea41ca92364af519", + "botanicalName": "Ficus microcarpa", + "name": "Ficus microcarpa", + "sourceUri": "wikimedia-search:Ficus%20microcarpa", + "localImageUri": "/plants/ficus-microcarpa--ca033402.webp", + "status": "existing" + }, + { + "id": "plant_a45983ad9bacfbd3", + "botanicalName": "Vriesea splendens", + "name": "Flammen-Bromelie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Bromelia1.jpg/500px-Bromelia1.jpg", + "localImageUri": "/plants/vriesea-splendens--flammen-bromelie--debc6faa.webp", + "status": "existing" + }, + { + "id": "plant_370e9f24edf68a0c", + "botanicalName": "Delonix regia", + "name": "Flammenbaum", + "sourceUri": "wikimedia-search:Delonix%20regia", + "localImageUri": "/plants/delonix-regia--flammenbaum--efa632a4.webp", + "status": "existing" + }, + { + "id": "plant_47552862396b817d", + "botanicalName": "Phlox paniculata", + "name": "Flammenblume", + "sourceUri": "wikimedia-search:Phlox%20paniculata", + "localImageUri": "/plants/phlox-paniculata--flammenblume--0bbdd41e.webp", + "status": "existing" + }, + { + "id": "plant_4385d6c520bf6b30", + "botanicalName": "Impatiens walleriana", + "name": "Fleissiges Lieschen", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/28/Impatienswalleriana.jpg/500px-Impatienswalleriana.jpg", + "localImageUri": "/plants/impatiens-walleriana--fleissiges-lieschen--5816f930.webp", + "status": "existing" + }, + { + "id": "plant_11018f19eabb8229", + "botanicalName": "Syringa vulgaris", + "name": "Flieder", + "sourceUri": "wikimedia-search:Syringa%20vulgaris", + "localImageUri": "/plants/syringa-vulgaris--flieder--7e22429d.webp", + "status": "existing" + }, + { + "id": "plant_a1224f40826b5089", + "botanicalName": "Begonia maculata", + "name": "Forellen-Begonie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/df/Begonia_maculata3073316230.jpg/500px-Begonia_maculata3073316230.jpg", + "localImageUri": "/plants/begonia-maculata--forellen-begonie--5cce47c8.webp", + "status": "existing" + }, + { + "id": "plant_30b30e6adcb6e218", + "botanicalName": "Forsythia x intermedia", + "name": "Forsythie", + "sourceUri": "wikimedia-search:Forsythia%20x%20intermedia", + "localImageUri": "/plants/forsythia-x-intermedia--forsythie--390c28f1.webp", + "status": "existing" + }, + { + "id": "plant_fbe673c97a27643c", + "botanicalName": "Adiantum raddianum", + "name": "Frauenhaarfarn", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/45/Starr_030807-0143_Adiantum_raddianum.jpg/500px-Starr_030807-0143_Adiantum_raddianum.jpg", + "localImageUri": "/plants/adiantum-raddianum--frauenhaarfarn--d47cef0b.webp", + "status": "existing" + }, + { + "id": "plant_2c359b2ed2eeb763", + "botanicalName": "Freesia refracta", + "name": "Freesie", + "sourceUri": "wikimedia-search:Freesia%20refracta", + "localImageUri": "/plants/freesia-refracta--freesie--9dafaec2.webp", + "status": "existing" + }, + { + "id": "plant_253febdb6b4c4860", + "botanicalName": "Fuchsia hybrida", + "name": "Fuchsie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Brincos_De_Princesa.jpg/500px-Brincos_De_Princesa.jpg", + "localImageUri": "/plants/fuchsia-hybrida--fuchsie--93ef43c2.webp", + "status": "existing" + }, + { + "id": "plant_416995465e65262d", + "botanicalName": "Amaranthus caudatus", + "name": "Fuchsschwanz", + "sourceUri": "wikimedia-search:Amaranthus%20caudatus", + "localImageUri": "/plants/amaranthus-caudatus--fuchsschwanz--ae0190ae.webp", + "status": "existing" + }, + { + "id": "plant_45589064f63546e7", + "botanicalName": "Bellis perennis", + "name": "Gaensebluemchen", + "sourceUri": "wikimedia-search:Bellis%20perennis", + "localImageUri": "/plants/bellis-perennis--gaensebluemchen--324d3eb0.webp", + "status": "existing" + }, + { + "id": "plant_7e81c1b15627e3d7", + "botanicalName": "Gardenia jasminoides", + "name": "Gardenie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/54/Gardenia_jasminoides_flower_Argentina.jpg/500px-Gardenia_jasminoides_flower_Argentina.jpg", + "localImageUri": "/plants/gardenia-jasminoides--gardenie--f8284265.webp", + "status": "existing" + }, + { + "id": "plant_78a6ccea1e54390f", + "botanicalName": "Impatiens balsamina", + "name": "Gartenbalsamine", + "sourceUri": "wikimedia-search:Impatiens%20balsamina", + "localImageUri": "/plants/impatiens-balsamina--gartenbalsamine--4e1447e8.webp", + "status": "existing" + }, + { + "id": "plant_6e54d649a0c3c691", + "botanicalName": "Hibiscus syriacus", + "name": "Gartenhibiskus", + "sourceUri": "wikimedia-search:Hibiscus%20syriacus", + "localImageUri": "/plants/hibiscus-syriacus--gartenhibiskus--4701a393.webp", + "status": "existing" + }, + { + "id": "plant_c63e701e278fa8ae", + "botanicalName": "Gasteria carinata", + "name": "Gasteria", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/91/2_Gasteria_carinata_var_carinata.jpg/500px-2_Gasteria_carinata_var_carinata.jpg", + "localImageUri": "/plants/gasteria-carinata--gasteria--b27de8c8.webp", + "status": "existing" + }, + { + "id": "plant_fa2afbb2eb4500a7", + "botanicalName": "Maranta leuconeura", + "name": "Gebet-Pflanze", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4a/Maranta_leuconeura3.jpg/500px-Maranta_leuconeura3.jpg", + "localImageUri": "/plants/maranta-leuconeura--gebet-pflanze--e50f6916.webp", + "status": "existing" + }, + { + "id": "plant_16c869313cd292ca", + "botanicalName": "Ficus lyrata", + "name": "Geigenfeige", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Starr_031108-0130_Ficus_lyrata.jpg/500px-Starr_031108-0130_Ficus_lyrata.jpg", + "localImageUri": "/plants/ficus-lyrata--geigenfeige--c025bb04.webp", + "status": "existing" + }, + { + "id": "plant_cfd64439fa554689", + "botanicalName": "Lonicera japonica", + "name": "Geissblatt", + "sourceUri": "wikimedia-search:Lonicera%20japonica", + "localImageUri": "/plants/lonicera-japonica--geissblatt--4b2c6fdb.webp", + "status": "existing" + }, + { + "id": "plant_25cb30720168c488", + "botanicalName": "Graptopetalum paraguayense", + "name": "Geisterpflanze", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/59/%28MHNT%29_Graptopetalum_paraguayense_-_leaves.jpg/500px-%28MHNT%29_Graptopetalum_paraguayense_-_leaves.jpg", + "localImageUri": "/plants/graptopetalum-paraguayense--geisterpflanze--9584de97.webp", + "status": "existing" + }, + { + "id": "plant_87b1168e48dec833", + "botanicalName": "Gerbera jamesonii", + "name": "Gerbera", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Gerbera_jamesonii_%28Asteraceae%29.jpg/500px-Gerbera_jamesonii_%28Asteraceae%29.jpg", + "localImageUri": "/plants/gerbera-jamesonii--gerbera--f17eec14.webp", + "status": "existing" + }, + { + "id": "plant_b93632ad7bfff83a", + "botanicalName": "Platycerium bifurcatum", + "name": "Geweihfarn", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Platycerium_bifurcatum_kz01.jpg/500px-Platycerium_bifurcatum_kz01.jpg", + "localImageUri": "/plants/platycerium-bifurcatum--geweihfarn--991495f9.webp", + "status": "existing" + }, + { + "id": "plant_d8cefda760f89a55", + "botanicalName": "Ginkgo biloba", + "name": "Ginkgo", + "sourceUri": "wikimedia-search:Ginkgo%20biloba", + "localImageUri": "/plants/ginkgo-biloba--ginkgo--8d8c3f3f.webp", + "status": "existing" + }, + { + "id": "plant_5037ed9b79cd8298", + "botanicalName": "Gladiolus hortulanus", + "name": "Gladiole", + "sourceUri": "wikimedia-search:Gladiolus%20hortulanus", + "localImageUri": "/plants/gladiolus-hortulanus--gladiole--e2a2d34f.webp", + "status": "existing" + }, + { + "id": "plant_7e449dc7aefa50dc", + "botanicalName": "Gloxinia speciosa", + "name": "Gloxinie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/Florada_da_Glox%C3%ADnia.jpg/500px-Florada_da_Glox%C3%ADnia.jpg", + "localImageUri": "/plants/gloxinia-speciosa--gloxinie--8a73752c.webp", + "status": "existing" + }, + { + "id": "plant_ef8440900dc6f48a", + "botanicalName": "Pachira aquatica", + "name": "Glueckskastanie", + "sourceUri": "wikimedia-search:Pachira%20aquatica", + "localImageUri": "/plants/pachira-aquatica--glueckskastanie--8e9a0935.webp", + "status": "existing" + }, + { + "id": "plant_d77c5e78b5a6cd52", + "botanicalName": "Echinocactus grusonii", + "name": "Goldene Tonne", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Echinocactus_grusonii_%28aka%29.jpg/500px-Echinocactus_grusonii_%28aka%29.jpg", + "localImageUri": "/plants/echinocactus-grusonii--goldene-tonne--d5268f53.webp", + "status": "existing" + }, + { + "id": "plant_86b6774738a97ccf", + "botanicalName": "Phyllostachys aurea", + "name": "Goldener Bambus", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Phyllostachys_aurea0.jpg/500px-Phyllostachys_aurea0.jpg", + "localImageUri": "/plants/phyllostachys-aurea--goldener-bambus--e05d0c9f.webp", + "status": "existing" + }, + { + "id": "plant_cd5e679bdf1106fa", + "botanicalName": "Dypsis lutescens", + "name": "Goldfruchtpalme", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/22/%E6%95%A3%E5%B0%BE%E8%91%B5Dypsis_lutescens_20210511145013_05.jpg/500px-%E6%95%A3%E5%B0%BE%E8%91%B5Dypsis_lutescens_20210511145013_05.jpg", + "localImageUri": "/plants/dypsis-lutescens--goldfruchtpalme--890812c2.webp", + "status": "existing" + }, + { + "id": "plant_64ff12d55ec3e694", + "botanicalName": "Punica granatum", + "name": "Granatapfelbaum", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/Pomegranate_Juice_%282019%29.jpg/500px-Pomegranate_Juice_%282019%29.jpg", + "localImageUri": "/plants/punica-granatum--granatapfelbaum--facf4f0c.webp", + "status": "existing" + }, + { + "id": "plant_6979e7e4cf35ae8e", + "botanicalName": "Urtica dioica", + "name": "Grosse Brennessel", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Fen_nettle_%28Urtica_dioica_ssp._galeopsifolia%29_-_geograph.org.uk_-_5423125.jpg/500px-Fen_nettle_%28Urtica_dioica_ssp._galeopsifolia%29_-_geograph.org.uk_-_5423125.jpg", + "localImageUri": "/plants/urtica-dioica--grosse-brennessel--b2ed905e.webp", + "status": "existing" + }, + { + "id": "plant_e4804808615a29be", + "botanicalName": "Schefflera actinophylla", + "name": "Grosse Strahlenaralie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/b/bc/Octopus_Tree_%28Schefflera_actinophylla%29_at_Hyderabad%2C_AP_W_283.jpg", + "localImageUri": "/plants/schefflera-actinophylla--grosse-strahlenaralie--a69cdd16.webp", + "status": "existing" + }, + { + "id": "plant_0ee7b22313a79a28", + "botanicalName": "Mentha spicata", + "name": "Gruene Minze", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/Minze.jpg/500px-Minze.jpg", + "localImageUri": "/plants/mentha-spicata--gruene-minze--7cb727ef.webp", + "status": "existing" + }, + { + "id": "plant_730c6fc12cf97511", + "botanicalName": "Psidium guajava", + "name": "Guave", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Psidium_guajava_fruit.jpg/500px-Psidium_guajava_fruit.jpg", + "localImageUri": "/plants/psidium-guajava--guave--5d507482.webp", + "status": "existing" + }, + { + "id": "plant_39c58604790693b9", + "botanicalName": "Ficus elastica", + "name": "Gummibaum", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/Ficus_elastica_leaves_02.JPG/500px-Ficus_elastica_leaves_02.JPG", + "localImageUri": "/plants/ficus-elastica--gummibaum--925b35e7.webp", + "status": "existing" + }, + { + "id": "plant_aa6664ed7adebcb5", + "botanicalName": "Cucumis sativus", + "name": "Gurke", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/96/ARS_cucumber.jpg/500px-ARS_cucumber.jpg", + "localImageUri": "/plants/cucumis-sativus--gurke--3b96fd46.webp", + "status": "existing" + }, + { + "id": "plant_46b49e1b0e69fa64", + "botanicalName": "Guzmania lingulata", + "name": "Guzmania", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Bromeliaceae03.jpg/500px-Bromeliaceae03.jpg", + "localImageUri": "/plants/guzmania-lingulata--guzmania--63fafdcb.webp", + "status": "existing" + }, + { + "id": "plant_81cd86630aca39e5", + "botanicalName": "Betula pendula", + "name": "Hange-Birke", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Betula_pendula_Finland.jpg/500px-Betula_pendula_Finland.jpg", + "localImageUri": "/plants/betula-pendula--hange-birke--aff0bb68.webp", + "status": "existing" + }, + { + "id": "plant_00e33defbd0b49c5", + "botanicalName": "Hyacinthoides non-scripta", + "name": "Hasengloeckchen", + "sourceUri": "wikimedia-search:Hyacinthoides%20non-scripta", + "localImageUri": "/plants/hyacinthoides-non-scripta--hasengloeckchen--cda24b58.webp", + "status": "existing" + }, + { + "id": "plant_f94ccafdbc6c519d", + "botanicalName": "Opuntia microdasys", + "name": "Hasenohren-Kaktus", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/36/Opuntia_microdasys_3.jpg/500px-Opuntia_microdasys_3.jpg", + "localImageUri": "/plants/opuntia-microdasys--hasenohren-kaktus--de2a7439.webp", + "status": "existing" + }, + { + "id": "plant_f297c0da1221e6d4", + "botanicalName": "Heliamphora nutans", + "name": "Heliamphora", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f9/Roraima_Heliamphora_nutans1.JPG/500px-Roraima_Heliamphora_nutans1.JPG", + "localImageUri": "/plants/heliamphora-nutans--heliamphora--16977b41.webp", + "status": "existing" + }, + { + "id": "plant_39436f8620e13b0e", + "botanicalName": "Heliconia psittacorum", + "name": "Heliconia", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Parrot_heliconia_%28Heliconia_psittacorum%29.jpg/500px-Parrot_heliconia_%28Heliconia_psittacorum%29.jpg", + "localImageUri": "/plants/heliconia-psittacorum--heliconia--15bad812.webp", + "status": "existing" + }, + { + "id": "plant_530216d88dff6849", + "botanicalName": "Heliotropium arborescens", + "name": "Heliotrop", + "sourceUri": "wikimedia-search:Heliotropium%20arborescens", + "localImageUri": "/plants/heliotropium-arborescens--heliotrop--73a11073.webp", + "status": "existing" + }, + { + "id": "plant_588b544697087860", + "botanicalName": "Symphyotrichum novi-belgii", + "name": "Herbstaster", + "sourceUri": "wikimedia-search:Symphyotrichum%20novi-belgii", + "localImageUri": "/plants/symphyotrichum-novi-belgii--herbstaster--615b51bf.webp", + "status": "existing" + }, + { + "id": "plant_b246d39c63f29a40", + "botanicalName": "Philodendron hederaceum", + "name": "Herzblatt-Philodendron", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Philodendron_scandens_subsp_oxycardium2.jpg/500px-Philodendron_scandens_subsp_oxycardium2.jpg", + "localImageUri": "/plants/philodendron-hederaceum--herzblatt-philodendron--54360959.webp", + "status": "existing" + }, + { + "id": "plant_3de588912c04dc7f", + "botanicalName": "Ceropegia woodii", + "name": "Herzkette", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/5/55/Ceropegia_linearis_subsp_woodii.jpg", + "localImageUri": "/plants/ceropegia-woodii--herzkette--b51fb231.webp", + "status": "existing" + }, + { + "id": "plant_8b5798718a1dc5c6", + "botanicalName": "Hibiscus rosa-sinensis", + "name": "Hibiskus", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/21/Hibiscus_Brilliant.jpg/500px-Hibiscus_Brilliant.jpg", + "localImageUri": "/plants/hibiscus-rosa-sinensis--hibiskus--9e6d8b54.webp", + "status": "existing" + }, + { + "id": "plant_59744831808b8fd7", + "botanicalName": "Viola cornuta", + "name": "Hornveilchen", + "sourceUri": "wikimedia-search:Viola%20cornuta", + "localImageUri": "/plants/viola-cornuta--hornveilchen--d2abebd6.webp", + "status": "existing" + }, + { + "id": "plant_38a5122c0bea580a", + "botanicalName": "Hydrangea macrophylla", + "name": "Hortensie", + "sourceUri": "wikimedia-search:Hydrangea%20macrophylla", + "localImageUri": "/plants/hydrangea-macrophylla--hortensie--78d76f22.webp", + "status": "existing" + }, + { + "id": "plant_0306abe03e6d7296", + "botanicalName": "Hyacinthus orientalis", + "name": "Hyazinthe", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Hyacinth_flower.jpg/500px-Hyacinth_flower.jpg", + "localImageUri": "/plants/hyacinthus-orientalis--hyazinthe--2c07af5d.webp", + "status": "existing" + }, + { + "id": "plant_be65cacf4e579727", + "botanicalName": "Monarda didyma", + "name": "Indianernessel", + "sourceUri": "wikimedia-search:Monarda%20didyma", + "localImageUri": "/plants/monarda-didyma--indianernessel--309858d1.webp", + "status": "existing" + }, + { + "id": "plant_4e66095e06f32cf4", + "botanicalName": "Azalea indica", + "name": "Indische Azalee", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/de/Rhododendron_indicum1.jpg/500px-Rhododendron_indicum1.jpg", + "localImageUri": "/plants/azalea-indica--indische-azalee--fe6e49a3.webp", + "status": "existing" + }, + { + "id": "plant_902876241a0c1f6f", + "botanicalName": "Zingiber officinale", + "name": "Ingwer", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Koeh-146-no_text.jpg/500px-Koeh-146-no_text.jpg", + "localImageUri": "/plants/zingiber-officinale--ingwer--597975c9.webp", + "status": "existing" + }, + { + "id": "plant_202d5c1a3f83e307", + "botanicalName": "Jacaranda mimosifolia", + "name": "Jacaranda", + "sourceUri": "wikimedia-search:Jacaranda%20mimosifolia", + "localImageUri": "/plants/jacaranda-mimosifolia--jacaranda--324b12c5.webp", + "status": "existing" + }, + { + "id": "plant_2f9ba405e4cbd7de", + "botanicalName": "Crassula ovata", + "name": "Jadepflanze", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Crassula_ovata_700.jpg/500px-Crassula_ovata_700.jpg", + "localImageUri": "/plants/crassula-ovata--jadepflanze--3ac94122.webp", + "status": "existing" + }, + { + "id": "plant_192fc2d6932b5621", + "botanicalName": "Aucuba japonica", + "name": "Japanische Aucube", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c6/Aucuba_japonica_Gold_Dust_NBG_LR.jpg/500px-Aucuba_japonica_Gold_Dust_NBG_LR.jpg", + "localImageUri": "/plants/aucuba-japonica--japanische-aucube--c4bcd588.webp", + "status": "existing" + }, + { + "id": "plant_a0c9b297c07374b5", + "botanicalName": "Rhododendron simsii", + "name": "Japanische Azalee", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Rhododendron_simsii-bunga_2-Lany_pirna.jpg/500px-Rhododendron_simsii-bunga_2-Lany_pirna.jpg", + "localImageUri": "/plants/rhododendron-simsii--japanische-azalee--ef16f2c0.webp", + "status": "existing" + }, + { + "id": "plant_28ae5636958be358", + "botanicalName": "Jasminum polyanthum", + "name": "Jasmin", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/%28MHNT%29_Jasminum_polyanthum_%E2%80%93_flowers_and_buds.jpg/500px-%28MHNT%29_Jasminum_polyanthum_%E2%80%93_flowers_and_buds.jpg", + "localImageUri": "/plants/jasminum-polyanthum--jasmin--14162cf1.webp", + "status": "existing" + }, + { + "id": "plant_8fea9248ff0c7bb5", + "botanicalName": "Hypericum perforatum", + "name": "Johanniskraut", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/%28MHNT%29_Hypericum_perforatum_flower_and_buttons.jpg/500px-%28MHNT%29_Hypericum_perforatum_flower_and_buttons.jpg", + "localImageUri": "/plants/hypericum-perforatum--johanniskraut--9bdb2ebc.webp", + "status": "existing" + }, + { + "id": "plant_9e91885abb04cb86", + "botanicalName": "Coffea arabica Nana", + "name": "Kaffeepflanze arabica nana", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/Starr-121108-1098-Coffea_arabica-Philippine_dwarf_habit_with_Forest_and_Angela-Pali_o_Waipio-Maui_%2825102146741%29.jpg/1280px-Starr-121108-1098-Coffea_arabica-Philippine_dwarf_habit_with_Forest_and_Angela-Pali_o_Waipio-Maui_%2825102146741%29.jpg", + "localImageUri": "/plants/coffea-arabica-nana--kaffeepflanze-arabica-nana--3dab6209.webp", + "status": "existing" + }, + { + "id": "plant_c2b3a25e00acf3e2", + "botanicalName": "Coffea arabica", + "name": "Kaffeestrauch", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Coffee_Flowers.JPG/500px-Coffee_Flowers.JPG", + "localImageUri": "/plants/coffea-arabica--kaffeestrauch--a5ffdda3.webp", + "status": "existing" + }, + { + "id": "plant_7597db1c1b395452", + "botanicalName": "Kalanchoe blossfeldiana", + "name": "Kalanchoe", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Kalanchoe_blossfeldiana_3.jpg/500px-Kalanchoe_blossfeldiana_3.jpg", + "localImageUri": "/plants/kalanchoe-blossfeldiana--kalanchoe--e040640f.webp", + "status": "existing" + }, + { + "id": "plant_78775c3119a08f01", + "botanicalName": "Eschscholzia californica", + "name": "Kalifornischer Mohn", + "sourceUri": "wikimedia-search:Eschscholzia%20californica", + "localImageUri": "/plants/eschscholzia-californica--kalifornischer-mohn--da7d0f79.webp", + "status": "existing" + }, + { + "id": "plant_735b19d4a6efe5c0", + "botanicalName": "Camellia japonica", + "name": "Kamelie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e9/Camellia_japonica_NBG.jpg/500px-Camellia_japonica_NBG.jpg", + "localImageUri": "/plants/camellia-japonica--kamelie--6a23eb3f.webp", + "status": "existing" + }, + { + "id": "plant_e0432335ee4f0033", + "botanicalName": "Chamomilla recutita", + "name": "Kamille", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c8/Matricaria_February_2008-1.jpg/500px-Matricaria_February_2008-1.jpg", + "localImageUri": "/plants/chamomilla-recutita--kamille--0bffdb72.webp", + "status": "existing" + }, + { + "id": "plant_de21871ad8dcaefd", + "botanicalName": "Kalanchoe tomentosa", + "name": "Kaninchen-Ohren", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/04/Kalanchoe_tomentosa_01.jpg/500px-Kalanchoe_tomentosa_01.jpg", + "localImageUri": "/plants/kalanchoe-tomentosa--kaninchen-ohren--2c3b1e90.webp", + "status": "existing" + }, + { + "id": "plant_cb7817f551f6c73e", + "botanicalName": "Nepenthes alata", + "name": "Kannenpflanze", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/7/77/Nepenthes_alata_ASR_062007_mt_ambucao_luzon.jpg", + "localImageUri": "/plants/nepenthes-alata--kannenpflanze--30016442.webp", + "status": "existing" + }, + { + "id": "plant_325a00f384ac1a15", + "botanicalName": "Aloe arborescens", + "name": "Kap-Aloe", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b9/Aloe_arborescens_Compton.JPG/500px-Aloe_arborescens_Compton.JPG", + "localImageUri": "/plants/aloe-arborescens--kap-aloe--2c4f60ef.webp", + "status": "existing" + }, + { + "id": "plant_bb4dea2113550a88", + "botanicalName": "Aloe ferox", + "name": "Kap-Aloe (ferox)", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/9/9e/Aloe_Ferox_between_Cofimvaba_and_Ngcobo.jpg", + "localImageUri": "/plants/aloe-ferox--kap-aloe-ferox--e78c3f65.webp", + "status": "existing" + }, + { + "id": "plant_d32498f051c71256", + "botanicalName": "Osteospermum ecklonis", + "name": "Kapmargerite", + "sourceUri": "wikimedia-search:Osteospermum%20ecklonis", + "localImageUri": "/plants/osteospermum-ecklonis--kapmargerite--7d0ac9d6.webp", + "status": "existing" + }, + { + "id": "plant_f0348c48dc721bb9", + "botanicalName": "Tropaeolum majus", + "name": "Kapuzinerkresse", + "sourceUri": "wikimedia-search:Tropaeolum%20majus", + "localImageUri": "/plants/tropaeolum-majus--kapuzinerkresse--c007c761.webp", + "status": "existing" + }, + { + "id": "plant_f8c518688fd2d49b", + "botanicalName": "Daucus carota", + "name": "Karotte", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/23/Daucus_carota_May_2008-1_edit.jpg/500px-Daucus_carota_May_2008-1_edit.jpg", + "localImageUri": "/plants/daucus-carota--karotte--85d90d33.webp", + "status": "existing" + }, + { + "id": "plant_dc535ae68a36c48c", + "botanicalName": "Nepeta cataria", + "name": "Katzenminze", + "sourceUri": "wikimedia-search:Nepeta%20cataria", + "localImageUri": "/plants/nepeta-cataria--katzenminze--7935cfe0.webp", + "status": "existing" + }, + { + "id": "plant_c605a83dcbce1a97", + "botanicalName": "Howea forsteriana", + "name": "Kentia-Palme", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/99/Howea_forsteriana_Lord_Howe_Island.jpg/500px-Howea_forsteriana_Lord_Howe_Island.jpg", + "localImageUri": "/plants/howea-forsteriana--kentia-palme--f2c205ea.webp", + "status": "existing" + }, + { + "id": "plant_8927d794f67ea97c", + "botanicalName": "Anthriscus cerefolium", + "name": "Kerbel", + "sourceUri": "wikimedia-search:Anthriscus%20cerefolium", + "localImageUri": "/plants/anthriscus-cerefolium--kerbel--eb8bf3ab.webp", + "status": "existing" + }, + { + "id": "plant_bf13d931fa5427de", + "botanicalName": "Cordyline australis", + "name": "Keulenlilie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/CabbageTreeKaihoka.jpg/500px-CabbageTreeKaihoka.jpg", + "localImageUri": "/plants/cordyline-australis--keulenlilie--31be351b.webp", + "status": "existing" + }, + { + "id": "plant_d47591d55ee11f4c", + "botanicalName": "Pinus sylvestris", + "name": "Kiefer", + "sourceUri": "wikimedia-search:Pinus%20sylvestris", + "localImageUri": "/plants/pinus-sylvestris--kiefer--6db5e3c6.webp", + "status": "existing" + }, + { + "id": "plant_3cc71b10ff1d5d6e", + "botanicalName": "Prunus laurocerasus", + "name": "Kirschlorbeer", + "sourceUri": "wikimedia-search:Prunus%20laurocerasus", + "localImageUri": "/plants/prunus-laurocerasus--kirschlorbeer--9291015b.webp", + "status": "existing" + }, + { + "id": "plant_205589ef30c6f380", + "botanicalName": "Oxalis triangularis", + "name": "Kleeblume", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Oxalis_triangularis6.jpg/500px-Oxalis_triangularis6.jpg", + "localImageUri": "/plants/oxalis-triangularis--kleeblume--9080763b.webp", + "status": "existing" + }, + { + "id": "plant_e1f0a5c763e6f721", + "botanicalName": "Hoya bella", + "name": "Kleine Wachsblume", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/%E7%BE%8E%E9%BA%97%E6%AF%AC%E8%98%AD_Hoya_bella_-%E9%A6%99%E6%B8%AF%E5%85%AC%E5%9C%92_Hong_Kong_Park-_%289240227808%29.jpg/500px-%E7%BE%8E%E9%BA%97%E6%AF%AC%E8%98%AD_Hoya_bella_-%E9%A6%99%E6%B8%AF%E5%85%AC%E5%9C%92_Hong_Kong_Park-_%289240227808%29.jpg", + "localImageUri": "/plants/hoya-bella--kleine-wachsblume--db73dcff.webp", + "status": "existing" + }, + { + "id": "plant_156a82fb0d4e7201", + "botanicalName": "Begonia tuberhybrida", + "name": "Knollen-Begonie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/Begonia-tuberhybride_Red.jpg/500px-Begonia-tuberhybride_Red.jpg", + "localImageUri": "/plants/begonia-tuberhybrida--knollen-begonie--7d9dfd00.webp", + "status": "existing" + }, + { + "id": "plant_6fdbc0c3fc6d0820", + "botanicalName": "Epiphyllum oxypetalum", + "name": "Koenigin der Nacht", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Epiphyllum_oxypetalum_flower.JPG/500px-Epiphyllum_oxypetalum_flower.JPG", + "localImageUri": "/plants/epiphyllum-oxypetalum--koenigin-der-nacht--7ecd1979.webp", + "status": "existing" + }, + { + "id": "plant_fb262dee6cb22325", + "botanicalName": "Protea cynaroides", + "name": "Koenigs-Protea", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3d/Protea_cynaroides_3.jpg/500px-Protea_cynaroides_3.jpg", + "localImageUri": "/plants/protea-cynaroides--koenigs-protea--2186e16d.webp", + "status": "existing" + }, + { + "id": "plant_c18b4430b4dfeef8", + "botanicalName": "Begonia rex", + "name": "Koenigsbegonie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Painted_Leaved_Begonia._Begonia_rex_Putz._Flore_des_serres_et_des_jardins_de_l%27Europe_v.12_%281857%29.jpg/500px-Painted_Leaved_Begonia._Begonia_rex_Putz._Flore_des_serres_et_des_jardins_de_l%27Europe_v.12_%281857%29.jpg", + "localImageUri": "/plants/begonia-rex--koenigsbegonie--b6083f44.webp", + "status": "existing" + }, + { + "id": "plant_6579aa953da5beea", + "botanicalName": "Verbascum thapsus", + "name": "Koenigskerze", + "sourceUri": "wikimedia-search:Verbascum%20thapsus", + "localImageUri": "/plants/verbascum-thapsus--koenigskerze--26f01a84.webp", + "status": "existing" + }, + { + "id": "plant_24e5004efcd91423", + "botanicalName": "Gaillardia aristata", + "name": "Kokardenblume", + "sourceUri": "wikimedia-search:Gaillardia%20aristata", + "localImageUri": "/plants/gaillardia-aristata--kokardenblume--050cf2e5.webp", + "status": "existing" + }, + { + "id": "plant_71f244d60e9fb18d", + "botanicalName": "Conophytum calculus", + "name": "Konophytum", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/1_Conophytum_calculus_-_RSA_3.jpg/500px-1_Conophytum_calculus_-_RSA_3.jpg", + "localImageUri": "/plants/conophytum-calculus--konophytum--4c3a116e.webp", + "status": "existing" + }, + { + "id": "plant_5f6dd525e28bd218", + "botanicalName": "Rhipsalis baccifera", + "name": "Korallenkaktus", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Rhipsalis_baccifera_01_ies.jpg/500px-Rhipsalis_baccifera_01_ies.jpg", + "localImageUri": "/plants/rhipsalis-baccifera--korallenkaktus--3097b146.webp", + "status": "existing" + }, + { + "id": "plant_589a537d2b599299", + "botanicalName": "Coriandrum sativum", + "name": "Koriander", + "sourceUri": "wikimedia-search:Coriandrum%20sativum", + "localImageUri": "/plants/coriandrum-sativum--koriander--c1d3ccee.webp", + "status": "existing" + }, + { + "id": "plant_9a590a40395f4882", + "botanicalName": "Centaurea cyanus", + "name": "Kornblume", + "sourceUri": "wikimedia-search:Centaurea%20cyanus", + "localImageUri": "/plants/centaurea-cyanus--kornblume--ff8efded.webp", + "status": "existing" + }, + { + "id": "plant_a6e9bf1a9c4162fb", + "botanicalName": "Cosmos bipinnatus", + "name": "Kosmee", + "sourceUri": "wikimedia-search:Cosmos%20bipinnatus", + "localImageUri": "/plants/cosmos-bipinnatus--kosmee--5a231205.webp", + "status": "existing" + }, + { + "id": "plant_612f629e95b2c540", + "botanicalName": "Cotyledon orbiculata", + "name": "Kotyledon", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Cotyledon_orbiculata_-_pigs_ear_-_Cape_Point_-_South_Africa_2.JPG/500px-Cotyledon_orbiculata_-_pigs_ear_-_Cape_Point_-_South_Africa_2.JPG", + "localImageUri": "/plants/cotyledon-orbiculata--kotyledon--e61a1c1a.webp", + "status": "existing" + }, + { + "id": "plant_f6cb2e28c94b0f3c", + "botanicalName": "Anthurium crystallinum", + "name": "Kristall-Anthurie", + "sourceUri": "wikimedia-search:Anthurium%20crystallinum", + "localImageUri": "/plants/anthurium-crystallinum--kristall-anthurie--2d5ec8d4.webp", + "status": "existing" + }, + { + "id": "plant_adce82fe150c9814", + "botanicalName": "Crocus vernus", + "name": "Krokus", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e2/Crocus_vernus_with_bee.jpg/500px-Crocus_vernus_with_bee.jpg", + "localImageUri": "/plants/crocus-vernus--krokus--31f51b70.webp", + "status": "existing" + }, + { + "id": "plant_830ccd232b784d9e", + "botanicalName": "Codiaeum variegatum", + "name": "Kroton", + "sourceUri": "wikimedia-search:Garden%20croton", + "localImageUri": "/plants/codiaeum-variegatum--kroton--fceb7491.webp", + "status": "existing" + }, + { + "id": "plant_64ba168636b5e8a3", + "botanicalName": "Curcuma longa", + "name": "Kurkuma", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/Turmeric_inflorescence.jpg/500px-Turmeric_inflorescence.jpg", + "localImageUri": "/plants/curcuma-longa--kurkuma--cb270150.webp", + "status": "existing" + }, + { + "id": "plant_bb51efcb52023c48", + "botanicalName": "Lithops julii", + "name": "Lebende Steine", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Lithops_julii_fulleri.jpg/500px-Lithops_julii_fulleri.jpg", + "localImageUri": "/plants/lithops-julii--lebende-steine--939c0d2c.webp", + "status": "existing" + }, + { + "id": "plant_93f2cc182268c96a", + "botanicalName": "Helleborus orientalis", + "name": "Lenzrose", + "sourceUri": "wikimedia-search:Helleborus%20orientalis", + "localImageUri": "/plants/helleborus-orientalis--lenzrose--f7df56b8.webp", + "status": "existing" + }, + { + "id": "plant_e969375587d68477", + "botanicalName": "Levisticum officinale", + "name": "Liebstoeckel", + "sourceUri": "wikimedia-search:Levisticum%20officinale", + "localImageUri": "/plants/levisticum-officinale--liebstoeckel--649f0af1.webp", + "status": "existing" + }, + { + "id": "plant_0a16a89a9de52d5c", + "botanicalName": "Tradescantia pallida", + "name": "Lila Tradescantia", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Tradescantia_pallida_kz03.jpg/500px-Tradescantia_pallida_kz03.jpg", + "localImageUri": "/plants/tradescantia-pallida--lila-tradescantia--fa444b81.webp", + "status": "existing" + }, + { + "id": "plant_a34bdd68ffb97e12", + "botanicalName": "Aeschynanthus radicans", + "name": "Lippenstiftpflanze", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/52/Aeschynanthus_radicans.jpg/500px-Aeschynanthus_radicans.jpg", + "localImageUri": "/plants/aeschynanthus-radicans--lippenstiftpflanze--c0f3a18c.webp", + "status": "existing" + }, + { + "id": "plant_fe714a89f340dc8c", + "botanicalName": "Antirrhinum majus", + "name": "Loewenmaeulchen", + "sourceUri": "wikimedia-search:Antirrhinum%20majus", + "localImageUri": "/plants/antirrhinum-majus--loewenmaeulchen--ee99a45e.webp", + "status": "existing" + }, + { + "id": "plant_061cff94e10bff7a", + "botanicalName": "Laurus nobilis", + "name": "Lorbeer", + "sourceUri": "wikimedia-search:Laurus%20nobilis", + "localImageUri": "/plants/laurus-nobilis--lorbeer--7fb425a5.webp", + "status": "existing" + }, + { + "id": "plant_db7b7c883a5fb716", + "botanicalName": "Tillandsia ionantha", + "name": "Luftpflanze", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b5/Purple_sky_plant_-_Andrey_Zharkikh.jpg/500px-Purple_sky_plant_-_Andrey_Zharkikh.jpg", + "localImageUri": "/plants/tillandsia-ionantha--luftpflanze--c221d48d.webp", + "status": "existing" + }, + { + "id": "plant_15527732e9ae75b4", + "botanicalName": "Lupinus polyphyllus", + "name": "Lupine", + "sourceUri": "wikimedia-search:Lupinus%20polyphyllus", + "localImageUri": "/plants/lupinus-polyphyllus--lupine--d528d819.webp", + "status": "existing" + }, + { + "id": "plant_fafb81415756f893", + "botanicalName": "Stephanotis floribunda", + "name": "Madagaskar-Jasmin", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Stephanotis_floribunda3L._Marie.jpg/500px-Stephanotis_floribunda3L._Marie.jpg", + "localImageUri": "/plants/stephanotis-floribunda--madagaskar-jasmin--f5b3e914.webp", + "status": "existing" + }, + { + "id": "plant_b9e7bf04918e8547", + "botanicalName": "Coreopsis tinctoria", + "name": "Maedchenauge", + "sourceUri": "wikimedia-search:Coreopsis%20tinctoria", + "localImageUri": "/plants/coreopsis-tinctoria--maedchenauge--64a5d938.webp", + "status": "existing" + }, + { + "id": "plant_7a9e8ffc731ea60b", + "botanicalName": "Magnolia grandiflora", + "name": "Magnolie", + "sourceUri": "wikimedia-search:Magnolia%20grandiflora", + "localImageUri": "/plants/magnolia-grandiflora--magnolie--5eaff200.webp", + "status": "existing" + }, + { + "id": "plant_0e1ce38a0405df52", + "botanicalName": "Convallaria majalis", + "name": "Maigloeckchen", + "sourceUri": "wikimedia-search:Convallaria%20majalis", + "localImageUri": "/plants/convallaria-majalis--maigloeckchen--d7acb648.webp", + "status": "existing" + }, + { + "id": "plant_cabb9c3df66307ba", + "botanicalName": "Dracaena fragrans", + "name": "Maisstrauch", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/db/Dracaena_fragrans_%282%29.jpg/500px-Dracaena_fragrans_%282%29.jpg", + "localImageUri": "/plants/dracaena-fragrans--maisstrauch--107c7d0f.webp", + "status": "existing" + }, + { + "id": "plant_b89779554bd0233f", + "botanicalName": "Origanum majorana", + "name": "Majoran", + "sourceUri": "wikimedia-search:Origanum%20majorana", + "localImageUri": "/plants/origanum-majorana--majoran--d0d23e9f.webp", + "status": "existing" + }, + { + "id": "plant_d52a80feceba729c", + "botanicalName": "Mammillaria zeilmanniana", + "name": "Mammillaria", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/Mammillaria_zeilmanniana.jpg/500px-Mammillaria_zeilmanniana.jpg", + "localImageUri": "/plants/mammillaria-zeilmanniana--mammillaria--ee6d834e.webp", + "status": "existing" + }, + { + "id": "plant_9406fa4ffbef305b", + "botanicalName": "Beta vulgaris", + "name": "Mangold", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/f/ff/Beta_vulgaris_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-167.jpg", + "localImageUri": "/plants/beta-vulgaris--mangold--7fb88006.webp", + "status": "existing" + }, + { + "id": "plant_39d8c8f7dced6c59", + "botanicalName": "Leucanthemum vulgare", + "name": "Margerite", + "sourceUri": "wikimedia-search:Leucanthemum%20vulgare", + "localImageUri": "/plants/leucanthemum-vulgare--margerite--f583d6a2.webp", + "status": "existing" + }, + { + "id": "plant_ca9b1576aab12566", + "botanicalName": "Epipremnum aureum Marble Queen", + "name": "Marmor-Efeutute", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/ca/Epipremnum_aureum_Marble_Queen.jpg/500px-Epipremnum_aureum_Marble_Queen.jpg", + "localImageUri": "/plants/epipremnum-aureum-marble-queen--marmor-efeutute--1d6745d9.webp", + "status": "existing" + }, + { + "id": "plant_e66a57622e22d994", + "botanicalName": "Salvia farinacea", + "name": "Mehlsalbei", + "sourceUri": "wikimedia-search:Salvia%20farinacea", + "localImageUri": "/plants/salvia-farinacea--mehlsalbei--a046f0ea.webp", + "status": "existing" + }, + { + "id": "plant_95de7815c2f690ce", + "botanicalName": "Washingtonia robusta", + "name": "Mexikanische Fächerpalme", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b8/Arecales_-_Washingtonia_robusta_-_1.jpg/500px-Arecales_-_Washingtonia_robusta_-_1.jpg", + "localImageUri": "/plants/washingtonia-robusta--mexikanische-facherpalme--ced2cfe1.webp", + "status": "existing" + }, + { + "id": "plant_01ed2f643e7d5d8e", + "botanicalName": "Rhaphidophora tetrasperma", + "name": "Mini-Monstera", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/db/Rhaphidophora_tetrasperma.jpg/500px-Rhaphidophora_tetrasperma.jpg", + "localImageUri": "/plants/rhaphidophora-tetrasperma--mini-monstera--8698ef03.webp", + "status": "existing" + }, + { + "id": "plant_6448079452dd9eb8", + "botanicalName": "Gazania rigens", + "name": "Mittagsgold", + "sourceUri": "wikimedia-search:Gazania%20rigens", + "localImageUri": "/plants/gazania-rigens--mittagsgold--cc595e45.webp", + "status": "existing" + }, + { + "id": "plant_8d0ea0639b4e5136", + "botanicalName": "Papaver rhoeas", + "name": "Mohn", + "sourceUri": "wikimedia-search:Papaver%20rhoeas", + "localImageUri": "/plants/papaver-rhoeas--mohn--32fb9e83.webp", + "status": "existing" + }, + { + "id": "plant_8e8b8bf4c4f7bdb6", + "botanicalName": "Gymnocalycium mihanovichii", + "name": "Mond-Kaktus", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/51/Gymnocalycium_mihanovichii_4.JPG/500px-Gymnocalycium_mihanovichii_4.JPG", + "localImageUri": "/plants/gymnocalycium-mihanovichii--mond-kaktus--c7e6e78b.webp", + "status": "existing" + }, + { + "id": "plant_e8ab689f2d26d8b2", + "botanicalName": "Pachyphytum oviferum", + "name": "Mondstein-Pflanze", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8f/%28MHNT%29_Pachyphytum_oviferum_-_Habitus.jpg/500px-%28MHNT%29_Pachyphytum_oviferum_-_Habitus.jpg", + "localImageUri": "/plants/pachyphytum-oviferum--mondstein-pflanze--66cf2adc.webp", + "status": "existing" + }, + { + "id": "plant_b843de18953d2232", + "botanicalName": "Monstera adansonii", + "name": "Monstera adansonii", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/Monstera_adansonii_79319231.jpg/500px-Monstera_adansonii_79319231.jpg", + "localImageUri": "/plants/monstera-adansonii--911eb5ba.webp", + "status": "existing" + }, + { + "id": "plant_44c152d886d0b190", + "botanicalName": "Monstera obliqua", + "name": "Monstera obliqua", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/Obiqula.jpg/500px-Obiqula.jpg", + "localImageUri": "/plants/monstera-obliqua--8ab6f307.webp", + "status": "existing" + }, + { + "id": "plant_da8adeffa961a540", + "botanicalName": "Crassula muscosa", + "name": "Moos-Crassula", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5e/Crassula_muscosa_Grubosz_2006-05-03_01.jpg/500px-Crassula_muscosa_Grubosz_2006-05-03_01.jpg", + "localImageUri": "/plants/crassula-muscosa--moos-crassula--41420e37.webp", + "status": "existing" + }, + { + "id": "plant_917a7775d4ada0c1", + "botanicalName": "Alpinia zerumbet", + "name": "Muschelingwer", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/200410_Alpinia_zerumbet_1.JPG/500px-200410_Alpinia_zerumbet_1.JPG", + "localImageUri": "/plants/alpinia-zerumbet--muschelingwer--f0c5c11e.webp", + "status": "existing" + }, + { + "id": "plant_eff2ecdef8205cc1", + "botanicalName": "Dianthus caryophyllus", + "name": "Nelke", + "sourceUri": "wikimedia-search:Dianthus%20caryophyllus", + "localImageUri": "/plants/dianthus-caryophyllus--nelke--1ccf57de.webp", + "status": "existing" + }, + { + "id": "plant_5358cd292660e315", + "botanicalName": "Nemesia strumosa", + "name": "Nemesie", + "sourceUri": "wikimedia-search:Nemesia%20strumosa", + "localImageUri": "/plants/nemesia-strumosa--nemesie--90e80dd2.webp", + "status": "existing" + }, + { + "id": "plant_de18a22fc81062c9", + "botanicalName": "Epipremnum pinnatum Neon", + "name": "Neon-Efeutute", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/de/Epipremnum_pinnatum_%27Neon%27%2C_Longwood_Gardens_01.jpg/500px-Epipremnum_pinnatum_%27Neon%27%2C_Longwood_Gardens_01.jpg", + "localImageUri": "/plants/epipremnum-pinnatum-neon--neon-efeutute--3e91b575.webp", + "status": "existing" + }, + { + "id": "plant_3d4bc95e6500e9fc", + "botanicalName": "Neoregelia carolinae", + "name": "Neoregelia", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/27/Neoregelia_carolinae_BotGardBln310505a.jpg/500px-Neoregelia_carolinae_BotGardBln310505a.jpg", + "localImageUri": "/plants/neoregelia-carolinae--neoregelia--454c3c96.webp", + "status": "existing" + }, + { + "id": "plant_ac3f55a2073b1427", + "botanicalName": "Fittonia albivenis", + "name": "Nervenpflanze", + "sourceUri": "wikimedia-search:Fittonia%20albivenis", + "localImageUri": "/plants/fittonia-albivenis--nervenpflanze--b674f5e6.webp", + "status": "existing" + }, + { + "id": "plant_c62ac934518110bb", + "botanicalName": "Impatiens hawkeri", + "name": "Neuguinea-Balsamine", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Impatiens_hawkeri%2C_beijo-pintado_%28flores_vermelhas%29_07.jpg/500px-Impatiens_hawkeri%2C_beijo-pintado_%28flores_vermelhas%29_07.jpg", + "localImageUri": "/plants/impatiens-hawkeri--neuguinea-balsamine--4e5c7c8f.webp", + "status": "existing" + }, + { + "id": "plant_8fe9abf012241581", + "botanicalName": "Araucaria heterophylla", + "name": "Norfolk-Tanne", + "sourceUri": "wikimedia-search:Araucaria%20heterophylla", + "localImageUri": "/plants/araucaria-heterophylla--norfolk-tanne--56ef2a36.webp", + "status": "existing" + }, + { + "id": "plant_3dec7298828d7d5b", + "botanicalName": "Nerium oleander", + "name": "Oleander", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cc/Nerium_oleander_flowers_leaves.jpg/500px-Nerium_oleander_flowers_leaves.jpg", + "localImageUri": "/plants/nerium-oleander--oleander--87c4b966.webp", + "status": "existing" + }, + { + "id": "plant_8915ad2e41841f3d", + "botanicalName": "Citrus sinensis", + "name": "Orangenbaum", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/OrangeBloss_wb.jpg/500px-OrangeBloss_wb.jpg", + "localImageUri": "/plants/citrus-sinensis--orangenbaum--294e1722.webp", + "status": "existing" + }, + { + "id": "plant_d61f0c50e94b917d", + "botanicalName": "Origanum vulgare", + "name": "Oregano", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Origanum_vulgare_-_harilik_pune.jpg/500px-Origanum_vulgare_-_harilik_pune.jpg", + "localImageUri": "/plants/origanum-vulgare--oregano--33c6269c.webp", + "status": "existing" + }, + { + "id": "plant_a62147e5f0805622", + "botanicalName": "Narcissus pseudonarcissus", + "name": "Osterglocke", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a4/Narcissus_pseudonarcissus_flower_300303.jpg/500px-Narcissus_pseudonarcissus_flower_300303.jpg", + "localImageUri": "/plants/narcissus-pseudonarcissus--osterglocke--32e917c0.webp", + "status": "existing" + }, + { + "id": "plant_f66ecda188a5efad", + "botanicalName": "Lilium longiflorum", + "name": "Ostertrompete", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Lilium_longiflorum_%28Easter_Lily%29.JPG/500px-Lilium_longiflorum_%28Easter_Lily%29.JPG", + "localImageUri": "/plants/lilium-longiflorum--ostertrompete--4b791484.webp", + "status": "existing" + }, + { + "id": "plant_8b92e803087c2f97", + "botanicalName": "Cycas revoluta", + "name": "Palmfarn", + "sourceUri": "wikimedia-search:Cycas%20revoluta", + "localImageUri": "/plants/cycas-revoluta--palmfarn--71371c45.webp", + "status": "existing" + }, + { + "id": "plant_e4f082a4e9f3a8c5", + "botanicalName": "Carica papaya", + "name": "Papaya", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Carica_papaya_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-029.jpg/500px-Carica_papaya_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-029.jpg", + "localImageUri": "/plants/carica-papaya--papaya--240dc331.webp", + "status": "existing" + }, + { + "id": "plant_612cf58237a77a91", + "botanicalName": "Strelitzia reginae", + "name": "Paradiesvogelblume", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Bird_of_Paradise_flower.JPG/500px-Bird_of_Paradise_flower.JPG", + "localImageUri": "/plants/strelitzia-reginae--paradiesvogelblume--3ee1f013.webp", + "status": "existing" + }, + { + "id": "plant_61ec02f0a706b922", + "botanicalName": "Cyperus alternifolius", + "name": "Paragraphenpflanze", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/7/76/Cyperus_alternifolius_2.jpg", + "localImageUri": "/plants/cyperus-alternifolius--paragraphenpflanze--986a54bf.webp", + "status": "existing" + }, + { + "id": "plant_13543a8abb8f50c8", + "botanicalName": "Passiflora caerulea", + "name": "Passionsblume", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Passiflora_caerulea_%282019-06-24%29_frontal-view.jpg/500px-Passiflora_caerulea_%282019-06-24%29_frontal-view.jpg", + "localImageUri": "/plants/passiflora-caerulea--passionsblume--b8effb5e.webp", + "status": "existing" + }, + { + "id": "plant_b9a0c1910297e2cb", + "botanicalName": "Senecio rowleyanus", + "name": "Perlenschnur-Pflanze", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/Senecio_rowleyanus_leaves.jpg/500px-Senecio_rowleyanus_leaves.jpg", + "localImageUri": "/plants/senecio-rowleyanus--perlenschnur-pflanze--803d2b22.webp", + "status": "existing" + }, + { + "id": "plant_ab8fc977bd930772", + "botanicalName": "Cereus peruvianus", + "name": "Peruanischer Fackelkaktus", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Cereus_repandus_in_Aruba_-_on_the_way_back_from_Altovista_chapel_%282896840490%29.jpg/500px-Cereus_repandus_in_Aruba_-_on_the_way_back_from_Altovista_chapel_%282896840490%29.jpg", + "localImageUri": "/plants/cereus-peruvianus--peruanischer-fackelkaktus--b087b5cf.webp", + "status": "existing" + }, + { + "id": "plant_f57319d9209a678f", + "botanicalName": "Petroselinum crispum", + "name": "Petersilie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Petroselinum.jpg/500px-Petroselinum.jpg", + "localImageUri": "/plants/petroselinum-crispum--petersilie--23a7cb86.webp", + "status": "existing" + }, + { + "id": "plant_d859b55b599f2742", + "botanicalName": "Petunia hybrida", + "name": "Petunie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/PetuniaFlower.JPG/500px-PetuniaFlower.JPG", + "localImageUri": "/plants/petunia-hybrida--petunie--af7deb4f.webp", + "status": "existing" + }, + { + "id": "plant_9f46ccdc5b9b10f3", + "botanicalName": "Syngonium podophyllum", + "name": "Pfeilblatt", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Zingiber_malaysianum.jpg/500px-Zingiber_malaysianum.jpg", + "localImageUri": "/plants/syngonium-podophyllum--pfeilblatt--ca7b7b9f.webp", + "status": "existing" + }, + { + "id": "plant_c7b763cec4d30529", + "botanicalName": "Beaucarnea recurvata", + "name": "Pferdeschwanzpalme", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7e/Beaucarnea_recurvata%2C_Ocampo%2C_Tamaulipas%2C_Mexico_1.jpg/500px-Beaucarnea_recurvata%2C_Ocampo%2C_Tamaulipas%2C_Mexico_1.jpg", + "localImageUri": "/plants/beaucarnea-recurvata--pferdeschwanzpalme--31691c81.webp", + "status": "existing" + }, + { + "id": "plant_0c3f812b6186ea56", + "botanicalName": "Paeonia lactiflora", + "name": "Pfingstrose", + "sourceUri": "wikimedia-search:Paeonia%20lactiflora", + "localImageUri": "/plants/paeonia-lactiflora--pfingstrose--c81e92ef.webp", + "status": "existing" + }, + { + "id": "plant_418e4442c57e9974", + "botanicalName": "Philodendron bipinnatifidum", + "name": "Philodendron bipinnatifidum", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Tree1.JPG/500px-Tree1.JPG", + "localImageUri": "/plants/philodendron-bipinnatifidum--f7a662b8.webp", + "status": "existing" + }, + { + "id": "plant_d1c45583a39e702e", + "botanicalName": "Philodendron hederaceum Brasil", + "name": "Philodendron Brasil", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/0/0b/Philodendron_hederaceum_hederaceum_Brasil_0zz.jpg", + "localImageUri": "/plants/philodendron-hederaceum-brasil--philodendron-brasil--993a964b.webp", + "status": "existing" + }, + { + "id": "plant_64223543ba5ff673", + "botanicalName": "Philodendron gloriosum", + "name": "Philodendron gloriosum", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Philodendron_gloriosum_%2829587099650%29.jpg/500px-Philodendron_gloriosum_%2829587099650%29.jpg", + "localImageUri": "/plants/philodendron-gloriosum--059733a1.webp", + "status": "existing" + }, + { + "id": "plant_deca5dabffc8f210", + "botanicalName": "Philodendron erubescens Pink Princess", + "name": "Philodendron Pink Princess", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/8/89/Philodendron_Pink_Princess.jpg", + "localImageUri": "/plants/philodendron-erubescens-pink-princess--philodendron-pink-princess--b027e5d1.webp", + "status": "existing" + }, + { + "id": "plant_c5bbd24975a2d56e", + "botanicalName": "Thaumatophyllum xanadu", + "name": "Philodendron Xanadu", + "sourceUri": "wikimedia-search:Thaumatophyllum%20xanadu", + "localImageUri": "/plants/thaumatophyllum-xanadu--philodendron-xanadu--dda107bf.webp", + "status": "existing" + }, + { + "id": "plant_6a5d7ac021669bb4", + "botanicalName": "Primula vulgaris", + "name": "Primel", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/Prole%C4%87no_cve%C4%87e_3.JPG/500px-Prole%C4%87no_cve%C4%87e_3.JPG", + "localImageUri": "/plants/primula-vulgaris--primel--038312ee.webp", + "status": "existing" + }, + { + "id": "plant_dbd06a3bc479c493", + "botanicalName": "Ipomoea purpurea", + "name": "Prunkwinde", + "sourceUri": "wikimedia-search:Ipomoea%20purpurea", + "localImageUri": "/plants/ipomoea-purpurea--prunkwinde--a9c61099.webp", + "status": "existing" + }, + { + "id": "plant_b82556f9406de287", + "botanicalName": "Hypoestes phyllostachya", + "name": "Punktblatt", + "sourceUri": "wikimedia-search:Hypoestes%20phyllostachya", + "localImageUri": "/plants/hypoestes-phyllostachya--punktblatt--08034897.webp", + "status": "existing" + }, + { + "id": "plant_045dd35819e8793f", + "botanicalName": "Sarracenia purpurea", + "name": "Purpursonnentau", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7c/Sarracenia_purpurea_Flowers.JPG/500px-Sarracenia_purpurea_Flowers.JPG", + "localImageUri": "/plants/sarracenia-purpurea--purpursonnentau--38d9e604.webp", + "status": "existing" + }, + { + "id": "plant_1feebf3d053224a9", + "botanicalName": "Raphanus sativus", + "name": "Radieschen", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Radish_3371103037_4ab07db0bf_o.jpg/500px-Radish_3371103037_4ab07db0bf_o.jpg", + "localImageUri": "/plants/raphanus-sativus--radieschen--797f22e6.webp", + "status": "existing" + }, + { + "id": "plant_af46a07c444780ca", + "botanicalName": "Peperomia polybotrya", + "name": "Raindrop-Peperomie", + "sourceUri": "wikimedia-search:Peperomia%20polybotrya", + "localImageUri": "/plants/peperomia-polybotrya--raindrop-peperomie--12a71756.webp", + "status": "existing" + }, + { + "id": "plant_ab8cfe05f8183d2c", + "botanicalName": "Ranunculus asiaticus", + "name": "Ranunkel", + "sourceUri": "wikimedia-search:Ranunculus%20asiaticus", + "localImageUri": "/plants/ranunculus-asiaticus--ranunkel--accafde4.webp", + "status": "existing" + }, + { + "id": "plant_563226faba183e0d", + "botanicalName": "Selaginella uncinata", + "name": "Regenbogenmoos", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Selaginella_uncinata_-_Berlin_Botanical_Garden_-_IMG_8722.JPG/500px-Selaginella_uncinata_-_Berlin_Botanical_Garden_-_IMG_8722.JPG", + "localImageUri": "/plants/selaginella-uncinata--regenbogenmoos--fac3dec7.webp", + "status": "existing" + }, + { + "id": "plant_8fd28228f90cb02c", + "botanicalName": "Rhododendron catawbiense", + "name": "Rhododendron", + "sourceUri": "wikimedia-search:Rhododendron%20catawbiense", + "localImageUri": "/plants/rhododendron-catawbiense--rhododendron--b7977ab9.webp", + "status": "existing" + }, + { + "id": "plant_a6883747d701df71", + "botanicalName": "Clivia miniata", + "name": "Riemenblatt", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c2/Clivia_miniata%2C_blomme_en_vrugte%2C_Manie_van_der_Schijff_BT%2C_a.jpg/500px-Clivia_miniata%2C_blomme_en_vrugte%2C_Manie_van_der_Schijff_BT%2C_a.jpg", + "localImageUri": "/plants/clivia-miniata--riemenblatt--29bc76f5.webp", + "status": "existing" + }, + { + "id": "plant_c6e77cf5ecbf70cb", + "botanicalName": "Calendula officinalis", + "name": "Ringelblume", + "sourceUri": "wikimedia-search:Calendula%20officinalis", + "localImageUri": "/plants/calendula-officinalis--ringelblume--03f33ce8.webp", + "status": "existing" + }, + { + "id": "plant_5e0e0211b3e815d1", + "botanicalName": "Peperomia caperata", + "name": "Rippenpeperomie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Peperomia_caperata_1-OB9.jpg/500px-Peperomia_caperata_1-OB9.jpg", + "localImageUri": "/plants/peperomia-caperata--rippenpeperomie--b3a48151.webp", + "status": "existing" + }, + { + "id": "plant_47384e6f56f96010", + "botanicalName": "Delphinium elatum", + "name": "Rittersporn", + "sourceUri": "wikimedia-search:Delphinium%20elatum", + "localImageUri": "/plants/delphinium-elatum--rittersporn--d7df6211.webp", + "status": "existing" + }, + { + "id": "plant_f3c4aea00446ce7d", + "botanicalName": "Hippeastrum hybrid", + "name": "Ritterstern", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Hippeastrum_hybrid_1.jpg/500px-Hippeastrum_hybrid_1.jpg", + "localImageUri": "/plants/hippeastrum-hybrid--ritterstern--82bc6dc8.webp", + "status": "existing" + }, + { + "id": "plant_cdba57900c250b2a", + "botanicalName": "Robinia pseudoacacia", + "name": "Robinie", + "sourceUri": "wikimedia-search:Robinia%20pseudoacacia", + "localImageUri": "/plants/robinia-pseudoacacia--robinie--a3887565.webp", + "status": "existing" + }, + { + "id": "plant_354a445932988de3", + "botanicalName": "Chamaemelum nobile", + "name": "Roemische Kamille", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/f/f2/Chamaemelum_nobile_kz02.jpg", + "localImageUri": "/plants/chamaemelum-nobile--roemische-kamille--9235aca6.webp", + "status": "existing" + }, + { + "id": "plant_2b5acacfe6dbc6dd", + "botanicalName": "Rosa x hybrida", + "name": "Rose", + "sourceUri": "wikimedia-search:Rosa%20x%20hybrida", + "localImageUri": "/plants/rosa-x-hybrida--rose--7375780c.webp", + "status": "existing" + }, + { + "id": "plant_ce9ff96b95f4fe81", + "botanicalName": "Pelargonium graveolens", + "name": "Rosengeranie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/%28MHNT%29_Pelargonium_graveolens_flower_and_leaves.jpg/500px-%28MHNT%29_Pelargonium_graveolens_flower_and_leaves.jpg", + "localImageUri": "/plants/pelargonium-graveolens--rosengeranie--d7f8a481.webp", + "status": "existing" + }, + { + "id": "plant_bc06c3ee948f7ba7", + "botanicalName": "Rosmarinus officinalis", + "name": "Rosmarin", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a3/Rosemary_in_bloom.JPG/500px-Rosemary_in_bloom.JPG", + "localImageUri": "/plants/rosmarinus-officinalis--rosmarin--2791f58d.webp", + "status": "existing" + }, + { + "id": "plant_a50df676efef7b7d", + "botanicalName": "Digitalis purpurea", + "name": "Roter Fingerhut", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Digitalis_purpurea_LC0101.jpg/500px-Digitalis_purpurea_LC0101.jpg", + "localImageUri": "/plants/digitalis-purpurea--roter-fingerhut--be177092.webp", + "status": "existing" + }, + { + "id": "plant_4f9c3ae955d4b1b0", + "botanicalName": "Philodendron erubescens", + "name": "Roter Philodendron", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Philodendron_erubescens_-_Leaves.jpg/500px-Philodendron_erubescens_-_Leaves.jpg", + "localImageUri": "/plants/philodendron-erubescens--roter-philodendron--5d917978.webp", + "status": "existing" + }, + { + "id": "plant_0790565aca23f0a8", + "botanicalName": "Rudbeckia hirta", + "name": "Rudbeckie", + "sourceUri": "wikimedia-search:Rudbeckia%20hirta", + "localImageUri": "/plants/rudbeckia-hirta--rudbeckie--e1dd8170.webp", + "status": "existing" + }, + { + "id": "plant_b6887f02c51a178f", + "botanicalName": "Lactuca sativa", + "name": "Salat", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Iceberg_lettuce_in_SB.jpg/500px-Iceberg_lettuce_in_SB.jpg", + "localImageUri": "/plants/lactuca-sativa--salat--7cd31564.webp", + "status": "existing" + }, + { + "id": "plant_e3f7fa02342527b0", + "botanicalName": "Salvia officinalis", + "name": "Salbei", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Salvia_officinalis0.jpg/500px-Salvia_officinalis0.jpg", + "localImageUri": "/plants/salvia-officinalis--salbei--9fe3bf8f.webp", + "status": "existing" + }, + { + "id": "plant_8ab2cdddfd49ca3a", + "botanicalName": "Anthurium clarinervium", + "name": "Samt-Anthurie", + "sourceUri": "wikimedia-search:Anthurium%20clarinervium", + "localImageUri": "/plants/anthurium-clarinervium--samt-anthurie--dd38d7fa.webp", + "status": "existing" + }, + { + "id": "plant_5ce8d8944fd3edc3", + "botanicalName": "Echinopsis pachanoi", + "name": "San-Pedro-Kaktus", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Starr_070320-5799_Echinopsis_pachanoi.jpg/500px-Starr_070320-5799_Echinopsis_pachanoi.jpg", + "localImageUri": "/plants/echinopsis-pachanoi--san-pedro-kaktus--7f1085bc.webp", + "status": "existing" + }, + { + "id": "plant_d30b54367d7c0ccc", + "botanicalName": "Scindapsus pictus", + "name": "Satinpothos", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/ca/Scindapsus_pictus_01.jpg/500px-Scindapsus_pictus_01.jpg", + "localImageUri": "/plants/scindapsus-pictus--satinpothos--8991b0e9.webp", + "status": "existing" + }, + { + "id": "plant_5ed455617815911c", + "botanicalName": "Rumex acetosa", + "name": "Sauerampfer", + "sourceUri": "wikimedia-search:Rumex%20acetosa", + "localImageUri": "/plants/rumex-acetosa--sauerampfer--8078fc90.webp", + "status": "existing" + }, + { + "id": "plant_cbc9b35001d4f2fa", + "botanicalName": "Achillea millefolium", + "name": "Schafgarbe", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Achillea_millefolium_%28bright%29.jpg/500px-Achillea_millefolium_%28bright%29.jpg", + "localImageUri": "/plants/achillea-millefolium--schafgarbe--a945b3a0.webp", + "status": "existing" + }, + { + "id": "plant_ceea5c9d9b527cea", + "botanicalName": "Mimosa pudica", + "name": "Schamkraut", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Mimosa_pudica_in_September_month.jpg/500px-Mimosa_pudica_in_September_month.jpg", + "localImageUri": "/plants/mimosa-pudica--schamkraut--89ce823f.webp", + "status": "existing" + }, + { + "id": "plant_0bbd3af303fd64ab", + "botanicalName": "Buddleja davidii", + "name": "Schmetterlingsflieder", + "sourceUri": "wikimedia-search:Buddleja%20davidii", + "localImageUri": "/plants/buddleja-davidii--schmetterlingsflieder--c6785fa7.webp", + "status": "existing" + }, + { + "id": "plant_f02576d98e962040", + "botanicalName": "Phalaenopsis amabilis", + "name": "Schmetterlingsorchidee", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/59/Phalaenopsis_amabilis_Orchi_198.jpg/500px-Phalaenopsis_amabilis_Orchi_198.jpg", + "localImageUri": "/plants/phalaenopsis-amabilis--schmetterlingsorchidee--3c14cbf2.webp", + "status": "existing" + }, + { + "id": "plant_a346ee92e571923a", + "botanicalName": "Allium tuberosum", + "name": "Schnittknoblauch", + "sourceUri": "wikimedia-search:Allium%20tuberosum", + "localImageUri": "/plants/allium-tuberosum--schnittknoblauch--3904b032.webp", + "status": "existing" + }, + { + "id": "plant_1b8072d12aee4246", + "botanicalName": "Allium schoenoprasum", + "name": "Schnittlauch", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/49/Allium_schoenoprasum_-_Bombus_lapidarius_-_Tootsi.jpg/500px-Allium_schoenoprasum_-_Bombus_lapidarius_-_Tootsi.jpg", + "localImageUri": "/plants/allium-schoenoprasum--schnittlauch--d820fe95.webp", + "status": "existing" + }, + { + "id": "plant_2dcb1ec9ac8b968f", + "botanicalName": "Pandanus veitchii", + "name": "Schraubenbaum", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/Pandanus_tectorius.jpg/500px-Pandanus_tectorius.jpg", + "localImageUri": "/plants/pandanus-veitchii--schraubenbaum--36aa501d.webp", + "status": "existing" + }, + { + "id": "plant_40f7fbbd6ef0e3ba", + "botanicalName": "Aspidistra elatior", + "name": "Schusterpflanze", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Aspidistra_elatior1.jpg/500px-Aspidistra_elatior1.jpg", + "localImageUri": "/plants/aspidistra-elatior--schusterpflanze--27471002.webp", + "status": "existing" + }, + { + "id": "plant_fb7db49b3c127f71", + "botanicalName": "Aeonium arboreum", + "name": "Schwarze Rose (Aeonium)", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/28/Madeira%2C_Palheiro_Gardens_-_Aeonium_arboreum_%28Marokko%29_IMG_2310.JPG/500px-Madeira%2C_Palheiro_Gardens_-_Aeonium_arboreum_%28Marokko%29_IMG_2310.JPG", + "localImageUri": "/plants/aeonium-arboreum--schwarze-rose-aeonium--2fa8210f.webp", + "status": "existing" + }, + { + "id": "plant_183e544c5601be51", + "botanicalName": "Sambucus nigra", + "name": "Schwarzer Holunder", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/61/Sambucus_nigra_004.jpg/500px-Sambucus_nigra_004.jpg", + "localImageUri": "/plants/sambucus-nigra--schwarzer-holunder--fd1fe0a5.webp", + "status": "existing" + }, + { + "id": "plant_6f49714ec9e1191f", + "botanicalName": "Asclepias tuberosa", + "name": "Seidenpflanze", + "sourceUri": "wikimedia-search:Asclepias%20tuberosa", + "localImageUri": "/plants/asclepias-tuberosa--seidenpflanze--d082aa6e.webp", + "status": "existing" + }, + { + "id": "plant_269c939743f4674a", + "botanicalName": "Leucanthemum x superbum", + "name": "Shasta-Margerite", + "sourceUri": "wikimedia-search:Leucanthemum%20x%20superbum", + "localImageUri": "/plants/leucanthemum-x-superbum--shasta-margerite--519d56a9.webp", + "status": "existing" + }, + { + "id": "plant_a44a902f4af980ef", + "botanicalName": "Perilla frutescens", + "name": "Shiso", + "sourceUri": "wikimedia-search:Perilla%20frutescens", + "localImageUri": "/plants/perilla-frutescens--shiso--c065ca09.webp", + "status": "existing" + }, + { + "id": "plant_3c6961985d686c33", + "botanicalName": "Salix alba", + "name": "Silber-Weide", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Salix_alba_leaves.jpg/500px-Salix_alba_leaves.jpg", + "localImageUri": "/plants/salix-alba--silber-weide--407a5b47.webp", + "status": "existing" + }, + { + "id": "plant_4d4483c9e8f98e94", + "botanicalName": "Aechmea fasciata", + "name": "Silbervase", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/23/Aechmea_fasciata2.jpg/500px-Aechmea_fasciata2.jpg", + "localImageUri": "/plants/aechmea-fasciata--silbervase--04efba01.webp", + "status": "existing" + }, + { + "id": "plant_24c71b67fe2ed42a", + "botanicalName": "Adenium socotranum", + "name": "Socotra-Wuestenrose", + "sourceUri": "wikimedia-search:Adenium%20socotranum", + "localImageUri": "/plants/adenium-socotranum--socotra-wuestenrose--0118195c.webp", + "status": "existing" + }, + { + "id": "plant_d9407787d1cc720e", + "botanicalName": "Helianthus annuus", + "name": "Sonnenblume", + "sourceUri": "wikimedia-search:Helianthus%20annuus", + "localImageUri": "/plants/helianthus-annuus--sonnenblume--d26f9031.webp", + "status": "existing" + }, + { + "id": "plant_a91db7a3318f3302", + "botanicalName": "Echinacea purpurea", + "name": "Sonnenhut", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Echinacea_purpurea_Grandview_Prairie.jpg/500px-Echinacea_purpurea_Grandview_Prairie.jpg", + "localImageUri": "/plants/echinacea-purpurea--sonnenhut--cd110eab.webp", + "status": "existing" + }, + { + "id": "plant_0aa802b967afc69a", + "botanicalName": "Drosera capensis", + "name": "Sonnentau", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Drosera_capensis_bend.JPG/500px-Drosera_capensis_bend.JPG", + "localImageUri": "/plants/drosera-capensis--sonnentau--7122f48c.webp", + "status": "existing" + }, + { + "id": "plant_db7dd5c2bff6c42d", + "botanicalName": "Tillandsia usneoides", + "name": "Spanisches Moos", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/Spanish_moss_at_the_Mcbryde_Garden_in_hawaii.jpg/500px-Spanish_moss_at_the_Mcbryde_Garden_in_hawaii.jpg", + "localImageUri": "/plants/tillandsia-usneoides--spanisches-moos--80677975.webp", + "status": "existing" + }, + { + "id": "plant_ac11d9bd0c391e9d", + "botanicalName": "Portulacaria afra", + "name": "Speckbaum", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Portulacaria_afra_02.JPG/500px-Portulacaria_afra_02.JPG", + "localImageUri": "/plants/portulacaria-afra--speckbaum--b630ec3c.webp", + "status": "existing" + }, + { + "id": "plant_477dc83da2cd56cb", + "botanicalName": "Peperomia obtusifolia", + "name": "Spiegelpeperomie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Peperomia_obtusifolia_3-OB9.jpg/500px-Peperomia_obtusifolia_3-OB9.jpg", + "localImageUri": "/plants/peperomia-obtusifolia--spiegelpeperomie--fffbf481.webp", + "status": "existing" + }, + { + "id": "plant_4e6527efa4ab752f", + "botanicalName": "Spiraea japonica", + "name": "Spierstrauch", + "sourceUri": "wikimedia-search:Spiraea%20japonica", + "localImageUri": "/plants/spiraea-japonica--spierstrauch--2fce09a7.webp", + "status": "existing" + }, + { + "id": "plant_4f624a47f15a976c", + "botanicalName": "Spinacia oleracea", + "name": "Spinat", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Spinacia_oleracea_Spinazie_bloeiend.jpg/500px-Spinacia_oleracea_Spinazie_bloeiend.jpg", + "localImageUri": "/plants/spinacia-oleracea--spinat--67379554.webp", + "status": "existing" + }, + { + "id": "plant_3c3e9d84b343cb19", + "botanicalName": "Acer platanoides", + "name": "Spitzahorn", + "sourceUri": "wikimedia-search:Acer%20platanoides", + "localImageUri": "/plants/acer-platanoides--spitzahorn--dc2fbf6a.webp", + "status": "existing" + }, + { + "id": "plant_c3b438f135460578", + "botanicalName": "Rhapis excelsa", + "name": "Stab-Palme", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Arya_-_Rhapis_excelsa_at_hotel_citradream_Cirebon_2019_0.jpg/500px-Arya_-_Rhapis_excelsa_at_hotel_citradream_Cirebon_2019_0.jpg", + "localImageUri": "/plants/rhapis-excelsa--stab-palme--3f2eded0.webp", + "status": "existing" + }, + { + "id": "plant_ec4cfefb4784d583", + "botanicalName": "Ilex aquifolium", + "name": "Stechpalme", + "sourceUri": "wikimedia-search:Ilex%20aquifolium", + "localImageUri": "/plants/ilex-aquifolium--stechpalme--19cff9ae.webp", + "status": "existing" + }, + { + "id": "plant_0bff1afe77c852a9", + "botanicalName": "Pelargonium zonale", + "name": "Stehende Geranie", + "sourceUri": "wikimedia-search:Pelargonium%20zonale", + "localImageUri": "/plants/pelargonium-zonale--stehende-geranie--2854b148.webp", + "status": "existing" + }, + { + "id": "plant_dfd8a974072ccdde", + "botanicalName": "Stevia rebaudiana", + "name": "Stevia", + "sourceUri": "wikimedia-search:Stevia%20rebaudiana", + "localImageUri": "/plants/stevia-rebaudiana--stevia--423f53ff.webp", + "status": "existing" + }, + { + "id": "plant_e6998b94b6aa9483", + "botanicalName": "Viola wittrockiana", + "name": "Stiefmuetterchen", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b8/PansyScan_%28cropped%29.jpg/500px-PansyScan_%28cropped%29.jpg", + "localImageUri": "/plants/viola-wittrockiana--stiefmuetterchen--d2cb587c.webp", + "status": "existing" + }, + { + "id": "plant_4e7aa106c2e0dbed", + "botanicalName": "Miltoniopsis roezlii", + "name": "Stiefmuetterchen-Orchidee", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bd/Miltoniopsis_roezlii_%28as_Odontoglossum_roezlii%29_-_pl._30_-_Bateman%2C_Monogr.Odont.jpg/500px-Miltoniopsis_roezlii_%28as_Odontoglossum_roezlii%29_-_pl._30_-_Bateman%2C_Monogr.Odont.jpg", + "localImageUri": "/plants/miltoniopsis-roezlii--stiefmuetterchen-orchidee--87379182.webp", + "status": "existing" + }, + { + "id": "plant_b608fca2dcc684e2", + "botanicalName": "Alcea rosea", + "name": "Stockrose", + "sourceUri": "wikimedia-search:Alcea%20rosea", + "localImageUri": "/plants/alcea-rosea--stockrose--4b6ec327.webp", + "status": "existing" + }, + { + "id": "plant_67521f8578f80480", + "botanicalName": "Schefflera arboricola", + "name": "Strahlenaralie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Schefflera_arboricola%2C_vrugte%2C_a%2C_Pretoria.jpg/500px-Schefflera_arboricola%2C_vrugte%2C_a%2C_Pretoria.jpg", + "localImageUri": "/plants/schefflera-arboricola--strahlenaralie--b445fcbb.webp", + "status": "existing" + }, + { + "id": "plant_29784101db6f97ac", + "botanicalName": "Curio radicans", + "name": "String of Bananas", + "sourceUri": "wikimedia-search:Curio%20radicans", + "localImageUri": "/plants/curio-radicans--string-of-bananas--cee5c6f3.webp", + "status": "existing" + }, + { + "id": "plant_a765276379bdfc03", + "botanicalName": "Curio x peregrinus", + "name": "String of Dolphins", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/0/00/Dolphinplant.jpg", + "localImageUri": "/plants/curio-x-peregrinus--string-of-dolphins--167250ea.webp", + "status": "existing" + }, + { + "id": "plant_15d0205868b79470", + "botanicalName": "Stromanthe sanguinea", + "name": "Stromanthe", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/38/Stromanthe_sanguinea_in_garden_in_Manaus%2C_Brazil.jpg/500px-Stromanthe_sanguinea_in_garden_in_Manaus%2C_Brazil.jpg", + "localImageUri": "/plants/stromanthe-sanguinea--stromanthe--a9ffe5b3.webp", + "status": "existing" + }, + { + "id": "plant_9d6e62be0b1cb281", + "botanicalName": "Tagetes patula", + "name": "Studentenblume", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/French_marigold_Tagetes_patula.jpg/500px-French_marigold_Tagetes_patula.jpg", + "localImageUri": "/plants/tagetes-patula--studentenblume--0da7d656.webp", + "status": "existing" + }, + { + "id": "plant_4b198e1fefa08544", + "botanicalName": "Ipomoea batatas", + "name": "Suesskartoffel", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Ipomoea_batatas_006.JPG/500px-Ipomoea_batatas_006.JPG", + "localImageUri": "/plants/ipomoea-batatas--suesskartoffel--09695c9f.webp", + "status": "existing" + }, + { + "id": "plant_592490afaac6a7aa", + "botanicalName": "Hemerocallis fulva", + "name": "Taglilie", + "sourceUri": "wikimedia-search:Hemerocallis%20fulva", + "localImageUri": "/plants/hemerocallis-fulva--taglilie--de9c4c6c.webp", + "status": "existing" + }, + { + "id": "plant_876974955b59c59e", + "botanicalName": "Oncidium sphacelatum", + "name": "Tanzerinnen-Orchidee", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Oncidium_sphacelatum03.jpg/500px-Oncidium_sphacelatum03.jpg", + "localImageUri": "/plants/oncidium-sphacelatum--tanzerinnen-orchidee--79ae7545.webp", + "status": "existing" + }, + { + "id": "plant_2ee0814c52ec43e5", + "botanicalName": "Colocasia esculenta", + "name": "Taro", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/30/Songe-R%C3%A9union.JPG/500px-Songe-R%C3%A9union.JPG", + "localImageUri": "/plants/colocasia-esculenta--taro--d23c3d35.webp", + "status": "existing" + }, + { + "id": "plant_8860c603977b7048", + "botanicalName": "Camellia sinensis", + "name": "Teestrauch", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/Csinensis.jpg/500px-Csinensis.jpg", + "localImageUri": "/plants/camellia-sinensis--teestrauch--2c1d14da.webp", + "status": "existing" + }, + { + "id": "plant_716160bf88dd9d13", + "botanicalName": "Plumeria rubra", + "name": "Tempel-Baum", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/Champa_tree_with_pink_flowers_in_Islamabad%2C_Pakistan.jpg/500px-Champa_tree_with_pink_flowers_in_Islamabad%2C_Pakistan.jpg", + "localImageUri": "/plants/plumeria-rubra--tempel-baum--657d110b.webp", + "status": "existing" + }, + { + "id": "plant_9b35df06e64f0898", + "botanicalName": "Thymus vulgaris", + "name": "Thymian", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4f/Thymus_vulgaris1.JPG/500px-Thymus_vulgaris1.JPG", + "localImageUri": "/plants/thymus-vulgaris--thymian--64a6471c.webp", + "status": "existing" + }, + { + "id": "plant_4318ad8d02f7a1e3", + "botanicalName": "Cordyline fruticosa", + "name": "Tiroler Keulenlilie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Cordyline_fruticosa_%2820262433874%29.jpg/500px-Cordyline_fruticosa_%2820262433874%29.jpg", + "localImageUri": "/plants/cordyline-fruticosa--tiroler-keulenlilie--4a44ec99.webp", + "status": "existing" + }, + { + "id": "plant_6209cff29d20de9d", + "botanicalName": "Solanum lycopersicum", + "name": "Tomate", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/89/Tomato_je.jpg/500px-Tomato_je.jpg", + "localImageUri": "/plants/solanum-lycopersicum--tomate--e68be402.webp", + "status": "existing" + }, + { + "id": "plant_ca4a549c5f190565", + "botanicalName": "Lamprocapnos spectabilis", + "name": "Traenendes Herz", + "sourceUri": "wikimedia-search:Lamprocapnos%20spectabilis", + "localImageUri": "/plants/lamprocapnos-spectabilis--traenendes-herz--ab9054da.webp", + "status": "existing" + }, + { + "id": "plant_5b5d63d3d16734c3", + "botanicalName": "Muscari armeniacum", + "name": "Traubenhyazinthe", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Muscari_armeniacum_4.jpg/500px-Muscari_armeniacum_4.jpg", + "localImageUri": "/plants/muscari-armeniacum--traubenhyazinthe--bc818bf4.webp", + "status": "existing" + }, + { + "id": "plant_79692a800f05a5e6", + "botanicalName": "Fuchsia triphylla", + "name": "Triphylla-Fuchsie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Fuchsia_triphylla_kz01.jpg/500px-Fuchsia_triphylla_kz01.jpg", + "localImageUri": "/plants/fuchsia-triphylla--triphylla-fuchsie--822e8e3b.webp", + "status": "existing" + }, + { + "id": "plant_31af49a80e8b525f", + "botanicalName": "Catalpa bignonioides", + "name": "Trompetenbaum", + "sourceUri": "wikimedia-search:Catalpa%20bignonioides", + "localImageUri": "/plants/catalpa-bignonioides--trompetenbaum--b3b0e8b4.webp", + "status": "existing" + }, + { + "id": "plant_b62179d49d13e958", + "botanicalName": "Campsis radicans", + "name": "Trompetenwinde", + "sourceUri": "wikimedia-search:Campsis%20radicans", + "localImageUri": "/plants/campsis-radicans--trompetenwinde--7ed75a41.webp", + "status": "existing" + }, + { + "id": "plant_6ad4ada285b323dd", + "botanicalName": "Polypodium vulgare", + "name": "Tueipelfarn", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/T%C3%BCpfelfarn_%28Polypodium_vulgare%29.jpg/500px-T%C3%BCpfelfarn_%28Polypodium_vulgare%29.jpg", + "localImageUri": "/plants/polypodium-vulgare--tueipelfarn--2e4f5046.webp", + "status": "existing" + }, + { + "id": "plant_f03bc24e17022dd9", + "botanicalName": "Microsorum punctatum", + "name": "Tueipelfarn (Microsorum)", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9f/Microsorum_punctatum.jpg/500px-Microsorum_punctatum.jpg", + "localImageUri": "/plants/microsorum-punctatum--tueipelfarn-microsorum--77fa4bea.webp", + "status": "existing" + }, + { + "id": "plant_a90c8b9c4cddc806", + "botanicalName": "Tulipa gesneriana", + "name": "Tulpe", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/%D7%A6%D7%91%D7%A2%D7%95%D7%A0%D7%99%D7%9D.JPG/500px-%D7%A6%D7%91%D7%A2%D7%95%D7%A0%D7%99%D7%9D.JPG", + "localImageUri": "/plants/tulipa-gesneriana--tulpe--373bf645.webp", + "status": "existing" + }, + { + "id": "plant_ea198ff58c8805c6", + "botanicalName": "Pilea peperomioides", + "name": "Ufopflanze", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Pilea_peperomioides_Chinese_money_plant.jpg/500px-Pilea_peperomioides_Chinese_money_plant.jpg", + "localImageUri": "/plants/pilea-peperomioides--ufopflanze--6b60c68b.webp", + "status": "existing" + }, + { + "id": "plant_40fc59a7783f4dbd", + "botanicalName": "Vanda coerulea", + "name": "Vanda-Orchidee", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b3/An_orchid_%28Vanda_caerulea%29%3B_flowering_stem._Watercolour._Wellcome_V0043303.jpg/500px-An_orchid_%28Vanda_caerulea%29%3B_flowering_stem._Watercolour._Wellcome_V0043303.jpg", + "localImageUri": "/plants/vanda-coerulea--vanda-orchidee--d3b6fab1.webp", + "status": "existing" + }, + { + "id": "plant_ec96801b21f4b888", + "botanicalName": "Vanilla planifolia", + "name": "Vanille", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Vanilla_planifolia_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-278.jpg/500px-Vanilla_planifolia_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-278.jpg", + "localImageUri": "/plants/vanilla-planifolia--vanille--39790d8a.webp", + "status": "existing" + }, + { + "id": "plant_e0c02d30e9553083", + "botanicalName": "Dionaea muscipula", + "name": "Venusfliegenfalle", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Venus_Flytrap_showing_trigger_hairs.jpg/500px-Venus_Flytrap_showing_trigger_hairs.jpg", + "localImageUri": "/plants/dionaea-muscipula--venusfliegenfalle--fbcebf61.webp", + "status": "existing" + }, + { + "id": "plant_78ed61e5bca062af", + "botanicalName": "Myosotis sylvatica", + "name": "Vergissmeinnicht", + "sourceUri": "wikimedia-search:Myosotis%20sylvatica", + "localImageUri": "/plants/myosotis-sylvatica--vergissmeinnicht--0d817fb7.webp", + "status": "existing" + }, + { + "id": "plant_621534b573f3fbd1", + "botanicalName": "Asplenium nidus", + "name": "Vogelnest-Farn", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Asplenium_nidus_%28Bukidnon%2C_Philippines%29_02.jpg/500px-Asplenium_nidus_%28Bukidnon%2C_Philippines%29_02.jpg", + "localImageUri": "/plants/asplenium-nidus--vogelnest-farn--c9fbbb3c.webp", + "status": "existing" + }, + { + "id": "plant_b109c47be52f9ec8", + "botanicalName": "Hoya carnosa", + "name": "Wachsblume", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/NKN-2007-06-13_114250_Hoya_Carnosa_%28Yvan_Leduc_author_for_Wikipedia%29.jpg/500px-NKN-2007-06-13_114250_Hoya_Carnosa_%28Yvan_Leduc_author_for_Wikipedia%29.jpg", + "localImageUri": "/plants/hoya-carnosa--wachsblume--4da8fed5.webp", + "status": "existing" + }, + { + "id": "plant_632f108725deeafe", + "botanicalName": "Lantana camara", + "name": "Wandelroeschen", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/52/LantanaFlowerLeaves.jpg/500px-LantanaFlowerLeaves.jpg", + "localImageUri": "/plants/lantana-camara--wandelroeschen--b8fc5640.webp", + "status": "existing" + }, + { + "id": "plant_57f737231af6effa", + "botanicalName": "Eutrema japonicum", + "name": "Wasabi", + "sourceUri": "wikimedia-search:Eutrema%20japonicum", + "localImageUri": "/plants/eutrema-japonicum--wasabi--0ea8f701.webp", + "status": "existing" + }, + { + "id": "plant_75007016cfcc5200", + "botanicalName": "Peperomia argyreia", + "name": "Wassermelonen-Peperomie", + "sourceUri": "wikimedia-search:Peperomia%20argyreia", + "localImageUri": "/plants/peperomia-argyreia--wassermelonen-peperomie--1f013dee.webp", + "status": "existing" + }, + { + "id": "plant_c64390ca3c3743fe", + "botanicalName": "Utricularia gibba", + "name": "Wasserschlauch", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bd/Utricularia_gibba_flower_01.jpg/500px-Utricularia_gibba_flower_01.jpg", + "localImageUri": "/plants/utricularia-gibba--wasserschlauch--13643b06.webp", + "status": "existing" + }, + { + "id": "plant_bd3c4350600627fd", + "botanicalName": "Weigela florida", + "name": "Weigelie", + "sourceUri": "wikimedia-search:Weigela%20florida", + "localImageUri": "/plants/weigela-florida--weigelie--0bf98f7f.webp", + "status": "existing" + }, + { + "id": "plant_33f62ca8680da000", + "botanicalName": "Schlumbergera truncata", + "name": "Weihnachtskaktus", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f1/Schlumbergera_truncata_%28Exotic_Flora_Plate_20%29.jpg/500px-Schlumbergera_truncata_%28Exotic_Flora_Plate_20%29.jpg", + "localImageUri": "/plants/schlumbergera-truncata--weihnachtskaktus--c8f10c80.webp", + "status": "existing" + }, + { + "id": "plant_8218a6240dd4a406", + "botanicalName": "Euphorbia pulcherrima", + "name": "Weihnachtsstern", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Weihnachtsstern_-_gro%C3%9F.jpg/500px-Weihnachtsstern_-_gro%C3%9F.jpg", + "localImageUri": "/plants/euphorbia-pulcherrima--weihnachtsstern--ce82aeac.webp", + "status": "existing" + }, + { + "id": "plant_4275140824142c04", + "botanicalName": "Strelitzia nicolai", + "name": "Weisse Strelitzie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Strelitzia_nicolai_3.jpg/500px-Strelitzia_nicolai_3.jpg", + "localImageUri": "/plants/strelitzia-nicolai--weisse-strelitzie--30b92c65.webp", + "status": "existing" + }, + { + "id": "plant_0a06480067428b83", + "botanicalName": "Tradescantia fluminensis", + "name": "Weisse Tradescantia", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/Tradescantia_fluminensis_%28Flowers%29.jpg/500px-Tradescantia_fluminensis_%28Flowers%29.jpg", + "localImageUri": "/plants/tradescantia-fluminensis--weisse-tradescantia--ed8ecd20.webp", + "status": "existing" + }, + { + "id": "plant_316228d023b525c1", + "botanicalName": "Artemisia absinthium", + "name": "Wermut", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/eb/Artemisia_absinthium_P1210748.jpg/500px-Artemisia_absinthium_P1210748.jpg", + "localImageUri": "/plants/artemisia-absinthium--wermut--26709c63.webp", + "status": "existing" + }, + { + "id": "plant_77608bbef47bdc04", + "botanicalName": "Adenium obesum", + "name": "Wuestenrose", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4a/Adenium_Obesum_Flower_Side_Macro_Mar22_D72_23052-58_ZS_P.jpg/500px-Adenium_Obesum_Flower_Side_Macro_Mar22_D72_23052-58_ZS_P.jpg", + "localImageUri": "/plants/adenium-obesum--wuestenrose--18b1b800.webp", + "status": "existing" + }, + { + "id": "plant_31c096c7b1717c86", + "botanicalName": "Hyssopus officinalis", + "name": "Ysop", + "sourceUri": "wikimedia-search:Hyssopus%20officinalis", + "localImageUri": "/plants/hyssopus-officinalis--ysop--d3df148e.webp", + "status": "existing" + }, + { + "id": "plant_247330481dff3519", + "botanicalName": "Yucca aloifolia", + "name": "Yucca aloifolia", + "sourceUri": "wikimedia-search:Yucca%20aloifolia", + "localImageUri": "/plants/yucca-aloifolia--ce8ca7a3.webp", + "status": "existing" + }, + { + "id": "plant_a0e4e7fa68bbad41", + "botanicalName": "Yucca elephantipes", + "name": "Yucca-Palme", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bd/Yucca_gigantea_-_Jard%C3%ADn_Bot%C3%A1nico_Canario_Viera_y_Clavijo_-_Gran_Canaria.jpg/500px-Yucca_gigantea_-_Jard%C3%ADn_Bot%C3%A1nico_Canario_Viera_y_Clavijo_-_Gran_Canaria.jpg", + "localImageUri": "/plants/yucca-elephantipes--yucca-palme--1e34e66e.webp", + "status": "existing" + }, + { + "id": "plant_28107fe5558dfaa3", + "botanicalName": "Hamamelis mollis", + "name": "Zaubernuss", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/ce/Hamamelis_mollis0.jpg/500px-Hamamelis_mollis0.jpg", + "localImageUri": "/plants/hamamelis-mollis--zaubernuss--7ef3c16c.webp", + "status": "existing" + }, + { + "id": "plant_75abff461b3d9bf8", + "botanicalName": "Haworthia fasciata", + "name": "Zebra-Haworthie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/1_Haworthia_fasciata_-MBB_Kabeljouws_River.jpg/500px-1_Haworthia_fasciata_-MBB_Kabeljouws_River.jpg", + "localImageUri": "/plants/haworthia-fasciata--zebra-haworthie--e4e7e4db.webp", + "status": "existing" + }, + { + "id": "plant_f7d0af5f2c284fff", + "botanicalName": "Tradescantia zebrina", + "name": "Zebrakraut", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/Zebrina_pendula_20060521_2_closer.jpg/500px-Zebrina_pendula_20060521_2_closer.jpg", + "localImageUri": "/plants/tradescantia-zebrina--zebrakraut--1e9a096a.webp", + "status": "existing" + }, + { + "id": "plant_54030db3ff0bde0a", + "botanicalName": "Cedrus libani", + "name": "Zeder", + "sourceUri": "wikimedia-search:Cedrus%20libani", + "localImageUri": "/plants/cedrus-libani--zeder--6af4a3dd.webp", + "status": "existing" + }, + { + "id": "plant_998c8c4ed16286d8", + "botanicalName": "Nicotiana alata", + "name": "Ziertabak", + "sourceUri": "wikimedia-search:Nicotiana%20alata", + "localImageUri": "/plants/nicotiana-alata--ziertabak--e83c441c.webp", + "status": "existing" + }, + { + "id": "plant_ec8a05c334d66976", + "botanicalName": "Zinnia elegans", + "name": "Zinnie", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Zinnienbl%C3%BCte_Zinnia_elegans_stack15_20190722-RM-7222254.jpg/500px-Zinnienbl%C3%BCte_Zinnia_elegans_stack15_20190722-RM-7222254.jpg", + "localImageUri": "/plants/zinnia-elegans--zinnie--6d666757.webp", + "status": "existing" + }, + { + "id": "plant_29250eba0cf2291f", + "botanicalName": "Citrus limon", + "name": "Zitronenbaum", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/P1030323.JPG/500px-P1030323.JPG", + "localImageUri": "/plants/citrus-limon--zitronenbaum--100d9901.webp", + "status": "existing" + }, + { + "id": "plant_3e605c281bb361cc", + "botanicalName": "Cymbopogon citratus", + "name": "Zitronengras", + "sourceUri": "wikimedia-search:Cymbopogon%20citratus", + "localImageUri": "/plants/cymbopogon-citratus--zitronengras--671a6414.webp", + "status": "existing" + }, + { + "id": "plant_8febd56fe7368d57", + "botanicalName": "Melissa officinalis", + "name": "Zitronenmelisse", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Lemon_balm_plant.jpg/500px-Lemon_balm_plant.jpg", + "localImageUri": "/plants/melissa-officinalis--zitronenmelisse--79ec1828.webp", + "status": "existing" + }, + { + "id": "plant_dc96f296e8d0e517", + "botanicalName": "Aloysia citrodora", + "name": "Zitronenverbene", + "sourceUri": "wikimedia-search:Aloysia%20citrodora", + "localImageUri": "/plants/aloysia-citrodora--zitronenverbene--92460709.webp", + "status": "existing" + }, + { + "id": "plant_3a3d31c9d818021b", + "botanicalName": "Phoenix roebelenii", + "name": "Zwergdattelpalme", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1d/Starr_070124-3839_Phoenix_roebelenii.jpg/500px-Starr_070124-3839_Phoenix_roebelenii.jpg", + "localImageUri": "/plants/phoenix-roebelenii--zwergdattelpalme--f83a8f6a.webp", + "status": "existing" + }, + { + "id": "plant_5c8f76b2c7d187f1", + "botanicalName": "Sansevieria cylindrica", + "name": "Zylindrischer Bogenhanf", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c8/Sansevieria_cylindrica_flowers_7.jpg/500px-Sansevieria_cylindrica_flowers_7.jpg", + "localImageUri": "/plants/sansevieria-cylindrica--zylindrischer-bogenhanf--5b3a59b5.webp", + "status": "existing" + }, + { + "id": "plant_7fe204e226887efa", + "botanicalName": "Cymbidium lowianum", + "name": "Zymbidium", + "sourceUri": "https://upload.wikimedia.org/wikipedia/commons/b/b7/Cymbidium_lowianum_-_Bot-DSCF1035.jpg", + "localImageUri": "/plants/cymbidium-lowianum--zymbidium--3ee7a3d5.webp", + "status": "existing" + }, + { + "id": "plant_d138e647d3e19b04", + "botanicalName": "Cupressus sempervirens", + "name": "Zypresse", + "sourceUri": "wikimedia-search:Cupressus%20sempervirens", + "localImageUri": "/plants/cupressus-sempervirens--zypresse--fece2137.webp", + "status": "existing" + } + ] +} \ No newline at end of file diff --git a/server/public/plants/maranta-leuconeura--gebet-pflanze--e50f6916.webp b/server/public/plants/maranta-leuconeura--gebet-pflanze--e50f6916.webp new file mode 100644 index 0000000..af95bbb Binary files /dev/null and b/server/public/plants/maranta-leuconeura--gebet-pflanze--e50f6916.webp differ diff --git a/server/public/plants/melissa-officinalis--zitronenmelisse--79ec1828.webp b/server/public/plants/melissa-officinalis--zitronenmelisse--79ec1828.webp new file mode 100644 index 0000000..97000f8 Binary files /dev/null and b/server/public/plants/melissa-officinalis--zitronenmelisse--79ec1828.webp differ diff --git a/server/public/plants/mentha-spicata--gruene-minze--7cb727ef.webp b/server/public/plants/mentha-spicata--gruene-minze--7cb727ef.webp new file mode 100644 index 0000000..db090ef Binary files /dev/null and b/server/public/plants/mentha-spicata--gruene-minze--7cb727ef.webp differ diff --git a/server/public/plants/microsorum-punctatum--tueipelfarn-microsorum--77fa4bea.webp b/server/public/plants/microsorum-punctatum--tueipelfarn-microsorum--77fa4bea.webp new file mode 100644 index 0000000..2f09536 Binary files /dev/null and b/server/public/plants/microsorum-punctatum--tueipelfarn-microsorum--77fa4bea.webp differ diff --git a/server/public/plants/miltoniopsis-roezlii--stiefmuetterchen-orchidee--87379182.webp b/server/public/plants/miltoniopsis-roezlii--stiefmuetterchen-orchidee--87379182.webp new file mode 100644 index 0000000..cfcfaea Binary files /dev/null and b/server/public/plants/miltoniopsis-roezlii--stiefmuetterchen-orchidee--87379182.webp differ diff --git a/server/public/plants/mimosa-pudica--schamkraut--89ce823f.webp b/server/public/plants/mimosa-pudica--schamkraut--89ce823f.webp new file mode 100644 index 0000000..8eeda19 Binary files /dev/null and b/server/public/plants/mimosa-pudica--schamkraut--89ce823f.webp differ diff --git a/server/public/plants/monarda-didyma--indianernessel--309858d1.webp b/server/public/plants/monarda-didyma--indianernessel--309858d1.webp new file mode 100644 index 0000000..0b14e26 Binary files /dev/null and b/server/public/plants/monarda-didyma--indianernessel--309858d1.webp differ diff --git a/server/public/plants/monstera-adansonii--911eb5ba.webp b/server/public/plants/monstera-adansonii--911eb5ba.webp new file mode 100644 index 0000000..887db25 Binary files /dev/null and b/server/public/plants/monstera-adansonii--911eb5ba.webp differ diff --git a/server/public/plants/monstera-deliciosa--monstera--17b8209e.webp b/server/public/plants/monstera-deliciosa--monstera--17b8209e.webp new file mode 100644 index 0000000..3b3b553 Binary files /dev/null and b/server/public/plants/monstera-deliciosa--monstera--17b8209e.webp differ diff --git a/server/public/plants/monstera-obliqua--8ab6f307.webp b/server/public/plants/monstera-obliqua--8ab6f307.webp new file mode 100644 index 0000000..8862cbb Binary files /dev/null and b/server/public/plants/monstera-obliqua--8ab6f307.webp differ diff --git a/server/public/plants/musa-acuminata--bananenpflanze--0a6a2ad8.webp b/server/public/plants/musa-acuminata--bananenpflanze--0a6a2ad8.webp new file mode 100644 index 0000000..993a5ac Binary files /dev/null and b/server/public/plants/musa-acuminata--bananenpflanze--0a6a2ad8.webp differ diff --git a/server/public/plants/muscari-armeniacum--traubenhyazinthe--bc818bf4.webp b/server/public/plants/muscari-armeniacum--traubenhyazinthe--bc818bf4.webp new file mode 100644 index 0000000..4e9e441 Binary files /dev/null and b/server/public/plants/muscari-armeniacum--traubenhyazinthe--bc818bf4.webp differ diff --git a/server/public/plants/myosotis-sylvatica--vergissmeinnicht--0d817fb7.webp b/server/public/plants/myosotis-sylvatica--vergissmeinnicht--0d817fb7.webp new file mode 100644 index 0000000..1f7e63e Binary files /dev/null and b/server/public/plants/myosotis-sylvatica--vergissmeinnicht--0d817fb7.webp differ diff --git a/server/public/plants/narcissus-pseudonarcissus--osterglocke--32e917c0.webp b/server/public/plants/narcissus-pseudonarcissus--osterglocke--32e917c0.webp new file mode 100644 index 0000000..1e78087 Binary files /dev/null and b/server/public/plants/narcissus-pseudonarcissus--osterglocke--32e917c0.webp differ diff --git a/server/public/plants/nemesia-strumosa--nemesie--90e80dd2.webp b/server/public/plants/nemesia-strumosa--nemesie--90e80dd2.webp new file mode 100644 index 0000000..04e9517 Binary files /dev/null and b/server/public/plants/nemesia-strumosa--nemesie--90e80dd2.webp differ diff --git a/server/public/plants/neoregelia-carolinae--neoregelia--454c3c96.webp b/server/public/plants/neoregelia-carolinae--neoregelia--454c3c96.webp new file mode 100644 index 0000000..e73400d Binary files /dev/null and b/server/public/plants/neoregelia-carolinae--neoregelia--454c3c96.webp differ diff --git a/server/public/plants/nepenthes-alata--kannenpflanze--30016442.webp b/server/public/plants/nepenthes-alata--kannenpflanze--30016442.webp new file mode 100644 index 0000000..04df059 Binary files /dev/null and b/server/public/plants/nepenthes-alata--kannenpflanze--30016442.webp differ diff --git a/server/public/plants/nepeta-cataria--katzenminze--7935cfe0.webp b/server/public/plants/nepeta-cataria--katzenminze--7935cfe0.webp new file mode 100644 index 0000000..acfeb3a Binary files /dev/null and b/server/public/plants/nepeta-cataria--katzenminze--7935cfe0.webp differ diff --git a/server/public/plants/nephrolepis-exaltata--schwertfarn--9049369c.webp b/server/public/plants/nephrolepis-exaltata--schwertfarn--9049369c.webp new file mode 100644 index 0000000..3ed468a Binary files /dev/null and b/server/public/plants/nephrolepis-exaltata--schwertfarn--9049369c.webp differ diff --git a/server/public/plants/nerium-oleander--oleander--87c4b966.webp b/server/public/plants/nerium-oleander--oleander--87c4b966.webp new file mode 100644 index 0000000..7b12d72 Binary files /dev/null and b/server/public/plants/nerium-oleander--oleander--87c4b966.webp differ diff --git a/server/public/plants/nicotiana-alata--ziertabak--e83c441c.webp b/server/public/plants/nicotiana-alata--ziertabak--e83c441c.webp new file mode 100644 index 0000000..50fda49 Binary files /dev/null and b/server/public/plants/nicotiana-alata--ziertabak--e83c441c.webp differ diff --git a/server/public/plants/ocimum-basilicum--basilikum--cdc33445.webp b/server/public/plants/ocimum-basilicum--basilikum--cdc33445.webp new file mode 100644 index 0000000..f0a4db7 Binary files /dev/null and b/server/public/plants/ocimum-basilicum--basilikum--cdc33445.webp differ diff --git a/server/public/plants/oncidium-sphacelatum--tanzerinnen-orchidee--79ae7545.webp b/server/public/plants/oncidium-sphacelatum--tanzerinnen-orchidee--79ae7545.webp new file mode 100644 index 0000000..c08b171 Binary files /dev/null and b/server/public/plants/oncidium-sphacelatum--tanzerinnen-orchidee--79ae7545.webp differ diff --git a/server/public/plants/opuntia-microdasys--hasenohren-kaktus--de2a7439.webp b/server/public/plants/opuntia-microdasys--hasenohren-kaktus--de2a7439.webp new file mode 100644 index 0000000..46cf7f9 Binary files /dev/null and b/server/public/plants/opuntia-microdasys--hasenohren-kaktus--de2a7439.webp differ diff --git a/server/public/plants/origanum-majorana--majoran--d0d23e9f.webp b/server/public/plants/origanum-majorana--majoran--d0d23e9f.webp new file mode 100644 index 0000000..cb6ec04 Binary files /dev/null and b/server/public/plants/origanum-majorana--majoran--d0d23e9f.webp differ diff --git a/server/public/plants/origanum-vulgare--oregano--33c6269c.webp b/server/public/plants/origanum-vulgare--oregano--33c6269c.webp new file mode 100644 index 0000000..0d4f00a Binary files /dev/null and b/server/public/plants/origanum-vulgare--oregano--33c6269c.webp differ diff --git a/server/public/plants/osteospermum-ecklonis--kapmargerite--7d0ac9d6.webp b/server/public/plants/osteospermum-ecklonis--kapmargerite--7d0ac9d6.webp new file mode 100644 index 0000000..6f519fb Binary files /dev/null and b/server/public/plants/osteospermum-ecklonis--kapmargerite--7d0ac9d6.webp differ diff --git a/server/public/plants/oxalis-triangularis--kleeblume--9080763b.webp b/server/public/plants/oxalis-triangularis--kleeblume--9080763b.webp new file mode 100644 index 0000000..fad4eed Binary files /dev/null and b/server/public/plants/oxalis-triangularis--kleeblume--9080763b.webp differ diff --git a/server/public/plants/pachira-aquatica--glueckskastanie--8e9a0935.webp b/server/public/plants/pachira-aquatica--glueckskastanie--8e9a0935.webp new file mode 100644 index 0000000..8d34d10 Binary files /dev/null and b/server/public/plants/pachira-aquatica--glueckskastanie--8e9a0935.webp differ diff --git a/server/public/plants/pachyphytum-oviferum--mondstein-pflanze--66cf2adc.webp b/server/public/plants/pachyphytum-oviferum--mondstein-pflanze--66cf2adc.webp new file mode 100644 index 0000000..cb9bac0 Binary files /dev/null and b/server/public/plants/pachyphytum-oviferum--mondstein-pflanze--66cf2adc.webp differ diff --git a/server/public/plants/paeonia-lactiflora--pfingstrose--c81e92ef.webp b/server/public/plants/paeonia-lactiflora--pfingstrose--c81e92ef.webp new file mode 100644 index 0000000..6a7f64e Binary files /dev/null and b/server/public/plants/paeonia-lactiflora--pfingstrose--c81e92ef.webp differ diff --git a/server/public/plants/pandanus-veitchii--schraubenbaum--36aa501d.webp b/server/public/plants/pandanus-veitchii--schraubenbaum--36aa501d.webp new file mode 100644 index 0000000..62d74cc Binary files /dev/null and b/server/public/plants/pandanus-veitchii--schraubenbaum--36aa501d.webp differ diff --git a/server/public/plants/papaver-rhoeas--mohn--32fb9e83.webp b/server/public/plants/papaver-rhoeas--mohn--32fb9e83.webp new file mode 100644 index 0000000..094cbd8 Binary files /dev/null and b/server/public/plants/papaver-rhoeas--mohn--32fb9e83.webp differ diff --git a/server/public/plants/passiflora-caerulea--passionsblume--b8effb5e.webp b/server/public/plants/passiflora-caerulea--passionsblume--b8effb5e.webp new file mode 100644 index 0000000..aba03d6 Binary files /dev/null and b/server/public/plants/passiflora-caerulea--passionsblume--b8effb5e.webp differ diff --git a/server/public/plants/pelargonium-graveolens--rosengeranie--d7f8a481.webp b/server/public/plants/pelargonium-graveolens--rosengeranie--d7f8a481.webp new file mode 100644 index 0000000..f64014e Binary files /dev/null and b/server/public/plants/pelargonium-graveolens--rosengeranie--d7f8a481.webp differ diff --git a/server/public/plants/pelargonium-peltatum--efeu-geranie--8cd609cc.webp b/server/public/plants/pelargonium-peltatum--efeu-geranie--8cd609cc.webp new file mode 100644 index 0000000..3b92f94 Binary files /dev/null and b/server/public/plants/pelargonium-peltatum--efeu-geranie--8cd609cc.webp differ diff --git a/server/public/plants/pelargonium-zonale--stehende-geranie--2854b148.webp b/server/public/plants/pelargonium-zonale--stehende-geranie--2854b148.webp new file mode 100644 index 0000000..84ad542 Binary files /dev/null and b/server/public/plants/pelargonium-zonale--stehende-geranie--2854b148.webp differ diff --git a/server/public/plants/peperomia-argyreia--wassermelonen-peperomie--1f013dee.webp b/server/public/plants/peperomia-argyreia--wassermelonen-peperomie--1f013dee.webp new file mode 100644 index 0000000..fca84bf Binary files /dev/null and b/server/public/plants/peperomia-argyreia--wassermelonen-peperomie--1f013dee.webp differ diff --git a/server/public/plants/peperomia-caperata--rippenpeperomie--b3a48151.webp b/server/public/plants/peperomia-caperata--rippenpeperomie--b3a48151.webp new file mode 100644 index 0000000..c21cec5 Binary files /dev/null and b/server/public/plants/peperomia-caperata--rippenpeperomie--b3a48151.webp differ diff --git a/server/public/plants/peperomia-obtusifolia--spiegelpeperomie--fffbf481.webp b/server/public/plants/peperomia-obtusifolia--spiegelpeperomie--fffbf481.webp new file mode 100644 index 0000000..4a1f7d6 Binary files /dev/null and b/server/public/plants/peperomia-obtusifolia--spiegelpeperomie--fffbf481.webp differ diff --git a/server/public/plants/peperomia-polybotrya--raindrop-peperomie--12a71756.webp b/server/public/plants/peperomia-polybotrya--raindrop-peperomie--12a71756.webp new file mode 100644 index 0000000..db637a9 Binary files /dev/null and b/server/public/plants/peperomia-polybotrya--raindrop-peperomie--12a71756.webp differ diff --git a/server/public/plants/perilla-frutescens--shiso--c065ca09.webp b/server/public/plants/perilla-frutescens--shiso--c065ca09.webp new file mode 100644 index 0000000..17092fe Binary files /dev/null and b/server/public/plants/perilla-frutescens--shiso--c065ca09.webp differ diff --git a/server/public/plants/petroselinum-crispum--petersilie--23a7cb86.webp b/server/public/plants/petroselinum-crispum--petersilie--23a7cb86.webp new file mode 100644 index 0000000..6076b20 Binary files /dev/null and b/server/public/plants/petroselinum-crispum--petersilie--23a7cb86.webp differ diff --git a/server/public/plants/petunia-hybrida--petunie--af7deb4f.webp b/server/public/plants/petunia-hybrida--petunie--af7deb4f.webp new file mode 100644 index 0000000..b923cb4 Binary files /dev/null and b/server/public/plants/petunia-hybrida--petunie--af7deb4f.webp differ diff --git a/server/public/plants/phalaenopsis-amabilis--schmetterlingsorchidee--3c14cbf2.webp b/server/public/plants/phalaenopsis-amabilis--schmetterlingsorchidee--3c14cbf2.webp new file mode 100644 index 0000000..6ddd9c2 Binary files /dev/null and b/server/public/plants/phalaenopsis-amabilis--schmetterlingsorchidee--3c14cbf2.webp differ diff --git a/server/public/plants/philodendron-bipinnatifidum--f7a662b8.webp b/server/public/plants/philodendron-bipinnatifidum--f7a662b8.webp new file mode 100644 index 0000000..818dfcd Binary files /dev/null and b/server/public/plants/philodendron-bipinnatifidum--f7a662b8.webp differ diff --git a/server/public/plants/philodendron-erubescens--roter-philodendron--5d917978.webp b/server/public/plants/philodendron-erubescens--roter-philodendron--5d917978.webp new file mode 100644 index 0000000..9a7d75f Binary files /dev/null and b/server/public/plants/philodendron-erubescens--roter-philodendron--5d917978.webp differ diff --git a/server/public/plants/philodendron-erubescens-pink-princess--philodendron-pink-princess--b027e5d1.webp b/server/public/plants/philodendron-erubescens-pink-princess--philodendron-pink-princess--b027e5d1.webp new file mode 100644 index 0000000..1bc9bb2 Binary files /dev/null and b/server/public/plants/philodendron-erubescens-pink-princess--philodendron-pink-princess--b027e5d1.webp differ diff --git a/server/public/plants/philodendron-gloriosum--059733a1.webp b/server/public/plants/philodendron-gloriosum--059733a1.webp new file mode 100644 index 0000000..ecc5ca0 Binary files /dev/null and b/server/public/plants/philodendron-gloriosum--059733a1.webp differ diff --git a/server/public/plants/philodendron-hederaceum--herzblatt-philodendron--54360959.webp b/server/public/plants/philodendron-hederaceum--herzblatt-philodendron--54360959.webp new file mode 100644 index 0000000..0d03aba Binary files /dev/null and b/server/public/plants/philodendron-hederaceum--herzblatt-philodendron--54360959.webp differ diff --git a/server/public/plants/philodendron-hederaceum-brasil--philodendron-brasil--993a964b.webp b/server/public/plants/philodendron-hederaceum-brasil--philodendron-brasil--993a964b.webp new file mode 100644 index 0000000..4e7f828 Binary files /dev/null and b/server/public/plants/philodendron-hederaceum-brasil--philodendron-brasil--993a964b.webp differ diff --git a/server/public/plants/phlebodium-aureum--blaues-kanaelfarn--a630296a.webp b/server/public/plants/phlebodium-aureum--blaues-kanaelfarn--a630296a.webp new file mode 100644 index 0000000..06a82b2 Binary files /dev/null and b/server/public/plants/phlebodium-aureum--blaues-kanaelfarn--a630296a.webp differ diff --git a/server/public/plants/phlox-paniculata--flammenblume--0bbdd41e.webp b/server/public/plants/phlox-paniculata--flammenblume--0bbdd41e.webp new file mode 100644 index 0000000..f1acdbf Binary files /dev/null and b/server/public/plants/phlox-paniculata--flammenblume--0bbdd41e.webp differ diff --git a/server/public/plants/phoenix-roebelenii--zwergdattelpalme--f83a8f6a.webp b/server/public/plants/phoenix-roebelenii--zwergdattelpalme--f83a8f6a.webp new file mode 100644 index 0000000..4175806 Binary files /dev/null and b/server/public/plants/phoenix-roebelenii--zwergdattelpalme--f83a8f6a.webp differ diff --git a/server/public/plants/phyllostachys-aurea--goldener-bambus--e05d0c9f.webp b/server/public/plants/phyllostachys-aurea--goldener-bambus--e05d0c9f.webp new file mode 100644 index 0000000..7a252e8 Binary files /dev/null and b/server/public/plants/phyllostachys-aurea--goldener-bambus--e05d0c9f.webp differ diff --git a/server/public/plants/picea-abies--fichte--400d9dc4.webp b/server/public/plants/picea-abies--fichte--400d9dc4.webp new file mode 100644 index 0000000..db483e1 Binary files /dev/null and b/server/public/plants/picea-abies--fichte--400d9dc4.webp differ diff --git a/server/public/plants/pilea-cadierei--aluminium-pflanze--3e1e1bd9.webp b/server/public/plants/pilea-cadierei--aluminium-pflanze--3e1e1bd9.webp new file mode 100644 index 0000000..71faa19 Binary files /dev/null and b/server/public/plants/pilea-cadierei--aluminium-pflanze--3e1e1bd9.webp differ diff --git a/server/public/plants/pilea-peperomioides--ufopflanze--6b60c68b.webp b/server/public/plants/pilea-peperomioides--ufopflanze--6b60c68b.webp new file mode 100644 index 0000000..4dc6b7a Binary files /dev/null and b/server/public/plants/pilea-peperomioides--ufopflanze--6b60c68b.webp differ diff --git a/server/public/plants/pinguicula-grandiflora--fettkraut--8ec9dead.webp b/server/public/plants/pinguicula-grandiflora--fettkraut--8ec9dead.webp new file mode 100644 index 0000000..31ceb34 Binary files /dev/null and b/server/public/plants/pinguicula-grandiflora--fettkraut--8ec9dead.webp differ diff --git a/server/public/plants/pinus-sylvestris--kiefer--6db5e3c6.webp b/server/public/plants/pinus-sylvestris--kiefer--6db5e3c6.webp new file mode 100644 index 0000000..9681179 Binary files /dev/null and b/server/public/plants/pinus-sylvestris--kiefer--6db5e3c6.webp differ diff --git a/server/public/plants/platycerium-bifurcatum--geweihfarn--991495f9.webp b/server/public/plants/platycerium-bifurcatum--geweihfarn--991495f9.webp new file mode 100644 index 0000000..f983ee2 Binary files /dev/null and b/server/public/plants/platycerium-bifurcatum--geweihfarn--991495f9.webp differ diff --git a/server/public/plants/plectranthus-scutellarioides--buntnessel--7e6c3a78.webp b/server/public/plants/plectranthus-scutellarioides--buntnessel--7e6c3a78.webp new file mode 100644 index 0000000..2bf1f62 Binary files /dev/null and b/server/public/plants/plectranthus-scutellarioides--buntnessel--7e6c3a78.webp differ diff --git a/server/public/plants/plumbago-auriculata--bleiwurz--a1ea78f5.webp b/server/public/plants/plumbago-auriculata--bleiwurz--a1ea78f5.webp new file mode 100644 index 0000000..4ead849 Binary files /dev/null and b/server/public/plants/plumbago-auriculata--bleiwurz--a1ea78f5.webp differ diff --git a/server/public/plants/plumeria-rubra--tempel-baum--657d110b.webp b/server/public/plants/plumeria-rubra--tempel-baum--657d110b.webp new file mode 100644 index 0000000..7b1fce0 Binary files /dev/null and b/server/public/plants/plumeria-rubra--tempel-baum--657d110b.webp differ diff --git a/server/public/plants/polypodium-vulgare--tueipelfarn--2e4f5046.webp b/server/public/plants/polypodium-vulgare--tueipelfarn--2e4f5046.webp new file mode 100644 index 0000000..a89dadb Binary files /dev/null and b/server/public/plants/polypodium-vulgare--tueipelfarn--2e4f5046.webp differ diff --git a/server/public/plants/portulacaria-afra--speckbaum--b630ec3c.webp b/server/public/plants/portulacaria-afra--speckbaum--b630ec3c.webp new file mode 100644 index 0000000..bf99652 Binary files /dev/null and b/server/public/plants/portulacaria-afra--speckbaum--b630ec3c.webp differ diff --git a/server/public/plants/primula-vulgaris--primel--038312ee.webp b/server/public/plants/primula-vulgaris--primel--038312ee.webp new file mode 100644 index 0000000..ea5a21c Binary files /dev/null and b/server/public/plants/primula-vulgaris--primel--038312ee.webp differ diff --git a/server/public/plants/protea-cynaroides--koenigs-protea--2186e16d.webp b/server/public/plants/protea-cynaroides--koenigs-protea--2186e16d.webp new file mode 100644 index 0000000..68b16ba Binary files /dev/null and b/server/public/plants/protea-cynaroides--koenigs-protea--2186e16d.webp differ diff --git a/server/public/plants/prunus-laurocerasus--kirschlorbeer--9291015b.webp b/server/public/plants/prunus-laurocerasus--kirschlorbeer--9291015b.webp new file mode 100644 index 0000000..640a8f1 Binary files /dev/null and b/server/public/plants/prunus-laurocerasus--kirschlorbeer--9291015b.webp differ diff --git a/server/public/plants/psidium-guajava--guave--5d507482.webp b/server/public/plants/psidium-guajava--guave--5d507482.webp new file mode 100644 index 0000000..49a67d6 Binary files /dev/null and b/server/public/plants/psidium-guajava--guave--5d507482.webp differ diff --git a/server/public/plants/punica-granatum--granatapfelbaum--facf4f0c.webp b/server/public/plants/punica-granatum--granatapfelbaum--facf4f0c.webp new file mode 100644 index 0000000..c51c01e Binary files /dev/null and b/server/public/plants/punica-granatum--granatapfelbaum--facf4f0c.webp differ diff --git a/server/public/plants/quercus-robur--eiche--ea94af29.webp b/server/public/plants/quercus-robur--eiche--ea94af29.webp new file mode 100644 index 0000000..38a2b88 Binary files /dev/null and b/server/public/plants/quercus-robur--eiche--ea94af29.webp differ diff --git a/server/public/plants/ranunculus-asiaticus--ranunkel--accafde4.webp b/server/public/plants/ranunculus-asiaticus--ranunkel--accafde4.webp new file mode 100644 index 0000000..cbcafb3 Binary files /dev/null and b/server/public/plants/ranunculus-asiaticus--ranunkel--accafde4.webp differ diff --git a/server/public/plants/raphanus-sativus--radieschen--797f22e6.webp b/server/public/plants/raphanus-sativus--radieschen--797f22e6.webp new file mode 100644 index 0000000..9b68ee5 Binary files /dev/null and b/server/public/plants/raphanus-sativus--radieschen--797f22e6.webp differ diff --git a/server/public/plants/rhaphidophora-tetrasperma--mini-monstera--8698ef03.webp b/server/public/plants/rhaphidophora-tetrasperma--mini-monstera--8698ef03.webp new file mode 100644 index 0000000..05ee872 Binary files /dev/null and b/server/public/plants/rhaphidophora-tetrasperma--mini-monstera--8698ef03.webp differ diff --git a/server/public/plants/rhapis-excelsa--stab-palme--3f2eded0.webp b/server/public/plants/rhapis-excelsa--stab-palme--3f2eded0.webp new file mode 100644 index 0000000..2c41247 Binary files /dev/null and b/server/public/plants/rhapis-excelsa--stab-palme--3f2eded0.webp differ diff --git a/server/public/plants/rhipsalis-baccifera--korallenkaktus--3097b146.webp b/server/public/plants/rhipsalis-baccifera--korallenkaktus--3097b146.webp new file mode 100644 index 0000000..af24b83 Binary files /dev/null and b/server/public/plants/rhipsalis-baccifera--korallenkaktus--3097b146.webp differ diff --git a/server/public/plants/rhododendron-catawbiense--rhododendron--b7977ab9.webp b/server/public/plants/rhododendron-catawbiense--rhododendron--b7977ab9.webp new file mode 100644 index 0000000..0562b4b Binary files /dev/null and b/server/public/plants/rhododendron-catawbiense--rhododendron--b7977ab9.webp differ diff --git a/server/public/plants/rhododendron-simsii--japanische-azalee--ef16f2c0.webp b/server/public/plants/rhododendron-simsii--japanische-azalee--ef16f2c0.webp new file mode 100644 index 0000000..4ca9dab Binary files /dev/null and b/server/public/plants/rhododendron-simsii--japanische-azalee--ef16f2c0.webp differ diff --git a/server/public/plants/robinia-pseudoacacia--robinie--a3887565.webp b/server/public/plants/robinia-pseudoacacia--robinie--a3887565.webp new file mode 100644 index 0000000..ce767ed Binary files /dev/null and b/server/public/plants/robinia-pseudoacacia--robinie--a3887565.webp differ diff --git a/server/public/plants/rosa-chinensis--chinesische-rose--2c0514b0.webp b/server/public/plants/rosa-chinensis--chinesische-rose--2c0514b0.webp new file mode 100644 index 0000000..d75f0d1 Binary files /dev/null and b/server/public/plants/rosa-chinensis--chinesische-rose--2c0514b0.webp differ diff --git a/server/public/plants/rosa-x-hybrida--rose--7375780c.webp b/server/public/plants/rosa-x-hybrida--rose--7375780c.webp new file mode 100644 index 0000000..9bc0826 Binary files /dev/null and b/server/public/plants/rosa-x-hybrida--rose--7375780c.webp differ diff --git a/server/public/plants/rosmarinus-officinalis--rosmarin--2791f58d.webp b/server/public/plants/rosmarinus-officinalis--rosmarin--2791f58d.webp new file mode 100644 index 0000000..9e07958 Binary files /dev/null and b/server/public/plants/rosmarinus-officinalis--rosmarin--2791f58d.webp differ diff --git a/server/public/plants/rudbeckia-hirta--rudbeckie--e1dd8170.webp b/server/public/plants/rudbeckia-hirta--rudbeckie--e1dd8170.webp new file mode 100644 index 0000000..ab72462 Binary files /dev/null and b/server/public/plants/rudbeckia-hirta--rudbeckie--e1dd8170.webp differ diff --git a/server/public/plants/rumex-acetosa--sauerampfer--8078fc90.webp b/server/public/plants/rumex-acetosa--sauerampfer--8078fc90.webp new file mode 100644 index 0000000..3549f80 Binary files /dev/null and b/server/public/plants/rumex-acetosa--sauerampfer--8078fc90.webp differ diff --git a/server/public/plants/saintpaulia-ionantha--afrikanisches-veilchen--bc75f4a8.webp b/server/public/plants/saintpaulia-ionantha--afrikanisches-veilchen--bc75f4a8.webp new file mode 100644 index 0000000..aeb0e3f Binary files /dev/null and b/server/public/plants/saintpaulia-ionantha--afrikanisches-veilchen--bc75f4a8.webp differ diff --git a/server/public/plants/salix-alba--silber-weide--407a5b47.webp b/server/public/plants/salix-alba--silber-weide--407a5b47.webp new file mode 100644 index 0000000..af76ec0 Binary files /dev/null and b/server/public/plants/salix-alba--silber-weide--407a5b47.webp differ diff --git a/server/public/plants/salvia-farinacea--mehlsalbei--a046f0ea.webp b/server/public/plants/salvia-farinacea--mehlsalbei--a046f0ea.webp new file mode 100644 index 0000000..218e1a9 Binary files /dev/null and b/server/public/plants/salvia-farinacea--mehlsalbei--a046f0ea.webp differ diff --git a/server/public/plants/salvia-officinalis--salbei--9fe3bf8f.webp b/server/public/plants/salvia-officinalis--salbei--9fe3bf8f.webp new file mode 100644 index 0000000..37bf3a1 Binary files /dev/null and b/server/public/plants/salvia-officinalis--salbei--9fe3bf8f.webp differ diff --git a/server/public/plants/salvia-splendens--feuersalbei--09913571.webp b/server/public/plants/salvia-splendens--feuersalbei--09913571.webp new file mode 100644 index 0000000..e9dd1eb Binary files /dev/null and b/server/public/plants/salvia-splendens--feuersalbei--09913571.webp differ diff --git a/server/public/plants/sambucus-nigra--schwarzer-holunder--fd1fe0a5.webp b/server/public/plants/sambucus-nigra--schwarzer-holunder--fd1fe0a5.webp new file mode 100644 index 0000000..5265926 Binary files /dev/null and b/server/public/plants/sambucus-nigra--schwarzer-holunder--fd1fe0a5.webp differ diff --git a/server/public/plants/sansevieria-cylindrica--zylindrischer-bogenhanf--5b3a59b5.webp b/server/public/plants/sansevieria-cylindrica--zylindrischer-bogenhanf--5b3a59b5.webp new file mode 100644 index 0000000..6523381 Binary files /dev/null and b/server/public/plants/sansevieria-cylindrica--zylindrischer-bogenhanf--5b3a59b5.webp differ diff --git a/server/public/plants/sansevieria-trifasciata--bogenhanf--4ba42e15.webp b/server/public/plants/sansevieria-trifasciata--bogenhanf--4ba42e15.webp new file mode 100644 index 0000000..f77a636 Binary files /dev/null and b/server/public/plants/sansevieria-trifasciata--bogenhanf--4ba42e15.webp differ diff --git a/server/public/plants/sarracenia-purpurea--purpursonnentau--38d9e604.webp b/server/public/plants/sarracenia-purpurea--purpursonnentau--38d9e604.webp new file mode 100644 index 0000000..0ebfe25 Binary files /dev/null and b/server/public/plants/sarracenia-purpurea--purpursonnentau--38d9e604.webp differ diff --git a/server/public/plants/satureja-hortensis--bohnenkraut--b5b822ab.webp b/server/public/plants/satureja-hortensis--bohnenkraut--b5b822ab.webp new file mode 100644 index 0000000..6b76f47 Binary files /dev/null and b/server/public/plants/satureja-hortensis--bohnenkraut--b5b822ab.webp differ diff --git a/server/public/plants/schefflera-actinophylla--grosse-strahlenaralie--a69cdd16.webp b/server/public/plants/schefflera-actinophylla--grosse-strahlenaralie--a69cdd16.webp new file mode 100644 index 0000000..f092b15 Binary files /dev/null and b/server/public/plants/schefflera-actinophylla--grosse-strahlenaralie--a69cdd16.webp differ diff --git a/server/public/plants/schefflera-arboricola--strahlenaralie--b445fcbb.webp b/server/public/plants/schefflera-arboricola--strahlenaralie--b445fcbb.webp new file mode 100644 index 0000000..551b85f Binary files /dev/null and b/server/public/plants/schefflera-arboricola--strahlenaralie--b445fcbb.webp differ diff --git a/server/public/plants/schefflera-elegantissima--falsche-aralie--ff7f753e.webp b/server/public/plants/schefflera-elegantissima--falsche-aralie--ff7f753e.webp new file mode 100644 index 0000000..d51f638 Binary files /dev/null and b/server/public/plants/schefflera-elegantissima--falsche-aralie--ff7f753e.webp differ diff --git a/server/public/plants/schlumbergera-truncata--weihnachtskaktus--c8f10c80.webp b/server/public/plants/schlumbergera-truncata--weihnachtskaktus--c8f10c80.webp new file mode 100644 index 0000000..22f230c Binary files /dev/null and b/server/public/plants/schlumbergera-truncata--weihnachtskaktus--c8f10c80.webp differ diff --git a/server/public/plants/scindapsus-pictus--satinpothos--8991b0e9.webp b/server/public/plants/scindapsus-pictus--satinpothos--8991b0e9.webp new file mode 100644 index 0000000..cfdd8c8 Binary files /dev/null and b/server/public/plants/scindapsus-pictus--satinpothos--8991b0e9.webp differ diff --git a/server/public/plants/sedum-morganianum--eselschwanz--f6256abc.webp b/server/public/plants/sedum-morganianum--eselschwanz--f6256abc.webp new file mode 100644 index 0000000..640136a Binary files /dev/null and b/server/public/plants/sedum-morganianum--eselschwanz--f6256abc.webp differ diff --git a/server/public/plants/selaginella-uncinata--regenbogenmoos--fac3dec7.webp b/server/public/plants/selaginella-uncinata--regenbogenmoos--fac3dec7.webp new file mode 100644 index 0000000..86fdb47 Binary files /dev/null and b/server/public/plants/selaginella-uncinata--regenbogenmoos--fac3dec7.webp differ diff --git a/server/public/plants/senecio-rowleyanus--perlenschnur-pflanze--803d2b22.webp b/server/public/plants/senecio-rowleyanus--perlenschnur-pflanze--803d2b22.webp new file mode 100644 index 0000000..12b11b8 Binary files /dev/null and b/server/public/plants/senecio-rowleyanus--perlenschnur-pflanze--803d2b22.webp differ diff --git a/server/public/plants/senecio-serpens--blauer-kreuzkraut--4ec1f347.webp b/server/public/plants/senecio-serpens--blauer-kreuzkraut--4ec1f347.webp new file mode 100644 index 0000000..482efff Binary files /dev/null and b/server/public/plants/senecio-serpens--blauer-kreuzkraut--4ec1f347.webp differ diff --git a/server/public/plants/solanum-lycopersicum--tomate--e68be402.webp b/server/public/plants/solanum-lycopersicum--tomate--e68be402.webp new file mode 100644 index 0000000..7175baf Binary files /dev/null and b/server/public/plants/solanum-lycopersicum--tomate--e68be402.webp differ diff --git a/server/public/plants/solanum-melongena--aubergine--5f3bad2f.webp b/server/public/plants/solanum-melongena--aubergine--5f3bad2f.webp new file mode 100644 index 0000000..bfe2638 Binary files /dev/null and b/server/public/plants/solanum-melongena--aubergine--5f3bad2f.webp differ diff --git a/server/public/plants/soleirolia-soleirolii--bubikopf--b1b13e0f.webp b/server/public/plants/soleirolia-soleirolii--bubikopf--b1b13e0f.webp new file mode 100644 index 0000000..0a25137 Binary files /dev/null and b/server/public/plants/soleirolia-soleirolii--bubikopf--b1b13e0f.webp differ diff --git a/server/public/plants/sorbus-aucuparia--eberesche--8ebfe649.webp b/server/public/plants/sorbus-aucuparia--eberesche--8ebfe649.webp new file mode 100644 index 0000000..a8866fd Binary files /dev/null and b/server/public/plants/sorbus-aucuparia--eberesche--8ebfe649.webp differ diff --git a/server/public/plants/spathiphyllum-wallisii--einblatt--6ff28539.webp b/server/public/plants/spathiphyllum-wallisii--einblatt--6ff28539.webp new file mode 100644 index 0000000..fd4754a Binary files /dev/null and b/server/public/plants/spathiphyllum-wallisii--einblatt--6ff28539.webp differ diff --git a/server/public/plants/spinacia-oleracea--spinat--67379554.webp b/server/public/plants/spinacia-oleracea--spinat--67379554.webp new file mode 100644 index 0000000..3c17a66 Binary files /dev/null and b/server/public/plants/spinacia-oleracea--spinat--67379554.webp differ diff --git a/server/public/plants/spiraea-japonica--spierstrauch--2fce09a7.webp b/server/public/plants/spiraea-japonica--spierstrauch--2fce09a7.webp new file mode 100644 index 0000000..d51d98a Binary files /dev/null and b/server/public/plants/spiraea-japonica--spierstrauch--2fce09a7.webp differ diff --git a/server/public/plants/stapelia-grandiflora--aasblume--b87af483.webp b/server/public/plants/stapelia-grandiflora--aasblume--b87af483.webp new file mode 100644 index 0000000..3ead0f3 Binary files /dev/null and b/server/public/plants/stapelia-grandiflora--aasblume--b87af483.webp differ diff --git a/server/public/plants/stephanotis-floribunda--madagaskar-jasmin--f5b3e914.webp b/server/public/plants/stephanotis-floribunda--madagaskar-jasmin--f5b3e914.webp new file mode 100644 index 0000000..5a2b72f Binary files /dev/null and b/server/public/plants/stephanotis-floribunda--madagaskar-jasmin--f5b3e914.webp differ diff --git a/server/public/plants/stevia-rebaudiana--stevia--423f53ff.webp b/server/public/plants/stevia-rebaudiana--stevia--423f53ff.webp new file mode 100644 index 0000000..980c955 Binary files /dev/null and b/server/public/plants/stevia-rebaudiana--stevia--423f53ff.webp differ diff --git a/server/public/plants/strelitzia-nicolai--weisse-strelitzie--30b92c65.webp b/server/public/plants/strelitzia-nicolai--weisse-strelitzie--30b92c65.webp new file mode 100644 index 0000000..2b75386 Binary files /dev/null and b/server/public/plants/strelitzia-nicolai--weisse-strelitzie--30b92c65.webp differ diff --git a/server/public/plants/strelitzia-reginae--paradiesvogelblume--3ee1f013.webp b/server/public/plants/strelitzia-reginae--paradiesvogelblume--3ee1f013.webp new file mode 100644 index 0000000..11cc917 Binary files /dev/null and b/server/public/plants/strelitzia-reginae--paradiesvogelblume--3ee1f013.webp differ diff --git a/server/public/plants/streptocarpus-hybridus--drehfrucht--d30e3476.webp b/server/public/plants/streptocarpus-hybridus--drehfrucht--d30e3476.webp new file mode 100644 index 0000000..2f8b7b8 Binary files /dev/null and b/server/public/plants/streptocarpus-hybridus--drehfrucht--d30e3476.webp differ diff --git a/server/public/plants/stromanthe-sanguinea--stromanthe--a9ffe5b3.webp b/server/public/plants/stromanthe-sanguinea--stromanthe--a9ffe5b3.webp new file mode 100644 index 0000000..e1c3a9a Binary files /dev/null and b/server/public/plants/stromanthe-sanguinea--stromanthe--a9ffe5b3.webp differ diff --git a/server/public/plants/symphyotrichum-novi-belgii--herbstaster--615b51bf.webp b/server/public/plants/symphyotrichum-novi-belgii--herbstaster--615b51bf.webp new file mode 100644 index 0000000..57f0d7c Binary files /dev/null and b/server/public/plants/symphyotrichum-novi-belgii--herbstaster--615b51bf.webp differ diff --git a/server/public/plants/syngonium-podophyllum--pfeilblatt--ca7b7b9f.webp b/server/public/plants/syngonium-podophyllum--pfeilblatt--ca7b7b9f.webp new file mode 100644 index 0000000..1de7d88 Binary files /dev/null and b/server/public/plants/syngonium-podophyllum--pfeilblatt--ca7b7b9f.webp differ diff --git a/server/public/plants/syringa-vulgaris--flieder--7e22429d.webp b/server/public/plants/syringa-vulgaris--flieder--7e22429d.webp new file mode 100644 index 0000000..6c81bfa Binary files /dev/null and b/server/public/plants/syringa-vulgaris--flieder--7e22429d.webp differ diff --git a/server/public/plants/tagetes-patula--studentenblume--0da7d656.webp b/server/public/plants/tagetes-patula--studentenblume--0da7d656.webp new file mode 100644 index 0000000..5d730b8 Binary files /dev/null and b/server/public/plants/tagetes-patula--studentenblume--0da7d656.webp differ diff --git a/server/public/plants/thaumatophyllum-xanadu--philodendron-xanadu--dda107bf.webp b/server/public/plants/thaumatophyllum-xanadu--philodendron-xanadu--dda107bf.webp new file mode 100644 index 0000000..fb6b4d9 Binary files /dev/null and b/server/public/plants/thaumatophyllum-xanadu--philodendron-xanadu--dda107bf.webp differ diff --git a/server/public/plants/thymus-vulgaris--thymian--64a6471c.webp b/server/public/plants/thymus-vulgaris--thymian--64a6471c.webp new file mode 100644 index 0000000..a0a883b Binary files /dev/null and b/server/public/plants/thymus-vulgaris--thymian--64a6471c.webp differ diff --git a/server/public/plants/tillandsia-ionantha--luftpflanze--c221d48d.webp b/server/public/plants/tillandsia-ionantha--luftpflanze--c221d48d.webp new file mode 100644 index 0000000..f31affe Binary files /dev/null and b/server/public/plants/tillandsia-ionantha--luftpflanze--c221d48d.webp differ diff --git a/server/public/plants/tillandsia-usneoides--spanisches-moos--80677975.webp b/server/public/plants/tillandsia-usneoides--spanisches-moos--80677975.webp new file mode 100644 index 0000000..6f8e1c4 Binary files /dev/null and b/server/public/plants/tillandsia-usneoides--spanisches-moos--80677975.webp differ diff --git a/server/public/plants/tradescantia-fluminensis--weisse-tradescantia--ed8ecd20.webp b/server/public/plants/tradescantia-fluminensis--weisse-tradescantia--ed8ecd20.webp new file mode 100644 index 0000000..16099c5 Binary files /dev/null and b/server/public/plants/tradescantia-fluminensis--weisse-tradescantia--ed8ecd20.webp differ diff --git a/server/public/plants/tradescantia-pallida--lila-tradescantia--fa444b81.webp b/server/public/plants/tradescantia-pallida--lila-tradescantia--fa444b81.webp new file mode 100644 index 0000000..21770e6 Binary files /dev/null and b/server/public/plants/tradescantia-pallida--lila-tradescantia--fa444b81.webp differ diff --git a/server/public/plants/tradescantia-zebrina--zebrakraut--1e9a096a.webp b/server/public/plants/tradescantia-zebrina--zebrakraut--1e9a096a.webp new file mode 100644 index 0000000..c406d6c Binary files /dev/null and b/server/public/plants/tradescantia-zebrina--zebrakraut--1e9a096a.webp differ diff --git a/server/public/plants/tropaeolum-majus--kapuzinerkresse--c007c761.webp b/server/public/plants/tropaeolum-majus--kapuzinerkresse--c007c761.webp new file mode 100644 index 0000000..b45009d Binary files /dev/null and b/server/public/plants/tropaeolum-majus--kapuzinerkresse--c007c761.webp differ diff --git a/server/public/plants/tulipa-gesneriana--tulpe--373bf645.webp b/server/public/plants/tulipa-gesneriana--tulpe--373bf645.webp new file mode 100644 index 0000000..657295c Binary files /dev/null and b/server/public/plants/tulipa-gesneriana--tulpe--373bf645.webp differ diff --git a/server/public/plants/urtica-dioica--grosse-brennessel--b2ed905e.webp b/server/public/plants/urtica-dioica--grosse-brennessel--b2ed905e.webp new file mode 100644 index 0000000..d827f57 Binary files /dev/null and b/server/public/plants/urtica-dioica--grosse-brennessel--b2ed905e.webp differ diff --git a/server/public/plants/utricularia-gibba--wasserschlauch--13643b06.webp b/server/public/plants/utricularia-gibba--wasserschlauch--13643b06.webp new file mode 100644 index 0000000..72f6373 Binary files /dev/null and b/server/public/plants/utricularia-gibba--wasserschlauch--13643b06.webp differ diff --git a/server/public/plants/valeriana-officinalis--baldrian--7bc7a2ae.webp b/server/public/plants/valeriana-officinalis--baldrian--7bc7a2ae.webp new file mode 100644 index 0000000..6950ace Binary files /dev/null and b/server/public/plants/valeriana-officinalis--baldrian--7bc7a2ae.webp differ diff --git a/server/public/plants/vanda-coerulea--vanda-orchidee--d3b6fab1.webp b/server/public/plants/vanda-coerulea--vanda-orchidee--d3b6fab1.webp new file mode 100644 index 0000000..26ff441 Binary files /dev/null and b/server/public/plants/vanda-coerulea--vanda-orchidee--d3b6fab1.webp differ diff --git a/server/public/plants/vanilla-planifolia--vanille--39790d8a.webp b/server/public/plants/vanilla-planifolia--vanille--39790d8a.webp new file mode 100644 index 0000000..a079790 Binary files /dev/null and b/server/public/plants/vanilla-planifolia--vanille--39790d8a.webp differ diff --git a/server/public/plants/verbascum-thapsus--koenigskerze--26f01a84.webp b/server/public/plants/verbascum-thapsus--koenigskerze--26f01a84.webp new file mode 100644 index 0000000..4f77cd8 Binary files /dev/null and b/server/public/plants/verbascum-thapsus--koenigskerze--26f01a84.webp differ diff --git a/server/public/plants/verbena-bonariensis--eisenkraut--486982ce.webp b/server/public/plants/verbena-bonariensis--eisenkraut--486982ce.webp new file mode 100644 index 0000000..0630b4a Binary files /dev/null and b/server/public/plants/verbena-bonariensis--eisenkraut--486982ce.webp differ diff --git a/server/public/plants/viola-cornuta--hornveilchen--d2abebd6.webp b/server/public/plants/viola-cornuta--hornveilchen--d2abebd6.webp new file mode 100644 index 0000000..ebe74bd Binary files /dev/null and b/server/public/plants/viola-cornuta--hornveilchen--d2abebd6.webp differ diff --git a/server/public/plants/viola-wittrockiana--stiefmuetterchen--d2cb587c.webp b/server/public/plants/viola-wittrockiana--stiefmuetterchen--d2cb587c.webp new file mode 100644 index 0000000..2e1b99f Binary files /dev/null and b/server/public/plants/viola-wittrockiana--stiefmuetterchen--d2cb587c.webp differ diff --git a/server/public/plants/vriesea-splendens--flammen-bromelie--debc6faa.webp b/server/public/plants/vriesea-splendens--flammen-bromelie--debc6faa.webp new file mode 100644 index 0000000..a7d8c03 Binary files /dev/null and b/server/public/plants/vriesea-splendens--flammen-bromelie--debc6faa.webp differ diff --git a/server/public/plants/washingtonia-robusta--mexikanische-facherpalme--ced2cfe1.webp b/server/public/plants/washingtonia-robusta--mexikanische-facherpalme--ced2cfe1.webp new file mode 100644 index 0000000..95525b7 Binary files /dev/null and b/server/public/plants/washingtonia-robusta--mexikanische-facherpalme--ced2cfe1.webp differ diff --git a/server/public/plants/weigela-florida--weigelie--0bf98f7f.webp b/server/public/plants/weigela-florida--weigelie--0bf98f7f.webp new file mode 100644 index 0000000..4eaaf7d Binary files /dev/null and b/server/public/plants/weigela-florida--weigelie--0bf98f7f.webp differ diff --git a/server/public/plants/wikimedia-search-cache.json b/server/public/plants/wikimedia-search-cache.json new file mode 100644 index 0000000..f37dc00 --- /dev/null +++ b/server/public/plants/wikimedia-search-cache.json @@ -0,0 +1,387 @@ +{ + "Stapelia grandiflora": "https://upload.wikimedia.org/wikipedia/commons/6/67/Carrion_Plant_%28Stapelia_grandiflora%29_2.jpg", + "Saintpaulia ionantha": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/2007-04-20Saintpaulia_ionantha04.jpg/1280px-2007-04-20Saintpaulia_ionantha04.jpg", + "Agave americana": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Agave_July_2011-1.jpg/1280px-Agave_July_2011-1.jpg", + "Alocasia amazonica": "https://upload.wikimedia.org/wikipedia/commons/0/0e/Alocasia_x_amazonica_a2.jpg", + "Arnica montana": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Arnica_montana_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-015.jpg/1280px-Arnica_montana_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-015.jpg", + "Valeriana officinalis": "https://upload.wikimedia.org/wikipedia/commons/1/17/Valeriana_officinalis_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-143.jpg", + "Bambusa vulgaris": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/51/Bambusa_vulgaris_%28Dominica%29.jpg/1280px-Bambusa_vulgaris_%28Dominica%29.jpg", + "Musa acuminata": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Musa_acuminata_kz01.jpg/1280px-Musa_acuminata_kz01.jpg", + "Chamaedorea elegans": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/Chamaedorea_elegans.jpg/1280px-Chamaedorea_elegans.jpg", + "Senecio serpens": "https://upload.wikimedia.org/wikipedia/commons/2/2b/Senecio_serpens.jpg", + "Phlebodium aureum": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/Starr_050107-2831_Phlebodium_aureum.jpg/1280px-Starr_050107-2831_Phlebodium_aureum.jpg", + "Canna indica": "https://upload.wikimedia.org/wikipedia/commons/9/99/Canna_indica_%28wild_species%29_flowers.JPG", + "Geranium sanguineum": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e2/Geranium_sanguineum_-_verev_kurereha.jpg/1280px-Geranium_sanguineum_-_verev_kurereha.jpg", + "Ficus retusa": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9d/Ficus_retusa_2zz.jpg/1280px-Ficus_retusa_2zz.jpg", + "Bougainvillea spectabilis": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Starr_030418-0058_Bougainvillea_spectabilis.jpg/1280px-Starr_030418-0058_Bougainvillea_spectabilis.jpg", + "Caladium bicolor": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b8/Caladium_bicolor_%27Florida_Sweetheart%27_Plant_2220px.jpg/1280px-Caladium_bicolor_%27Florida_Sweetheart%27_Plant_2220px.jpg", + "Calibrachoa hybrida": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e2/Basket_of_Calibrachoa_parviflora_by_A_-_2020-06-18.jpg/1280px-Basket_of_Calibrachoa_parviflora_by_A_-_2020-06-18.jpg", + "Callisia repens": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Turtle_Vine_%28Callisia_repens%29_1.jpg/1280px-Turtle_Vine_%28Callisia_repens%29_1.jpg", + "Cattleya labiata": "https://upload.wikimedia.org/wikipedia/commons/9/97/Cattleya_labiata_2.jpg", + "Capsicum annuum": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cc/Capsicum_annuum.JPG/1280px-Capsicum_annuum.JPG", + "Livistona chinensis": "https://upload.wikimedia.org/wikipedia/commons/f/f6/Livistona-chinensis.jpg", + "Rosa chinensis": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Rosa_chinensis_04-08-2012_01.jpg/1280px-Rosa_chinensis_04-08-2012_01.jpg", + "Columnea gloriosa": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Columnea_gloriosa_137-8378.jpg/1280px-Columnea_gloriosa_137-8378.jpg", + "Dieffenbachia seguine": "https://upload.wikimedia.org/wikipedia/commons/8/80/Dieffenbachia_seguine1FKST.jpg", + "Dischidia ruscifolia": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/%E7%99%BE%E8%90%AC%E5%BF%83_Dischidia_ruscifolia_-%E9%A6%99%E6%B8%AF%E5%8B%95%E6%A4%8D%E7%89%A9%E5%85%AC%E5%9C%92_Hong_Kong_Botanical_Garden-_%289240152650%29.jpg/1280px-%E7%99%BE%E8%90%AC%E5%BF%83_Dischidia_ruscifolia_-%E9%A6%99%E6%B8%AF%E5%8B%95%E6%A4%8D%E7%89%A9%E5%85%AC%E5%9C%92_Hong_Kong_Botanical_Garden-_%289240152650%29.jpg", + "Dracaena marginata": "https://upload.wikimedia.org/wikipedia/commons/f/f9/Dracaena_marginata_IndoorPlant_0605k.jpg", + "Streptocarpus hybridus": "https://upload.wikimedia.org/wikipedia/commons/9/9f/2007-03-20Streptocarpus01.jpg", + "Dudleya brittonii": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/10/Dudleya_Brittonii.jpg/1280px-Dudleya_Brittonii.jpg", + "Acer palmatum": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/de/Portland_Japanese_Garden_maple.jpg/1280px-Portland_Japanese_Garden_maple.jpg", + "Fatsia japonica": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Fatsia_japonica.003_-_Zapateira.jpg/1280px-Fatsia_japonica.003_-_Zapateira.jpg", + "Vriesea splendens": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Vriesea_splendens_flower.jpg/1280px-Vriesea_splendens_flower.jpg", + "Impatiens walleriana": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Impatiens_walleriana_01.JPG/1280px-Impatiens_walleriana_01.JPG", + "Begonia maculata": "https://upload.wikimedia.org/wikipedia/commons/d/df/Begonia_maculata3073316230.jpg", + "Adiantum raddianum": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/45/Starr_030807-0143_Adiantum_raddianum.jpg/1280px-Starr_030807-0143_Adiantum_raddianum.jpg", + "Fuchsia hybrida": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cc/Fuchsia_%C3%97_hybrida.jpg/1280px-Fuchsia_%C3%97_hybrida.jpg", + "Gasteria carinata": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/12/Gasteria_carinata_hh.jpg/1280px-Gasteria_carinata_hh.jpg", + "Ficus lyrata": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Starr_031108-0130_Ficus_lyrata.jpg/1280px-Starr_031108-0130_Ficus_lyrata.jpg", + "Graptopetalum paraguayense": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/59/%28MHNT%29_Graptopetalum_paraguayense_-_leaves.jpg/1280px-%28MHNT%29_Graptopetalum_paraguayense_-_leaves.jpg", + "Platycerium bifurcatum": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/Platycerium_bifurcatum_%28Corne_d%27%C3%A9lan%29_-_107.jpg/1280px-Platycerium_bifurcatum_%28Corne_d%27%C3%A9lan%29_-_107.jpg", + "Gloxinia speciosa": "https://upload.wikimedia.org/wikipedia/commons/8/87/Sinnningia_speciosa_im_Querbeet-Wintergarten.jpg", + "Echinocactus grusonii": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Echinocactus_grusonii_qtl1.jpg/1280px-Echinocactus_grusonii_qtl1.jpg", + "Phyllostachys aurea": "https://upload.wikimedia.org/wikipedia/commons/3/3b/Phyllostachys_aurea0.jpg", + "Punica granatum": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/db/Illustration_Punica_granatum2.jpg/1280px-Illustration_Punica_granatum2.jpg", + "Schefflera actinophylla": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Schefflera_actinophylla_02.JPG/1280px-Schefflera_actinophylla_02.JPG", + "Ficus elastica": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/88/Ficus_November_2008-1.jpg/1280px-Ficus_November_2008-1.jpg", + "Cucumis sativus": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/07/Cucumis_sativus_0001.JPG/1280px-Cucumis_sativus_0001.JPG", + "Betula pendula": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Betula_pendula_in_Sedovo_1.jpg/1280px-Betula_pendula_in_Sedovo_1.jpg", + "Philodendron hederaceum": "https://upload.wikimedia.org/wikipedia/commons/b/bb/Philodendron_scandens_subsp_oxycardium2.jpg", + "Ceropegia woodii": "https://upload.wikimedia.org/wikipedia/commons/5/55/Ceropegia_linearis_subsp_woodii.jpg", + "Hyacinthus orientalis": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ae/Garden_Hyacinth_Hyacinthus_orientalis_%27Blue_Jacket%27_Flower_2000px.jpg/1280px-Garden_Hyacinth_Hyacinthus_orientalis_%27Blue_Jacket%27_Flower_2000px.jpg", + "Azalea indica": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/de/Rhododendron_indicum1.jpg/1280px-Rhododendron_indicum1.jpg", + "Zingiber officinale": "https://upload.wikimedia.org/wikipedia/commons/c/c1/Ginger_Plant_vs.jpg", + "Crassula ovata": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5d/Crassula_ovata_RTBG.jpg/1280px-Crassula_ovata_RTBG.jpg", + "Rhododendron simsii": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9b/Rhododendron_simsii_01.JPG/1280px-Rhododendron_simsii_01.JPG", + "Coffea arabica": "https://upload.wikimedia.org/wikipedia/commons/1/10/Coffea_arabica_2.jpg", + "Kalanchoe blossfeldiana": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Kalanchoe_blossfeldiana_%28Florist_Kalanchoe%29.jpg/1280px-Kalanchoe_blossfeldiana_%28Florist_Kalanchoe%29.jpg", + "Camellia japonica": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Camellia_japonica_var._decumbens_3.JPG/1280px-Camellia_japonica_var._decumbens_3.JPG", + "Chamomilla recutita": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Chamomile%40original_size.jpg/1280px-Chamomile%40original_size.jpg", + "Aloe arborescens": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Aloe_arborescens_01.JPG/1280px-Aloe_arborescens_01.JPG", + "Aloe ferox": "https://upload.wikimedia.org/wikipedia/commons/9/9e/Aloe_Ferox_between_Cofimvaba_and_Ngcobo.jpg", + "Daucus carota": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/23/Daucus_carota_May_2008-1_edit.jpg/1280px-Daucus_carota_May_2008-1_edit.jpg", + "Oxalis triangularis": "https://upload.wikimedia.org/wikipedia/commons/1/15/Oxalis_triangularis6.jpg", + "Hoya bella": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/%E7%BE%8E%E9%BA%97%E6%AF%AC%E8%98%AD_Hoya_bella_-%E9%A6%99%E6%B8%AF%E5%85%AC%E5%9C%92_Hong_Kong_Park-_%289240227808%29.jpg/1280px-%E7%BE%8E%E9%BA%97%E6%AF%AC%E8%98%AD_Hoya_bella_-%E9%A6%99%E6%B8%AF%E5%85%AC%E5%9C%92_Hong_Kong_Park-_%289240227808%29.jpg", + "Begonia tuberhybrida": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Begonia_x_tuberhybrida_1005Pink1.JPG/1280px-Begonia_x_tuberhybrida_1005Pink1.JPG", + "Epiphyllum oxypetalum": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/59/Kakteen_IMG_4213.jpg/1280px-Kakteen_IMG_4213.jpg", + "Protea cynaroides": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3d/Protea_cynaroides_3.jpg/1280px-Protea_cynaroides_3.jpg", + "Conophytum calculus": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Conophytum_calculus_-_Namaqualand_-_South_Africa_5.jpg/1280px-Conophytum_calculus_-_Namaqualand_-_South_Africa_5.jpg", + "Rhipsalis baccifera": "https://upload.wikimedia.org/wikipedia/commons/b/ba/Rhipsalis_baccifera_01_ies.jpg", + "Cotyledon orbiculata": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bb/Cotyledon_orbiculata_2.jpg/1280px-Cotyledon_orbiculata_2.jpg", + "Lithops julii": "https://upload.wikimedia.org/wikipedia/commons/4/4d/Lithops_julii_Nicos_Farm_strain.jpg", + "Tradescantia pallida": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Tradescantia_pallida_C.jpg/1280px-Tradescantia_pallida_C.jpg", + "Aeschynanthus radicans": "https://upload.wikimedia.org/wikipedia/commons/5/52/Aeschynanthus_radicans.jpg", + "Tillandsia ionantha": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Matthaei_Botanical_Gardens_-_IMG_8999.JPG/1280px-Matthaei_Botanical_Gardens_-_IMG_8999.JPG", + "Stephanotis floribunda": "https://upload.wikimedia.org/wikipedia/commons/9/9d/Stephanotis_floribunda.jpg", + "Dracaena fragrans": "https://upload.wikimedia.org/wikipedia/commons/6/64/Dracaena_fragrans_a1.jpg", + "Beta vulgaris": "https://upload.wikimedia.org/wikipedia/commons/f/ff/Beta_vulgaris_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-167.jpg", + "Rhaphidophora tetrasperma": "https://upload.wikimedia.org/wikipedia/commons/d/db/Rhaphidophora_tetrasperma.jpg", + "Pachyphytum oviferum": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/39/Pachyphytum_oviferum_1.jpg/1280px-Pachyphytum_oviferum_1.jpg", + "Monstera adansonii": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Monstera_adansonii_CBM.png/1280px-Monstera_adansonii_CBM.png", + "Crassula muscosa": "https://upload.wikimedia.org/wikipedia/commons/5/5e/Crassula_muscosa_Grubosz_2006-05-03_01.jpg", + "Epipremnum pinnatum Neon": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/de/Epipremnum_pinnatum_%27Neon%27%2C_Longwood_Gardens_01.jpg/1280px-Epipremnum_pinnatum_%27Neon%27%2C_Longwood_Gardens_01.jpg", + "Lilium longiflorum": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Lilium_longiflorum_%28Easter_Lily%29.JPG/1280px-Lilium_longiflorum_%28Easter_Lily%29.JPG", + "Senecio rowleyanus": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Senecio_rowleyanus.jpg/1280px-Senecio_rowleyanus.jpg", + "Petroselinum crispum": "https://upload.wikimedia.org/wikipedia/commons/2/2d/Petroselinum_crispum_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-103.jpg", + "Petunia hybrida": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/Petunia_x_hybrida_a2.JPG/1280px-Petunia_x_hybrida_a2.JPG", + "Syngonium podophyllum": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/07/Syngonium_podophyllum_Golden_0zz.jpg/1280px-Syngonium_podophyllum_Golden_0zz.jpg", + "Philodendron bipinnatifidum": "https://upload.wikimedia.org/wikipedia/commons/c/c1/Tree1.JPG", + "Philodendron gloriosum": "https://upload.wikimedia.org/wikipedia/commons/f/f1/Philodendron_gloriosum.jpg", + "Primula vulgaris": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/76/Chipping_Sodbury_MMB_02_primula_vulgaris.jpg/1280px-Chipping_Sodbury_MMB_02_primula_vulgaris.jpg", + "Raphanus sativus": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Raphanus_sativus_of_Salem.jpg/1280px-Raphanus_sativus_of_Salem.jpg", + "Selaginella uncinata": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Selaginella_uncinata_-_Berlin_Botanical_Garden_-_IMG_8722.JPG/1280px-Selaginella_uncinata_-_Berlin_Botanical_Garden_-_IMG_8722.JPG", + "Peperomia caperata": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Peperomia_caperata_1-OB9.jpg/1280px-Peperomia_caperata_1-OB9.jpg", + "Hippeastrum hybrid": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Hippeastrum_hybrid_1.jpg/1280px-Hippeastrum_hybrid_1.jpg", + "Digitalis purpurea": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Digitalis_purpurea_LC0101.jpg/1280px-Digitalis_purpurea_LC0101.jpg", + "Lactuca sativa": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Romaine_lettuce.jpg/1280px-Romaine_lettuce.jpg", + "Salvia officinalis": "https://upload.wikimedia.org/wikipedia/commons/5/5a/Salvia_officinalis0.jpg", + "Scindapsus pictus": "https://upload.wikimedia.org/wikipedia/commons/c/ca/Scindapsus_pictus_01.jpg", + "Mimosa pudica": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/04/Touch_Me_not.jpg/1280px-Touch_Me_not.jpg", + "Phalaenopsis amabilis": "https://upload.wikimedia.org/wikipedia/commons/3/32/Phalaenopsis_amabilis_Orchi_03.jpg", + "Allium schoenoprasum": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/74/Allium_schoenoprasum_J1.JPG/1280px-Allium_schoenoprasum_J1.JPG", + "Pandanus veitchii": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/Pandanus_tectorius.jpg/1280px-Pandanus_tectorius.jpg", + "Aeonium arboreum": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c4/Aeonium_arboreum_01.jpg/1280px-Aeonium_arboreum_01.jpg", + "Adenium socotranum": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Adenium_seedling_2day_Uthandi_Aug21_D72_20609-21_ZP.jpg/1280px-Adenium_seedling_2day_Uthandi_Aug21_D72_20609-21_ZP.jpg", + "Echinacea purpurea": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b5/Monarch_Butterfly_Danaus_plexippus_on_Echinacea_purpurea_2800px.jpg/1280px-Monarch_Butterfly_Danaus_plexippus_on_Echinacea_purpurea_2800px.jpg", + "Tillandsia usneoides": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/74/Tillandsia_usneoides_%28Bromeliaceae%29_%2825004066956%29.jpg/1280px-Tillandsia_usneoides_%28Bromeliaceae%29_%2825004066956%29.jpg", + "Rhapis excelsa": "https://upload.wikimedia.org/wikipedia/commons/7/7d/Rhapis_excelsa.jpg", + "Viola wittrockiana": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/91/Pansy_viola_x_wittrockiana_blue.jpg/1280px-Pansy_viola_x_wittrockiana_blue.jpg", + "Schefflera arboricola": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Schefflera_arboricola%2C_vrugte%2C_a%2C_Pretoria.jpg/1280px-Schefflera_arboricola%2C_vrugte%2C_a%2C_Pretoria.jpg", + "Tagetes patula": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/French_marigold_garden_2009_G1.jpg/1280px-French_marigold_garden_2009_G1.jpg", + "Oncidium sphacelatum": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Oncidium_sphacelatum03.jpg/1280px-Oncidium_sphacelatum03.jpg", + "Colocasia esculenta": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Taro_leaf_underside%2C_backlit_by_sun.jpg/1280px-Taro_leaf_underside%2C_backlit_by_sun.jpg", + "Camellia sinensis": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e3/Camellia_sinensis_MHNT.BOT.2016.12.24.jpg/1280px-Camellia_sinensis_MHNT.BOT.2016.12.24.jpg", + "Plumeria rubra": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/White_Plumeria_from_Kannur_-_Kerala.jpg/1280px-White_Plumeria_from_Kannur_-_Kerala.jpg", + "Thymus vulgaris": "https://upload.wikimedia.org/wikipedia/commons/1/12/Thymus_vulgaris_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-271.jpg", + "Cordyline fruticosa": "https://upload.wikimedia.org/wikipedia/commons/0/05/Ti_plant_%28Cordyline_fruticosa%29.jpg", + "Solanum lycopersicum": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/89/Tomato_je.jpg/1280px-Tomato_je.jpg", + "Polypodium vulgare": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/33/Polypodium_vulgare%2C_sores_%28Matthieu_Gauvain%29.JPG/1280px-Polypodium_vulgare%2C_sores_%28Matthieu_Gauvain%29.JPG", + "Microsorum punctatum": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9f/Microsorum_punctatum.jpg/1280px-Microsorum_punctatum.jpg", + "Tulipa gesneriana": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/%D7%A6%D7%91%D7%A2%D7%95%D7%A0%D7%99%D7%9D.JPG/1280px-%D7%A6%D7%91%D7%A2%D7%95%D7%A0%D7%99%D7%9D.JPG", + "Vanilla planifolia": "https://upload.wikimedia.org/wikipedia/commons/4/40/Vanilla_planifolia_1.jpg", + "Asplenium nidus": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Bird%27s-nest_Fern_Asplenium_nidus_Leaves_1.jpg/1280px-Bird%27s-nest_Fern_Asplenium_nidus_Leaves_1.jpg", + "Lantana camara": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/Twin_lantana_camara_edit.jpg/1280px-Twin_lantana_camara_edit.jpg", + "Schlumbergera truncata": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/61/Schlumbergera_truncata_flordemaio.jpg/1280px-Schlumbergera_truncata_flordemaio.jpg", + "Euphorbia pulcherrima": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5d/2008_05_17_-_Euphorbia_pulcherrima_05a.JPG/1280px-2008_05_17_-_Euphorbia_pulcherrima_05a.JPG", + "Tradescantia fluminensis": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/Tradescantia_fluminensis_Flower_1.jpg/1280px-Tradescantia_fluminensis_Flower_1.jpg", + "Yucca elephantipes": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Yucca_elephantipes_HRM2.JPG/1280px-Yucca_elephantipes_HRM2.JPG", + "Hamamelis mollis": "https://upload.wikimedia.org/wikipedia/commons/c/ce/Hamamelis_mollis0.jpg", + "Haworthia fasciata": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/13/Haworthia_fasciata_%28Vermont%29.jpg/1280px-Haworthia_fasciata_%28Vermont%29.jpg", + "Tradescantia zebrina": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Zebrina_pendula_20060521_2.JPG/1280px-Zebrina_pendula_20060521_2.JPG", + "Zinnia elegans": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d7/Zinnia_elegans_with_Bombus_01.JPG/1280px-Zinnia_elegans_with_Bombus_01.JPG", + "Citrus limon": "https://upload.wikimedia.org/wikipedia/commons/e/e4/Lemon.jpg", + "Melissa officinalis": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f9/Melissa_officinalis_1.jpg/1280px-Melissa_officinalis_1.jpg", + "Phoenix roebelenii": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1d/Starr_070124-3839_Phoenix_roebelenii.jpg/1280px-Starr_070124-3839_Phoenix_roebelenii.jpg", + "Cymbidium lowianum": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Cymbidium_lowianum_var._concolor_3.jpg/1280px-Cymbidium_lowianum_var._concolor_3.jpg", + "Jasminum%20sambac": null, + "Pilea%20cadierei": null, + "Alocasia%20zebrina": null, + "Anemone%20coronaria": null, + "Jasminum sambac": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/75/JasminumSambac.jpg/1280px-JasminumSambac.jpg", + "Anemone coronaria": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Blue_Anemone_coronaria.JPG/1280px-Blue_Anemone_coronaria.JPG", + "Pilea cadierei": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/30/PileaCadierei.jpg/1280px-PileaCadierei.jpg", + "Alocasia zebrina": "https://upload.wikimedia.org/wikipedia/commons/4/43/Alocasia_zebrina_Reticulata_1zz.jpg", + "Iris%20germanica": null, + "Dianthus%20barbatus": null, + "Iris germanica": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Iris_germanica_001.jpg/1280px-Iris_germanica_001.jpg", + "Dianthus barbatus": "https://upload.wikimedia.org/wikipedia/commons/4/4f/Dianthus_barbatus_PID1688-4.jpg", + "Lavatera%20trimestris": null, + "Lavatera trimestris": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/57/Flower_April_2010-1a.jpg/1280px-Flower_April_2010-1a.jpg", + "Satureja%20hortensis": null, + "Satureja hortensis": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5f/Satureja_hortensis_bgiu.jpg/1280px-Satureja_hortensis_bgiu.jpg", + "Borago%20officinalis": null, + "Borago officinalis": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/54/Borago_officinalis_%28flower%29.jpg/1280px-Borago_officinalis_%28flower%29.jpg", + "Soleirolia%20soleirolii": null, + "Soleirolia soleirolii": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ed/Soleirolia_soleirolii_kz05.jpg/1280px-Soleirolia_soleirolii_kz05.jpg", + "Buxus%20sempervirens": null, + "Buxus sempervirens": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Buisfleurs.jpg/1280px-Buisfleurs.jpg", + "Plectranthus%20scutellarioides": null, + "Plectranthus scutellarioides": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9c/Solenostemon_scutellarioides_%28Coleus_x_hybridus%29_%27Inky_Fingers%27_Leaf_Cluster_2730px.jpg/1280px-Solenostemon_scutellarioides_%28Coleus_x_hybridus%29_%27Inky_Fingers%27_Leaf_Cluster_2730px.jpg", + "Goeppertia%20insignis": null, + "Goeppertia insignis": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/94/Goeppertia_insignis.jpg/1280px-Goeppertia_insignis.jpg", + "Goeppertia%20ornata": null, + "Goeppertia ornata": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/42/CalatheaOrnataRoseo-Lineata.jpg/1280px-CalatheaOrnataRoseo-Lineata.jpg", + "Clematis%20viticella": null, + "Clematis viticella": "https://upload.wikimedia.org/wikipedia/commons/4/4f/Clematis_viticella3UME.jpg", + "Helichrysum%20italicum": null, + "Helichrysum italicum": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Helichrysum_italicum_%28immortelle%29.JPG/1280px-Helichrysum_italicum_%28immortelle%29.JPG", + "Anethum%20graveolens": null, + "Anethum graveolens": "https://upload.wikimedia.org/wikipedia/commons/5/56/Anethum_graveolens_02.jpg", + "Lathyrus%20odoratus": null, + "Lathyrus odoratus": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/72/Lathyrus_odoratus_Painted_Lady.jpg/1280px-Lathyrus_odoratus_Painted_Lady.jpg", + "Sorbus%20aucuparia": null, + "Sorbus aucuparia": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/2020_year._Herbarium._Sorbus_aucuparia._img-035.jpg/1280px-2020_year._Herbarium._Sorbus_aucuparia._img-035.jpg", + "Quercus%20robur": null, + "Quercus robur": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/Langaa_egeskov_rimfrost.jpg/1280px-Langaa_egeskov_rimfrost.jpg", + "Begonia%20semperflorens-cultorum": null, + "Begonia semperflorens-cultorum": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/28/Begonia_semperflorens.jpg/1280px-Begonia_semperflorens.jpg", + "Verbena%20bonariensis": null, + "Verbena bonariensis": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/Verbena_bonariensis.jpg/1280px-Verbena_bonariensis.jpg", + "Artemisia%20dracunculus": null, + "Artemisia dracunculus": "https://upload.wikimedia.org/wikipedia/commons/6/6c/Estragon_1511.jpg", + "Eucalyptus%20globulus": null, + "Eucalyptus globulus": "https://upload.wikimedia.org/wikipedia/commons/7/74/Eucalyptus_globulus_globulus.jpg", + "Schefflera%20elegantissima": null, + "Schefflera elegantissima": "https://upload.wikimedia.org/wikipedia/commons/6/64/Schefflera_elegantissima.jpg", + "Salvia%20splendens": null, + "Salvia splendens": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Salvia_splendens_%28357118788%29.jpg/1280px-Salvia_splendens_%28357118788%29.jpg", + "Picea%20abies": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/Picea_abies_%27Rubra_Spicata%27_5_2021_Norway-_%2851176180455%29.jpg/1280px-Picea_abies_%27Rubra_Spicata%27_5_2021_Norway-_%2851176180455%29.jpg", + "Ficus%20altissima": null, + "Ficus altissima": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/60/Ficus_altissima1.jpg/1280px-Ficus_altissima1.jpg", + "Ficus%20microcarpa": null, + "Ficus microcarpa": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Bonsai_Adam_and_Eve_%28PPL2-Enhanced%29_julesvernex2.jpg/1280px-Bonsai_Adam_and_Eve_%28PPL2-Enhanced%29_julesvernex2.jpg", + "Delonix%20regia": null, + "Delonix regia": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Flame_tree_mali.jpg/1280px-Flame_tree_mali.jpg", + "Phlox%20paniculata": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e2/Phlox_paniculata_%27Opening_Act_Blush%27_6_2021_Garden_Phlox-_%2851242863119%29.jpg/1280px-Phlox_paniculata_%27Opening_Act_Blush%27_6_2021_Garden_Phlox-_%2851242863119%29.jpg", + "Syringa%20vulgaris": "https://upload.wikimedia.org/wikipedia/commons/2/2b/Syringa_vulgaris1.jpg", + "Forsythia%20x%20intermedia": null, + "Forsythia x intermedia": "https://upload.wikimedia.org/wikipedia/commons/b/b7/Forsythia-intermedia.JPG", + "Freesia%20refracta": null, + "Freesia refracta": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/FreesiaRefracta1.JPG/1280px-FreesiaRefracta1.JPG", + "Amaranthus%20caudatus": null, + "Amaranthus caudatus": "https://upload.wikimedia.org/wikipedia/commons/b/b6/Amaranthus_caudatus1.jpg", + "Bellis%20perennis": null, + "Bellis perennis": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Pink_twinged_daisy_on_table_edit.jpg/1280px-Pink_twinged_daisy_on_table_edit.jpg", + "Impatiens%20balsamina": null, + "Impatiens balsamina": "https://upload.wikimedia.org/wikipedia/commons/f/f8/Impatiens_balsamina1.jpg", + "Hibiscus%20syriacus": null, + "Hibiscus syriacus": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Hibiscus-syriacus.jpg/1280px-Hibiscus-syriacus.jpg", + "Lonicera%20japonica": null, + "Lonicera japonica": "https://upload.wikimedia.org/wikipedia/commons/b/b9/Honeysuckle_2.jpg", + "Ginkgo%20biloba": null, + "Ginkgo biloba": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Ginkgo_biloba_MHNT.BOT.2010.13.1.jpg/1280px-Ginkgo_biloba_MHNT.BOT.2010.13.1.jpg", + "Gladiolus%20hortulanus": null, + "Gladiolus hortulanus": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Gartengladiole_apricot.JPG/1280px-Gartengladiole_apricot.JPG", + "Pachira%20aquatica": null, + "Pachira aquatica": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Pachira_aquatica_%28inflorescense%29.jpg/1280px-Pachira_aquatica_%28inflorescense%29.jpg", + "Hyacinthoides%20non-scripta": null, + "Hyacinthoides non-scripta": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Hyacinthoides_non-scripta_%28Common_Bluebell%29.jpg/1280px-Hyacinthoides_non-scripta_%28Common_Bluebell%29.jpg", + "Heliotropium%20arborescens": null, + "Heliotropium arborescens": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cb/Heliotropium_arborescens_%27Mini_Marine%27_Heliotrope_Flower_2500px.jpg/1280px-Heliotropium_arborescens_%27Mini_Marine%27_Heliotrope_Flower_2500px.jpg", + "Symphyotrichum%20novi-belgii": null, + "Symphyotrichum novi-belgii": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Symphyotrichum_novi-belgii20090914_120.jpg/1280px-Symphyotrichum_novi-belgii20090914_120.jpg", + "Viola%20cornuta": null, + "Viola cornuta": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Viola_cornuta_2008.jpg/1280px-Viola_cornuta_2008.jpg", + "Hydrangea%20macrophylla": null, + "Hydrangea macrophylla": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/Hydrangea_macrophylla_-_Hortensia_hydrangea.jpg/1280px-Hydrangea_macrophylla_-_Hortensia_hydrangea.jpg", + "Monarda%20didyma": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cd/Monarda_didyma_%27Colrain_Red%27_6_2021_Bee_Balm-_%2851273491889%29.jpg/1280px-Monarda_didyma_%27Colrain_Red%27_6_2021_Bee_Balm-_%2851273491889%29.jpg", + "Jacaranda%20mimosifolia": null, + "Jacaranda mimosifolia": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Jacaranda_mimosifolia_5334.jpg/1280px-Jacaranda_mimosifolia_5334.jpg", + "Coffea%20arabica%20Nana": null, + "Coffea arabica Nana": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Henry_G._Gilbert_Nursery_and_Seed_Trade_Catalog_Collection_%28IA_catalogueofgreen00dcla_0%29.pdf/page1-1016px-Henry_G._Gilbert_Nursery_and_Seed_Trade_Catalog_Collection_%28IA_catalogueofgreen00dcla_0%29.pdf.jpg", + "Eschscholzia%20californica": null, + "Eschscholzia californica": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Eschscholzia_californica_in_Sedovo_006.jpg/1280px-Eschscholzia_californica_in_Sedovo_006.jpg", + "Osteospermum%20ecklonis": null, + "Osteospermum ecklonis": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/Osteospermum_ecklonis1.JPG/1280px-Osteospermum_ecklonis1.JPG", + "Tropaeolum%20majus": null, + "Tropaeolum majus": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/87/Tropaeolum_majus_2005_G1.jpg/1280px-Tropaeolum_majus_2005_G1.jpg", + "Nepeta%20cataria": null, + "Nepeta cataria": "https://upload.wikimedia.org/wikipedia/commons/1/12/Nepeta_cataria_Sturm24.jpg", + "Anthriscus%20cerefolium": null, + "Anthriscus cerefolium": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Kerbel_%28Anthriscus_cerefolium%29_mit_Echter_Mehltau_%28Erysiphe_heraclei%29_Befall%2C_Schlaghecken.jpg/1280px-Kerbel_%28Anthriscus_cerefolium%29_mit_Echter_Mehltau_%28Erysiphe_heraclei%29_Befall%2C_Schlaghecken.jpg", + "Pinus%20sylvestris": null, + "Pinus sylvestris": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5b/Meenikunno_maastikukaiteala.jpg/1280px-Meenikunno_maastikukaiteala.jpg", + "Prunus%20laurocerasus": null, + "Prunus laurocerasus": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/57/Fr%C3%BChling_bl%C3%BChender_Kirschenbaum.jpg/1280px-Fr%C3%BChling_bl%C3%BChender_Kirschenbaum.jpg", + "Verbascum%20thapsus": null, + "Verbascum thapsus": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/33/Koningskaars_R01.jpg/1280px-Koningskaars_R01.jpg", + "Gaillardia%20aristata": null, + "Gaillardia aristata": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/Gaillardia_July_2011-2.jpg/1280px-Gaillardia_July_2011-2.jpg", + "Coriandrum%20sativum": null, + "Coriandrum sativum": "https://upload.wikimedia.org/wikipedia/commons/1/13/Coriandrum_sativum_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-193.jpg", + "Centaurea%20cyanus": null, + "Centaurea cyanus": "https://upload.wikimedia.org/wikipedia/commons/e/e3/CentaureaCyanus-bloem-kl.jpg", + "Cosmos%20bipinnatus": null, + "Cosmos bipinnatus": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Cosmos_bipinnatus%2C_Burdwan%2C_West_Bengal%2C_India_10_01_2013.jpg/1280px-Cosmos_bipinnatus%2C_Burdwan%2C_West_Bengal%2C_India_10_01_2013.jpg", + "Anthurium%20crystallinum": null, + "Anthurium crystallinum": "https://upload.wikimedia.org/wikipedia/commons/6/61/Alismatales_-_Anthurium_crystallinum_2.jpg", + "Codiaeum%20variegatum": null, + "Codiaeum variegatum": null, + "Kroton": null, + "Helleborus%20orientalis": null, + "Helleborus orientalis": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Helleborus_orientalis._Lenteroos_03.JPG/1280px-Helleborus_orientalis._Lenteroos_03.JPG", + "Levisticum%20officinale": null, + "Levisticum officinale": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4c/Liebst%C3%B6ckel_%28Levisticum_officinale%29_mit_einem_Echten_Mehltau_%28Erysiphe_heraclei%29_Befall.%2C_Schlaghecken.jpg/1280px-Liebst%C3%B6ckel_%28Levisticum_officinale%29_mit_einem_Echten_Mehltau_%28Erysiphe_heraclei%29_Befall.%2C_Schlaghecken.jpg", + "Antirrhinum%20majus": null, + "Antirrhinum majus": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/64/Antirrhinum_majus_full_MichaD.jpg/1280px-Antirrhinum_majus_full_MichaD.jpg", + "Laurus%20nobilis": null, + "Laurus nobilis": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Laurus_nobilis_MHNT_Fleurs.jpg/1280px-Laurus_nobilis_MHNT_Fleurs.jpg", + "Lupinus%20polyphyllus": null, + "Lupinus polyphyllus": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Lupinus_polyphyllus_MHNT.BOT.2004.0.463.jpg/1280px-Lupinus_polyphyllus_MHNT.BOT.2004.0.463.jpg", + "Coreopsis%20tinctoria": null, + "Coreopsis tinctoria": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Coreopsis_tinctoria_cultivar_Uptick_Cream_and_Red_4.JPG/1280px-Coreopsis_tinctoria_cultivar_Uptick_Cream_and_Red_4.JPG", + "Magnolia%20grandiflora": null, + "Magnolia grandiflora": "https://upload.wikimedia.org/wikipedia/commons/4/48/Magnolia_%C3%97_soulangeana_blossom.jpg", + "Convallaria%20majalis": null, + "Convallaria majalis": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Beech%2C_ferns_and_lily_of_the_valley_in_Gullmarsskogen_1.jpg/1280px-Beech%2C_ferns_and_lily_of_the_valley_in_Gullmarsskogen_1.jpg", + "Origanum%20majorana": null, + "Origanum majorana": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Origanum_majorana.jpg/1280px-Origanum_majorana.jpg", + "Leucanthemum%20vulgare": null, + "Leucanthemum vulgare": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Leucanthemum_vulgare_%27Filigran%27_Flower_2200px.jpg/1280px-Leucanthemum_vulgare_%27Filigran%27_Flower_2200px.jpg", + "Salvia%20farinacea": null, + "Salvia farinacea": "https://upload.wikimedia.org/wikipedia/commons/6/64/Salvia_farinacea1.jpg", + "Gazania%20rigens": null, + "Gazania rigens": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3d/Gazania_rigens-1.jpg/1280px-Gazania_rigens-1.jpg", + "Papaver%20rhoeas": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/04/Papaver_rhoeas_6_2021_Poppy-_%2851237437202%29.jpg/1280px-Papaver_rhoeas_6_2021_Poppy-_%2851237437202%29.jpg", + "Dianthus%20caryophyllus": null, + "Dianthus caryophyllus": "https://upload.wikimedia.org/wikipedia/commons/8/80/Gartennelke_1.jpg", + "Nemesia%20strumosa": null, + "Nemesia strumosa": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Nemesia_strumosa_two_colours.jpg/1280px-Nemesia_strumosa_two_colours.jpg", + "Fittonia%20albivenis": null, + "Fittonia albivenis": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/72/Colpfl25.jpg/1280px-Colpfl25.jpg", + "Araucaria%20heterophylla": null, + "Araucaria heterophylla": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/38/Araucaria_heterophylla_Norfolk_Island_0.jpg/1280px-Araucaria_heterophylla_Norfolk_Island_0.jpg", + "Cycas%20revoluta": "https://upload.wikimedia.org/wikipedia/commons/6/6d/Cycas_revoluta%2BFlorero.jpg", + "Paeonia%20lactiflora": null, + "Paeonia lactiflora": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/P%C3%B6rtschach_Winklern_10.-Oktober-Stra%C3%9Fe_67_Paeonia_lactiflora_24052014_2076.jpg/1280px-P%C3%B6rtschach_Winklern_10.-Oktober-Stra%C3%9Fe_67_Paeonia_lactiflora_24052014_2076.jpg", + "Philodendron%20hederaceum%20Brasil": null, + "Philodendron hederaceum Brasil": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Wikipedia_13._Fotoworkshop_Botanischer_Garten_Erlangen_2013_by-RaBoe_136.jpg/1280px-Wikipedia_13._Fotoworkshop_Botanischer_Garten_Erlangen_2013_by-RaBoe_136.jpg", + "Philodendron%20erubescens%20Pink%20Princess": null, + "Philodendron erubescens Pink Princess": "https://upload.wikimedia.org/wikipedia/commons/6/64/Arum_Family_-_Araceae_%283072475611%29.jpg", + "Thaumatophyllum%20xanadu": null, + "Thaumatophyllum xanadu": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Philodendron_xanadu_AK1.jpg/1280px-Philodendron_xanadu_AK1.jpg", + "Ipomoea%20purpurea": null, + "Ipomoea purpurea": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/Ipomoea_July_2011-4.jpg/1280px-Ipomoea_July_2011-4.jpg", + "Hypoestes%20phyllostachya": null, + "Hypoestes phyllostachya": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Starr_080117-1693_Hypoestes_phyllostachya.jpg/1280px-Starr_080117-1693_Hypoestes_phyllostachya.jpg", + "Peperomia%20polybotrya": null, + "Peperomia polybotrya": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/87/Coin_Leaf_Peperomia_%28Peperomia_polybotrya_%27Jayde%27%29.jpg/1280px-Coin_Leaf_Peperomia_%28Peperomia_polybotrya_%27Jayde%27%29.jpg", + "Ranunculus%20asiaticus": null, + "Ranunculus asiaticus": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/23/Persian_Buttercup_01.jpg/1280px-Persian_Buttercup_01.jpg", + "Rhododendron%20catawbiense": null, + "Rhododendron catawbiense": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Rhododendron-catawbiense.jpg/1280px-Rhododendron-catawbiense.jpg", + "Calendula%20officinalis": "https://upload.wikimedia.org/wikipedia/commons/4/41/Calendula_officinalis_01.jpg", + "Delphinium%20elatum": null, + "Delphinium elatum": "https://upload.wikimedia.org/wikipedia/commons/5/54/Delphinium_elatum_a2.jpg", + "Robinia%20pseudoacacia": null, + "Robinia pseudoacacia": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Robinia_pseudoacacia_fruits.jpg/1280px-Robinia_pseudoacacia_fruits.jpg", + "Chamaemelum%20nobile": null, + "Chamaemelum nobile": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Chamomile%40original_size.jpg/1280px-Chamomile%40original_size.jpg", + "Rosa%20x%20hybrida": null, + "Rosa x hybrida": "https://upload.wikimedia.org/wikipedia/commons/d/db/Rosa_x_hybrida_iceberg_Reimer_Kordes_1958.JPG", + "Rudbeckia%20hirta": null, + "Rudbeckia hirta": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Black_eyed_susan_20040717_110754_2.1474.jpg/1280px-Black_eyed_susan_20040717_110754_2.1474.jpg", + "Anthurium%20clarinervium": null, + "Anthurium clarinervium": "https://upload.wikimedia.org/wikipedia/commons/6/65/Anthurium_clarinervium.jpg", + "Rumex%20acetosa": null, + "Rumex acetosa": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/Rumex_acetosa_-_Hapu_oblikas.jpg/1280px-Rumex_acetosa_-_Hapu_oblikas.jpg", + "Buddleja%20davidii": null, + "Buddleja davidii": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Distelfalter%2C_Vanessa_cardui_AUF_Schmetterlingsflieder%2C_Buddleja_davidii_1.JPG/1280px-Distelfalter%2C_Vanessa_cardui_AUF_Schmetterlingsflieder%2C_Buddleja_davidii_1.JPG", + "Allium%20tuberosum": null, + "Allium tuberosum": "https://upload.wikimedia.org/wikipedia/commons/a/a8/Allium_tuberosum1.jpg", + "Asclepias%20tuberosa": null, + "Asclepias tuberosa": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Butterfly_Weed_Asclepias_tuberosa_Flower_Buds_3008px.jpg/1280px-Butterfly_Weed_Asclepias_tuberosa_Flower_Buds_3008px.jpg", + "Leucanthemum%20x%20superbum": null, + "Perilla%20frutescens": null, + "Leucanthemum x superbum": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/Leucanthemum_x_superbum_%27Becky%27_in_NH.jpg/1280px-Leucanthemum_x_superbum_%27Becky%27_in_NH.jpg", + "Perilla frutescens": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/Perilla_frutescens%27_flower.jpg/1280px-Perilla_frutescens%27_flower.jpg", + "Helianthus%20annuus": null, + "Spiraea%20japonica": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Spiraea_japonica_%27Gold_Mound%27_6_2021_Japanese_Spirea-_%2851238159051%29.jpg/1280px-Spiraea_japonica_%27Gold_Mound%27_6_2021_Japanese_Spirea-_%2851238159051%29.jpg", + "Helianthus annuus": "https://upload.wikimedia.org/wikipedia/commons/6/66/Sunflower_l.jpg", + "Acer%20platanoides": null, + "Acer platanoides": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/2020_year._Herbarium._Acer_platanoides._img-012.jpg/1280px-2020_year._Herbarium._Acer_platanoides._img-012.jpg", + "Ilex%20aquifolium": null, + "Ilex aquifolium": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4f/Mahonia_aquifolium_qtl1.jpg/1280px-Mahonia_aquifolium_qtl1.jpg", + "Pelargonium%20zonale": "https://upload.wikimedia.org/wikipedia/commons/6/64/Normal_Pelargonium-zonale-376.jpg", + "Stevia%20rebaudiana": null, + "Stevia rebaudiana": "https://upload.wikimedia.org/wikipedia/commons/d/d9/Stevia-rebaudiana-total.JPG", + "Alcea%20rosea": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Alcea_rosea_6_2021_Hollyhock-_%2851264042906%29.jpg/1280px-Alcea_rosea_6_2021_Hollyhock-_%2851264042906%29.jpg", + "Curio%20radicans": null, + "Curio radicans": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Senecio_radicans%2C_jard%C3%ADn_bot%C3%A1nico_de_Tallinn%2C_Estonia%2C_2012-08-13%2C_DD_01.JPG/1280px-Senecio_radicans%2C_jard%C3%ADn_bot%C3%A1nico_de_Tallinn%2C_Estonia%2C_2012-08-13%2C_DD_01.JPG", + "Curio%20x%20peregrinus": null, + "Curio x peregrinus": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9f/Getty_Research_Institute_%28IA_johannchristiank00kund%29.pdf/page1-725px-Getty_Research_Institute_%28IA_johannchristiank00kund%29.pdf.jpg", + "Hemerocallis%20fulva": "https://upload.wikimedia.org/wikipedia/commons/0/0e/Hemerocallis_fulva_-_flower_view_02.jpg", + "Lamprocapnos%20spectabilis": null, + "Lamprocapnos spectabilis": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/df/Tr%C3%A4nendes_Herz_%28Dicentra_spectabilis%29.jpg/1280px-Tr%C3%A4nendes_Herz_%28Dicentra_spectabilis%29.jpg", + "Catalpa%20bignonioides": null, + "Catalpa bignonioides": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Catalpa_bignonioides_Aurea_JPG1a.jpg/1280px-Catalpa_bignonioides_Aurea_JPG1a.jpg", + "Campsis%20radicans": null, + "Campsis radicans": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/Campsis_radicans_0.4_R.jpg/1280px-Campsis_radicans_0.4_R.jpg", + "Myosotis%20sylvatica": null, + "Myosotis sylvatica": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Myosotis_sylvatica_%28aka%29.jpg/1280px-Myosotis_sylvatica_%28aka%29.jpg", + "Eutrema%20japonicum": null, + "Eutrema japonicum": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5d/Wasabia_japonica_1.JPG/1280px-Wasabia_japonica_1.JPG", + "Peperomia%20argyreia": null, + "Peperomia argyreia": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/ac/Peperomia_argyreia.jpg/1280px-Peperomia_argyreia.jpg", + "Weigela%20florida": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7e/Weigela_florida_%27Bokrashine%27_%27SHINING_SENSATION%27_6_2021_Weigela-_%2851239536602%29.jpg/1280px-Weigela_florida_%27Bokrashine%27_%27SHINING_SENSATION%27_6_2021_Weigela-_%2851239536602%29.jpg", + "Hyssopus%20officinalis": null, + "Hyssopus officinalis": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Hyssopus-officinalis-habit.jpg/1280px-Hyssopus-officinalis-habit.jpg", + "Yucca%20aloifolia": null, + "Yucca aloifolia": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Yucca_aloifolia_4.jpg/1280px-Yucca_aloifolia_4.jpg", + "Cedrus%20libani": null, + "Cedrus libani": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Cedrus_libani_foliage_PAN.JPG/1280px-Cedrus_libani_foliage_PAN.JPG", + "Nicotiana%20alata": null, + "Nicotiana alata": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/45/Nicotiana_alata1By_Carl_E_Lewis.jpg/1280px-Nicotiana_alata1By_Carl_E_Lewis.jpg", + "Cymbopogon%20citratus": null, + "Cymbopogon citratus": "https://upload.wikimedia.org/wikipedia/commons/b/bd/YosriNov04Pokok_Serai.JPG", + "Aloysia%20citrodora": null, + "Aloysia citrodora": "https://upload.wikimedia.org/wikipedia/commons/a/a6/Aloysia_citriodora_002.jpg", + "Cupressus%20sempervirens": null, + "Cupressus sempervirens": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9c/Cypress_Halefka.JPG/1280px-Cypress_Halefka.JPG", + "Cycas revoluta": "https://upload.wikimedia.org/wikipedia/commons/f/f4/Cycas_revoluta1327A.JPG", + "Calendula officinalis": "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/Calendula_in_Autumn.jpg/1280px-Calendula_in_Autumn.jpg", + "Pelargonium zonale": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Pelargonium_zonale_%28Geraniaceae%29.jpg/1280px-Pelargonium_zonale_%28Geraniaceae%29.jpg", + "Hemerocallis fulva": "https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Daylily_%28Hemerocallis_fulva%29_v2.jpg/1280px-Daylily_%28Hemerocallis_fulva%29_v2.jpg", + "Garden croton": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Colpfl05.jpg/1280px-Colpfl05.jpg", + "Senecio peregrinus": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/Figure_2._Schematic_representation_of_homoploid_and_allopolyploid_hybrid_speciation._Updated.svg/1280px-Figure_2._Schematic_representation_of_homoploid_and_allopolyploid_hybrid_speciation._Updated.svg.png" +} \ No newline at end of file diff --git a/server/public/plants/wisteria-sinensis--chinesischer-blauregen--8887793e.webp b/server/public/plants/wisteria-sinensis--chinesischer-blauregen--8887793e.webp new file mode 100644 index 0000000..9147916 Binary files /dev/null and b/server/public/plants/wisteria-sinensis--chinesischer-blauregen--8887793e.webp differ diff --git a/server/public/plants/yucca-aloifolia--ce8ca7a3.webp b/server/public/plants/yucca-aloifolia--ce8ca7a3.webp new file mode 100644 index 0000000..9828eba Binary files /dev/null and b/server/public/plants/yucca-aloifolia--ce8ca7a3.webp differ diff --git a/server/public/plants/yucca-elephantipes--yucca-palme--1e34e66e.webp b/server/public/plants/yucca-elephantipes--yucca-palme--1e34e66e.webp new file mode 100644 index 0000000..d4e6d58 Binary files /dev/null and b/server/public/plants/yucca-elephantipes--yucca-palme--1e34e66e.webp differ diff --git a/server/public/plants/zamioculcas-zamiifolia--zamioculcas--dd98f155.webp b/server/public/plants/zamioculcas-zamiifolia--zamioculcas--dd98f155.webp new file mode 100644 index 0000000..b582dfb Binary files /dev/null and b/server/public/plants/zamioculcas-zamiifolia--zamioculcas--dd98f155.webp differ diff --git a/server/public/plants/zantedeschia-aethiopica--calla--c739da85.webp b/server/public/plants/zantedeschia-aethiopica--calla--c739da85.webp new file mode 100644 index 0000000..5a63503 Binary files /dev/null and b/server/public/plants/zantedeschia-aethiopica--calla--c739da85.webp differ diff --git a/server/public/plants/zingiber-officinale--ingwer--597975c9.webp b/server/public/plants/zingiber-officinale--ingwer--597975c9.webp new file mode 100644 index 0000000..911d0cd Binary files /dev/null and b/server/public/plants/zingiber-officinale--ingwer--597975c9.webp differ diff --git a/server/public/plants/zinnia-elegans--zinnie--6d666757.webp b/server/public/plants/zinnia-elegans--zinnie--6d666757.webp new file mode 100644 index 0000000..c22ec34 Binary files /dev/null and b/server/public/plants/zinnia-elegans--zinnie--6d666757.webp differ diff --git a/server/scripts/download-plant-images.js b/server/scripts/download-plant-images.js new file mode 100644 index 0000000..3a85ff3 --- /dev/null +++ b/server/scripts/download-plant-images.js @@ -0,0 +1,486 @@ +#!/usr/bin/env node +/* eslint-disable no-console */ +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); +require('dotenv').config(); + +const sharp = require('sharp'); +const { openDatabase, closeDatabase, all, run } = require('../lib/sqlite'); +const { ensurePlantSchema } = require('../lib/plants'); + +const OUTPUT_DIR = path.join(__dirname, '..', 'public', 'plants'); +const MANIFEST_PATH = path.join(OUTPUT_DIR, 'manifest.json'); +const ROOT_DIR = path.join(__dirname, '..', '..'); +const PLANTS_DUMP_PATH = path.join(ROOT_DIR, 'plants_dump_utf8.json'); +const SEARCH_CACHE_PATH = path.join(OUTPUT_DIR, 'wikimedia-search-cache.json'); +const MAX_CONCURRENCY = Number(process.env.PLANT_IMAGE_CONCURRENCY || 1); +const REQUEST_TIMEOUT_MS = 20000; +const MAX_FETCH_RETRIES = 5; +const WIKIMEDIA_SEARCH_PREFIX = 'wikimedia-search:'; + +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +const slugify = (value) => { + const normalized = String(value || '') + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .toLowerCase() + .replace(/[^a-z0-9]+/g, '-') + .replace(/^-+|-+$/g, ''); + return normalized || 'plant'; +}; + +const buildFileBaseName = (plant) => { + const botanicalSlug = slugify(plant.botanicalName); + const nameSlug = slugify(plant.name); + const suffix = crypto + .createHash('sha1') + .update(`${plant.id}|${plant.botanicalName}|${plant.name}`) + .digest('hex') + .slice(0, 8); + + if (nameSlug && nameSlug !== botanicalSlug) { + return `${botanicalSlug}--${nameSlug}--${suffix}`; + } + + return `${botanicalSlug}--${suffix}`; +}; + +const ensureOutputDir = () => { + fs.mkdirSync(OUTPUT_DIR, { recursive: true }); +}; + +const loadRefreshMatchers = () => new Set( + String(process.env.PLANT_IMAGE_REFRESH || '') + .split(',') + .map((value) => value.trim().toLowerCase()) + .filter(Boolean), +); + +const loadManifest = () => { + try { + const raw = fs.readFileSync(MANIFEST_PATH, 'utf8'); + return JSON.parse(raw); + } catch { + return { generatedAt: null, items: [] }; + } +}; + +const saveManifest = (manifest) => { + fs.writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2)); +}; + +const loadSearchCache = () => { + try { + return JSON.parse(fs.readFileSync(SEARCH_CACHE_PATH, 'utf8')); + } catch { + return {}; + } +}; + +const saveSearchCache = (cache) => { + fs.writeFileSync(SEARCH_CACHE_PATH, JSON.stringify(cache, null, 2)); +}; + +const shouldRefreshPlantImage = (plant, refreshMatchers) => { + if (!refreshMatchers || refreshMatchers.size === 0) return false; + + return [ + plant.id, + plant.name, + plant.botanicalName, + ].some((value) => refreshMatchers.has(String(value || '').trim().toLowerCase())); +}; + +const loadDumpFallbackMap = () => { + try { + const raw = fs.readFileSync(PLANTS_DUMP_PATH, 'utf8'); + const entries = JSON.parse(raw); + if (!Array.isArray(entries)) return new Map(); + + const map = new Map(); + for (const entry of entries) { + if (!entry || typeof entry.botanicalName !== 'string' || typeof entry.imageUri !== 'string') continue; + const key = entry.botanicalName.trim().toLowerCase(); + if (!key || !/^https?:\/\//i.test(entry.imageUri)) continue; + if (!map.has(key)) map.set(key, entry.imageUri.trim()); + } + return map; + } catch { + return new Map(); + } +}; + +const getRetryDelayMs = (attempt, retryAfterHeader) => { + const retryAfterSeconds = Number(retryAfterHeader); + if (Number.isFinite(retryAfterSeconds) && retryAfterSeconds > 0) { + return retryAfterSeconds * 1000; + } + return Math.min(30000, 3000 * 2 ** attempt); +}; + +const tryDecode = (value) => { + try { + return decodeURIComponent(value); + } catch { + return value; + } +}; + +const decodeRepeatedly = (value, rounds = 3) => { + let current = value; + for (let index = 0; index < rounds; index += 1) { + const decoded = tryDecode(current); + if (decoded === current) break; + current = decoded; + } + return current; +}; + +const toWikimediaFilePathUrl = (rawUrl) => { + if (typeof rawUrl !== 'string' || !rawUrl.includes('upload.wikimedia.org/wikipedia/commons/')) { + return null; + } + + const cleanUrl = rawUrl.split(/[?#]/)[0]; + const parts = cleanUrl.split('/').filter(Boolean); + if (parts.length < 2) return null; + + let fileName = null; + const thumbIndex = parts.indexOf('thumb'); + + if (thumbIndex >= 0 && parts.length >= thumbIndex + 5) { + fileName = parts[parts.length - 2]; + } else { + fileName = parts[parts.length - 1]; + } + + if (!fileName) return null; + const decoded = tryDecode(fileName).trim(); + if (!decoded) return null; + + return `https://commons.wikimedia.org/wiki/Special:FilePath/${encodeURIComponent(decoded)}`; +}; + +const parseWikimediaSearchQuery = (value) => { + if (typeof value !== 'string') return null; + + const trimmed = value.trim(); + if (!trimmed.toLowerCase().startsWith(WIKIMEDIA_SEARCH_PREFIX)) return null; + + const rawQuery = trimmed.slice(WIKIMEDIA_SEARCH_PREFIX.length).trim(); + if (!rawQuery) return null; + + return decodeRepeatedly(rawQuery); +}; + +const fetchImageBuffer = async (url, attempt = 0, redirectCount = 0) => { + if (redirectCount > 5) { + throw new Error('Too many redirects'); + } + + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS); + + try { + const response = await fetch(url, { + headers: { + 'User-Agent': 'GreenLens-PlantImageImporter/1.0', + 'Accept': 'image/avif,image/webp,image/apng,image/*,*/*;q=0.8', + 'Referer': 'https://commons.wikimedia.org/', + }, + redirect: 'manual', + signal: controller.signal, + }); + + if ([301, 302, 303, 307, 308].includes(response.status)) { + const location = response.headers.get('location'); + if (!location) throw new Error(`Redirect without location for ${url}`); + const nextUrl = new URL(location, url).toString(); + return fetchImageBuffer(nextUrl, attempt, redirectCount + 1); + } + + if ((response.status === 429 || response.status >= 500) && attempt < MAX_FETCH_RETRIES) { + const delayMs = getRetryDelayMs(attempt, response.headers.get('retry-after')); + await sleep(delayMs); + return fetchImageBuffer(url, attempt + 1, redirectCount); + } + + if (!response.ok) { + throw new Error(`HTTP ${response.status}`); + } + + const arrayBuffer = await response.arrayBuffer(); + return Buffer.from(arrayBuffer); + } finally { + clearTimeout(timeout); + } +}; + +const searchWikimediaImage = async (query, searchCache) => { + const normalizedQuery = String(query || '').trim(); + if (!normalizedQuery) return null; + + if (Object.prototype.hasOwnProperty.call(searchCache, normalizedQuery)) { + return searchCache[normalizedQuery] || null; + } + + const apiUrl = `https://commons.wikimedia.org/w/api.php?action=query&generator=search&gsrnamespace=6&gsrsearch=${encodeURIComponent(normalizedQuery)}&gsrlimit=5&prop=imageinfo&iiprop=url&iiurlwidth=1200&format=json`; + + try { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS); + const response = await fetch(apiUrl, { + headers: { + 'User-Agent': 'GreenLens-PlantImageImporter/1.0', + 'Accept': 'application/json', + }, + signal: controller.signal, + }); + clearTimeout(timeout); + + if (!response.ok) { + searchCache[normalizedQuery] = null; + saveSearchCache(searchCache); + return null; + } + + const data = await response.json(); + const pages = data?.query?.pages ? Object.values(data.query.pages) : []; + + for (const page of pages) { + const imageInfo = page?.imageinfo?.[0]; + const candidate = imageInfo?.thumburl || imageInfo?.url || null; + if (candidate && /^https?:\/\//i.test(candidate)) { + searchCache[normalizedQuery] = candidate; + saveSearchCache(searchCache); + return candidate; + } + } + } catch { + // Ignore and cache as null below. + } + + searchCache[normalizedQuery] = null; + saveSearchCache(searchCache); + return null; +}; + +const convertToWebp = async (inputBuffer, outputPath) => { + const tempPath = `${outputPath}.tmp-${process.pid}-${Date.now()}.webp`; + await sharp(inputBuffer) + .rotate() + .resize({ + width: 1200, + height: 1200, + fit: 'inside', + withoutEnlargement: true, + }) + .webp({ quality: 82 }) + .toFile(tempPath); + + fs.copyFileSync(tempPath, outputPath); + fs.unlinkSync(tempPath); +}; + +const updatePlantImageUri = async (db, plantId, localImageUri) => { + await run( + db, + 'UPDATE plants SET imageUri = ?, imageStatus = ?, updatedAt = datetime(\'now\') WHERE id = ?', + [localImageUri, 'ok', plantId], + ); +}; + +const processPlant = async (db, plant, manifestItems, dumpFallbackMap, searchCache, refreshMatchers) => { + const currentUri = String(plant.imageUri || '').trim(); + const placeholderQuery = parseWikimediaSearchQuery(currentUri); + const fileBaseName = buildFileBaseName(plant); + const fileName = `${fileBaseName}.webp`; + const localImageUri = `/plants/${fileName}`; + const outputPath = path.join(OUTPUT_DIR, fileName); + const dumpFallbackUri = dumpFallbackMap.get(String(plant.botanicalName || '').trim().toLowerCase()) || null; + const shouldRefresh = shouldRefreshPlantImage(plant, refreshMatchers); + + if (fs.existsSync(outputPath) && !shouldRefresh) { + await updatePlantImageUri(db, plant.id, localImageUri); + manifestItems.push({ + id: plant.id, + botanicalName: plant.botanicalName, + name: plant.name, + sourceUri: currentUri, + localImageUri, + status: 'existing', + }); + return { status: 'existing', plantId: plant.id, localImageUri }; + } + + if (!/^https?:\/\//i.test(currentUri) && !placeholderQuery) { + manifestItems.push({ + id: plant.id, + botanicalName: plant.botanicalName, + name: plant.name, + sourceUri: currentUri, + localImageUri, + status: 'skipped', + reason: 'Current imageUri is not a remote URL and no local file exists yet.', + }); + return { status: 'skipped', plantId: plant.id, localImageUri }; + } + + let lastError = null; + let sourceUsed = currentUri; + let buffer = null; + + const searchedUri = await searchWikimediaImage(placeholderQuery, searchCache) + || await searchWikimediaImage(plant.botanicalName, searchCache) + || await searchWikimediaImage(plant.name, searchCache); + + const candidateUris = [ + /^https?:\/\//i.test(currentUri) ? currentUri : null, + /^https?:\/\//i.test(currentUri) ? toWikimediaFilePathUrl(currentUri) : null, + dumpFallbackUri, + toWikimediaFilePathUrl(dumpFallbackUri), + searchedUri, + toWikimediaFilePathUrl(searchedUri), + ].filter(Boolean); + + for (const candidateUri of [...new Set(candidateUris)]) { + try { + buffer = await fetchImageBuffer(candidateUri); + sourceUsed = candidateUri; + break; + } catch (error) { + lastError = error; + } + } + + if (!buffer) { + throw lastError || new Error('Image download failed'); + } + + await convertToWebp(buffer, outputPath); + await updatePlantImageUri(db, plant.id, localImageUri); + + manifestItems.push({ + id: plant.id, + botanicalName: plant.botanicalName, + name: plant.name, + sourceUri: sourceUsed, + localImageUri, + status: 'downloaded', + }); + + await sleep(900); + return { status: 'downloaded', plantId: plant.id, localImageUri }; +}; + +const runWithConcurrency = async (items, worker, concurrency) => { + const queue = [...items]; + const results = []; + + const runners = Array.from({ length: Math.min(concurrency, queue.length) }, async () => { + while (queue.length > 0) { + const item = queue.shift(); + if (!item) return; + results.push(await worker(item)); + } + }); + + await Promise.all(runners); + return results; +}; + +const main = async () => { + ensureOutputDir(); + const manifest = loadManifest(); + const manifestItems = []; + const dumpFallbackMap = loadDumpFallbackMap(); + const searchCache = loadSearchCache(); + const refreshMatchers = loadRefreshMatchers(); + const db = await openDatabase(); + + try { + await ensurePlantSchema(db); + const plants = await all( + db, + `SELECT id, name, botanicalName, imageUri + FROM plants + ORDER BY name COLLATE NOCASE ASC`, + ); + + console.log(`Preparing ${plants.length} plant images...`); + + const failures = []; + let completed = 0; + + await runWithConcurrency( + plants, + async (plant) => { + try { + const result = await processPlant(db, plant, manifestItems, dumpFallbackMap, searchCache, refreshMatchers); + completed += 1; + console.log(`[${completed}/${plants.length}] ${plant.botanicalName} -> ${result.status}`); + return result; + } catch (error) { + completed += 1; + const message = error instanceof Error ? error.message : String(error); + console.error(`[${completed}/${plants.length}] ${plant.botanicalName} -> failed: ${message}`); + failures.push({ + id: plant.id, + name: plant.name, + botanicalName: plant.botanicalName, + sourceUri: plant.imageUri, + error: message, + }); + manifestItems.push({ + id: plant.id, + botanicalName: plant.botanicalName, + name: plant.name, + sourceUri: plant.imageUri, + status: 'failed', + error: message, + }); + return { status: 'failed', plantId: plant.id }; + } + }, + MAX_CONCURRENCY, + ); + + const downloadedCount = manifestItems.filter((item) => item.status === 'downloaded').length; + const existingCount = manifestItems.filter((item) => item.status === 'existing').length; + const skippedCount = manifestItems.filter((item) => item.status === 'skipped').length; + + saveManifest({ + generatedAt: new Date().toISOString(), + summary: { + totalPlants: plants.length, + downloadedCount, + existingCount, + skippedCount, + failureCount: failures.length, + }, + failures, + items: manifestItems, + }); + + console.log(''); + console.log(`Downloaded: ${downloadedCount}`); + console.log(`Already present: ${existingCount}`); + console.log(`Skipped: ${skippedCount}`); + console.log(`Failed: ${failures.length}`); + console.log(`Manifest: ${MANIFEST_PATH}`); + + if (failures.length > 0) { + process.exitCode = 1; + } + } finally { + await closeDatabase(db); + } +}; + +main().catch((error) => { + console.error('Plant image import failed.'); + console.error(error instanceof Error ? error.stack || error.message : String(error)); + process.exit(1); +}); diff --git a/services/authService.ts b/services/authService.ts index 04dd32d..102f116 100644 --- a/services/authService.ts +++ b/services/authService.ts @@ -118,4 +118,20 @@ export const AuthService = { return 'unreachable'; } }, + + async checkIfFirstRun(): Promise { + const flag = await SecureStore.getItemAsync('greenlens_first_run_complete'); + return flag !== 'true'; + }, + + async markFirstRunComplete(): Promise { + await SecureStore.setItemAsync('greenlens_first_run_complete', 'true'); + }, + + async clearAllData(): Promise { + await clearStoredSession(); + await SecureStore.deleteItemAsync('greenlens_first_run_complete'); + // Note: SQLite tables aren't cleared here to avoid destroying user data + // without explicit consent, but session tokens are wiped. + }, }; diff --git a/services/backend/backendApiClient.ts b/services/backend/backendApiClient.ts new file mode 100644 index 0000000..d26cd8f --- /dev/null +++ b/services/backend/backendApiClient.ts @@ -0,0 +1,277 @@ +import { + BackendApiError, + BackendErrorCode, + BillingSummary, + HealthCheckResponse, + PurchaseProductId, + ScanPlantResponse, + SemanticSearchResponse, + ServiceHealthResponse, + SimulatedWebhookEvent, + SimulatePurchaseResponse, + SimulateWebhookResponse, +} from './contracts'; +import { getAuthToken } from './userIdentityService'; +import { mockBackendService } from './mockBackendService'; +import { CareInfo, Language } from '../../types'; + +const BACKEND_BASE_URL = (process.env.EXPO_PUBLIC_BACKEND_URL || process.env.EXPO_PUBLIC_PAYMENT_SERVER_URL || '').trim(); +const REQUEST_TIMEOUT_MS = 15000; + +const mapHttpStatusToErrorCode = (status: number): BackendErrorCode => { + if (status === 400) return 'BAD_REQUEST'; + if (status === 401 || status === 403) return 'UNAUTHORIZED'; + if (status === 402) return 'INSUFFICIENT_CREDITS'; + if (status === 408 || status === 504) return 'TIMEOUT'; + return 'PROVIDER_ERROR'; +}; + +const buildBackendUrl = (path: string): string => { + const base = BACKEND_BASE_URL.replace(/\/$/, ''); + return `${base}${path}`; +}; + +const parseMaybeJson = (value: string): Record | null => { + if (!value) return null; + try { + return JSON.parse(value) as Record; + } catch { + return null; + } +}; + +const makeRequest = async ( + path: string, + options: { + method: 'GET' | 'POST'; + token: string; + idempotencyKey?: string; + body?: Record; + }, +): Promise => { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS); + + try { + const headers: Record = { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${options.token}`, + }; + if (options.idempotencyKey) { + headers['Idempotency-Key'] = options.idempotencyKey; + } + + const response = await fetch(buildBackendUrl(path), { + method: options.method, + headers, + body: options.body ? JSON.stringify(options.body) : undefined, + signal: controller.signal, + }); + + const rawText = await response.text(); + const jsonPayload = parseMaybeJson(rawText); + + if (!response.ok) { + const payloadCode = jsonPayload?.code; + const code = typeof payloadCode === 'string' + ? payloadCode as BackendErrorCode + : mapHttpStatusToErrorCode(response.status); + const payloadMessage = jsonPayload?.message; + const message = typeof payloadMessage === 'string' + ? payloadMessage + : `Backend request failed with status ${response.status}.`; + throw new BackendApiError(code, message, response.status, jsonPayload || undefined); + } + + if (jsonPayload == null) { + throw new BackendApiError('PROVIDER_ERROR', 'Backend returned invalid JSON.', 502); + } + + return jsonPayload as T; + } catch (error) { + if (error instanceof BackendApiError) throw error; + if (error instanceof Error && error.name === 'AbortError') { + throw new BackendApiError('TIMEOUT', 'Backend request timed out.', 408); + } + throw new BackendApiError('PROVIDER_ERROR', 'Backend request failed unexpectedly.', 500, { + detail: error instanceof Error ? error.message : String(error), + }); + } finally { + clearTimeout(timeout); + } +}; + +export const backendApiClient = { + getServiceHealth: async (): Promise => { + if (!BACKEND_BASE_URL) { + return { + ok: true, + uptimeSec: 0, + timestamp: new Date().toISOString(), + openAiConfigured: Boolean(process.env.EXPO_PUBLIC_OPENAI_API_KEY), + dbReady: true, + dbPath: 'in-app-mock-backend', + stripeConfigured: Boolean(process.env.EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY), + scanModel: (process.env.EXPO_PUBLIC_OPENAI_SCAN_MODEL || 'gpt-5').trim(), + healthModel: (process.env.EXPO_PUBLIC_OPENAI_HEALTH_MODEL || process.env.EXPO_PUBLIC_OPENAI_SCAN_MODEL || 'gpt-5').trim(), + }; + } + + const token = await getAuthToken(); + return makeRequest('/health', { + method: 'GET', + token, + }); + }, + + getBillingSummary: async (): Promise => { + const token = await getAuthToken(); + if (!BACKEND_BASE_URL) { + return mockBackendService.getBillingSummary(token); + } + + return makeRequest('/v1/billing/summary', { + method: 'GET', + token, + }); + }, + + scanPlant: async (params: { + idempotencyKey: string; + imageUri: string; + language: Language; + }): Promise => { + const token = await getAuthToken(); + if (!BACKEND_BASE_URL) { + return mockBackendService.scanPlant({ + userId: token, + idempotencyKey: params.idempotencyKey, + imageUri: params.imageUri, + language: params.language, + }); + } + + return makeRequest('/v1/scan', { + method: 'POST', + token, + idempotencyKey: params.idempotencyKey, + body: { + imageUri: params.imageUri, + language: params.language, + }, + }); + }, + + semanticSearch: async (params: { + idempotencyKey: string; + query: string; + language: Language; + }): Promise => { + const token = await getAuthToken(); + if (!BACKEND_BASE_URL) { + return mockBackendService.semanticSearch({ + userId: token, + idempotencyKey: params.idempotencyKey, + query: params.query, + language: params.language, + }); + } + + return makeRequest('/v1/search/semantic', { + method: 'POST', + token, + idempotencyKey: params.idempotencyKey, + body: { + query: params.query, + language: params.language, + }, + }); + }, + + runHealthCheck: async (params: { + idempotencyKey: string; + imageUri: string; + language: Language; + plantContext?: { + name: string; + botanicalName: string; + careInfo: CareInfo; + description?: string; + }; + }): Promise => { + const token = await getAuthToken(); + if (!BACKEND_BASE_URL) { + return mockBackendService.healthCheck({ + userId: token, + idempotencyKey: params.idempotencyKey, + imageUri: params.imageUri, + language: params.language, + plantContext: params.plantContext, + }); + } + + return makeRequest('/v1/health-check', { + method: 'POST', + token, + idempotencyKey: params.idempotencyKey, + body: { + imageUri: params.imageUri, + language: params.language, + plantContext: params.plantContext, + }, + }); + }, + + simulatePurchase: async (params: { + idempotencyKey: string; + productId: PurchaseProductId; + }): Promise => { + const token = await getAuthToken(); + if (!BACKEND_BASE_URL) { + return mockBackendService.simulatePurchase({ + userId: token, + idempotencyKey: params.idempotencyKey, + productId: params.productId, + }); + } + + return makeRequest('/v1/billing/simulate-purchase', { + method: 'POST', + token, + idempotencyKey: params.idempotencyKey, + body: { + productId: params.productId, + }, + }); + }, + + simulateWebhook: async (params: { + idempotencyKey: string; + event: SimulatedWebhookEvent; + payload?: { credits?: number }; + }): Promise => { + const token = await getAuthToken(); + if (!BACKEND_BASE_URL) { + return mockBackendService.simulateWebhook({ + userId: token, + idempotencyKey: params.idempotencyKey, + event: params.event, + payload: params.payload, + }); + } + + return makeRequest('/v1/billing/simulate-webhook', { + method: 'POST', + token, + idempotencyKey: params.idempotencyKey, + body: { + event: params.event, + payload: params.payload || {}, + }, + }); + }, +}; + +export const isInsufficientCreditsError = (error: unknown): boolean => { + return error instanceof BackendApiError && error.code === 'INSUFFICIENT_CREDITS'; +}; diff --git a/services/backend/contracts.ts b/services/backend/contracts.ts new file mode 100644 index 0000000..57162f6 --- /dev/null +++ b/services/backend/contracts.ts @@ -0,0 +1,156 @@ +import { CareInfo, IdentificationResult, Language, PlantHealthCheck } from '../../types'; + +export type PlanId = 'free' | 'pro'; +export type BillingProvider = 'mock' | 'revenuecat' | 'stripe'; +export type PurchaseProductId = 'monthly_pro' | 'yearly_pro' | 'topup_small' | 'topup_medium' | 'topup_large'; +export type SimulatedWebhookEvent = + | 'entitlement_granted' + | 'entitlement_revoked' + | 'topup_granted' + | 'credits_depleted'; + +export interface BackendDatabaseEntry extends IdentificationResult { + imageUri: string; + imageStatus?: 'ok' | 'missing' | 'invalid'; + categories: string[]; +} + +export interface CreditState { + monthlyAllowance: number; + usedThisCycle: number; + topupBalance: number; + available: number; + cycleStartedAt: string; + cycleEndsAt: string; +} + +export interface EntitlementState { + plan: PlanId; + provider: BillingProvider; + status: 'active' | 'inactive'; + renewsAt: string | null; +} + +export interface BillingSummary { + entitlement: EntitlementState; + credits: CreditState; + availableProducts: PurchaseProductId[]; +} + +export interface ScanPlantRequest { + userId: string; + idempotencyKey: string; + imageUri: string; + language: Language; +} + +export interface ScanPlantResponse { + result: IdentificationResult; + creditsCharged: number; + modelPath: string[]; + modelUsed?: string | null; + modelFallbackCount?: number; + billing: BillingSummary; +} + +export interface SemanticSearchRequest { + userId: string; + idempotencyKey: string; + query: string; + language: Language; +} + +export interface SemanticSearchResponse { + status: 'success' | 'no_results'; + results: BackendDatabaseEntry[]; + creditsCharged: number; + billing: BillingSummary; +} + +export interface HealthCheckRequest { + userId: string; + idempotencyKey: string; + imageUri: string; + language: Language; + plantContext?: { + name: string; + botanicalName: string; + careInfo: CareInfo; + description?: string; + }; +} + +export interface HealthCheckResponse { + healthCheck: PlantHealthCheck; + creditsCharged: number; + modelUsed?: string | null; + modelFallbackCount?: number; + billing: BillingSummary; +} + +export interface ServiceHealthResponse { + ok: boolean; + uptimeSec: number; + timestamp: string; + openAiConfigured: boolean; + dbReady?: boolean; + dbPath?: string; + stripeConfigured?: boolean; + scanModel?: string; + healthModel?: string; +} + +export interface SimulatePurchaseRequest { + userId: string; + idempotencyKey: string; + productId: PurchaseProductId; +} + +export interface SimulatePurchaseResponse { + appliedProduct: PurchaseProductId; + billing: BillingSummary; +} + +export interface SimulateWebhookRequest { + userId: string; + idempotencyKey: string; + event: SimulatedWebhookEvent; + payload?: { + credits?: number; + }; +} + +export interface SimulateWebhookResponse { + event: SimulatedWebhookEvent; + billing: BillingSummary; +} + +export type BackendErrorCode = + | 'INSUFFICIENT_CREDITS' + | 'UNAUTHORIZED' + | 'TIMEOUT' + | 'PROVIDER_ERROR' + | 'BAD_REQUEST'; + +export class BackendApiError extends Error { + public readonly code: BackendErrorCode; + public readonly status: number; + public readonly metadata?: Record; + + constructor( + code: BackendErrorCode, + message: string, + status = 500, + metadata?: Record, + ) { + super(message); + this.name = 'BackendApiError'; + this.code = code; + this.status = status; + this.metadata = metadata; + } +} + +export const isBackendApiError = (error: unknown): error is BackendApiError => { + return error instanceof BackendApiError; +}; diff --git a/services/backend/mockBackendService.ts b/services/backend/mockBackendService.ts new file mode 100644 index 0000000..1d94b18 --- /dev/null +++ b/services/backend/mockBackendService.ts @@ -0,0 +1,975 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; +import { + BackendApiError, + BillingProvider, + BillingSummary, + HealthCheckRequest, + HealthCheckResponse, + PlanId, + PurchaseProductId, + ScanPlantRequest, + ScanPlantResponse, + SemanticSearchRequest, + SemanticSearchResponse, + SimulatePurchaseRequest, + SimulatePurchaseResponse, + SimulateWebhookRequest, + SimulateWebhookResponse, + isBackendApiError, +} from './contracts'; +import { getMockPlantByImage, searchMockCatalog } from './mockCatalog'; +import { openAiScanService } from './openAiScanService'; +import { IdentificationResult, PlantHealthCheck } from '../../types'; + +const MOCK_ACCOUNT_STORE_KEY = 'greenlens_mock_backend_accounts_v1'; +const MOCK_IDEMPOTENCY_STORE_KEY = 'greenlens_mock_backend_idempotency_v1'; + +const FREE_MONTHLY_CREDITS = 15; +const GUEST_TRIAL_CREDITS = 5; +const PRO_MONTHLY_CREDITS = 250; + +const SCAN_PRIMARY_COST = 1; +const SCAN_REVIEW_COST = 1; +const SEMANTIC_SEARCH_COST = 2; +const HEALTH_CHECK_COST = 2; + +const LOW_CONFIDENCE_REVIEW_THRESHOLD = 0.8; +const FREE_SIMULATED_DELAY_MS = 1100; +const PRO_SIMULATED_DELAY_MS = 280; + +const TOPUP_DEFAULT_CREDITS = 60; + +const TOPUP_CREDITS_BY_PRODUCT: Record = { + monthly_pro: 0, + yearly_pro: 0, + topup_small: 25, + topup_medium: 75, + topup_large: 200, +}; + +interface MockAccountRecord { + userId: string; + plan: PlanId; + provider: BillingProvider; + cycleStartedAt: string; + cycleEndsAt: string; + monthlyAllowance: number; + usedThisCycle: number; + topupBalance: number; + renewsAt: string | null; + updatedAt: string; +} + +interface IdempotencyRecord { + response: unknown; + createdAt: string; +} + +type AccountStore = Record; +type IdempotencyStore = Record; + +const userLocks = new Map>(); + +const nowIso = (): string => new Date().toISOString(); + +const startOfUtcMonth = (date: Date): Date => { + return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1, 0, 0, 0, 0)); +}; + +const addUtcMonths = (date: Date, months: number): Date => { + return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + months, 1, 0, 0, 0, 0)); +}; + +const addDays = (date: Date, days: number): Date => { + const result = new Date(date.getTime()); + result.setUTCDate(result.getUTCDate() + days); + return result; +}; + +const getCycleBounds = (now: Date) => { + const cycleStartedAt = startOfUtcMonth(now); + const cycleEndsAt = addUtcMonths(cycleStartedAt, 1); + return { cycleStartedAt, cycleEndsAt }; +}; + +const getMonthlyAllowanceForPlan = (plan: PlanId, userId?: string): number => { + if (userId === 'guest') return GUEST_TRIAL_CREDITS; + return plan === 'pro' ? PRO_MONTHLY_CREDITS : FREE_MONTHLY_CREDITS; +}; + +const getSimulatedDelay = (plan: PlanId): number => { + return plan === 'pro' ? PRO_SIMULATED_DELAY_MS : FREE_SIMULATED_DELAY_MS; +}; + +const sleep = async (ms: number): Promise => { + if (ms <= 0) return; + await new Promise(resolve => setTimeout(resolve, ms)); +}; + +const withUserLock = async (userId: string, worker: () => Promise): Promise => { + const previousLock = userLocks.get(userId) || Promise.resolve(); + let releaseLock: () => void = () => {}; + const activeLock = new Promise((resolve) => { + releaseLock = resolve; + }); + userLocks.set(userId, activeLock); + + await previousLock; + try { + return await worker(); + } finally { + releaseLock(); + if (userLocks.get(userId) === activeLock) { + userLocks.delete(userId); + } + } +}; + +const readJson = async (key: string, fallbackValue: T): Promise => { + try { + const raw = await AsyncStorage.getItem(key); + if (!raw) return fallbackValue; + return JSON.parse(raw) as T; + } catch (error) { + console.error(`Failed to read mock backend key ${key}`, error); + return fallbackValue; + } +}; + +const writeJson = async (key: string, value: T): Promise => { + try { + await AsyncStorage.setItem(key, JSON.stringify(value)); + } catch (error) { + console.error(`Failed to write mock backend key ${key}`, error); + } +}; + +const loadStores = async (): Promise<{ accounts: AccountStore; idempotency: IdempotencyStore }> => { + const [accounts, idempotency] = await Promise.all([ + readJson(MOCK_ACCOUNT_STORE_KEY, {}), + readJson(MOCK_IDEMPOTENCY_STORE_KEY, {}), + ]); + return { accounts, idempotency }; +}; + +const persistStores = async (stores: { accounts: AccountStore; idempotency: IdempotencyStore }): Promise => { + await Promise.all([ + writeJson(MOCK_ACCOUNT_STORE_KEY, stores.accounts), + writeJson(MOCK_IDEMPOTENCY_STORE_KEY, stores.idempotency), + ]); +}; + +const buildDefaultAccount = (userId: string, now: Date): MockAccountRecord => { + const { cycleStartedAt, cycleEndsAt } = getCycleBounds(now); + const allowance = getMonthlyAllowanceForPlan('free', userId); + return { + userId, + plan: 'free', + provider: 'mock', + cycleStartedAt: cycleStartedAt.toISOString(), + cycleEndsAt: cycleEndsAt.toISOString(), + monthlyAllowance: allowance, + usedThisCycle: 0, + topupBalance: 0, + renewsAt: null, + updatedAt: nowIso(), + }; +}; + +const alignAccountToCurrentCycle = (account: MockAccountRecord, now: Date): MockAccountRecord => { + const next = { ...account }; + const expectedMonthlyAllowance = getMonthlyAllowanceForPlan(next.plan, next.userId); + if (next.monthlyAllowance !== expectedMonthlyAllowance) { + next.monthlyAllowance = expectedMonthlyAllowance; + } + + if (!next.renewsAt && next.plan === 'pro' && next.provider === 'mock') { + next.renewsAt = addDays(now, 30).toISOString(); + } + + const cycleEndsAtMs = new Date(next.cycleEndsAt).getTime(); + if (Number.isNaN(cycleEndsAtMs) || now.getTime() >= cycleEndsAtMs) { + const { cycleStartedAt, cycleEndsAt } = getCycleBounds(now); + next.cycleStartedAt = cycleStartedAt.toISOString(); + next.cycleEndsAt = cycleEndsAt.toISOString(); + next.usedThisCycle = 0; + next.monthlyAllowance = expectedMonthlyAllowance; + } + + return next; +}; + +const getOrCreateAccount = (stores: { accounts: AccountStore }, userId: string): MockAccountRecord => { + const now = new Date(); + const existing = stores.accounts[userId] || buildDefaultAccount(userId, now); + const aligned = alignAccountToCurrentCycle(existing, now); + stores.accounts[userId] = aligned; + return aligned; +}; + +const getAvailableCredits = (account: MockAccountRecord): number => { + const monthlyRemaining = Math.max(0, account.monthlyAllowance - account.usedThisCycle); + return monthlyRemaining + Math.max(0, account.topupBalance); +}; + +const buildBillingSummary = (account: MockAccountRecord): BillingSummary => { + return { + entitlement: { + plan: account.plan, + provider: account.provider, + status: 'active', + renewsAt: account.renewsAt, + }, + credits: { + monthlyAllowance: account.monthlyAllowance, + usedThisCycle: account.usedThisCycle, + topupBalance: account.topupBalance, + available: getAvailableCredits(account), + cycleStartedAt: account.cycleStartedAt, + cycleEndsAt: account.cycleEndsAt, + }, + availableProducts: ['monthly_pro', 'yearly_pro', 'topup_small', 'topup_medium', 'topup_large'], + }; +}; + +const readIdempotentResponse = (store: IdempotencyStore, key: string): T | null => { + const record = store[key]; + if (!record) return null; + return record.response as T; +}; + +const writeIdempotentResponse = (store: IdempotencyStore, key: string, value: T): void => { + store[key] = { + response: value, + createdAt: nowIso(), + }; +}; + +const consumeCredits = (account: MockAccountRecord, cost: number): number => { + if (cost <= 0) return 0; + + const available = getAvailableCredits(account); + if (available < cost) { + throw new BackendApiError( + 'INSUFFICIENT_CREDITS', + `Insufficient credits. Required ${cost}, available ${available}.`, + 402, + { required: cost, available }, + ); + } + + let remaining = cost; + const monthlyRemaining = Math.max(0, account.monthlyAllowance - account.usedThisCycle); + if (monthlyRemaining > 0) { + const monthlyUsage = Math.min(monthlyRemaining, remaining); + account.usedThisCycle += monthlyUsage; + remaining -= monthlyUsage; + } + + if (remaining > 0 && account.topupBalance > 0) { + const topupUsage = Math.min(account.topupBalance, remaining); + account.topupBalance -= topupUsage; + remaining -= topupUsage; + } + + return cost; +}; + +const consumeCreditsWithIdempotency = ( + account: MockAccountRecord, + idempotencyStore: IdempotencyStore, + key: string, + cost: number, +): number => { + const existing = readIdempotentResponse<{ charged: number }>(idempotencyStore, key); + if (existing) return existing.charged; + + const charged = consumeCredits(account, cost); + writeIdempotentResponse(idempotencyStore, key, { charged }); + return charged; +}; + +const endpointKey = (scope: string, userId: string, idempotencyKey: string): string => { + return `endpoint:${scope}:${userId}:${idempotencyKey}`; +}; + +const chargeKey = (scope: string, userId: string, idempotencyKey: string): string => { + return `charge:${scope}:${userId}:${idempotencyKey}`; +}; + +const hashString = (value: string): number => { + let hash = 0; + for (let i = 0; i < value.length; i += 1) { + hash = ((hash << 5) - hash + value.charCodeAt(i)) | 0; + } + return Math.abs(hash); +}; + +const clampConfidence = (value: number): number => { + return Math.max(0.05, Math.min(0.99, Number(value.toFixed(2)))); +}; + +const buildMockHealthCheck = (request: HealthCheckRequest, creditsCharged: number): PlantHealthCheck => { + const source = [ + request.imageUri, + request.plantContext?.name || '', + request.plantContext?.botanicalName || '', + request.plantContext?.careInfo?.light || '', + request.plantContext?.careInfo?.temp || '', + ].join('|'); + const hash = hashString(source); + const score = 40 + (hash % 56); + + const status: PlantHealthCheck['status'] = score >= 75 + ? 'healthy' + : score >= 55 + ? 'watch' + : 'critical'; + + const confidenceBase = 0.45 + ((hash % 20) / 100); + const confidenceMid = 0.35 + (((hash >> 2) % 20) / 100); + const confidenceLow = 0.25 + (((hash >> 4) % 20) / 100); + + if (request.language === 'de') { + const likelyIssues = status === 'critical' + ? [ + { + title: 'Moegliche Ueberwaesserung', + confidence: clampConfidence(confidenceBase + 0.22), + details: 'Gelbe, weiche Blaetter koennen auf zu nasse Erde hindeuten.', + }, + { + title: 'Wurzelstress', + confidence: clampConfidence(confidenceMid + 0.15), + details: 'Pruefe, ob das Substrat verdichtet ist oder unangenehm riecht.', + }, + { + title: 'Lichtmangel', + confidence: clampConfidence(confidenceLow + 0.1), + details: 'Zu wenig Licht kann zu Vergilbung und schwaecherem Wuchs fuehren.', + }, + ] + : status === 'watch' + ? [ + { + title: 'Leichter Naehrstoffmangel', + confidence: clampConfidence(confidenceBase), + details: 'Ein Teil der Vergilbung kann durch fehlende Naehrstoffe entstehen.', + }, + { + title: 'Unregelmaessiges Giessen', + confidence: clampConfidence(confidenceMid), + details: 'Zu grosse Schwankungen zwischen trocken und sehr nass belasten die Pflanze.', + }, + { + title: 'Standortstress', + confidence: clampConfidence(confidenceLow), + details: 'Zugluft oder haeufige Standortwechsel koennen Blattreaktionen ausloesen.', + }, + ] + : [ + { + title: 'Leichte Lichtanpassung noetig', + confidence: clampConfidence(confidenceBase - 0.1), + details: 'Einige Blaetter zeigen milde Stressanzeichen, insgesamt wirkt die Pflanze stabil.', + }, + { + title: 'Naechsten Duengertermin beobachten', + confidence: clampConfidence(confidenceMid - 0.1), + details: 'Bei weiterem Vergilben Duengung in kleiner Dosis einplanen.', + }, + { + title: 'Normale Blattalterung', + confidence: clampConfidence(confidenceLow - 0.05), + details: 'Aeltere untere Blaetter duerfen gelegentlich gelb werden.', + }, + ]; + + const actionsNow = status === 'critical' + ? [ + 'Giessen fuer 3-5 Tage pausieren und Feuchtigkeit tief im Topf pruefen.', + 'Gelbe oder matschige Blaetter sauber entfernen.', + 'Topf auf gute Drainage pruefen; stehendes Wasser sofort entfernen.', + ] + : status === 'watch' + ? [ + 'Giessrhythmus fuer die naechsten 7 Tage konsistent halten.', + 'Pflanze heller, aber ohne harte Mittagssonne stellen.', + 'Auf Schaedlinge an Blattunterseiten kontrollieren.', + ] + : [ + 'Aktuellen Pflegeplan beibehalten.', + 'Nur bei deutlich trockener Erde giessen.', + 'Gelbe Altblaetter nach Bedarf entfernen.', + ]; + + const plan7Days = status === 'critical' + ? [ + 'Tag 1: Feuchtigkeit messen und Uebertopf entleeren.', + 'Tag 3: Blattfarbe und Festigkeit erneut pruefen.', + 'Tag 5: Bei nasser Erde Umtopfen mit luftiger Mischung erwaegen.', + 'Tag 7: Neuen Foto-Health-Check ausfuehren.', + ] + : [ + 'Tag 1: Standort und Lichtdauer notieren.', + 'Tag 3: Leichte Drehung fuer gleichmaessigen Wuchs.', + 'Tag 5: Bodenfeuchte vor Giessen kontrollieren.', + 'Tag 7: Vergleichsfoto erstellen.', + ]; + + return { + generatedAt: nowIso(), + overallHealthScore: score, + status, + likelyIssues, + actionsNow, + plan7Days, + creditsCharged, + imageUri: request.imageUri, + }; + } + + if (request.language === 'es') { + const likelyIssues = status === 'critical' + ? [ + { + title: 'Posible exceso de riego', + confidence: clampConfidence(confidenceBase + 0.22), + details: 'Hojas amarillas y blandas pueden indicar demasiada humedad.', + }, + { + title: 'Estres de raiz', + confidence: clampConfidence(confidenceMid + 0.15), + details: 'Revisa si el sustrato esta compacto o con mal olor.', + }, + { + title: 'Falta de luz', + confidence: clampConfidence(confidenceLow + 0.1), + details: 'La luz insuficiente puede causar amarilleo y crecimiento lento.', + }, + ] + : status === 'watch' + ? [ + { + title: 'Deficit leve de nutrientes', + confidence: clampConfidence(confidenceBase), + details: 'Parte del amarilleo puede venir de nutricion insuficiente.', + }, + { + title: 'Riego irregular', + confidence: clampConfidence(confidenceMid), + details: 'Cambios bruscos entre seco y muy humedo estresan la planta.', + }, + { + title: 'Estres de ubicacion', + confidence: clampConfidence(confidenceLow), + details: 'Corrientes de aire o cambios frecuentes pueden afectar las hojas.', + }, + ] + : [ + { + title: 'Ajuste suave de luz', + confidence: clampConfidence(confidenceBase - 0.1), + details: 'Se observan signos leves, pero el estado general es bueno.', + }, + { + title: 'Monitorear fertilizacion', + confidence: clampConfidence(confidenceMid - 0.1), + details: 'Si continua el amarilleo, aplicar dosis pequena de fertilizante.', + }, + { + title: 'Envejecimiento normal', + confidence: clampConfidence(confidenceLow - 0.05), + details: 'Hojas inferiores viejas pueden amarillear de forma natural.', + }, + ]; + + const actionsNow = status === 'critical' + ? [ + 'Pausar riego 3-5 dias y comprobar humedad profunda.', + 'Retirar hojas amarillas o blandas con herramienta limpia.', + 'Verificar drenaje y eliminar agua acumulada.', + ] + : status === 'watch' + ? [ + 'Mantener riego estable durante 7 dias.', + 'Mover a una zona mas luminosa sin sol fuerte directo.', + 'Revisar plagas en el reverso de las hojas.', + ] + : [ + 'Mantener rutina actual de cuidado.', + 'Regar solo cuando el sustrato este claramente seco.', + 'Retirar hojas amarillas antiguas si hace falta.', + ]; + + const plan7Days = status === 'critical' + ? [ + 'Dia 1: Medir humedad y vaciar agua retenida.', + 'Dia 3: Revisar color y firmeza de hojas.', + 'Dia 5: Si sigue muy humedo, considerar trasplante con mezcla aireada.', + 'Dia 7: Repetir health-check con foto nueva.', + ] + : [ + 'Dia 1: Registrar ubicacion y horas de luz.', + 'Dia 3: Girar planta ligeramente para crecimiento uniforme.', + 'Dia 5: Comprobar humedad antes de regar.', + 'Dia 7: Tomar foto de comparacion.', + ]; + + return { + generatedAt: nowIso(), + overallHealthScore: score, + status, + likelyIssues, + actionsNow, + plan7Days, + creditsCharged, + imageUri: request.imageUri, + }; + } + + const likelyIssues = status === 'critical' + ? [ + { + title: 'Possible overwatering', + confidence: clampConfidence(confidenceBase + 0.22), + details: 'Yellow and soft leaves can indicate excess moisture.', + }, + { + title: 'Root stress', + confidence: clampConfidence(confidenceMid + 0.15), + details: 'Check if the substrate is compacted or has a sour smell.', + }, + { + title: 'Low light stress', + confidence: clampConfidence(confidenceLow + 0.1), + details: 'Insufficient light can trigger yellowing and slower growth.', + }, + ] + : status === 'watch' + ? [ + { + title: 'Mild nutrient deficiency', + confidence: clampConfidence(confidenceBase), + details: 'Part of the yellowing may come from missing nutrients.', + }, + { + title: 'Inconsistent watering', + confidence: clampConfidence(confidenceMid), + details: 'Large swings between dry and wet can stress foliage.', + }, + { + title: 'Placement stress', + confidence: clampConfidence(confidenceLow), + details: 'Drafts or frequent location changes can affect leaves.', + }, + ] + : [ + { + title: 'Minor light adjustment', + confidence: clampConfidence(confidenceBase - 0.1), + details: 'Mild stress signs are present, but overall condition looks stable.', + }, + { + title: 'Monitor next feeding', + confidence: clampConfidence(confidenceMid - 0.1), + details: 'If yellowing continues, apply a light fertilizer dose.', + }, + { + title: 'Normal leaf aging', + confidence: clampConfidence(confidenceLow - 0.05), + details: 'Older lower leaves can yellow naturally over time.', + }, + ]; + + const actionsNow = status === 'critical' + ? [ + 'Pause watering for 3-5 days and check deep soil moisture.', + 'Remove yellow or mushy leaves with clean tools.', + 'Ensure good drainage and empty standing water.', + ] + : status === 'watch' + ? [ + 'Keep watering schedule stable for 7 days.', + 'Move to brighter indirect light.', + 'Inspect leaf undersides for pests.', + ] + : [ + 'Keep the current care routine.', + 'Water only when soil is clearly dry.', + 'Trim older yellow leaves if needed.', + ]; + + const plan7Days = status === 'critical' + ? [ + 'Day 1: Check moisture and remove excess water.', + 'Day 3: Re-check leaf color and firmness.', + 'Day 5: If still soggy, repot into an airy mix.', + 'Day 7: Run another health-check photo.', + ] + : [ + 'Day 1: Note light duration and placement.', + 'Day 3: Rotate plant slightly for even growth.', + 'Day 5: Check soil moisture before watering.', + 'Day 7: Take a comparison photo.', + ]; + + return { + generatedAt: nowIso(), + overallHealthScore: score, + status, + likelyIssues, + actionsNow, + plan7Days, + creditsCharged, + imageUri: request.imageUri, + }; +}; + +export const mockBackendService = { + getBillingSummary: async (userId: string): Promise => { + return withUserLock(userId, async () => { + const stores = await loadStores(); + const account = getOrCreateAccount(stores, userId); + account.updatedAt = nowIso(); + await persistStores(stores); + return buildBillingSummary(account); + }); + }, + + scanPlant: async (request: ScanPlantRequest): Promise => { + const { response, simulatedDelayMs } = await withUserLock(request.userId, async () => { + const stores = await loadStores(); + const account = getOrCreateAccount(stores, request.userId); + + const idemEndpointKey = endpointKey('scan', request.userId, request.idempotencyKey); + const cachedResponse = readIdempotentResponse(stores.idempotency, idemEndpointKey); + if (cachedResponse) { + return { + response: cachedResponse, + simulatedDelayMs: getSimulatedDelay(account.plan), + }; + } + + let creditsCharged = 0; + const modelPath: string[] = []; + + creditsCharged += consumeCreditsWithIdempotency( + account, + stores.idempotency, + chargeKey('scan-primary', request.userId, request.idempotencyKey), + SCAN_PRIMARY_COST, + ); + + let usedOpenAi = false; + let result: IdentificationResult = getMockPlantByImage(request.imageUri, request.language, false); + + if (openAiScanService.isConfigured()) { + const openAiPrimary = await openAiScanService.identifyPlant( + request.imageUri, + request.language, + 'primary', + account.plan === 'pro' ? 'pro' : 'free', + ); + if (openAiPrimary) { + result = openAiPrimary; + usedOpenAi = true; + modelPath.push('openai-primary'); + } else { + result = getMockPlantByImage(request.imageUri, request.language, false); + modelPath.push('openai-primary-failed'); + modelPath.push('mock-primary-fallback'); + } + } else { + modelPath.push('mock-primary'); + } + + const shouldReview = result.confidence < LOW_CONFIDENCE_REVIEW_THRESHOLD; + if (shouldReview && account.plan === 'pro') { + try { + creditsCharged += consumeCreditsWithIdempotency( + account, + stores.idempotency, + chargeKey('scan-review', request.userId, request.idempotencyKey), + SCAN_REVIEW_COST, + ); + if (usedOpenAi) { + const openAiReview = await openAiScanService.identifyPlant( + request.imageUri, + request.language, + 'review', + account.plan === 'pro' ? 'pro' : 'free', + ); + if (openAiReview) { + result = openAiReview; + modelPath.push('openai-review'); + } else { + modelPath.push('openai-review-failed'); + } + } else { + result = getMockPlantByImage(request.imageUri, request.language, true); + modelPath.push('mock-review'); + } + } catch (error) { + if (isBackendApiError(error) && error.code === 'INSUFFICIENT_CREDITS') { + modelPath.push('review-skipped-insufficient-credits'); + } else { + throw error; + } + } + } else if (shouldReview) { + modelPath.push('review-skipped-free-plan'); + } + + account.updatedAt = nowIso(); + const response: ScanPlantResponse = { + result, + creditsCharged, + modelPath, + billing: buildBillingSummary(account), + }; + + writeIdempotentResponse(stores.idempotency, idemEndpointKey, response); + await persistStores(stores); + + return { + response, + simulatedDelayMs: getSimulatedDelay(account.plan), + }; + }); + + await sleep(simulatedDelayMs); + return response; + }, + + semanticSearch: async (request: SemanticSearchRequest): Promise => { + const { response, simulatedDelayMs } = await withUserLock(request.userId, async () => { + const stores = await loadStores(); + const account = getOrCreateAccount(stores, request.userId); + + const idemEndpointKey = endpointKey('semantic-search', request.userId, request.idempotencyKey); + const cachedResponse = readIdempotentResponse(stores.idempotency, idemEndpointKey); + if (cachedResponse) { + return { + response: cachedResponse, + simulatedDelayMs: getSimulatedDelay(account.plan), + }; + } + + const normalizedQuery = request.query.trim(); + if (!normalizedQuery) { + const noResultResponse: SemanticSearchResponse = { + status: 'no_results', + results: [], + creditsCharged: 0, + billing: buildBillingSummary(account), + }; + writeIdempotentResponse(stores.idempotency, idemEndpointKey, noResultResponse); + await persistStores(stores); + return { + response: noResultResponse, + simulatedDelayMs: getSimulatedDelay(account.plan), + }; + } + + const creditsCharged = consumeCreditsWithIdempotency( + account, + stores.idempotency, + chargeKey('semantic-search', request.userId, request.idempotencyKey), + SEMANTIC_SEARCH_COST, + ); + + const results = searchMockCatalog(request.query, request.language, 18); + account.updatedAt = nowIso(); + + const response: SemanticSearchResponse = { + status: results.length > 0 ? 'success' : 'no_results', + results, + creditsCharged, + billing: buildBillingSummary(account), + }; + + writeIdempotentResponse(stores.idempotency, idemEndpointKey, response); + await persistStores(stores); + + return { + response, + simulatedDelayMs: getSimulatedDelay(account.plan), + }; + }); + + await sleep(simulatedDelayMs); + return response; + }, + + healthCheck: async (request: HealthCheckRequest): Promise => { + const { response, simulatedDelayMs } = await withUserLock(request.userId, async () => { + const stores = await loadStores(); + const account = getOrCreateAccount(stores, request.userId); + + const idemEndpointKey = endpointKey('health-check', request.userId, request.idempotencyKey); + const cachedResponse = readIdempotentResponse(stores.idempotency, idemEndpointKey); + if (cachedResponse) { + return { + response: cachedResponse, + simulatedDelayMs: getSimulatedDelay(account.plan), + }; + } + + const normalizedImageUri = request.imageUri.trim(); + if (!normalizedImageUri) { + throw new BackendApiError('BAD_REQUEST', 'Health check requires an image URI.', 400); + } + + if (!openAiScanService.isConfigured()) { + throw new BackendApiError( + 'PROVIDER_ERROR', + 'OpenAI health check is unavailable. Please configure EXPO_PUBLIC_OPENAI_API_KEY.', + 502, + ); + } + + const aiAnalysis = await openAiScanService.analyzePlantHealth( + normalizedImageUri, + request.language, + request.plantContext, + ); + if (!aiAnalysis) { + throw new BackendApiError( + 'PROVIDER_ERROR', + 'OpenAI health check failed. Please verify API key, network access, and image quality.', + 502, + ); + } + + const creditsCharged = consumeCreditsWithIdempotency( + account, + stores.idempotency, + chargeKey('health-check', request.userId, request.idempotencyKey), + HEALTH_CHECK_COST, + ); + + const healthCheck: PlantHealthCheck = { + generatedAt: nowIso(), + overallHealthScore: aiAnalysis.overallHealthScore, + status: aiAnalysis.status, + likelyIssues: aiAnalysis.likelyIssues, + actionsNow: aiAnalysis.actionsNow, + plan7Days: aiAnalysis.plan7Days, + creditsCharged, + imageUri: normalizedImageUri, + }; + account.updatedAt = nowIso(); + + const response: HealthCheckResponse = { + healthCheck, + creditsCharged, + billing: buildBillingSummary(account), + }; + + writeIdempotentResponse(stores.idempotency, idemEndpointKey, response); + await persistStores(stores); + + return { + response, + simulatedDelayMs: getSimulatedDelay(account.plan), + }; + }); + + await sleep(simulatedDelayMs); + return response; + }, + + simulatePurchase: async (request: SimulatePurchaseRequest): Promise => { + return withUserLock(request.userId, async () => { + const stores = await loadStores(); + const account = getOrCreateAccount(stores, request.userId); + + const idemEndpointKey = endpointKey('simulate-purchase', request.userId, request.idempotencyKey); + const cachedResponse = readIdempotentResponse(stores.idempotency, idemEndpointKey); + if (cachedResponse) return cachedResponse; + + if (request.productId === 'monthly_pro' || request.productId === 'yearly_pro') { + const now = new Date(); + const { cycleStartedAt, cycleEndsAt } = getCycleBounds(now); + account.plan = 'pro'; + account.provider = 'mock'; + account.monthlyAllowance = PRO_MONTHLY_CREDITS; + account.usedThisCycle = 0; + account.cycleStartedAt = cycleStartedAt.toISOString(); + account.cycleEndsAt = cycleEndsAt.toISOString(); + account.renewsAt = addDays(now, 30).toISOString(); + } else { + const credits = TOPUP_CREDITS_BY_PRODUCT[request.productId]; + account.topupBalance += credits; + } + + account.updatedAt = nowIso(); + + const response: SimulatePurchaseResponse = { + appliedProduct: request.productId, + billing: buildBillingSummary(account), + }; + + writeIdempotentResponse(stores.idempotency, idemEndpointKey, response); + await persistStores(stores); + return response; + }); + }, + + simulateWebhook: async (request: SimulateWebhookRequest): Promise => { + return withUserLock(request.userId, async () => { + const stores = await loadStores(); + const account = getOrCreateAccount(stores, request.userId); + + const idemEndpointKey = endpointKey('simulate-webhook', request.userId, request.idempotencyKey); + const cachedResponse = readIdempotentResponse(stores.idempotency, idemEndpointKey); + if (cachedResponse) return cachedResponse; + + if (request.event === 'entitlement_granted') { + const now = new Date(); + const { cycleStartedAt, cycleEndsAt } = getCycleBounds(now); + account.plan = 'pro'; + account.provider = 'revenuecat'; + account.monthlyAllowance = PRO_MONTHLY_CREDITS; + account.usedThisCycle = 0; + account.cycleStartedAt = cycleStartedAt.toISOString(); + account.cycleEndsAt = cycleEndsAt.toISOString(); + account.renewsAt = addDays(now, 30).toISOString(); + } + + if (request.event === 'entitlement_revoked') { + const now = new Date(); + const { cycleStartedAt, cycleEndsAt } = getCycleBounds(now); + account.plan = 'free'; + account.provider = 'revenuecat'; + account.monthlyAllowance = FREE_MONTHLY_CREDITS; + account.usedThisCycle = 0; + account.cycleStartedAt = cycleStartedAt.toISOString(); + account.cycleEndsAt = cycleEndsAt.toISOString(); + account.renewsAt = null; + } + + if (request.event === 'topup_granted') { + const credits = Math.max(1, request.payload?.credits || TOPUP_DEFAULT_CREDITS); + account.topupBalance += credits; + } + + if (request.event === 'credits_depleted') { + account.usedThisCycle = account.monthlyAllowance; + account.topupBalance = 0; + } + + account.updatedAt = nowIso(); + + const response: SimulateWebhookResponse = { + event: request.event, + billing: buildBillingSummary(account), + }; + + writeIdempotentResponse(stores.idempotency, idemEndpointKey, response); + await persistStores(stores); + return response; + }); + }, +}; diff --git a/services/backend/mockCatalog.ts b/services/backend/mockCatalog.ts new file mode 100644 index 0000000..d2464be --- /dev/null +++ b/services/backend/mockCatalog.ts @@ -0,0 +1,299 @@ +import { Language } from '../../types'; +import { BackendDatabaseEntry } from './contracts'; +import { LEXICON_BATCH_1_ENTRIES } from '../../constants/lexiconBatch1'; +import { LEXICON_BATCH_2_ENTRIES } from '../../constants/lexiconBatch2'; +import { normalizeSearchText, rankHybridEntries } from '../../utils/hybridSearch'; + +interface MockPlantSeed { + botanicalName: string; + names: Record; + descriptions: Record; + imageUri: string; + categories: string[]; + baseConfidence: number; + care: { + waterIntervalDays: number; + light: Record; + temp: string; + }; +} + +const PLANTS: MockPlantSeed[] = [ + { + botanicalName: 'Monstera deliciosa', + names: { de: 'Monstera', en: 'Monstera', es: 'Monstera' }, + descriptions: { + de: 'Beliebte Zimmerpflanze mit grossen gelochten Blaettern. Mag helles indirektes Licht.', + en: 'Popular indoor plant with large split leaves. Prefers bright indirect light.', + es: 'Planta de interior popular con hojas grandes. Prefiere luz brillante indirecta.', + }, + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Monstera_deliciosa2.jpg/500px-Monstera_deliciosa2.jpg', + categories: ['easy', 'low_light', 'air_purifier'], + baseConfidence: 0.76, + care: { + waterIntervalDays: 7, + light: { de: 'Halbschatten', en: 'Partial shade', es: 'Sombra parcial' }, + temp: '18-24C', + }, + }, + { + botanicalName: 'Sansevieria trifasciata', + names: { de: 'Bogenhanf', en: 'Snake Plant', es: 'Lengua de suegra' }, + descriptions: { + de: 'Sehr robust und trockenheitsvertraeglich. Kommt auch mit wenig Licht klar.', + en: 'Very resilient and drought tolerant. Handles low light well.', + es: 'Muy resistente y tolera sequia. Funciona bien con poca luz.', + }, + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/Snake_Plant_%28Sansevieria_trifasciata_%27Laurentii%27%29.jpg/500px-Snake_Plant_%28Sansevieria_trifasciata_%27Laurentii%27%29.jpg', + categories: ['easy', 'succulent', 'low_light'], + baseConfidence: 0.73, + care: { + waterIntervalDays: 14, + light: { de: 'Schatten bis Sonne', en: 'Shade to sun', es: 'Sombra a sol' }, + temp: '16-30C', + }, + }, + { + botanicalName: 'Aloe vera', + names: { de: 'Aloe Vera', en: 'Aloe Vera', es: 'Aloe Vera' }, + descriptions: { + de: 'Sukkulente mit heilender Gelstruktur in den Blaettern. Braucht viel Licht.', + en: 'Succulent with gel-filled leaves. Needs plenty of light.', + es: 'Suculenta con hojas de gel. Necesita bastante luz.', + }, + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Aloe_vera_flower_inset.png/500px-Aloe_vera_flower_inset.png', + categories: ['succulent', 'easy', 'sun'], + baseConfidence: 0.78, + care: { + waterIntervalDays: 12, + light: { de: 'Sonnig', en: 'Sunny', es: 'Soleado' }, + temp: '18-30C', + }, + }, + { + botanicalName: 'Epipremnum aureum', + names: { de: 'Efeutute', en: 'Pothos', es: 'Poto' }, + descriptions: { + de: 'Schnell wachsende Haengepflanze fuer Einsteiger. Vertraegt variierende Bedingungen.', + en: 'Fast-growing trailing plant ideal for beginners. Handles varied conditions.', + es: 'Planta colgante de crecimiento rapido para principiantes.', + }, + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Money_Plant_%28Epipremnum_aureum%29_4.jpg/500px-Money_Plant_%28Epipremnum_aureum%29_4.jpg', + categories: ['easy', 'hanging', 'air_purifier'], + baseConfidence: 0.74, + care: { + waterIntervalDays: 7, + light: { de: 'Halbschatten bis hell', en: 'Partial shade to bright', es: 'Sombra parcial a brillante' }, + temp: '18-27C', + }, + }, + { + botanicalName: 'Spathiphyllum', + names: { de: 'Einblatt', en: 'Peace Lily', es: 'Cuna de moises' }, + descriptions: { + de: 'Bluetenpflanze fuer Innenraeume. Zeigt Wasserbedarf schnell durch haengende Blaetter.', + en: 'Indoor flowering plant. Droops clearly when it needs water.', + es: 'Planta de flor de interior. Muestra rapido cuando necesita riego.', + }, + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/bd/Spathiphyllum_cochlearispathum_RTBG.jpg/500px-Spathiphyllum_cochlearispathum_RTBG.jpg', + categories: ['flowering', 'low_light'], + baseConfidence: 0.72, + care: { + waterIntervalDays: 5, + light: { de: 'Halbschatten', en: 'Partial shade', es: 'Sombra parcial' }, + temp: '18-26C', + }, + }, + { + botanicalName: 'Zamioculcas zamiifolia', + names: { de: 'Gluecksfeder', en: 'ZZ Plant', es: 'Planta ZZ' }, + descriptions: { + de: 'Extrem pflegeleichte Pflanze mit dickem Rhizom. Perfekt fuer wenig Zeit.', + en: 'Extremely low-maintenance plant with thick rhizomes. Great for busy schedules.', + es: 'Planta muy facil de cuidar con rizomas gruesos.', + }, + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Zamioculcas_zamiifolia_1.jpg/500px-Zamioculcas_zamiifolia_1.jpg', + categories: ['easy', 'low_light'], + baseConfidence: 0.77, + care: { + waterIntervalDays: 14, + light: { de: 'Wenig Licht bis hell', en: 'Low light to bright', es: 'Poca luz a brillante' }, + temp: '18-28C', + }, + }, + { + botanicalName: 'Calathea orbifolia', + names: { de: 'Korbmarante', en: 'Calathea', es: 'Calathea' }, + descriptions: { + de: 'Dekorative Blaetter mit Muster. Liebt gleichmaessige Feuchte und hohe Luftfeuchtigkeit.', + en: 'Decorative patterned leaves. Prefers steady moisture and humidity.', + es: 'Hojas decorativas con patron. Prefiere humedad constante.', + }, + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Calathea_orbifolia_2.jpg/500px-Calathea_orbifolia_2.jpg', + categories: ['patterned', 'pet_friendly'], + baseConfidence: 0.68, + care: { + waterIntervalDays: 4, + light: { de: 'Halbschatten', en: 'Partial shade', es: 'Sombra parcial' }, + temp: '18-25C', + }, + }, + { + botanicalName: 'Chlorophytum comosum', + names: { de: 'Gruenlilie', en: 'Spider Plant', es: 'Cinta' }, + descriptions: { + de: 'Unkomplizierte Zimmerpflanze mit langen gebogenen Blaettern. Vermehrt sich schnell.', + en: 'Easy houseplant with long arched leaves. Propagates quickly.', + es: 'Planta sencilla con hojas largas arqueadas. Se multiplica rapido.', + }, + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/Hierbabuena_0611_Revised.jpg/500px-Hierbabuena_0611_Revised.jpg', + categories: ['easy', 'pet_friendly', 'air_purifier'], + baseConfidence: 0.79, + care: { + waterIntervalDays: 6, + light: { de: 'Hell bis halbschattig', en: 'Bright to partial shade', es: 'Brillante a sombra parcial' }, + temp: '16-24C', + }, + }, + { + botanicalName: 'Anthurium andraeanum', + names: { de: 'Flamingoblume', en: 'Anthurium', es: 'Anturio' }, + descriptions: { + de: 'Auffaellige Hochblaetter und lange Bluetezeit. Braucht Waerme und gleichmaessige Feuchte.', + en: 'Known for vivid spathes and long bloom cycles. Likes warmth and even moisture.', + es: 'Conocida por sus flores vistosas. Requiere calor y riego regular.', + }, + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/AnthuriumAndraenum.jpg/500px-AnthuriumAndraenum.jpg', + categories: ['flowering', 'high_humidity'], + baseConfidence: 0.71, + care: { + waterIntervalDays: 6, + light: { de: 'Hell ohne direkte Sonne', en: 'Bright indirect light', es: 'Luz brillante indirecta' }, + temp: '18-27C', + }, + }, + { + botanicalName: 'Nephrolepis exaltata', + names: { de: 'Schwertfarn', en: 'Boston Fern', es: 'Helecho de Boston' }, + descriptions: { + de: 'Fein gefiederter Farn. Benoetigt regelmaessige Feuchte und keine direkte Sonne.', + en: 'Fine-textured fern. Needs regular moisture and no harsh direct sun.', + es: 'Helecho de textura fina. Necesita humedad constante.', + }, + imageUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/30/Boston_Fern_%282873392811%29.png/500px-Boston_Fern_%282873392811%29.png', + categories: ['pet_friendly', 'air_purifier', 'high_humidity'], + baseConfidence: 0.7, + care: { + waterIntervalDays: 3, + light: { de: 'Halbschatten', en: 'Partial shade', es: 'Sombra parcial' }, + temp: '16-24C', + }, + }, +]; + +const hashString = (value: string): number => { + let hash = 2166136261; + for (let i = 0; i < value.length; i += 1) { + hash ^= value.charCodeAt(i); + hash = Math.imul(hash, 16777619); + } + return hash >>> 0; +}; + +const clampConfidence = (value: number): number => { + return Number(Math.max(0.4, Math.min(0.99, value)).toFixed(2)); +}; + +const toEntry = ( + seed: MockPlantSeed, + lang: Language, + confidence: number, +): BackendDatabaseEntry => { + return { + name: seed.names[lang], + botanicalName: seed.botanicalName, + description: seed.descriptions[lang], + confidence: clampConfidence(confidence), + careInfo: { + waterIntervalDays: seed.care.waterIntervalDays, + light: seed.care.light[lang], + temp: seed.care.temp, + }, + imageUri: seed.imageUri, + categories: seed.categories, + }; +}; + +const getFullCatalog = (lang: Language): BackendDatabaseEntry[] => { + const seeds = PLANTS.map(seed => toEntry(seed, lang, seed.baseConfidence)); + const batches = getBatchCatalog(lang); + const catalog = [...seeds, ...batches]; + + const seenBotanical = new Set(); + const seenImage = new Set(); + + return catalog.filter(e => { + const botanicalKey = normalizeSearchText(e.botanicalName); + const imageKey = e.imageUri.trim(); + + if (seenBotanical.has(botanicalKey) || seenImage.has(imageKey)) { + return false; + } + + seenBotanical.add(botanicalKey); + seenImage.add(imageKey); + return true; + }); +}; + +export const getMockCatalog = (lang: Language): BackendDatabaseEntry[] => { + return getFullCatalog(lang); +}; + +export const getMockPlantByImage = ( + imageUri: string, + lang: Language, + preferHighConfidence: boolean, +): BackendDatabaseEntry => { + const seeds = PLANTS; + const indexHash = hashString(`${lang}:${imageUri}`); + const selectedSeed = seeds[indexHash % seeds.length]; + + const varianceHash = hashString(`confidence:${imageUri}:${selectedSeed.botanicalName}`); + const variance = (varianceHash % 28) / 100; // 0.00 - 0.27 + const confidenceBase = selectedSeed.baseConfidence - 0.08 + variance; + const confidence = preferHighConfidence ? confidenceBase + 0.09 : confidenceBase; + + return toEntry(selectedSeed, lang, confidence); +}; + +const getBatchCatalog = (lang: Language): BackendDatabaseEntry[] => { + const all = [...LEXICON_BATCH_1_ENTRIES, ...LEXICON_BATCH_2_ENTRIES]; + return all.map(entry => ({ + name: entry.name, + botanicalName: entry.botanicalName, + description: entry.description || '', + confidence: entry.confidence, + careInfo: { + waterIntervalDays: entry.careInfo.waterIntervalDays, + light: entry.careInfo.light, + temp: entry.careInfo.temp, + }, + imageUri: entry.imageUri, + categories: entry.categories, + })); +}; + +export const searchMockCatalog = ( + query: string, + lang: Language, + limit = 12, +): BackendDatabaseEntry[] => { + const normalizedQuery = normalizeSearchText(query); + const deduped = getFullCatalog(lang); + + if (!normalizedQuery) return deduped.slice(0, limit); + + return rankHybridEntries(deduped, normalizedQuery, limit) + .map((candidate) => candidate.entry); +}; diff --git a/services/backend/openAiScanService.ts b/services/backend/openAiScanService.ts new file mode 100644 index 0000000..39a848e --- /dev/null +++ b/services/backend/openAiScanService.ts @@ -0,0 +1,564 @@ +import { CareInfo, IdentificationResult, Language } from '../../types'; + +type OpenAiScanMode = 'primary' | 'review'; + +export interface OpenAiHealthIssue { + title: string; + confidence: number; + details: string; +} + +export interface OpenAiHealthAnalysis { + overallHealthScore: number; + status: 'healthy' | 'watch' | 'critical'; + likelyIssues: OpenAiHealthIssue[]; + actionsNow: string[]; + plan7Days: string[]; +} + +const OPENAI_API_KEY = (process.env.EXPO_PUBLIC_OPENAI_API_KEY || '').trim(); +const OPENAI_SCAN_MODEL = (process.env.EXPO_PUBLIC_OPENAI_SCAN_MODEL || 'gpt-5-mini').trim(); +const OPENAI_SCAN_MODEL_PRO = (process.env.EXPO_PUBLIC_OPENAI_SCAN_MODEL_PRO || OPENAI_SCAN_MODEL).trim(); +const OPENAI_HEALTH_MODEL = (process.env.EXPO_PUBLIC_OPENAI_HEALTH_MODEL || OPENAI_SCAN_MODEL).trim(); +const OPENAI_SCAN_FALLBACK_MODELS = (process.env.EXPO_PUBLIC_OPENAI_SCAN_FALLBACK_MODELS || 'gpt-5-mini,gpt-4.1-mini').trim(); +const OPENAI_SCAN_FALLBACK_MODELS_PRO = (process.env.EXPO_PUBLIC_OPENAI_SCAN_FALLBACK_MODELS_PRO || OPENAI_SCAN_FALLBACK_MODELS).trim(); +const OPENAI_HEALTH_FALLBACK_MODELS = (process.env.EXPO_PUBLIC_OPENAI_HEALTH_FALLBACK_MODELS || OPENAI_SCAN_FALLBACK_MODELS).trim(); +const OPENAI_CHAT_COMPLETIONS_URL = 'https://api.openai.com/v1/chat/completions'; +const OPENAI_TIMEOUT_MS = (() => { + const raw = (process.env.EXPO_PUBLIC_OPENAI_TIMEOUT_MS || '45000').trim(); + const parsed = Number.parseInt(raw, 10); + if (Number.isFinite(parsed) && parsed >= 10000) return parsed; + return 45000; +})(); + +const parseModelChain = (primaryModel: string, fallbackModels: string): string[] => { + const models = [primaryModel]; + fallbackModels.split(',').forEach((model) => { + const normalized = model.trim(); + if (normalized) models.push(normalized); + }); + return [...new Set(models)]; +}; + +const OPENAI_SCAN_MODEL_CHAIN = parseModelChain(OPENAI_SCAN_MODEL, OPENAI_SCAN_FALLBACK_MODELS); +const OPENAI_SCAN_MODEL_CHAIN_PRO = parseModelChain(OPENAI_SCAN_MODEL_PRO, OPENAI_SCAN_FALLBACK_MODELS_PRO); +const OPENAI_HEALTH_MODEL_CHAIN = parseModelChain(OPENAI_HEALTH_MODEL, OPENAI_HEALTH_FALLBACK_MODELS); + +const getScanModelChain = (plan: 'free' | 'pro'): string[] => { + return plan === 'pro' ? OPENAI_SCAN_MODEL_CHAIN_PRO : OPENAI_SCAN_MODEL_CHAIN; +}; + +const clamp = (value: number, min: number, max: number): number => { + return Math.min(max, Math.max(min, value)); +}; + +const toErrorMessage = (error: unknown): string => { + if (error instanceof Error) return error.message; + return String(error); +}; + +const summarizeImageUri = (imageUri: string): string => { + const trimmed = imageUri.trim(); + if (!trimmed) return 'empty'; + if (trimmed.startsWith('data:image')) return `data-uri(${Math.round(trimmed.length / 1024)}kb)`; + return trimmed.length > 120 ? `${trimmed.slice(0, 120)}...` : trimmed; +}; + +const toJsonString = (content: string): string => { + const trimmed = content.trim(); + if (!trimmed) return trimmed; + + const fenced = trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i); + if (fenced?.[1]) return fenced[1].trim(); + return trimmed; +}; + +const parseContentToJson = (content: string): Record | null => { + try { + const parsed = JSON.parse(toJsonString(content)); + if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) { + return parsed as Record; + } + return null; + } catch { + return null; + } +}; + +const getString = (value: unknown): string => { + return typeof value === 'string' ? value.trim() : ''; +}; + +const getNumber = (value: unknown): number | null => { + if (typeof value === 'number' && Number.isFinite(value)) return value; + if (typeof value === 'string' && value.trim()) { + const parsed = Number(value); + if (Number.isFinite(parsed)) return parsed; + } + return null; +}; + +const getStringArray = (value: unknown): string[] => { + if (!Array.isArray(value)) return []; + return value + .map((item) => (typeof item === 'string' ? item.trim() : '')) + .filter(Boolean); +}; + +const normalizeResult = ( + raw: Record, + language: Language, +): IdentificationResult | null => { + const name = getString(raw.name); + const botanicalName = getString(raw.botanicalName); + const description = getString(raw.description); + const confidenceRaw = getNumber(raw.confidence); + const careInfoRaw = raw.careInfo; + + if (!name || !botanicalName || !careInfoRaw || typeof careInfoRaw !== 'object' || Array.isArray(careInfoRaw)) { + return null; + } + + const careInfoObj = careInfoRaw as Record; + const waterIntervalRaw = getNumber(careInfoObj.waterIntervalDays); + const light = getString(careInfoObj.light); + const temp = getString(careInfoObj.temp); + + if (waterIntervalRaw == null || !light || !temp) { + return null; + } + + const fallbackDescription = language === 'de' + ? `${name} wurde per KI erkannt. Pflegehinweise sind unten aufgefuehrt.` + : language === 'es' + ? `${name} se detecto con IA. Debajo veras recomendaciones de cuidado.` + : `${name} was identified with AI. Care guidance is shown below.`; + + return { + name, + botanicalName, + confidence: clamp(confidenceRaw ?? 0.72, 0.05, 0.99), + description: description || fallbackDescription, + careInfo: { + waterIntervalDays: Math.round(clamp(waterIntervalRaw, 1, 45)), + light, + temp, + }, + }; +}; + +const getLanguageLabel = (language: Language): string => { + if (language === 'de') return 'German'; + if (language === 'es') return 'Spanish'; + return 'English'; +}; + +const buildPrompt = (language: Language, mode: OpenAiScanMode): string => { + const reviewInstruction = mode === 'review' + ? 'Re-check your first hypothesis with stricter botanical accuracy and correct any mismatch.' + : 'Identify the most likely houseplant species from this image with conservative confidence.'; + + const nameLanguageInstruction = language === 'en' + ? '- "name" must be an English common name only. Never return a German or other non-English common name. If no reliable English common name is known, use "botanicalName" as "name" instead of inventing or translating.' + : `- "name" must be strictly written in ${getLanguageLabel(language)}. If a reliable common name in that language is not known, use "botanicalName" as "name" instead of inventing a localized name.`; + + return [ + `${reviewInstruction}`, + `Return strict JSON only in this shape:`, + `{"name":"...","botanicalName":"...","confidence":0.0,"description":"...","careInfo":{"waterIntervalDays":7,"light":"...","temp":"..."}}`, + `Rules:`, + nameLanguageInstruction, + `- "description" and "careInfo.light" must be written in ${getLanguageLabel(language)}.`, + `- "botanicalName" must use accepted Latin scientific naming and must not be invented or misspelled.`, + `- If species is uncertain, prefer genus-level naming (for example: "Calathea sp.").`, + `- "confidence" must be between 0 and 1.`, + `- Keep confidence <= 0.55 when the image is ambiguous, blurred, or partially visible.`, + `- "waterIntervalDays" must be an integer between 1 and 45.`, + `- Do not include markdown, explanations, or extra keys.`, + ].join('\n'); +}; + +const buildHealthPrompt = ( + language: Language, + plantContext?: { + name: string; + botanicalName: string; + careInfo: CareInfo; + description?: string; + }, +): string => { + const contextLines = plantContext + ? [ + `Plant context:`, + `- name: ${plantContext.name}`, + `- botanicalName: ${plantContext.botanicalName}`, + `- care.light: ${plantContext.careInfo.light}`, + `- care.temp: ${plantContext.careInfo.temp}`, + `- care.waterIntervalDays: ${plantContext.careInfo.waterIntervalDays}`, + `- description: ${plantContext.description || 'n/a'}`, + ] + : ['Plant context: not provided']; + + return [ + `Analyze this plant photo for real health condition signs with focus on yellowing leaves, watering stress, pests, and light stress.`, + `Return strict JSON only in this shape:`, + `{"overallHealthScore":72,"status":"watch","likelyIssues":[{"title":"...","confidence":0.64,"details":"..."}],"actionsNow":["..."],"plan7Days":["..."]}`, + `Rules:`, + `- "overallHealthScore" must be an integer between 0 and 100.`, + `- "status" must be one of: "healthy", "watch", "critical".`, + `- "likelyIssues" must contain 1 to 4 items sorted by confidence descending.`, + `- "confidence" must be between 0 and 1.`, + `- "title", "details", "actionsNow", and "plan7Days" must be written in ${getLanguageLabel(language)}.`, + `- "actionsNow" should be immediate steps for the next 24 hours.`, + `- "plan7Days" should be short actionable steps for the next week.`, + `- Do not include markdown, explanations, or extra keys.`, + ...contextLines, + ].join('\n'); +}; + +const buildFallbackHealthAnalysis = ( + language: Language, + plantContext?: { + name: string; + botanicalName: string; + careInfo: CareInfo; + description?: string; + }, +): OpenAiHealthAnalysis => { + if (language === 'de') { + return { + overallHealthScore: 58, + status: 'watch', + likelyIssues: [ + { + title: 'Eingeschraenkte KI-Analyse', + confidence: 0.42, + details: `${plantContext?.name || 'Die Pflanze'} konnte wegen instabiler Antwort nicht vollstaendig bewertet werden.`, + }, + ], + actionsNow: [ + 'Neues Foto bei hellem, indirektem Licht aufnehmen.', + 'Blaetter auf Flecken, Schaedlinge und trockene Raender pruefen.', + 'Erst giessen, wenn die oberen 2-3 cm Erde trocken sind.', + ], + plan7Days: [ + 'In 2 Tagen mit neuem Foto erneut pruefen.', + 'Farbe und Blattspannung taeglich beobachten.', + 'Bei Verschlechterung Standort und Giessrhythmus anpassen.', + ], + }; + } + + if (language === 'es') { + return { + overallHealthScore: 58, + status: 'watch', + likelyIssues: [ + { + title: 'Analisis de IA limitado', + confidence: 0.42, + details: `${plantContext?.name || 'La planta'} no pudo evaluarse por completo por una respuesta inestable.`, + }, + ], + actionsNow: [ + 'Tomar una foto nueva con luz brillante e indirecta.', + 'Revisar hojas por manchas, plagas y bordes secos.', + 'Regar solo si los 2-3 cm superiores del sustrato estan secos.', + ], + plan7Days: [ + 'Revisar otra vez en 2 dias con una foto nueva.', + 'Observar color y firmeza de hojas cada dia.', + 'Si empeora, ajustar ubicacion y frecuencia de riego.', + ], + }; + } + + return { + overallHealthScore: 58, + status: 'watch', + likelyIssues: [ + { + title: 'Limited AI analysis', + confidence: 0.42, + details: `${plantContext?.name || 'This plant'} could not be fully assessed due to an unstable provider response.`, + }, + ], + actionsNow: [ + 'Capture a new photo in bright indirect light.', + 'Inspect leaves for spots, pests, and dry edges.', + 'Water only if the top 2-3 cm of soil is dry.', + ], + plan7Days: [ + 'Re-check in 2 days with a new photo.', + 'Track leaf color and firmness daily.', + 'If symptoms worsen, adjust placement and watering cadence.', + ], + }; +}; + +const normalizeHealthAnalysis = ( + raw: Record, + language: Language, +): OpenAiHealthAnalysis | null => { + const scoreRaw = getNumber(raw.overallHealthScore); + const statusRaw = getString(raw.status); + const issuesRaw = raw.likelyIssues; + const actionsNowRaw = getStringArray(raw.actionsNow).slice(0, 6); + const plan7DaysRaw = getStringArray(raw.plan7Days).slice(0, 7); + + if (scoreRaw == null || !statusRaw || !Array.isArray(issuesRaw)) { + return null; + } + + const status: OpenAiHealthAnalysis['status'] = statusRaw === 'healthy' || statusRaw === 'watch' || statusRaw === 'critical' + ? statusRaw + : 'watch'; + + const likelyIssues = issuesRaw + .map((entry) => { + if (!entry || typeof entry !== 'object' || Array.isArray(entry)) return null; + const issueObj = entry as Record; + const title = getString(issueObj.title); + const details = getString(issueObj.details); + const confidenceRaw = getNumber(issueObj.confidence); + if (!title || !details || confidenceRaw == null) return null; + return { + title, + details, + confidence: clamp(confidenceRaw, 0.05, 0.99), + } as OpenAiHealthIssue; + }) + .filter((entry): entry is OpenAiHealthIssue => Boolean(entry)) + .slice(0, 4); + + if (likelyIssues.length === 0 || actionsNowRaw.length === 0 || plan7DaysRaw.length === 0) { + const fallbackIssue = language === 'de' + ? 'Die KI konnte keine stabilen Gesundheitsmerkmale extrahieren.' + : language === 'es' + ? 'La IA no pudo extraer senales de salud estables.' + : 'AI could not extract stable health signals.'; + return { + overallHealthScore: Math.round(clamp(scoreRaw, 0, 100)), + status, + likelyIssues: [ + { + title: language === 'de' + ? 'Analyse unsicher' + : language === 'es' + ? 'Analisis incierto' + : 'Uncertain analysis', + confidence: 0.35, + details: fallbackIssue, + }, + ], + actionsNow: actionsNowRaw.length > 0 + ? actionsNowRaw + : [language === 'de' ? 'Neues, schaerferes Foto aufnehmen.' : language === 'es' ? 'Tomar una foto nueva y mas nitida.' : 'Capture a new, sharper photo.'], + plan7Days: plan7DaysRaw.length > 0 + ? plan7DaysRaw + : [language === 'de' ? 'In 2 Tagen erneut pruefen.' : language === 'es' ? 'Volver a revisar en 2 dias.' : 'Re-check in 2 days.'], + }; + } + + return { + overallHealthScore: Math.round(clamp(scoreRaw, 0, 100)), + status, + likelyIssues, + actionsNow: actionsNowRaw, + plan7Days: plan7DaysRaw, + }; +}; + +const extractMessageContent = (payload: unknown): string => { + const response = payload as { + choices?: Array<{ + message?: { + content?: string | Array<{ type?: string; text?: string }>; + }; + }>; + }; + + const content = response.choices?.[0]?.message?.content; + if (typeof content === 'string') return content; + if (Array.isArray(content)) { + return content + .map((chunk) => (chunk?.type === 'text' ? chunk.text || '' : '')) + .join('') + .trim(); + } + return ''; +}; + +const postChatCompletion = async ( + modelChain: string[], + imageUri: string, + messages: Array>, +): Promise<{ payload: Record | null; modelUsed: string | null; attemptedModels: string[] }> => { + const attemptedModels: string[] = []; + + for (const model of modelChain) { + attemptedModels.push(model); + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), OPENAI_TIMEOUT_MS); + + try { + const response = await fetch(OPENAI_CHAT_COMPLETIONS_URL, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${OPENAI_API_KEY}`, + }, + body: JSON.stringify({ + model, + response_format: { type: 'json_object' }, + messages, + }), + signal: controller.signal, + }); + + if (!response.ok) { + const body = await response.text(); + console.warn('OpenAI request HTTP error.', { + status: response.status, + model, + image: summarizeImageUri(imageUri), + bodyPreview: body.slice(0, 300), + }); + continue; + } + + const payload = (await response.json()) as Record; + return { payload, modelUsed: model, attemptedModels }; + } catch (error) { + const isTimeoutAbort = error instanceof Error && error.name === 'AbortError'; + console.warn('OpenAI request failed.', { + model, + timeoutMs: OPENAI_TIMEOUT_MS, + aborted: isTimeoutAbort, + error: toErrorMessage(error), + image: summarizeImageUri(imageUri), + }); + continue; + } finally { + clearTimeout(timeout); + } + } + + return { payload: null, modelUsed: null, attemptedModels }; +}; + +export const openAiScanService = { + isConfigured: (): boolean => Boolean(OPENAI_API_KEY), + + identifyPlant: async ( + imageUri: string, + language: Language, + mode: OpenAiScanMode = 'primary', + plan: 'free' | 'pro' = 'free', + ): Promise => { + if (!OPENAI_API_KEY) return null; + const modelChain = getScanModelChain(plan); + const completion = await postChatCompletion( + modelChain, + imageUri, + [ + { + role: 'system', + content: 'You are a plant identification assistant. Return strict JSON only.', + }, + { + role: 'user', + content: [ + { type: 'text', text: buildPrompt(language, mode) }, + { type: 'image_url', image_url: { url: imageUri } }, + ], + }, + ], + ); + + if (!completion.payload) return null; + + const content = extractMessageContent(completion.payload); + if (!content) { + console.warn('OpenAI plant scan returned empty message content.', { + model: completion.modelUsed || modelChain[0], + mode, + image: summarizeImageUri(imageUri), + }); + return null; + } + + const parsed = parseContentToJson(content); + if (!parsed) { + console.warn('OpenAI plant scan returned non-JSON content.', { + model: completion.modelUsed || modelChain[0], + mode, + preview: content.slice(0, 220), + }); + return null; + } + + const normalized = normalizeResult(parsed, language); + if (!normalized) { + console.warn('OpenAI plant scan JSON did not match required schema.', { + model: completion.modelUsed || modelChain[0], + mode, + keys: Object.keys(parsed), + }); + } + + return normalized; + }, + + analyzePlantHealth: async ( + imageUri: string, + language: Language, + plantContext?: { + name: string; + botanicalName: string; + careInfo: CareInfo; + description?: string; + }, + ): Promise => { + if (!OPENAI_API_KEY) return null; + const completion = await postChatCompletion( + OPENAI_HEALTH_MODEL_CHAIN, + imageUri, + [ + { + role: 'system', + content: 'You are a plant health diagnosis assistant. Return strict JSON only.', + }, + { + role: 'user', + content: [ + { type: 'text', text: buildHealthPrompt(language, plantContext) }, + { type: 'image_url', image_url: { url: imageUri } }, + ], + }, + ], + ); + + if (!completion.payload) return buildFallbackHealthAnalysis(language, plantContext); + + const content = extractMessageContent(completion.payload); + if (!content) { + console.warn('OpenAI health check returned empty content.', { + model: completion.modelUsed || OPENAI_HEALTH_MODEL_CHAIN[0], + image: summarizeImageUri(imageUri), + }); + return buildFallbackHealthAnalysis(language, plantContext); + } + + const parsed = parseContentToJson(content); + if (!parsed) { + console.warn('OpenAI health check returned non-JSON content.', { + model: completion.modelUsed || OPENAI_HEALTH_MODEL_CHAIN[0], + preview: content.slice(0, 220), + }); + return buildFallbackHealthAnalysis(language, plantContext); + } + + return normalizeHealthAnalysis(parsed, language) || buildFallbackHealthAnalysis(language, plantContext); + }, +}; diff --git a/services/backend/userIdentityService.ts b/services/backend/userIdentityService.ts new file mode 100644 index 0000000..cbcd2e9 --- /dev/null +++ b/services/backend/userIdentityService.ts @@ -0,0 +1,17 @@ +import * as SecureStore from 'expo-secure-store'; + +const SESSION_KEY = 'greenlens_session_v3'; + +export const getAuthToken = async (): Promise => { + try { + const raw = await SecureStore.getItemAsync(SESSION_KEY); + if (raw) { + const session = JSON.parse(raw); + if (typeof session?.token === 'string' && session.token) { + return session.token; + } + } + } catch {} + // Return 'guest' instead of throwing to allow guest mode + return 'guest'; +}; diff --git a/services/database.ts b/services/database.ts new file mode 100644 index 0000000..6659f0d --- /dev/null +++ b/services/database.ts @@ -0,0 +1,344 @@ +import * as SQLite from 'expo-sqlite'; +import { Plant, CareInfo, Language, AppearanceMode, ColorPalette } from '../types'; + +// ─── DB-Instanz ──────────────────────────────────────────────────────────────── + +let _db: SQLite.SQLiteDatabase | null = null; +let _isDatabaseInitialized = false; + +export const getDb = (): SQLite.SQLiteDatabase => { + if (!_db) _db = SQLite.openDatabaseSync('greenlens.db'); + return _db; +}; + +// ─── Schema ──────────────────────────────────────────────────────────────────── + +export const initDatabase = (): void => { + if (_isDatabaseInitialized) return; + + const db = getDb(); + + try { + db.execSync(` + PRAGMA foreign_keys = ON; + PRAGMA journal_mode = WAL; + + CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + email TEXT NOT NULL UNIQUE COLLATE NOCASE, + name TEXT NOT NULL DEFAULT '', + password_hash TEXT NOT NULL, + created_at TEXT NOT NULL DEFAULT (datetime('now')) + ); + + CREATE TABLE IF NOT EXISTS user_settings ( + user_id INTEGER PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE, + language TEXT NOT NULL DEFAULT 'de', + language_set INTEGER NOT NULL DEFAULT 0, + appearance_mode TEXT NOT NULL DEFAULT 'system', + color_palette TEXT NOT NULL DEFAULT 'forest', + profile_image TEXT, + onboarding_done INTEGER NOT NULL DEFAULT 0 + ); + + CREATE TABLE IF NOT EXISTS plants ( + id TEXT PRIMARY KEY, + user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, + name TEXT NOT NULL, + botanical_name TEXT NOT NULL DEFAULT '', + image_uri TEXT NOT NULL DEFAULT '', + date_added TEXT NOT NULL, + care_info TEXT NOT NULL DEFAULT '{}', + last_watered TEXT NOT NULL, + watering_history TEXT NOT NULL DEFAULT '[]', + gallery TEXT NOT NULL DEFAULT '[]', + description TEXT, + notifications_enabled INTEGER NOT NULL DEFAULT 0, + health_checks TEXT NOT NULL DEFAULT '[]' + ); + + CREATE TABLE IF NOT EXISTS lexicon_search_history ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, + query TEXT NOT NULL, + created_at TEXT NOT NULL DEFAULT (datetime('now')) + ); + + CREATE TABLE IF NOT EXISTS app_meta ( + key TEXT PRIMARY KEY, + value TEXT NOT NULL + ); + `); + _isDatabaseInitialized = true; + } catch (error) { + console.error('Failed to initialize SQLite schema.', error); + throw error; + } + + // Migration: add language_set column to existing databases + try { + db.runSync('ALTER TABLE user_settings ADD COLUMN language_set INTEGER NOT NULL DEFAULT 0'); + } catch (_) { /* column already exists */ } +}; + +// ─── App Meta ───────────────────────────────────────────────────────────────── + +export const AppMetaDb = { + get(key: string): string | null { + const row = getDb().getFirstSync<{ value: string }>( + 'SELECT value FROM app_meta WHERE key = ?', + [key], + ); + return row?.value ?? null; + }, + + set(key: string, value: string): void { + getDb().runSync( + 'INSERT INTO app_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value', + [key, value], + ); + }, +}; + +// ─── Auth ────────────────────────────────────────────────────────────────────── +// Credential management has moved to the server (server/lib/auth.js + JWT). +// AuthDb only manages the local device user (id=1) used for plants/settings queries. + +export interface DbUser { + id: number; + email: string; + name: string; +} + +export const AuthDb = { + // Ensures a local device user exists. Maps email to a unique local ID. + ensureLocalUser(email: string, name: string): { id: number } { + const db = getDb(); + const normalizedEmail = email.trim().toLowerCase(); + + // Check if this specific email already has a local account + const existing = db.getFirstSync<{ id: number }>('SELECT id FROM users WHERE email = ?', [normalizedEmail]); + + if (existing) { + // Update name just in case it changed on server + db.runSync('UPDATE users SET name = ? WHERE id = ?', [name.trim(), existing.id]); + return { id: existing.id }; + } + + // Create a new local user if it doesn't exist + const result = db.runSync( + 'INSERT INTO users (email, name, password_hash) VALUES (?, ?, ?)', + [normalizedEmail, name.trim(), 'server-auth'], + ); + + const newUserId = result.lastInsertRowId; + db.runSync('INSERT OR IGNORE INTO user_settings (user_id) VALUES (?)', [newUserId]); + + return { id: newUserId }; + }, + + getUserById(id: number): DbUser | null { + const db = getDb(); + const user = db.getFirstSync( + 'SELECT id, email, name FROM users WHERE id = ?', + [id], + ); + return user || null; + }, +}; + +// ─── Settings ────────────────────────────────────────────────────────────────── + +export const SettingsDb = { + get(userId: number) { + const db = getDb(); + db.runSync('INSERT OR IGNORE INTO user_settings (user_id) VALUES (?)', [userId]); + return db.getFirstSync<{ + language: string; + language_set: number; + appearance_mode: string; + color_palette: string; + profile_image: string | null; + onboarding_done: number; + }>('SELECT * FROM user_settings WHERE user_id = ?', [userId])!; + }, + + setLanguage(userId: number, lang: Language) { + getDb().runSync('UPDATE user_settings SET language = ?, language_set = 1 WHERE user_id = ?', [lang, userId]); + }, + + setAppearanceMode(userId: number, mode: AppearanceMode) { + getDb().runSync('UPDATE user_settings SET appearance_mode = ? WHERE user_id = ?', [mode, userId]); + }, + + setColorPalette(userId: number, palette: ColorPalette) { + getDb().runSync('UPDATE user_settings SET color_palette = ? WHERE user_id = ?', [palette, userId]); + }, + + setProfileImage(userId: number, uri: string | null) { + getDb().runSync('UPDATE user_settings SET profile_image = ? WHERE user_id = ?', [uri, userId]); + }, + + setOnboardingDone(userId: number, done: boolean) { + getDb().runSync( + 'UPDATE user_settings SET onboarding_done = ? WHERE user_id = ?', + [done ? 1 : 0, userId], + ); + }, + + setName(userId: number, name: string) { + getDb().runSync('UPDATE users SET name = ? WHERE id = ?', [name.trim(), userId]); + }, +}; + +// ─── Plants ──────────────────────────────────────────────────────────────────── + +const DEFAULT_CARE_INFO: CareInfo = { + waterIntervalDays: 7, + light: 'Bright indirect light', + temp: '18-25 C', +}; + +const safeJsonParse = (value: unknown, fallback: T, fieldName: string, plantId: string): T => { + if (typeof value !== 'string' || !value.trim()) return fallback; + + try { + return JSON.parse(value) as T; + } catch (error) { + console.warn('Failed to parse plant JSON field. Falling back to defaults.', { + plantId, + fieldName, + error: error instanceof Error ? error.message : String(error), + }); + return fallback; + } +}; + +const parsePlant = (row: any): Plant => ({ + id: row.id, + name: row.name, + botanicalName: row.botanical_name, + imageUri: row.image_uri, + dateAdded: row.date_added, + careInfo: safeJsonParse(row.care_info, DEFAULT_CARE_INFO, 'care_info', row.id), + lastWatered: row.last_watered, + wateringHistory: safeJsonParse(row.watering_history, [], 'watering_history', row.id), + gallery: safeJsonParse(row.gallery, [], 'gallery', row.id), + description: row.description ?? undefined, + notificationsEnabled: row.notifications_enabled === 1, + healthChecks: safeJsonParse(row.health_checks, [], 'health_checks', row.id), +}); + +export const PlantsDb = { + getAll(userId: number): Plant[] { + const rows = getDb().getAllSync( + 'SELECT * FROM plants WHERE user_id = ? ORDER BY date_added DESC', + [userId], + ); + return rows.map(parsePlant); + }, + + insert(userId: number, plant: Plant): void { + getDb().runSync( + `INSERT INTO plants + (id, user_id, name, botanical_name, image_uri, date_added, + care_info, last_watered, watering_history, gallery, + description, notifications_enabled, health_checks) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + [ + plant.id, + userId, + plant.name, + plant.botanicalName, + plant.imageUri, + plant.dateAdded, + JSON.stringify(plant.careInfo), + plant.lastWatered, + JSON.stringify(plant.wateringHistory ?? []), + JSON.stringify(plant.gallery ?? []), + plant.description ?? null, + plant.notificationsEnabled ? 1 : 0, + JSON.stringify(plant.healthChecks ?? []), + ], + ); + }, + + update(userId: number, plant: Plant): void { + getDb().runSync( + `UPDATE plants SET + name = ?, botanical_name = ?, image_uri = ?, + care_info = ?, last_watered = ?, watering_history = ?, + gallery = ?, description = ?, notifications_enabled = ?, health_checks = ? + WHERE id = ? AND user_id = ?`, + [ + plant.name, + plant.botanicalName, + plant.imageUri, + JSON.stringify(plant.careInfo), + plant.lastWatered, + JSON.stringify(plant.wateringHistory ?? []), + JSON.stringify(plant.gallery ?? []), + plant.description ?? null, + plant.notificationsEnabled ? 1 : 0, + JSON.stringify(plant.healthChecks ?? []), + plant.id, + userId, + ], + ); + }, + + delete(userId: number, plantId: string): void { + getDb().runSync('DELETE FROM plants WHERE id = ? AND user_id = ?', [plantId, userId]); + }, +}; + +// ─── Lexicon Search History ──────────────────────────────────────────────────── + +const HISTORY_LIMIT = 10; + +const normalize = (v: string) => + v.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').trim().replace(/\s+/g, ' '); + +export const LexiconHistoryDb = { + getAll(userId: number): string[] { + return getDb() + .getAllSync<{ query: string }>( + 'SELECT query FROM lexicon_search_history WHERE user_id = ? ORDER BY created_at DESC LIMIT ?', + [userId, HISTORY_LIMIT], + ) + .map((r) => r.query); + }, + + add(userId: number, query: string): void { + const trimmed = query.trim(); + if (!trimmed) return; + const db = getDb(); + // Duplikate entfernen + const normalized = normalize(trimmed); + const existing = db.getAllSync<{ id: number; query: string }>( + 'SELECT id, query FROM lexicon_search_history WHERE user_id = ?', + [userId], + ); + for (const row of existing) { + if (normalize(row.query) === normalized) { + db.runSync('DELETE FROM lexicon_search_history WHERE id = ?', [row.id]); + } + } + db.runSync( + 'INSERT INTO lexicon_search_history (user_id, query) VALUES (?, ?)', + [userId, trimmed], + ); + // Limit halten + const oldest = db.getAllSync<{ id: number }>( + 'SELECT id FROM lexicon_search_history WHERE user_id = ? ORDER BY created_at DESC LIMIT -1 OFFSET ?', + [userId, HISTORY_LIMIT], + ); + for (const row of oldest) { + db.runSync('DELETE FROM lexicon_search_history WHERE id = ?', [row.id]); + } + }, + + clear(userId: number): void { + getDb().runSync('DELETE FROM lexicon_search_history WHERE user_id = ?', [userId]); + }, +}; diff --git a/services/imageCacheService.ts b/services/imageCacheService.ts new file mode 100644 index 0000000..2ce6ee2 --- /dev/null +++ b/services/imageCacheService.ts @@ -0,0 +1,113 @@ +import * as FileSystemLegacy from 'expo-file-system/legacy'; + + +const getCacheDir = (): string => { + const baseDir = FileSystemLegacy.documentDirectory ?? FileSystemLegacy.cacheDirectory; + if (!baseDir) { + throw new Error('No writable file system directory is available for image caching.'); + } + return `${baseDir}plant-images/`; +}; + +const ensureCacheDir = async (): Promise => { + const cacheDir = getCacheDir(); + const dirInfo = await FileSystemLegacy.getInfoAsync(cacheDir); + if (!dirInfo.exists) { + await FileSystemLegacy.makeDirectoryAsync(cacheDir, { intermediates: true }); + } + return cacheDir; +}; + +const hashString = (value: string): string => { + // FNV-1a 32-bit hash for stable cache file names. + let hash = 2166136261; + for (let index = 0; index < value.length; index += 1) { + hash ^= value.charCodeAt(index); + hash = Math.imul(hash, 16777619); + } + return (hash >>> 0).toString(36); +}; + +const getDataUriExtension = (uri: string): string => { + const mimeMatch = uri.match(/^data:(image\/[a-zA-Z0-9.+-]+);base64,/i); + const mimeType = mimeMatch?.[1]?.toLowerCase() || ''; + + if (mimeType.includes('png')) return 'png'; + if (mimeType.includes('webp')) return 'webp'; + if (mimeType.includes('gif')) return 'gif'; + if (mimeType.includes('heic')) return 'heic'; + if (mimeType.includes('heif')) return 'heif'; + return 'jpg'; +}; + +const getUriExtension = (uri: string): string => { + const cleanPath = uri.split(/[?#]/)[0]; + const extensionMatch = cleanPath.match(/\.([a-zA-Z0-9]+)$/); + return extensionMatch?.[1]?.toLowerCase() || 'jpg'; +}; + +const getFileName = (uri: string): string => { + const extension = uri.startsWith('data:') + ? getDataUriExtension(uri) + : getUriExtension(uri); + return `${hashString(uri)}.${extension}`; +}; + +export const ImageCacheService = { + /** + * Check if an image is already cached locally. + */ + isCached: async (uri: string): Promise<{ exists: boolean; localUri: string }> => { + const cacheDir = await ensureCacheDir(); + const fileName = getFileName(uri); + const localUri = `${cacheDir}${fileName}`; + const info = await FileSystemLegacy.getInfoAsync(localUri); + return { exists: info.exists, localUri }; + }, + + /** + * Cache an image (base64 data URI or remote URL) and return the local file path. + */ + cacheImage: async (uri: string): Promise => { + const cacheDir = await ensureCacheDir(); + + const fileName = getFileName(uri); + const localUri = `${cacheDir}${fileName}`; + const info = await FileSystemLegacy.getInfoAsync(localUri); + const exists = info.exists; + if (exists) return localUri; + + if (uri.startsWith('data:')) { + // Extract base64 content after the comma + const base64Data = uri.split(',')[1]; + if (!base64Data) throw new Error('Invalid base64 data URI'); + await FileSystemLegacy.writeAsStringAsync(localUri, base64Data, { + encoding: FileSystemLegacy.EncodingType.Base64, + }); + } else if (/^(file:\/\/|content:\/\/)/i.test(uri)) { + await FileSystemLegacy.copyAsync({ from: uri, to: localUri }); + } else { + // Remote URL - download it + const downloadResult = await FileSystemLegacy.downloadAsync(uri, localUri); + if (downloadResult.status !== 200) { + throw new Error(`Failed to download image: HTTP ${downloadResult.status}`); + } + } + + return localUri; + }, + + /** + * Delete a cached image by its local path. + */ + deleteCachedImage: async (localUri: string): Promise => { + try { + const info = await FileSystemLegacy.getInfoAsync(localUri); + if (info.exists) { + await FileSystemLegacy.deleteAsync(localUri, { idempotent: true }); + } + } catch (e) { + console.error('Failed to delete cached image', e); + } + }, +}; diff --git a/services/notificationService.ts b/services/notificationService.ts new file mode 100644 index 0000000..94ebebf --- /dev/null +++ b/services/notificationService.ts @@ -0,0 +1,43 @@ +import * as Notifications from 'expo-notifications'; +import { Platform } from 'react-native'; +import { Plant } from '../types'; + +Notifications.setNotificationHandler({ + handleNotification: async () => ({ + shouldShowAlert: true, + shouldShowBanner: true, + shouldShowList: true, + shouldPlaySound: true, + shouldSetBadge: false, + }), +}); + +export async function requestPermissions(): Promise { + const { status: existing } = await Notifications.getPermissionsAsync(); + if (existing === 'granted') return true; + + const { status } = await Notifications.requestPermissionsAsync(); + return status === 'granted'; +} + +export async function scheduleWateringReminder(plant: Plant): Promise { + const intervalDays = plant.careInfo.waterIntervalDays; + + await Notifications.scheduleNotificationAsync({ + identifier: `water-${plant.id}`, + content: { + title: 'Watering Reminder 💧', + body: `Time to water your ${plant.name}!`, + data: { plantId: plant.id }, + }, + trigger: { + type: Notifications.SchedulableTriggerInputTypes.TIME_INTERVAL, + seconds: intervalDays * 24 * 60 * 60, + repeats: true, + }, + }); +} + +export async function cancelReminder(plantId: string): Promise { + await Notifications.cancelScheduledNotificationAsync(`water-${plantId}`); +} diff --git a/services/plantDatabaseService.ts b/services/plantDatabaseService.ts index 944d071..dc378c3 100644 --- a/services/plantDatabaseService.ts +++ b/services/plantDatabaseService.ts @@ -1,253 +1,132 @@ - import { IdentificationResult, Language } from '../types'; +import { resolveImageUri, tryResolveImageUri } from '../utils/imageUri'; +import { getConfiguredApiBaseUrl } from '../utils/backendUrl'; +import { backendApiClient } from './backend/backendApiClient'; +import { BackendDatabaseEntry, isBackendApiError } from './backend/contracts'; +import { createIdempotencyKey } from '../utils/idempotency'; +import { getMockCatalog, searchMockCatalog } from './backend/mockCatalog'; -interface DatabaseEntry extends IdentificationResult { - imageUri: string; // Default image for the lexicon +export interface DatabaseEntry extends IdentificationResult { + imageUri: string; + imageStatus?: 'ok' | 'missing' | 'invalid'; categories: string[]; } -const PLANT_DATABASE: Record = { - de: [ - { - name: "Monstera", - botanicalName: "Monstera deliciosa", - confidence: 1.0, - careInfo: { waterIntervalDays: 7, light: "Halbschatten", temp: "18-24°C" }, - description: "Die Monstera Deliciosa, auch Fensterblatt genannt, ist bekannt für ihre großen, geteilten Blätter. Sie ist pflegeleicht und reinigt die Luft in Innenräumen effektiv.", - imageUri: "https://images.unsplash.com/photo-1614594975525-e45190c55d0b?q=80&w=400&auto=format&fit=crop", - categories: ["easy", "low_light", "air_purifier"] - }, - { - name: "Birkenfeige", - botanicalName: "Ficus benjamina", - confidence: 1.0, - careInfo: { waterIntervalDays: 5, light: "Hell", temp: "16-24°C" }, - description: "Die Birkenfeige ist eine beliebte Zimmerpflanze mit eleganten, überhängenden Zweigen und glänzenden Blättern. Sie reagiert empfindlich auf Standortwechsel.", - imageUri: "https://images.unsplash.com/photo-1509223197845-458d87318791?q=80&w=400&auto=format&fit=crop", - categories: ["tree", "bright_light"] - }, - { - name: "Echeveria", - botanicalName: "Echeveria elegans", - confidence: 1.0, - careInfo: { waterIntervalDays: 14, light: "Sonnig", temp: "18-28°C" }, - description: "Diese Sukkulente bildet wunderschöne Rosetten und speichert Wasser in ihren dicken Blättern. Sie ist ideal für sonnige Fensterbänke und sehr pflegeleicht.", - imageUri: "https://images.unsplash.com/photo-1520302669765-66b37fb890d7?q=80&w=400&auto=format&fit=crop", - categories: ["succulent", "easy", "small"] - }, - { - name: "Bogenhanf", - botanicalName: "Sansevieria trifasciata", - confidence: 1.0, - careInfo: { waterIntervalDays: 21, light: "Schatten bis Sonne", temp: "15-30°C" }, - description: "Der Bogenhanf ist fast unzerstörbar. Er kommt mit wenig Licht und Wasser aus und ist einer der besten Luftreiniger für das Schlafzimmer.", - imageUri: "https://images.unsplash.com/photo-1620127530668-37c2275ae158?q=80&w=400&auto=format&fit=crop", - categories: ["succulent", "easy", "low_light", "air_purifier"] - }, - { - name: "Echte Aloe", - botanicalName: "Aloe vera", - confidence: 1.0, - careInfo: { waterIntervalDays: 14, light: "Sonnig", temp: "20-30°C" }, - description: "Eine Heilpflanze, deren Gel bei Sonnenbrand hilft. Sie benötigt einen sehr hellen Standort und wenig Wasser.", - imageUri: "https://images.unsplash.com/photo-1567689265771-828557d4766c?q=80&w=400&auto=format&fit=crop", - categories: ["succulent", "medicinal", "sun"] - }, - { - name: "Grünlilie", - botanicalName: "Chlorophytum comosum", - confidence: 1.0, - careInfo: { waterIntervalDays: 7, light: "Halbschatten", temp: "15-23°C" }, - description: "Die Grünlilie ist extrem anpassungsfähig und bildet schnell Ableger. Sie verzeiht Gießfehler und ist ideal für Anfänger.", - imageUri: "https://images.unsplash.com/photo-1616766649725-b44c698308eb?q=80&w=400&auto=format&fit=crop", - categories: ["easy", "hanging", "pet_friendly"] - }, - { - name: "Einblatt", - botanicalName: "Spathiphyllum", - confidence: 1.0, - careInfo: { waterIntervalDays: 5, light: "Halbschatten", temp: "18-25°C" }, - description: "Das Einblatt zeigt durch hängende Blätter an, wann es Wasser braucht. Es blüht auch bei weniger Licht wunderschön weiß.", - imageUri: "https://images.unsplash.com/photo-1610496185876-06835a64627d?q=80&w=400&auto=format&fit=crop", - categories: ["flowering", "low_light", "air_purifier"] - }, - { - name: "Korbmarante", - botanicalName: "Calathea", - confidence: 1.0, - careInfo: { waterIntervalDays: 4, light: "Halbschatten", temp: "18-24°C" }, - description: "Calatheas sind bekannt für ihre gemusterten Blätter, die sich nachts zusammenfalten. Sie benötigen hohe Luftfeuchtigkeit.", - imageUri: "https://images.unsplash.com/photo-1600869680373-b82fa72f8823?q=80&w=400&auto=format&fit=crop", - categories: ["patterned", "pet_friendly", "high_humidity"] - } - ], - en: [ - { - name: "Monstera", - botanicalName: "Monstera deliciosa", - confidence: 1.0, - careInfo: { waterIntervalDays: 7, light: "Partial Shade", temp: "18-24°C" }, - description: "The Monstera Deliciosa, also known as the Swiss Cheese Plant, is known for its large, split leaves. It is easy to care for and effectively purifies indoor air.", - imageUri: "https://images.unsplash.com/photo-1614594975525-e45190c55d0b?q=80&w=400&auto=format&fit=crop", - categories: ["easy", "low_light", "air_purifier"] - }, - { - name: "Weeping Fig", - botanicalName: "Ficus benjamina", - confidence: 1.0, - careInfo: { waterIntervalDays: 5, light: "Bright", temp: "16-24°C" }, - description: "The Weeping Fig is a popular houseplant with elegant, drooping branches and glossy leaves. It is sensitive to changes in location.", - imageUri: "https://images.unsplash.com/photo-1509223197845-458d87318791?q=80&w=400&auto=format&fit=crop", - categories: ["tree", "bright_light"] - }, - { - name: "Mexican Snowball", - botanicalName: "Echeveria elegans", - confidence: 1.0, - careInfo: { waterIntervalDays: 14, light: "Sunny", temp: "18-28°C" }, - description: "This succulent forms beautiful rosettes and stores water in its thick leaves. It is ideal for sunny windowsills and very low maintenance.", - imageUri: "https://images.unsplash.com/photo-1520302669765-66b37fb890d7?q=80&w=400&auto=format&fit=crop", - categories: ["succulent", "easy", "small"] - }, - { - name: "Snake Plant", - botanicalName: "Sansevieria trifasciata", - confidence: 1.0, - careInfo: { waterIntervalDays: 21, light: "Shade to Sun", temp: "15-30°C" }, - description: "The Snake Plant is nearly indestructible. It tolerates low light and drought and is one of the best air purifiers for the bedroom.", - imageUri: "https://images.unsplash.com/photo-1620127530668-37c2275ae158?q=80&w=400&auto=format&fit=crop", - categories: ["succulent", "easy", "low_light", "air_purifier"] - }, - { - name: "Aloe Vera", - botanicalName: "Aloe vera", - confidence: 1.0, - careInfo: { waterIntervalDays: 14, light: "Sunny", temp: "20-30°C" }, - description: "A medicinal plant whose gel helps with sunburn. It requires a very bright spot and little water.", - imageUri: "https://images.unsplash.com/photo-1567689265771-828557d4766c?q=80&w=400&auto=format&fit=crop", - categories: ["succulent", "medicinal", "sun"] - }, - { - name: "Spider Plant", - botanicalName: "Chlorophytum comosum", - confidence: 1.0, - careInfo: { waterIntervalDays: 7, light: "Partial Shade", temp: "15-23°C" }, - description: "The Spider Plant is extremely adaptable and quickly forms offshoots. It forgives watering mistakes and is ideal for beginners.", - imageUri: "https://images.unsplash.com/photo-1616766649725-b44c698308eb?q=80&w=400&auto=format&fit=crop", - categories: ["easy", "hanging", "pet_friendly"] - }, - { - name: "Peace Lily", - botanicalName: "Spathiphyllum", - confidence: 1.0, - careInfo: { waterIntervalDays: 5, light: "Partial Shade", temp: "18-25°C" }, - description: "The Peace Lily shows when it needs water by drooping its leaves. It blooms beautifully white even in lower light.", - imageUri: "https://images.unsplash.com/photo-1610496185876-06835a64627d?q=80&w=400&auto=format&fit=crop", - categories: ["flowering", "low_light", "air_purifier"] - }, - { - name: "Calathea", - botanicalName: "Calathea", - confidence: 1.0, - careInfo: { waterIntervalDays: 4, light: "Partial Shade", temp: "18-24°C" }, - description: "Calatheas are known for their patterned leaves that fold up at night. They require high humidity.", - imageUri: "https://images.unsplash.com/photo-1600869680373-b82fa72f8823?q=80&w=400&auto=format&fit=crop", - categories: ["patterned", "pet_friendly", "high_humidity"] - } - ], - es: [ - { - name: "Costilla de Adán", - botanicalName: "Monstera deliciosa", - confidence: 1.0, - careInfo: { waterIntervalDays: 7, light: "Sombra Parcial", temp: "18-24°C" }, - description: "La Monstera Deliciosa es conocida por sus grandes hojas divididas. Es fácil de cuidar y purifica el aire interior de manera efectiva.", - imageUri: "https://images.unsplash.com/photo-1614594975525-e45190c55d0b?q=80&w=400&auto=format&fit=crop", - categories: ["easy", "low_light", "air_purifier"] - }, - { - name: "Ficus Benjamina", - botanicalName: "Ficus benjamina", - confidence: 1.0, - careInfo: { waterIntervalDays: 5, light: "Brillante", temp: "16-24°C" }, - description: "El Ficus Benjamina es una planta de interior popular con ramas elegantes y caídas y hojas brillantes. Es sensible a los cambios de ubicación.", - imageUri: "https://images.unsplash.com/photo-1509223197845-458d87318791?q=80&w=400&auto=format&fit=crop", - categories: ["tree", "bright_light"] - }, - { - name: "Rosa de Alabastro", - botanicalName: "Echeveria elegans", - confidence: 1.0, - careInfo: { waterIntervalDays: 14, light: "Soleado", temp: "18-28°C" }, - description: "Esta suculenta forma hermosas rosetas y almacena agua en sus hojas gruesas. Es ideal para alféizares soleados y requiere muy poco mantenimiento.", - imageUri: "https://images.unsplash.com/photo-1520302669765-66b37fb890d7?q=80&w=400&auto=format&fit=crop", - categories: ["succulent", "easy", "small"] - }, - { - name: "Lengua de Suegra", - botanicalName: "Sansevieria trifasciata", - confidence: 1.0, - careInfo: { waterIntervalDays: 21, light: "Sombra a Sol", temp: "15-30°C" }, - description: "La Sansevieria es casi indestructible. Tolera poca luz y sequía, y es uno de los mejores purificadores de aire para el dormitorio.", - imageUri: "https://images.unsplash.com/photo-1620127530668-37c2275ae158?q=80&w=400&auto=format&fit=crop", - categories: ["succulent", "easy", "low_light", "air_purifier"] - }, - { - name: "Aloe Vera", - botanicalName: "Aloe vera", - confidence: 1.0, - careInfo: { waterIntervalDays: 14, light: "Soleado", temp: "20-30°C" }, - description: "Una planta medicinal cuyo gel ayuda con las quemaduras solares. Requiere un lugar muy luminoso y poca agua.", - imageUri: "https://images.unsplash.com/photo-1567689265771-828557d4766c?q=80&w=400&auto=format&fit=crop", - categories: ["succulent", "medicinal", "sun"] - }, - { - name: "Cinta", - botanicalName: "Chlorophytum comosum", - confidence: 1.0, - careInfo: { waterIntervalDays: 7, light: "Sombra Parcial", temp: "15-23°C" }, - description: "La Cinta es extremadamente adaptable y forma retoños rápidamente. Perdona los errores de riego y es ideal para principiantes.", - imageUri: "https://images.unsplash.com/photo-1616766649725-b44c698308eb?q=80&w=400&auto=format&fit=crop", - categories: ["easy", "hanging", "pet_friendly"] - }, - { - name: "Cuna de Moisés", - botanicalName: "Spathiphyllum", - confidence: 1.0, - careInfo: { waterIntervalDays: 5, light: "Sombra Parcial", temp: "18-25°C" }, - description: "La Cuna de Moisés muestra cuándo necesita agua al dejar caer sus hojas. Florece hermosamente en blanco incluso con poca luz.", - imageUri: "https://images.unsplash.com/photo-1610496185876-06835a64627d?q=80&w=400&auto=format&fit=crop", - categories: ["flowering", "low_light", "air_purifier"] - }, - { - name: "Calathea", - botanicalName: "Calathea", - confidence: 1.0, - careInfo: { waterIntervalDays: 4, light: "Sombra Parcial", temp: "18-24°C" }, - description: "Las Calatheas son conocidas por sus hojas estampadas que se pliegan por la noche. Requieren alta humedad.", - imageUri: "https://images.unsplash.com/photo-1600869680373-b82fa72f8823?q=80&w=400&auto=format&fit=crop", - categories: ["patterned", "pet_friendly", "high_humidity"] - } - ] +interface SearchOptions { + category?: string | null; + limit?: number; +} + +export type SemanticSearchStatus = 'success' | 'timeout' | 'provider_error' | 'no_results' | 'insufficient_credits'; + +export interface SemanticSearchResult { + status: SemanticSearchStatus; + results: DatabaseEntry[]; +} + +const DEFAULT_SEARCH_LIMIT = 500; + +const hasConfiguredPlantBackend = (): boolean => Boolean( + String( + process.env.EXPO_PUBLIC_API_URL + || process.env.EXPO_PUBLIC_BACKEND_URL + || process.env.EXPO_PUBLIC_PAYMENT_SERVER_URL + || '', + ).trim(), +); + +const normalizeImageStatus = (status?: string, imageUri?: string): 'ok' | 'missing' | 'invalid' => { + if (status === 'ok' || status === 'missing' || status === 'invalid') return status; + const resolved = tryResolveImageUri(imageUri || ''); + if (resolved) return 'ok'; + return imageUri && imageUri.trim() ? 'invalid' : 'missing'; +}; + +const mapBackendEntry = (entry: Partial & { imageUri?: string | null }): DatabaseEntry => { + const imageStatus = normalizeImageStatus(entry.imageStatus, entry.imageUri || undefined); + const strictImageUri = tryResolveImageUri(entry.imageUri || undefined); + const imageUri = imageStatus === 'ok' + ? (strictImageUri || resolveImageUri(entry.imageUri)) + : (typeof entry.imageUri === 'string' ? entry.imageUri.trim() : ''); + + return { + name: entry.name || '', + botanicalName: entry.botanicalName || '', + confidence: typeof entry.confidence === 'number' ? entry.confidence : 0, + description: entry.description || '', + careInfo: entry.careInfo || { waterIntervalDays: 7, light: 'Unknown', temp: 'Unknown' }, + imageUri, + imageStatus, + categories: Array.isArray(entry.categories) ? entry.categories : [], + }; }; export const PlantDatabaseService = { - getAllPlants: (lang: Language): DatabaseEntry[] => { - return PLANT_DATABASE[lang] || PLANT_DATABASE['de']; + async getAllPlants(lang: Language): Promise { + if (!hasConfiguredPlantBackend()) { + return getMockCatalog(lang).map(mapBackendEntry); + } + + try { + const response = await fetch(`${getConfiguredApiBaseUrl()}/plants?lang=${lang}`); + if (!response.ok) throw new Error('Network response was not ok'); + const data = await response.json(); + if (!Array.isArray(data)) return []; + return data.map(mapBackendEntry); + } catch (e) { + console.error('Failed to fetch plants', e); + return []; + } }, - searchPlants: (query: string, lang: Language): DatabaseEntry[] => { - const plants = PLANT_DATABASE[lang] || PLANT_DATABASE['de']; - const lowerQuery = query.toLowerCase(); - - return plants.filter(p => - p.name.toLowerCase().includes(lowerQuery) || - p.botanicalName.toLowerCase().includes(lowerQuery) - ); + async searchPlants(query: string, lang: Language, options: SearchOptions = {}): Promise { + const { category, limit = DEFAULT_SEARCH_LIMIT } = options; + + if (!hasConfiguredPlantBackend()) { + let results = searchMockCatalog(query || '', lang, limit); + if (category) { + results = results.filter(r => r.categories.includes(category)); + } + return results.map(mapBackendEntry); + } + + const url = new URL(`${getConfiguredApiBaseUrl()}/plants`); + url.searchParams.append('lang', lang); + if (query) url.searchParams.append('q', query); + if (category) url.searchParams.append('category', category); + if (limit) url.searchParams.append('limit', limit.toString()); + + try { + const response = await fetch(url.toString()); + if (!response.ok) throw new Error('Network response was not ok'); + const data = await response.json(); + if (!Array.isArray(data)) return []; + return data.map(mapBackendEntry); + } catch (e) { + console.error('Failed to search plants', e); + return []; + } + }, + + async semanticSearchDetailed(query: string, lang: Language): Promise { + const idempotencyKey = createIdempotencyKey(`semantic-${query}-${lang}`); + try { + const response = await backendApiClient.semanticSearch({ + query, + language: lang, + idempotencyKey, + }); + + const results: DatabaseEntry[] = (response.results as BackendDatabaseEntry[]).map(mapBackendEntry); + return { status: results.length > 0 ? 'success' : 'no_results', results }; + } catch (error) { + if (isBackendApiError(error)) { + if (error.code === 'INSUFFICIENT_CREDITS') { + return { status: 'insufficient_credits', results: [] }; + } + return { status: 'provider_error', results: [] }; + } + return { status: 'timeout', results: [] }; + } }, - - getRandomPlant: (lang: Language): DatabaseEntry => { - const plants = PLANT_DATABASE[lang] || PLANT_DATABASE['de']; - return plants[Math.floor(Math.random() * plants.length)]; - } }; diff --git a/services/plantRecognitionService.ts b/services/plantRecognitionService.ts index af27302..431f525 100644 --- a/services/plantRecognitionService.ts +++ b/services/plantRecognitionService.ts @@ -1,85 +1,24 @@ - import { IdentificationResult, Language } from '../types'; -import { GoogleGenAI, Type } from "@google/genai"; -import { PlantDatabaseService } from './plantDatabaseService'; +import { backendApiClient } from './backend/backendApiClient'; +import { createIdempotencyKey } from '../utils/idempotency'; -// Helper to convert base64 data URL to raw base64 string -const cleanBase64 = (dataUrl: string) => { - return dataUrl.split(',')[1]; -}; +interface IdentifyOptions { + idempotencyKey?: string; +} export const PlantRecognitionService = { - identify: async (imageUri: string, lang: Language = 'de'): Promise => { - // 1. Check if we have an API Key. If so, use Gemini - if (process.env.API_KEY) { - try { - const ai = new GoogleGenAI({ apiKey: process.env.API_KEY }); - - // Dynamic prompt based on language - const promptLang = lang === 'de' ? 'German' : lang === 'es' ? 'Spanish' : 'English'; - const promptText = `Identify this plant. Provide the common ${promptLang} name, the botanical name, a description (2 sentences) in ${promptLang}, an estimated confidence (0-1), and care info (water interval in days, light in ${promptLang}, temp). Response must be JSON.`; - - const response = await ai.models.generateContent({ - model: 'gemini-3-pro-preview', - contents: { - parts: [ - { - inlineData: { - mimeType: 'image/jpeg', - data: cleanBase64(imageUri), - }, - }, - { - text: promptText - } - ], - }, - config: { - responseMimeType: "application/json", - responseSchema: { - type: Type.OBJECT, - properties: { - name: { type: Type.STRING }, - botanicalName: { type: Type.STRING }, - description: { type: Type.STRING }, - confidence: { type: Type.NUMBER }, - careInfo: { - type: Type.OBJECT, - properties: { - waterIntervalDays: { type: Type.NUMBER }, - light: { type: Type.STRING }, - temp: { type: Type.STRING }, - }, - required: ["waterIntervalDays", "light", "temp"] - } - }, - required: ["name", "botanicalName", "confidence", "careInfo", "description"] - } - } - }); - - if (response.text) { - return JSON.parse(response.text) as IdentificationResult; - } - } catch (error) { - console.error("Gemini analysis failed, falling back to mock.", error); - } - } - - // 2. Mock Process (Fallback) - return new Promise((resolve) => { - setTimeout(() => { - // Use the centralized database service for consistent mock results - const randomResult = PlantDatabaseService.getRandomPlant(lang); - - // Create a clean IdentificationResult without categories/imageUri if we want to strictly adhere to that type, - // though Typescript allows extra props. - // We simulate that the recognition might not be 100% like the db - resolve({ - ...randomResult, - confidence: 0.85 + Math.random() * 0.14 - }); - }, 2500); + identify: async ( + imageUri: string, + lang: Language = 'de', + options: IdentifyOptions = {}, + ): Promise => { + const idempotencyKey = options.idempotencyKey || createIdempotencyKey('scan'); + const response = await backendApiClient.scanPlant({ + idempotencyKey, + imageUri, + language: lang, }); - } + + return response.result; + }, }; diff --git a/services/storageService.ts b/services/storageService.ts index b6f014e..f5578af 100644 --- a/services/storageService.ts +++ b/services/storageService.ts @@ -1,12 +1,36 @@ -import { Plant, Language } from '../types'; +import AsyncStorage from '@react-native-async-storage/async-storage'; +import { Plant, Language, AppearanceMode, ColorPalette } from '../types'; const STORAGE_KEY = 'greenlens_plants'; const LANG_KEY = 'greenlens_language'; +const ONBOARDING_KEY = 'greenlens_onboarding_complete'; +const APPEARANCE_MODE_KEY = 'greenlens_appearance_mode'; +const COLOR_PALETTE_KEY = 'greenlens_color_palette'; +const PROFILE_IMAGE_KEY = 'greenlens_profile_image'; +const PROFILE_NAME_KEY = 'greenlens_profile_name'; +const LEXICON_SEARCH_HISTORY_KEY = 'greenlens_lexicon_search_history'; +const LEXICON_SEARCH_HISTORY_LIMIT = 10; +const DEFAULT_PROFILE_NAME = 'GreenLens User'; + +const isAppearanceMode = (value: string | null): value is AppearanceMode => + value === 'system' || value === 'light' || value === 'dark'; + +const isColorPalette = (value: string | null): value is ColorPalette => + value === 'forest' || value === 'ocean' || value === 'sunset' || value === 'mono'; + +const normalizeSearchQuery = (value: string): string => { + return value + .toLowerCase() + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .trim() + .replace(/\s+/g, ' '); +}; export const StorageService = { - getPlants: (): Plant[] => { + getPlants: async (): Promise => { try { - const json = localStorage.getItem(STORAGE_KEY); + const json = await AsyncStorage.getItem(STORAGE_KEY); return json ? JSON.parse(json) : []; } catch (e) { console.error('Failed to load plants', e); @@ -14,37 +38,142 @@ export const StorageService = { } }, - savePlant: (plant: Plant): void => { - const plants = StorageService.getPlants(); + savePlant: async (plant: Plant): Promise => { + const plants = await StorageService.getPlants(); const updatedPlants = [plant, ...plants]; - localStorage.setItem(STORAGE_KEY, JSON.stringify(updatedPlants)); + await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(updatedPlants)); }, - deletePlant: (id: string): void => { - const plants = StorageService.getPlants(); + deletePlant: async (id: string): Promise => { + const plants = await StorageService.getPlants(); const updatedPlants = plants.filter(p => p.id !== id); - localStorage.setItem(STORAGE_KEY, JSON.stringify(updatedPlants)); + await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(updatedPlants)); }, - updatePlant: (updatedPlant: Plant): void => { - const plants = StorageService.getPlants(); + updatePlant: async (updatedPlant: Plant): Promise => { + const plants = await StorageService.getPlants(); const index = plants.findIndex(p => p.id === updatedPlant.id); if (index !== -1) { plants[index] = updatedPlant; - localStorage.setItem(STORAGE_KEY, JSON.stringify(plants)); + await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(plants)); } }, - getLanguage: (): Language => { + getLanguage: async (): Promise => { try { - const lang = localStorage.getItem(LANG_KEY); - return (lang as Language) || 'de'; + const lang = await AsyncStorage.getItem(LANG_KEY); + return (lang as Language) || 'en'; } catch (e) { - return 'de'; + return 'en'; } }, - saveLanguage: (lang: Language): void => { - localStorage.setItem(LANG_KEY, lang); - } -}; \ No newline at end of file + saveLanguage: async (lang: Language): Promise => { + await AsyncStorage.setItem(LANG_KEY, lang); + }, + + getAppearanceMode: async (): Promise => { + try { + const mode = await AsyncStorage.getItem(APPEARANCE_MODE_KEY); + return isAppearanceMode(mode) ? mode : 'system'; + } catch (e) { + return 'system'; + } + }, + + saveAppearanceMode: async (mode: AppearanceMode): Promise => { + await AsyncStorage.setItem(APPEARANCE_MODE_KEY, mode); + }, + + getColorPalette: async (): Promise => { + try { + const palette = await AsyncStorage.getItem(COLOR_PALETTE_KEY); + return isColorPalette(palette) ? palette : 'forest'; + } catch (e) { + return 'forest'; + } + }, + + saveColorPalette: async (palette: ColorPalette): Promise => { + await AsyncStorage.setItem(COLOR_PALETTE_KEY, palette); + }, + + getProfileImage: async (): Promise => { + try { + const imageUri = await AsyncStorage.getItem(PROFILE_IMAGE_KEY); + return imageUri || null; + } catch (e) { + return null; + } + }, + + saveProfileImage: async (imageUri: string | null): Promise => { + if (!imageUri) { + await AsyncStorage.removeItem(PROFILE_IMAGE_KEY); + return; + } + await AsyncStorage.setItem(PROFILE_IMAGE_KEY, imageUri); + }, + + getProfileName: async (): Promise => { + try { + const profileName = await AsyncStorage.getItem(PROFILE_NAME_KEY); + const normalized = profileName?.trim(); + return normalized || DEFAULT_PROFILE_NAME; + } catch (e) { + return DEFAULT_PROFILE_NAME; + } + }, + + saveProfileName: async (name: string): Promise => { + const normalized = name.trim(); + await AsyncStorage.setItem(PROFILE_NAME_KEY, normalized || DEFAULT_PROFILE_NAME); + }, + + getOnboardingComplete: async (): Promise => { + try { + const value = await AsyncStorage.getItem(ONBOARDING_KEY); + return value === 'true'; + } catch (e) { + return false; + } + }, + + setOnboardingComplete: async (complete: boolean): Promise => { + await AsyncStorage.setItem(ONBOARDING_KEY, complete ? 'true' : 'false'); + }, + + getLexiconSearchHistory: async (): Promise => { + try { + const value = await AsyncStorage.getItem(LEXICON_SEARCH_HISTORY_KEY); + if (!value) return []; + + const parsed = JSON.parse(value); + if (!Array.isArray(parsed)) return []; + + return parsed.filter((item): item is string => typeof item === 'string'); + } catch (e) { + console.error('Failed to load lexicon search history', e); + return []; + } + }, + + saveLexiconSearchQuery: async (query: string): Promise => { + const trimmed = query.trim(); + if (!trimmed) return; + + const history = await StorageService.getLexiconSearchHistory(); + const normalized = normalizeSearchQuery(trimmed); + + const deduped = history.filter( + item => normalizeSearchQuery(item) !== normalized + ); + + const updated = [trimmed, ...deduped].slice(0, LEXICON_SEARCH_HISTORY_LIMIT); + await AsyncStorage.setItem(LEXICON_SEARCH_HISTORY_KEY, JSON.stringify(updated)); + }, + + clearLexiconSearchHistory: async (): Promise => { + await AsyncStorage.removeItem(LEXICON_SEARCH_HISTORY_KEY); + }, +}; diff --git a/skills-lock.json b/skills-lock.json new file mode 100644 index 0000000..0a4bb6c --- /dev/null +++ b/skills-lock.json @@ -0,0 +1,165 @@ +{ + "version": 1, + "skills": { + "ab-test-setup": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "77524b67477802e6cfef718f32abf777da8100374baf8600cd8e5059c3a171cb" + }, + "ad-creative": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "31e23cda4aaf9877fc7cfdafae6c1249a56440d733d7d2e42a7788cd19bb70f7" + }, + "ai-seo": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "f53993e33de7a755602502030d0327ff02899c547a68a75fabcb8a0e3e2e1081" + }, + "analytics-tracking": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "9efe485c17f685451469164d9a4db7c60359fec64dc497dcdf49f2347cf4b67d" + }, + "churn-prevention": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "e9f19c55664af241bac4371d0088b341dce23c6164c5de4c90a509bdf891b83b" + }, + "cold-email": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "7fe88e3c53b3d2e10ad7748299d08a9df213d42268d36ebc05e019f8133df816" + }, + "competitor-alternatives": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "58e1eeceb03b7c7fe965dfb9c73c07fdd0e890bff3b50ef4910b8059217b62d3" + }, + "content-strategy": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "e9eebb0fd871ad3643ddf2a1440ed835efd7f8263282669f36b880885833b7db" + }, + "copy-editing": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "8fa9a2ca4c2761e65e8577951cc89678d233e9e772df13f835eda9783355d3ce" + }, + "copywriting": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "bd3a2e8bec64237aca86cd363fa5349a417eb86d3351447642cc1c5862089c47" + }, + "email-sequence": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "8aff0ca4a1fd1069a693482423155e0731fba4b4ace42a623c74709bf38332ea" + }, + "form-cro": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "3a2cd8fcf153e5e12cef8729241e8c79a433b82fe29b97af42d1764f7d433834" + }, + "free-tool-strategy": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "6e39eb687dbd019f09b3aaaa470c69b6165ebf5654cbc7ef3e2c55061f22b494" + }, + "launch-strategy": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "65670227c4199495634d2b3f8b451ae3cef6397b36db22130fabab89de6a4ba4" + }, + "marketing-ideas": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "b863d744ba010d7314aeb6a23d261971256b9e31e264d1d0a7aac299697c3063" + }, + "marketing-psychology": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "4099d985cf1f5beb26072924cae1e2815295842db72f7861443329adb5d760ce" + }, + "onboarding-cro": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "a7e7eb898095ae6a074158c5ce1d7a6354835ebac48ee416451c9e71f2f58cba" + }, + "page-cro": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "1a02571c4906e5edaf557d49cfc3dc55a6580faa5f0f41c739642172fe448a75" + }, + "paid-ads": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "32310721ddd7cdfd66ef357b7229733d86e11f8edd6fa409ab45c7d6ff2e8334" + }, + "paywall-upgrade-cro": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "1921f4c1077122a0be8bf4459962dae5f40e3e0a147b9ac57e6b7b645d6194d7" + }, + "popup-cro": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "999d0f84fffcac338262664c6a86abf3e5d63e6a68e493881d668274ab8d43d3" + }, + "pricing-strategy": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "5060f95f95db58873b835be2258dc50a959fb814d6466ac11e917cc4a3d632d2" + }, + "product-marketing-context": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "bb407005ef4e68b9b17b870d711ce1a9e09c03611a5fa01d69faf78a8f18eef9" + }, + "programmatic-seo": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "b675dbe0f0d25efbfa788f7b6e01a231d8f7333cacd19c1cf678cdbe7ea1514a" + }, + "referral-program": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "d2720b8a5e40947adad2bc02779e03a1573674268c23a0c41256f9c45123dfad" + }, + "revops": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "8c862ea72ee996f036076badea64178fc0b14a2e4ed56980c90a198321fe1348" + }, + "sales-enablement": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "d37d3b0c74bc74b1bfb584c0bc788a69840bb09ca96a1bd1968235d4f1e91f27" + }, + "schema-markup": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "e6bc10a2a493b85ced75e3db37a1c2a188bb000ba917639414dd56ac2d9cf7d3" + }, + "seo-audit": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "1c7e3a6fb4173f4e505d69cb4c3861af3287d0eeca7a6797a60a0707b5961a96" + }, + "signup-flow-cro": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "3e0d9c47a37593ecac415bc5120ea1d4e478a12bd90258965d89aa4b1b6566c1" + }, + "site-architecture": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "eed0be7862737aa7ef0da29b16fc01c07013b2b03812a9d6d7b93513f1555099" + }, + "social-content": { + "source": "coreyhaines31/marketingskills", + "sourceType": "github", + "computedHash": "9ed34ccfb465a526f2a737129c933a1054985932e64d0055dfd74ed645d86f88" + } + } +} diff --git a/tsconfig.json b/tsconfig.json index 2c6eed5..750e573 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,29 +1,20 @@ { + "extends": "expo/tsconfig.base", "compilerOptions": { - "target": "ES2022", - "experimentalDecorators": true, - "useDefineForClassFields": false, - "module": "ESNext", - "lib": [ - "ES2022", - "DOM", - "DOM.Iterable" - ], - "skipLibCheck": true, - "types": [ - "node" - ], - "moduleResolution": "bundler", - "isolatedModules": true, - "moduleDetection": "force", - "allowJs": true, - "jsx": "react-jsx", + "strict": true, "paths": { "@/*": [ "./*" ] - }, - "allowImportingTsExtensions": true, - "noEmit": true - } + } + }, + "include": [ + "**/*.ts", + "**/*.tsx" + ], + "exclude": [ + "greenlns-landing", + "server", + "landing" + ] } \ No newline at end of file diff --git a/twitter_30_day_viral_plan.md b/twitter_30_day_viral_plan.md new file mode 100644 index 0000000..16e0ced --- /dev/null +++ b/twitter_30_day_viral_plan.md @@ -0,0 +1,529 @@ +# GreenLens X/Twitter 30-Tage Plan + +Stand: 9. Maerz 2026 + +## Kanalentscheidung + +Primaer auf dem eigenen X-Account posten. + +Warum: +- X ist account-first, nicht community-first. +- Reichweite entsteht ueber starke Singles, Threads, Replies und Quote-Posts. +- Communities sind nur fuer sekundaeres Seeding und Research sinnvoll. +- Harte Promo in Communities wird oft entfernt oder ignoriert. + +## Positionierung + +Nicht als allgemeine Plant-Care-App auftreten. + +Scharfer Wedge: +- Plant ER fuer urbane Pflanzen-Anfaenger +- Diagnose bei Panikmomenten +- Symptome in klare naechste Schritte uebersetzen + +Core Promise: +- Weniger raten. Schneller verstehen, was deiner Pflanze fehlt. + +## Verifizierte Seeding-Orte + +Diese Orte sind eher fuer native, hilfreiche Teilnahme geeignet als fuer Promo-Links. + +1. X eigener Account +- Hauptkanal fuer alle Posts, Threads und Serien +- Pinned Post mit klarer Panic-CTA + +2. Replies unter passenden X-Accounts +- Plant-Creator +- Home-Decor / Urban Jungle +- Beginner Gardening +- AI-App / Consumer-App / Build-in-Public Accounts + +3. Reddit r/plantclinic +- Nur fuer echte Hilfsbeitraege und Diagnose-Faelle +- Kontext ist Pflicht: Dauer, Licht, Wasser, Erde +- Sick-plant-only Fokus + +4. Reddit r/houseplants +- Eher fuer Diskussion und allgemeine Fragen +- Selbstpromo ist ungern gesehen + +5. Reddit r/IndoorGarden +- Aktuell kein verlaesslicher Kanal, weil die Community als privat gelistet wurde +- Nicht fuer kurzfristiges Seeding einplanen + +6. Reddit r/monstera, r/succulents, r/cactus +- Nur wenn der Post exakt zum Pflanzentyp passt +- Spezial-Communities eher fuer Research und hilfreiche Antworten + +## Community-Regel + +Wenn du extern postest: +- Kein Copy-Paste vom Tweet +- Kein direkter App-Pitch im ersten Absatz +- Erst Diagnose oder Hilfe liefern +- Link nur, wenn die Community es erlaubt und der Post ohne Link schon Wert hat + +## Profil-Setup vor Tag 1 + +1. Bio: +- AI Plant ER fuer Zimmerpflanzen +- Ich zeige, wie du gelbe Blaetter, braune Spitzen und Pflegefehler schneller erkennst + +2. Pinned Post: +- Wer du bist +- Fuer wen GreenLens ist +- 1 klarer CTA: Profil folgen oder Diagnose-Thread lesen + +3. Link: +- auf eine einfache Landing mit einem einzigen Ziel +- ideal: Scan your dying plant now + +## KPI-Ziele + +Minimum: +- 75k Monatsviews +- 3 Posts ueber 5k +- 150 Profilbesuche + +Soll: +- 250k Monatsviews +- 6 bis 10 Posts ueber 10k +- 400 Profilbesuche + +Stretch: +- 1 Mio Monatsviews +- 1 bis 2 Breakout-Posts ueber 50k +- starke Winner-Serien plus Reply-Distribution + +## Tagesrhythmus + +Mo-Fr: +- 2 originare Posts +- 15 bis 25 qualifizierte Replies + +Sa-So: +- 1 originarer Post +- 10 bis 15 Replies + +Jede Woche: +- 3 Threads +- 2 Proof-Posts mit Bild, Screenshot oder Vorher/Nachher + +## 30 Tage mit fertigen Posts + +Hinweis: +- Posts leicht pointiert formuliert +- bei Bedarf deutsch oder englisch spiegeln +- CTA sparsam einsetzen + +### Tag 1 + +Post 1: +Die meisten Zimmerpflanzen sterben nicht ploetzlich. +Sie senden erst 2 bis 3 kleine Warnsignale. +Die meisten Menschen sehen sie nur zu spaet. + +Post 2: +Gelbe Blaetter bedeuten nicht automatisch: +"mehr Wasser". +Oft ist genau das der Fehler. + +### Tag 2 + +Post 1: +Wenn deine Monstera haengt, ist das Problem oft nicht Gießen. +Es ist meistens ein Mix aus Licht, Timing und zu viel Aktionismus. + +Post 2: +3 Symptome, die wie Wassermangel aussehen, aber keine sind: +1. weiche Stiele +2. muffige Erde +3. gelb + matschig statt trocken + knusprig + +### Tag 3 + +Post 1: +Pflanzen-Anfaenger machen oft denselben Denkfehler: +Sie behandeln jedes Symptom sofort. +Statt erst die Ursache einzugrenzen. + +Post 2: +Braune Blattspitzen sind keine "Pflanze ist kaputt"-Diagnose. +Sie sind ein Hinweis. +Nicht das Urteil. + +### Tag 4 + +Post 1: +Unpopulaere Meinung: +Viele ueberpflegen ihre Zimmerpflanzen in den Tod. + +Post 2: +Wenn du nur 3 Dinge pruefen willst, bevor du irgendetwas aenderst: +1. Licht +2. Erdfeuchte +3. Drainage + +### Tag 5 + +Post 1: +Der schnellste Weg, eine Pflanze zu verlieren: +Jeden Tag etwas Neues ausprobieren. + +Post 2: +Panik-Gießen ist wahrscheinlich der teuerste Pflegefehler bei Zimmerpflanzen. + +### Tag 6 + +Post 1: +Thread: +7 Warnsignale, dass deine Zimmerpflanze nicht "einfach nur muede" ist + +1. neue gelbe Blaetter +2. schlaffe Blattstiele +3. schwarze weiche Stellen +4. dauerhaft nasse Erde +5. fauliger Geruch +6. neues Blatt stoppt komplett +7. Flecken werden groesser + +Wenn 3 davon gleichzeitig auftreten, brauchst du keine Motivation. +Du brauchst Diagnose. + +Post 2: +Wenn du Pflanzen liebst, musst du lernen: +Nicht jedes Problem ist ein Wasserproblem. + +### Tag 7 + +Post 1: +Mein Lieblings-Shortcut bei kranken Zimmerpflanzen: +Nicht fragen "Was fehlt?" +Sondern: +"Was habe ich in den letzten 14 Tagen veraendert?" + +Post 2: +Die Pflanze ist selten "ploetzlich schwierig". +Meistens hat sich ihr Setup veraendert. + +### Tag 8 + +Post 1: +Viele gießen nach Kalender. +Gesunde Pflanzen werden aber nicht nach Kalender gepflegt. + +Post 2: +Wenn die Erde oben trocken ist, sagt das fast nichts. +Entscheidend ist, was tiefer im Topf passiert. + +### Tag 9 + +Post 1: +3 Gruende, warum "mehr Licht" keine universelle Loesung ist: +1. Hitzestress +2. Standortwechsel +3. falsches Timing bei geschwaechter Pflanze + +Post 2: +Eine Pflanze mit Stress sofort umzustellen, ist oft wie ein Patient mit Fieber in einen Sprint zu schicken. + +### Tag 10 + +Post 1: +Build in public: +Je mehr kranke Pflanzenfaelle ich anschaue, desto klarer wird: +Menschen brauchen keine 100 Tipps. +Sie brauchen den naechsten richtigen Schritt. + +Post 2: +Das Problem bei Plant Care Content: +Zu viel allgemeiner Rat. +Zu wenig Symptom -> Ursache -> Handlung. + +### Tag 11 + +Post 1: +Wenn Blaetter gelb werden, frage ich immer zuerst: +gleichmaessig gelb oder fleckig? +weich oder trocken? +alt oder neu? + +Post 2: +Gute Diagnose beginnt nicht mit einem Duenger. +Sondern mit besseren Fragen. + +### Tag 12 + +Post 1: +Thread: +So wuerde ich eine kranke Zimmerpflanze in 5 Minuten triagieren + +1. Pflanze isolieren +2. Erdfeuchte pruefen +3. Blaetter Vorder- und Rueckseite checken +4. Standort notieren +5. erst dann handeln + +Post 2: +Die meisten Pflanzenprobleme eskalieren, weil Menschen zu frueh behandeln und zu spaet beobachten. + +### Tag 13 + +Post 1: +Hot take: +"Easy care" ist fuer Anfaenger oft irrefuehrend. +Easy fuer wen? + +Post 2: +Die beste Anfaengerpflanze ist nicht die "haerteste". +Sondern die, deren Signale du frueh lesen lernst. + +### Tag 14 + +Post 1: +Wenn du Thripse erst bemerkst, wenn das Blatt schlimm aussieht, bist du schon spaet. + +Post 2: +Viele Schaedlinge sehen am Anfang nicht nach Schaedlingen aus. +Sie sehen aus wie "komische Flecken". + +### Tag 15 + +Post 1: +Thread: +5 Pflegefehler, die wie Pech aussehen + +1. Topf ohne echte Drainage +2. Uebertopf mit Restwasser +3. Gießen nach Gewohnheit +4. sofortiges Umtopfen bei Stress +5. zu viele Mittel gleichzeitig + +Post 2: +Pflanzenpflege fuehlt sich chaotisch an, wenn dir ein Diagnose-System fehlt. + +### Tag 16 + +Post 1: +Ich traue Pflanzentipps ohne Kontext nicht mehr. +Ohne Licht, Wasser, Erde und Zeitachse ist fast jede Antwort zu allgemein. + +Post 2: +Fotos helfen. +Aber Kontext rettet die Diagnose. + +### Tag 17 + +Post 1: +Die Frage ist nicht: +"Soll ich gießen?" +Die bessere Frage ist: +"Warum sieht sie heute so aus?" + +Post 2: +Wer Symptome nur mit mehr Pflege beantwortet, verdoppelt oft den Fehler. + +### Tag 18 + +Post 1: +Build in public: +GreenLens sollte nie wie eine generische Plant-App wirken. +Eher wie: +Plant ER fuer Momente, in denen du Angst hast, die Pflanze zu verlieren. + +Post 2: +Das staerkste Produktversprechen ist gerade nicht: +"Pflege deine Pflanzen besser." +Sondern: +"Finde schneller raus, was gerade schiefläuft." + +### Tag 19 + +Post 1: +Thread: +3 Symptome, bei denen ich nicht mehr abwarte + +1. schwarzer weicher Stamm +2. fauliger Geruch aus dem Topf +3. schneller Verfall bei neuem Wachstum + +Post 2: +Nicht jedes Problem braucht Geduld. +Manche brauchen eine schnelle Eskalation. + +### Tag 20 + +Post 1: +Wenn du 4 verschiedene Tipps bekommst, ist das oft kein Zeichen fuer Komplexitaet. +Sondern fuer fehlende Diagnose. + +Post 2: +Menschen wollen bei Pflanzenproblemen Sicherheit. +Deshalb fuehlen sich klare naechste Schritte so wertvoll an. + +### Tag 21 + +Post 1: +Unterschaetzter Fehler: +Zu viele Apps, Tipps und Stimmen gleichzeitig. +Das erzeugt Aktivitaet. +Nicht Klarheit. + +Post 2: +Eine gute Diagnose reduziert Optionen. +Eine schlechte vergroessert Panik. + +### Tag 22 + +Post 1: +Thread: +So erkennst du, ob "mehr Wasser" die Lage verschlimmern wuerde + +1. Erde ist unten noch nass +2. Blatt wird weich statt trocken +3. Gelb kommt vor Braun +4. es riecht dumpf + +Post 2: +Viele Pflanzen sehen durstig aus, wenn ihre Wurzeln eigentlich schon zu viel Wasser hatten. + +### Tag 23 + +Post 1: +Wenn ich Plant Care Content schreibe, denke ich nicht an Hobby. +Ich denke an Triage. + +Post 2: +Das Veraendern von 5 Dingen gleichzeitig ist der schnellste Weg, nie zu verstehen, was geholfen hat. + +### Tag 24 + +Post 1: +Vorher/Nachher-Post: +Vorher: +"Meine Monstera stirbt" +Nachher: +"Es war kein Wassermangel. Es war dauerhaft nasse Erde + zu wenig Licht." + +Post 2: +Viele "Rettungen" beginnen nicht mit dem perfekten Tipp. +Sondern mit dem ersten ausgeschlossenen Fehler. + +### Tag 25 + +Post 1: +Die beste Gewohnheit fuer Pflanzen-Anfaenger: +Beobachtung vor Intervention. + +Post 2: +Ein Diagnosefoto ohne Zeitachse ist wie ein Arztbesuch ohne Vorgeschichte. + +### Tag 26 + +Post 1: +Thread: +Wenn deine Pflanze ploetzlich schlechter aussieht, pruefe diese Reihenfolge + +1. Was hat sich veraendert? +2. Wie nass ist die Erde wirklich? +3. Gibt es Schaedlingsspuren? +4. Ist neues Wachstum betroffen? +5. Was musst du heute nicht tun? + +Post 2: +Oft rettet nicht die perfekte Massnahme. +Sondern das Vermeiden der falschen. + +### Tag 27 + +Post 1: +Kontroverse Meinung: +Die meisten Menschen brauchen keinen weiteren Plant Hack. +Sie brauchen weniger Widerspruch und mehr Priorisierung. + +Post 2: +Wer Pflanzen retten will, muss lernen, zwischen Symptom und Ursache zu unterscheiden. + +### Tag 28 + +Post 1: +Build in public: +Je schaerfer ich GreenLens auf "dying plant moments" fokussiere, desto klarer wird auch der Content. + +Post 2: +Generische Reichweite ist billig. +Relevante Reichweite beginnt mit einem scharfen Problem. + +### Tag 29 + +Post 1: +Thread: +Die 5 haeufigsten Denkfehler bei sterbenden Zimmerpflanzen + +1. mehr Wasser = mehr Hilfe +2. gelb = trocken +3. neues Blatt = alles okay +4. Duenger als erste Reaktion +5. alle Tipps gleichzeitig umsetzen + +Post 2: +Gute Pflanzenpflege fuehlt sich ruhiger an. +Nicht hektischer. + +### Tag 30 + +Post 1: +Wenn ich nur einen Satz fuer Pflanzen-Anfaenger lassen duerfte: +Behandle erst die Ursache. +Nicht nur das sichtbare Problem. + +Post 2: +Falls du eine Pflanze hast, bei der du gerade nur noch raetst: +Genau dort beginnt der eigentliche Wert von guter Diagnose. + +## 3 wiederkehrende CTA-Muster + +1. +Wenn du willst, mache ich Teil 2 mit den haeufigsten Monstera-Fehlern. + +2. +Soll ich daraus eine 5-Minuten-Checkliste machen? + +3. +Welche Symptome werden deiner Meinung nach am haeufigsten falsch gelesen? + +## Reply-Playbooks fuer Distribution + +1. +Stimmt. Der entscheidende Punkt ist oft nicht das Symptom, sondern was in den letzten 7 bis 14 Tagen geaendert wurde. + +2. +Viele verwechseln hier Durst mit Wurzelstress. Sieht aehnlich aus, braucht aber eine ganz andere Reaktion. + +3. +Genau deshalb finde ich Kontext wichtiger als einzelne Fotos: Licht, Wasser, Drainage und Zeitachse veraendern die Diagnose komplett. + +4. +Wuerde ich aehnlich sehen. Mich interessiert nur, ob die Erde unten noch nass war. Das kippt die Interpretation oft. + +5. +Das ist ein gutes Beispiel dafuer, warum "mehr Pflege" nicht immer mehr hilft. + +## Kill-Regeln + +Nach 7 Tagen stoppen: +- Formate mit sehr niedriger View-to-Engagement-Rate +- zu breite Plant-Care-Posts ohne akutes Problem +- Posts, die Likes bekommen, aber keine Profilbesuche ausloesen + +Nach 14 Tagen verdoppeln: +- jede Serie mit ueberdurchschnittlicher Reichweite +- Symptom-Posts mit vielen Replies +- Threads, aus denen sich 3 bis 5 Singles extrahieren lassen + +## Quellen fuer Community-Einschaetzung + +- X erlaubt u. a. das Anpassen des Profils und das Anpinnen eines Posts, was fuer den eigenen Account-Funnel relevant ist: https://help.x.com/nl/managing-your-account/how-to-customize-your-profile +- r/plantclinic zeigt in aktuellen AutoModerator-Hinweisen, dass Kontext wie Licht, Wasser, Erde und Problemhistorie Pflicht ist und Posts auf kranke Pflanzen fokussiert sind: https://www.reddit.com/r/plantclinic/comments/1rmntey/how_to_revive_this_plant/ ; https://www.reddit.com/r/plantclinic/comments/1rn67f1/removed/ +- r/houseplants verweist in Moderationsdiskussionen explizit auf eine Regel gegen Selbstpromo: https://www.reddit.com/r/houseplants/comments/h0wdse ; https://www.reddit.com/r/houseplants/comments/ljpkrg +- r/IndoorGarden wurde als privat gelistet und ist daher kein stabiler Seeding-Ort: https://www.reddit.com/r/SubredditMonitor/comments/14iu3v1 diff --git a/twitter_30_day_viral_plan_en.md b/twitter_30_day_viral_plan_en.md new file mode 100644 index 0000000..2aa04a0 --- /dev/null +++ b/twitter_30_day_viral_plan_en.md @@ -0,0 +1,529 @@ +# GreenLens X/Twitter 30-Day Plan + +Updated: March 9, 2026 + +## Channel Decision + +Post primarily on your own X account. + +Why: +- X is account-first, not community-first. +- Reach comes from strong singles, threads, replies, and quote posts. +- Communities are useful for secondary seeding and research only. +- Hard promo in communities usually gets ignored or removed. + +## Positioning + +Do not show up as a generic plant-care app. + +Sharp wedge: +- Plant ER for urban plant beginners +- Diagnosis in panic moments +- Turn symptoms into clear next steps + +Core promise: +- Less guessing. Faster clarity on what your plant actually needs. + +## Verified Seeding Places + +These places are better for native, helpful participation than for promo links. + +1. Your own X account +- Main channel for all posts, threads, and series +- Pinned post with a clear panic CTA + +2. Replies under relevant X accounts +- Plant creators +- Home decor / urban jungle +- Beginner gardening +- AI app / consumer app / build-in-public accounts + +3. Reddit r/plantclinic +- Only for real help and diagnosis cases +- Context is required: timeline, light, watering, soil +- Sick-plant-only focus + +4. Reddit r/houseplants +- Better for discussion and general questions +- Self-promo is usually unwelcome + +5. Reddit r/IndoorGarden +- Not a reliable channel right now because the community is listed as private +- Do not depend on it for short-term seeding + +6. Reddit r/monstera, r/succulents, r/cactus +- Only if the post fits the exact plant type +- Better for research and helpful answers than broad promotion + +## Community Rule + +If you post externally: +- Do not copy-paste the tweet +- Do not lead with an app pitch +- Deliver diagnosis or help first +- Only add a link if the community allows it and the post already has standalone value + +## Profile Setup Before Day 1 + +1. Bio: +- AI Plant ER for houseplants +- I show you how to spot yellow leaves, brown tips, and care mistakes faster + +2. Pinned post: +- Who you are +- Who GreenLens is for +- One clear CTA: follow the profile or read the diagnosis thread + +3. Link: +- Send traffic to a simple landing page with one goal +- Ideal: scan your dying plant now + +## KPI Targets + +Minimum: +- 75k monthly views +- 3 posts above 5k +- 150 profile visits + +Target: +- 250k monthly views +- 6 to 10 posts above 10k +- 400 profile visits + +Stretch: +- 1M monthly views +- 1 to 2 breakout posts above 50k +- Strong winner series plus reply distribution + +## Daily Rhythm + +Mon-Fri: +- 2 original posts +- 15 to 25 qualified replies + +Sat-Sun: +- 1 original post +- 10 to 15 replies + +Every week: +- 3 threads +- 2 proof posts with image, screenshot, or before/after + +## 30 Days of Ready-to-Post Content + +Notes: +- Posts are intentionally sharp +- Mirror into German only if needed +- Use CTAs sparingly + +### Day 1 + +Post 1: +Most houseplants do not die suddenly. +They send 2 or 3 small warning signs first. +Most people just see them too late. + +Post 2: +Yellow leaves do not automatically mean: +"give it more water." +That is often the exact mistake. + +### Day 2 + +Post 1: +If your Monstera is drooping, the issue is often not watering. +It is usually a mix of light, timing, and too much panic-driven action. + +Post 2: +3 symptoms that look like underwatering but are not: +1. soft stems +2. sour-smelling soil +3. yellow + mushy instead of dry + crispy + +### Day 3 + +Post 1: +Plant beginners make the same mistake over and over: +They treat the symptom immediately. +Instead of narrowing down the cause first. + +Post 2: +Brown leaf tips are not a "your plant is doomed" diagnosis. +They are a clue. +Not the verdict. + +### Day 4 + +Post 1: +Unpopular opinion: +Many people over-care their houseplants to death. + +Post 2: +If you only check 3 things before changing anything: +1. light +2. soil moisture +3. drainage + +### Day 5 + +Post 1: +The fastest way to lose a plant: +Try something new every single day. + +Post 2: +Panic watering is probably the most expensive plant-care mistake beginners make. + +### Day 6 + +Post 1: +Thread: +7 warning signs your houseplant is not "just tired" + +1. new yellow leaves +2. limp stems +3. black soft spots +4. constantly wet soil +5. rotten smell +6. new growth completely stalls +7. spots keep spreading + +If 3 of these show up at once, you do not need motivation. +You need diagnosis. + +Post 2: +If you love plants, you have to learn this: +Not every problem is a watering problem. + +### Day 7 + +Post 1: +My favorite shortcut with sick houseplants: +Do not ask "what does it need?" +Ask: +"what changed in the last 14 days?" + +Post 2: +The plant is rarely "suddenly difficult." +Usually the setup changed. + +### Day 8 + +Post 1: +Many people water by calendar. +Healthy plants are not cared for by calendar. + +Post 2: +If the top layer of soil looks dry, that tells you almost nothing. +What matters is deeper in the pot. + +### Day 9 + +Post 1: +3 reasons "more light" is not a universal fix: +1. heat stress +2. sudden relocation +3. bad timing on an already stressed plant + +Post 2: +Moving a stressed plant immediately is often like sending a feverish patient into a sprint. + +### Day 10 + +Post 1: +Build in public: +The more sick plant cases I look at, the clearer this gets: +People do not need 100 tips. +They need the next right step. + +Post 2: +The problem with plant-care content: +Too much generic advice. +Not enough symptom -> cause -> action. + +### Day 11 + +Post 1: +When leaves turn yellow, I always ask first: +even yellow or patchy? +soft or dry? +old leaves or new? + +Post 2: +Good diagnosis does not start with fertilizer. +It starts with better questions. + +### Day 12 + +Post 1: +Thread: +How I would triage a sick houseplant in 5 minutes + +1. isolate the plant +2. check soil moisture +3. inspect both sides of the leaves +4. note the location +5. act only after that + +Post 2: +Most plant problems escalate because people treat too early and observe too late. + +### Day 13 + +Post 1: +Hot take: +"Easy care" is often misleading for beginners. +Easy for who? + +Post 2: +The best beginner plant is not the toughest one. +It is the one whose signals you learn to read early. + +### Day 14 + +Post 1: +If you notice thrips only when the leaf already looks bad, you are late. + +Post 2: +Many pests do not look like pests at first. +They look like "weird marks." + +### Day 15 + +Post 1: +Thread: +5 plant-care mistakes that look like bad luck + +1. pot with no real drainage +2. decorative pot holding leftover water +3. watering by habit +4. immediate repotting under stress +5. too many treatments at once + +Post 2: +Plant care feels chaotic when you do not have a diagnosis system. + +### Day 16 + +Post 1: +I do not trust plant advice without context anymore. +Without light, watering, soil, and timeline, almost every answer is too general. + +Post 2: +Photos help. +Context saves the diagnosis. + +### Day 17 + +Post 1: +The question is not: +"Should I water?" +The better question is: +"Why does it look like this today?" + +Post 2: +If you answer every symptom with "more care," you often double the mistake. + +### Day 18 + +Post 1: +Build in public: +GreenLens should never feel like a generic plant app. +More like: +Plant ER for the moment you think you might lose the plant. + +Post 2: +The strongest product promise is not: +"take better care of your plants." +It is: +"find out faster what is actually going wrong." + +### Day 19 + +Post 1: +Thread: +3 symptoms I would not wait on + +1. black soft stem +2. rotten smell from the pot +3. fast decline in new growth + +Post 2: +Not every plant problem needs patience. +Some need fast escalation. + +### Day 20 + +Post 1: +If you get 4 different plant tips, that is often not a sign of complexity. +It is a sign of missing diagnosis. + +Post 2: +People want certainty when a plant is struggling. +That is why clear next steps feel so valuable. + +### Day 21 + +Post 1: +Underrated mistake: +Too many apps, tips, and voices at once. +That creates activity. +Not clarity. + +Post 2: +A good diagnosis reduces options. +A bad one increases panic. + +### Day 22 + +Post 1: +Thread: +How to tell if "more water" would make things worse + +1. the lower soil is still wet +2. the leaf feels soft, not dry +3. yellow comes before brown +4. the pot smells dull or sour + +Post 2: +Many plants look thirsty when their roots have actually had too much water. + +### Day 23 + +Post 1: +When I write plant-care content, I do not think in terms of hobby. +I think in terms of triage. + +Post 2: +Changing 5 things at once is the fastest way to never know what actually helped. + +### Day 24 + +Post 1: +Before/after post: +Before: +"My Monstera is dying" +After: +"It was not underwatering. It was constantly wet soil + too little light." + +Post 2: +Most plant rescues do not start with the perfect tip. +They start with the first ruled-out mistake. + +### Day 25 + +Post 1: +The best habit for plant beginners: +Observation before intervention. + +Post 2: +A diagnosis photo without a timeline is like a doctor visit with no history. + +### Day 26 + +Post 1: +Thread: +If your plant suddenly looks worse, check in this order + +1. what changed? +2. how wet is the soil really? +3. are there signs of pests? +4. is new growth affected? +5. what should you not do today? + +Post 2: +Often the rescue does not come from the perfect move. +It comes from avoiding the wrong one. + +### Day 27 + +Post 1: +Controversial opinion: +Most people do not need another plant hack. +They need less contradiction and more prioritization. + +Post 2: +If you want to save plants, you have to learn the difference between symptom and cause. + +### Day 28 + +Post 1: +Build in public: +The sharper I position GreenLens around dying-plant moments, the clearer the content becomes. + +Post 2: +Generic reach is cheap. +Relevant reach starts with a sharp problem. + +### Day 29 + +Post 1: +Thread: +The 5 most common thinking mistakes with dying houseplants + +1. more water = more help +2. yellow = dry +3. new leaf = everything is fine +4. fertilizer as the first reaction +5. applying every tip at once + +Post 2: +Good plant care feels calmer. +Not more hectic. + +### Day 30 + +Post 1: +If I could leave plant beginners with only one sentence: +Treat the cause first. +Not just the visible problem. + +Post 2: +If you have a plant right now and you are still guessing: +That is exactly where better diagnosis starts to matter. + +## 3 Repeatable CTA Patterns + +1. +If you want, I will do part 2 with the most common Monstera mistakes. + +2. +Want me to turn this into a 5-minute checklist? + +3. +Which plant symptoms do you think people misread most often? + +## Reply Playbooks for Distribution + +1. +True. The key is often not the symptom itself, but what changed in the last 7 to 14 days. + +2. +Many people confuse thirst with root stress here. Looks similar. Needs a completely different response. + +3. +This is exactly why context matters more than a single photo: light, watering, drainage, and timeline can completely change the diagnosis. + +4. +I would mostly agree. I would just want to know whether the soil was still wet at the bottom. That usually changes the interpretation. + +5. +This is a great example of why "more care" does not always mean more help. + +## Kill Rules + +After 7 days, stop: +- formats with very low view-to-engagement rate +- broad plant-care posts without an acute problem +- posts that get likes but do not create profile visits + +After 14 days, double down on: +- every series with above-average reach +- symptom posts that generate replies +- threads that can be broken into 3 to 5 strong singles + +## Sources for Community Assessment + +- X profile customization and pinning support the account-first funnel: https://help.x.com/en/managing-your-account/how-to-customize-your-profile +- r/plantclinic AutoModerator examples show that context such as light, watering, soil, and problem history is required and the subreddit is focused on sick plants: https://www.reddit.com/r/plantclinic/comments/1rmntey/how_to_revive_this_plant/ ; https://www.reddit.com/r/plantclinic/comments/1rn67f1/removed/ +- r/houseplants moderation discussions explicitly point to a no-self-promo rule: https://www.reddit.com/r/houseplants/comments/h0wdse ; https://www.reddit.com/r/houseplants/comments/ljpkrg +- r/IndoorGarden was listed as private and is not a stable seeding place: https://www.reddit.com/r/SubredditMonitor/comments/14iu3v1 diff --git a/types.ts b/types.ts index dff160f..e62cc72 100644 --- a/types.ts +++ b/types.ts @@ -1,10 +1,49 @@ +export interface LocalizedPlantContent { + name: string; + description: string; + light: string; +} + +export interface MultilingualPlantEntry { + botanicalName: string; + confidence: number; + careInfo: { + waterIntervalDays: number; + temp: string; + }; + imageUri: string; + categories: string[]; + translations: { + de: LocalizedPlantContent; + en: LocalizedPlantContent; + es: LocalizedPlantContent; + }; +} + export interface CareInfo { waterIntervalDays: number; light: string; temp: string; } +export interface PlantHealthIssue { + title: string; + confidence: number; + details: string; +} + +export interface PlantHealthCheck { + generatedAt: string; + overallHealthScore: number; + status: 'healthy' | 'watch' | 'critical'; + likelyIssues: PlantHealthIssue[]; + actionsNow: string[]; + plan7Days: string[]; + creditsCharged: number; + imageUri?: string; +} + export interface Plant { id: string; name: string; @@ -14,8 +53,10 @@ export interface Plant { careInfo: CareInfo; lastWatered: string; // Serialized Date wateringHistory?: string[]; // Array of serialized dates + gallery?: string[]; // Array of image URIs description?: string; notificationsEnabled?: boolean; + healthChecks?: PlantHealthCheck[]; } export interface IdentificationResult { @@ -33,3 +74,9 @@ export enum Tab { } export type Language = 'de' | 'en' | 'es'; + +export type AppearanceMode = 'system' | 'light' | 'dark'; + +export type AppColorScheme = 'light' | 'dark'; + +export type ColorPalette = 'forest' | 'ocean' | 'sunset' | 'mono'; diff --git a/utils/backendUrl.ts b/utils/backendUrl.ts new file mode 100644 index 0000000..3e04161 --- /dev/null +++ b/utils/backendUrl.ts @@ -0,0 +1,42 @@ +const DEFAULT_API_BASE_URL = 'http://localhost:3000/api'; + +const normalizeHttpUrl = (value?: string | null): string | null => { + const trimmed = String(value || '').trim(); + if (!trimmed) return null; + + try { + const parsed = new URL(trimmed); + return `${parsed.origin}${parsed.pathname}`.replace(/\/+$/, ''); + } catch { + return null; + } +}; + +export const getConfiguredApiBaseUrl = (): string => { + const explicitApiUrl = normalizeHttpUrl(process.env.EXPO_PUBLIC_API_URL); + if (explicitApiUrl) return explicitApiUrl; + + const backendBaseUrl = normalizeHttpUrl( + process.env.EXPO_PUBLIC_BACKEND_URL || process.env.EXPO_PUBLIC_PAYMENT_SERVER_URL, + ); + if (backendBaseUrl) { + return backendBaseUrl.endsWith('/api') ? backendBaseUrl : `${backendBaseUrl}/api`; + } + + return DEFAULT_API_BASE_URL; +}; + +export const getConfiguredAssetBaseUrl = (): string => { + const apiBaseUrl = getConfiguredApiBaseUrl(); + + try { + const parsed = new URL(apiBaseUrl); + const pathname = parsed.pathname.replace(/\/+$/, ''); + const assetPath = pathname.endsWith('/api') + ? pathname.slice(0, -4) + : pathname; + return `${parsed.origin}${assetPath}`.replace(/\/+$/, ''); + } catch { + return 'http://localhost:3000'; + } +}; diff --git a/utils/hybridSearch.ts b/utils/hybridSearch.ts new file mode 100644 index 0000000..d385449 --- /dev/null +++ b/utils/hybridSearch.ts @@ -0,0 +1,213 @@ +import { CareInfo } from '../types'; + +const { SEARCH_INTENT_CONFIG } = require('../constants/searchIntentConfig'); + +type SearchIntentConfig = { + aliases?: string[]; + entryHints?: string[]; + lightHints?: string[]; +}; + +export interface HybridSearchEntryLike { + name: string; + botanicalName?: string; + description?: string; + categories?: string[]; + careInfo?: Partial | null; +} + +interface RankedEntry { + entry: T; + score: number; +} + +const normalizeArray = (values: string[]): string[] => { + return [...new Set(values.map((value) => normalizeSearchText(value)).filter(Boolean))]; +}; + +export const normalizeSearchText = (value: string): string => { + return value + .toLowerCase() + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .trim() + .replace(/[^a-z0-9\s_-]+/g, ' ') + .replace(/[_-]+/g, ' ') + .replace(/\s+/g, ' '); +}; + +const tokenize = (normalizedValue: string): string[] => { + return normalizedValue.split(' ').filter(Boolean); +}; + +const tokenSetFromQuery = (normalizedQuery: string): Set => { + const rawTokens = tokenize(normalizedQuery); + const noise = new Set(SEARCH_INTENT_CONFIG.noiseTokens.map((token: string) => normalizeSearchText(token))); + return new Set(rawTokens.filter((token) => !noise.has(token))); +}; + +const includesPhrase = (normalizedQuery: string, normalizedAlias: string, queryTokens: Set): boolean => { + if (!normalizedAlias) return false; + if (normalizedQuery.includes(normalizedAlias)) return true; + + const aliasTokens = tokenize(normalizedAlias); + if (aliasTokens.length <= 1) return queryTokens.has(normalizedAlias); + return aliasTokens.every((token) => queryTokens.has(token)); +}; + +const detectQueryIntents = (normalizedQuery: string): string[] => { + const queryTokens = tokenSetFromQuery(normalizedQuery); + const intents = (Object.entries(SEARCH_INTENT_CONFIG.intents) as Array<[string, SearchIntentConfig]>) + .filter(([, value]) => + (value.aliases || []).some((alias) => includesPhrase(normalizedQuery, normalizeSearchText(alias), queryTokens))) + .map(([intentId]) => intentId); + return intents; +}; + +const getLevenshteinDistance = (left: string, right: string): number => { + const rows = left.length + 1; + const cols = right.length + 1; + const matrix: number[][] = Array.from({ length: rows }, (_, rowIndex) => [rowIndex]); + + for (let col = 0; col < cols; col += 1) { + matrix[0][col] = col; + } + + for (let row = 1; row < rows; row += 1) { + for (let col = 1; col < cols; col += 1) { + const cost = left[row - 1] === right[col - 1] ? 0 : 1; + matrix[row][col] = Math.min( + matrix[row - 1][col] + 1, + matrix[row][col - 1] + 1, + matrix[row - 1][col - 1] + cost, + ); + } + } + + return matrix[left.length][right.length]; +}; + +const fuzzyBonus = (normalizedQuery: string, candidates: string[]): number => { + if (normalizedQuery.length < 3 || normalizedQuery.length > 32) return 0; + + let best = Number.POSITIVE_INFINITY; + candidates.forEach((candidate) => { + if (!candidate) return; + tokenize(candidate).forEach((token) => { + best = Math.min(best, getLevenshteinDistance(normalizedQuery, token)); + }); + best = Math.min(best, getLevenshteinDistance(normalizedQuery, candidate)); + }); + + if (best === 1) return 14; + if (best === 2) return 8; + return 0; +}; + +const scoreTextMatch = (normalizedQuery: string, normalizedTarget: string, exact: number, prefix: number, contains: number): number => { + if (!normalizedQuery || !normalizedTarget) return 0; + if (normalizedTarget === normalizedQuery) return exact; + if (normalizedTarget.startsWith(normalizedQuery)) return prefix; + if (normalizedTarget.includes(normalizedQuery)) return contains; + return 0; +}; + +const buildDerivedIntentSignals = (entry: HybridSearchEntryLike): string[] => { + const normalizedDescription = normalizeSearchText(entry.description || ''); + const normalizedLight = normalizeSearchText(entry.careInfo?.light || ''); + + const derivedSignals = new Set(); + const normalizedCategories = (entry.categories || []).map((category) => normalizeSearchText(category)); + normalizedCategories.forEach((category) => derivedSignals.add(category)); + + (Object.entries(SEARCH_INTENT_CONFIG.intents) as Array<[string, SearchIntentConfig]>).forEach(([intentId, intentConfig]) => { + const entryHints = normalizeArray(intentConfig.entryHints || []); + if (entryHints.some((hint) => normalizedDescription.includes(hint))) { + derivedSignals.add(intentId); + } + + const lightHints = normalizeArray(intentConfig.lightHints || []); + if (lightHints.some((hint) => normalizedLight.includes(hint))) { + derivedSignals.add(intentId); + } + }); + + return [...derivedSignals]; +}; + +export const scoreHybridEntry = (entry: HybridSearchEntryLike, query: string): number => { + const normalizedQuery = normalizeSearchText(query); + if (!normalizedQuery) return 0; + + const normalizedName = normalizeSearchText(entry.name || ''); + const normalizedBotanical = normalizeSearchText(entry.botanicalName || ''); + const normalizedDescription = normalizeSearchText(entry.description || ''); + const normalizedCategories = (entry.categories || []).map((category) => normalizeSearchText(category)); + const derivedSignals = buildDerivedIntentSignals(entry); + const requestedIntents = detectQueryIntents(normalizedQuery); + + let score = 0; + score += Math.max( + scoreTextMatch(normalizedQuery, normalizedName, 140, 100, 64), + scoreTextMatch(normalizedQuery, normalizedBotanical, 130, 96, 58), + ); + + if (normalizedDescription.includes(normalizedQuery)) { + score += 24; + } + + score += fuzzyBonus(normalizedQuery, [normalizedName, normalizedBotanical, ...normalizedCategories]); + + let matchedIntentCount = 0; + requestedIntents.forEach((intentId) => { + const categoryHit = normalizedCategories.includes(intentId); + const derivedHit = derivedSignals.includes(intentId); + if (categoryHit) { + score += 92; + matchedIntentCount += 1; + return; + } + if (derivedHit) { + score += 56; + matchedIntentCount += 1; + } + }); + + if (matchedIntentCount >= 2) { + score += 38 * matchedIntentCount; + } else if (matchedIntentCount === 1) { + score += 10; + } + + const queryTokens = [...tokenSetFromQuery(normalizedQuery)]; + if (queryTokens.length > 1) { + const searchableText = [normalizedName, normalizedBotanical, normalizedDescription, ...normalizedCategories, ...derivedSignals].join(' '); + const tokenHits = queryTokens.filter((token) => searchableText.includes(token)).length; + score += tokenHits * 8; + if (tokenHits === queryTokens.length && queryTokens.length > 0) { + score += 16; + } + } + + return score; +}; + +export const rankHybridEntries = ( + entries: T[], + query: string, + limit = 30, +): RankedEntry[] => { + const normalizedQuery = normalizeSearchText(query); + if (!normalizedQuery) { + return entries.slice(0, limit).map((entry) => ({ entry, score: 0 })); + } + + return entries + .map((entry) => ({ entry, score: scoreHybridEntry(entry, normalizedQuery) })) + .filter((candidate) => candidate.score > 0) + .sort((left, right) => + right.score - left.score || + left.entry.name.length - right.entry.name.length || + left.entry.name.localeCompare(right.entry.name)) + .slice(0, limit); +}; diff --git a/utils/idempotency.ts b/utils/idempotency.ts new file mode 100644 index 0000000..895f95e --- /dev/null +++ b/utils/idempotency.ts @@ -0,0 +1,17 @@ +const sanitizeSeed = (value: string): string => { + return value + .toLowerCase() + .replace(/[^a-z0-9]+/g, '-') + .replace(/^-+|-+$/g, '') + .slice(0, 36); +}; + +export const createIdempotencyKey = (scope: string, seed?: string): string => { + const base = sanitizeSeed(scope || 'action') || 'action'; + const seedPart = seed ? sanitizeSeed(seed) : ''; + const timestamp = Date.now().toString(36); + const random = Math.random().toString(36).slice(2, 10); + return seedPart + ? `${base}-${seedPart}-${timestamp}-${random}` + : `${base}-${timestamp}-${random}`; +}; diff --git a/utils/imageUri.ts b/utils/imageUri.ts new file mode 100644 index 0000000..581a807 --- /dev/null +++ b/utils/imageUri.ts @@ -0,0 +1,217 @@ +import { getConfiguredAssetBaseUrl } from './backendUrl'; + +const WIKIMEDIA_FILEPATH_SEGMENT = 'Special:FilePath/'; +const WIKIMEDIA_REDIRECT_BASE = 'https://commons.wikimedia.org/wiki/Special:FilePath/'; + +export const DEFAULT_PLANT_IMAGE_URI = + 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Monstera_deliciosa2.jpg/330px-Monstera_deliciosa2.jpg'; + +// Verified working fallback images per category (from main database URLs) +const CATEGORY_FALLBACK_IMAGES: Record = { + succulent: 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/Aloe_Vera_houseplant.jpg/330px-Aloe_Vera_houseplant.jpg', + flowering: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/AnthuriumAndraenum.jpg/330px-AnthuriumAndraenum.jpg', + medicinal: 'https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Lavandula_angustifolia_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-087.jpg/330px-Lavandula_angustifolia_-_K%C3%B6hler%E2%80%93s_Medizinal-Pflanzen-087.jpg', + tree: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Ficus_benjamina.jpg/330px-Ficus_benjamina.jpg', + hanging: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Money_Plant_%28Epipremnum_aureum%29_4.jpg/330px-Money_Plant_%28Epipremnum_aureum%29_4.jpg', + patterned: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Starr_080716-9470_Calathea_crotalifera.jpg/330px-Starr_080716-9470_Calathea_crotalifera.jpg', + pet_friendly: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Chlorophytum_comosum_01.jpg/330px-Chlorophytum_comosum_01.jpg', + high_humidity: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/bd/Spathiphyllum_cochlearispathum_RTBG.jpg/330px-Spathiphyllum_cochlearispathum_RTBG.jpg', + air_purifier: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/Snake_Plant_%28Sansevieria_trifasciata_%27Laurentii%27%29.jpg/330px-Snake_Plant_%28Sansevieria_trifasciata_%27Laurentii%27%29.jpg', + sun: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Echeveria_elegans_-_1.jpg/330px-Echeveria_elegans_-_1.jpg', + low_light: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Zamioculcas_zamiifolia_1.jpg/330px-Zamioculcas_zamiifolia_1.jpg', + easy: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Pilea_peperomioides_Chinese_money_plant.jpg/330px-Pilea_peperomioides_Chinese_money_plant.jpg', + large: 'https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Strelitzia_nicolai_3.jpg/330px-Strelitzia_nicolai_3.jpg', +}; + +const CATEGORY_PRIORITY = [ + 'succulent', 'flowering', 'medicinal', 'tree', 'hanging', + 'patterned', 'pet_friendly', 'high_humidity', 'air_purifier', + 'sun', 'low_light', 'easy', 'large', +]; + +export const getCategoryFallbackImage = (categories: string[]): string => { + for (const cat of CATEGORY_PRIORITY) { + if (categories.includes(cat) && CATEGORY_FALLBACK_IMAGES[cat]) { + return CATEGORY_FALLBACK_IMAGES[cat]; + } + } + return DEFAULT_PLANT_IMAGE_URI; +}; + +const tryDecode = (value: string): string => { + try { + return decodeURIComponent(value); + } catch { + return value; + } +}; + +const decodeRepeatedly = (value: string, rounds = 3): string => { + let current = value; + for (let index = 0; index < rounds; index += 1) { + const decoded = tryDecode(current); + if (decoded === current) break; + current = decoded; + } + return current; +}; + +type PlantManifestItem = { + localImageUri?: string; + sourceUri?: string; +}; + +let manifestSourceByLocalUriCache: Map | null = null; +let wikimediaSearchCache: Record | null = null; + +const normalizePlantAssetPath = (value?: string | null): string | null => { + const trimmed = String(value || '').trim(); + if (!trimmed) return null; + + const withoutQuery = trimmed.split(/[?#]/)[0].replace(/\\/g, '/'); + const normalizedPath = withoutQuery.startsWith('/') ? withoutQuery : `/${withoutQuery}`; + if (!normalizedPath.startsWith('/plants/')) return null; + if (normalizedPath.includes('..')) return null; + return normalizedPath; +}; + +const loadManifestSourceByLocalUri = (): Map => { + if (manifestSourceByLocalUriCache) return manifestSourceByLocalUriCache; + + const nextCache = new Map(); + try { + const manifest = require('../server/public/plants/manifest.json') as { items?: PlantManifestItem[] }; + const items = Array.isArray(manifest?.items) ? manifest.items : []; + for (const item of items) { + const localImageUri = normalizePlantAssetPath(item?.localImageUri); + const sourceUri = String(item?.sourceUri || '').trim(); + if (!localImageUri || !sourceUri) continue; + nextCache.set(localImageUri, sourceUri); + } + } catch { + // Keep empty cache when manifest is unavailable. + } + + manifestSourceByLocalUriCache = nextCache; + return nextCache; +}; + +const loadWikimediaSearchCache = (): Record => { + if (wikimediaSearchCache) return wikimediaSearchCache; + + try { + wikimediaSearchCache = require('../server/public/plants/wikimedia-search-cache.json') as Record; + } catch { + wikimediaSearchCache = {}; + } + + return wikimediaSearchCache; +}; + +const resolveServerAssetPath = (rawPath: string): string | null => { + const normalizedPath = normalizePlantAssetPath(rawPath); + if (!normalizedPath) return null; + + return `${getConfiguredAssetBaseUrl()}${normalizedPath}`; +}; + +const unwrapMarkdownLink = (value: string): string => { + const markdownLink = value.match(/^\[[^\]]+]\((https?:\/\/[^)]+)\)(.*)$/i); + if (!markdownLink) return value; + const [, url, suffix] = markdownLink; + return `${url}${suffix || ''}`; +}; + +const convertWikimediaFilePathUrl = (value: string): string | null => { + const segmentIndex = value.indexOf(WIKIMEDIA_FILEPATH_SEGMENT); + if (segmentIndex < 0) return null; + + const fileNameStart = segmentIndex + WIKIMEDIA_FILEPATH_SEGMENT.length; + const rawFileName = value.slice(fileNameStart).split(/[?#]/)[0].trim(); + if (!rawFileName) return null; + + const decodedFileName = tryDecode(rawFileName).replace(/\s+/g, ' ').trim(); + const encodedFileName = encodeURIComponent(decodedFileName).replace(/%2F/g, '/'); + return `${WIKIMEDIA_REDIRECT_BASE}${encodedFileName}`; +}; + +export const getWikimediaFilePathFromThumbnailUrl = (url: string): string | null => { + if (!url.includes('upload.wikimedia.org/wikipedia/commons/thumb/')) return null; + + // Example: https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Monstera_deliciosa2.jpg/330px-Monstera_deliciosa2.jpg + // The filename is the segment between the second-to-last and last slash (in many cases) + // or use a more robust regex + const parts = url.split('/'); + // Filter out empty parts from trailing slashes + const filtered = parts.filter(p => !!p); + if (filtered.length < 5) return null; + + // For thumb URLs, the filename is typically the part before the last part (which is the px-filename) + // but let's be careful. + const lastName = filtered[filtered.length - 1]; + const secondLastName = filtered[filtered.length - 2]; + + // In thumb URLs, the last part is usually "330px-Filename.jpg" + // The second to last is "Filename.jpg" + if (lastName.includes('px-') && lastName.endsWith(secondLastName)) { + try { + return decodeURIComponent(secondLastName); + } catch { + return secondLastName; + } + } + + return null; +}; + +export const getPlantImageSourceFallbackUri = (rawUri?: string | null): string | null => { + const localImageUri = normalizePlantAssetPath(rawUri); + if (!localImageUri) return null; + + const sourceUri = loadManifestSourceByLocalUri().get(localImageUri); + if (!sourceUri) return null; + + if (/^https?:\/\//i.test(sourceUri)) { + return tryResolveImageUri(sourceUri); + } + + if (!sourceUri.startsWith('wikimedia-search:')) { + return null; + } + + const rawQuery = sourceUri.slice('wikimedia-search:'.length).trim(); + const decodedQuery = decodeRepeatedly(rawQuery); + if (!decodedQuery) return null; + + const searchCache = loadWikimediaSearchCache(); + const cachedUrl = searchCache[decodedQuery] + || searchCache[rawQuery] + || searchCache[encodeURIComponent(decodedQuery)] + || null; + + return cachedUrl ? tryResolveImageUri(cachedUrl) : null; +}; + +export const tryResolveImageUri = (rawUri?: string | null): string | null => { + if (!rawUri) return null; + + const trimmed = rawUri.trim(); + if (!trimmed) return null; + + const localAssetUri = resolveServerAssetPath(trimmed); + if (localAssetUri) return localAssetUri; + + const normalized = unwrapMarkdownLink(trimmed); + const converted = convertWikimediaFilePathUrl(normalized); + const candidate = (converted || normalized).replace(/^http:\/\//i, 'https://'); + + if (!/^(https?:\/\/|file:\/\/|content:\/\/|data:image\/|blob:)/i.test(candidate)) { + return null; + } + + return candidate; +}; + +export const resolveImageUri = (rawUri?: string | null): string => { + return tryResolveImageUri(rawUri) || DEFAULT_PLANT_IMAGE_URI; +}; diff --git a/utils/translations.ts b/utils/translations.ts index 77e8a92..3d51658 100644 --- a/utils/translations.ts +++ b/utils/translations.ts @@ -16,9 +16,23 @@ export const translations = { // Settings darkMode: 'Dark Mode', language: 'Sprache', + appearance: 'Design', + appearanceMode: 'Modus', + colorPalette: 'Farbpalette', + themeSystem: 'System', + themeLight: 'Hell', + themeDark: 'Dunkel', + paletteForest: 'Forest', + paletteOcean: 'Ocean', + paletteSunset: 'Sunset', + paletteMono: 'Mono', - // Empty States / Info + // Info noPlants: 'Noch keine Pflanzen.', + nextStepsTitle: 'Deine nächsten Schritte', + stepScan: 'Erste Pflanze scannen', + stepLexicon: 'Pflanzenlexikon erkunden', + stepTheme: 'Design anpassen', // Filters allGood: 'Alles gut', @@ -29,6 +43,17 @@ export const translations = { categories: 'Kategorien entdecken', resultsInPlants: 'Ergebnisse in "Meine Pflanzen"', noResults: 'Keine Pflanzen gefunden.', + searchMyPlants: 'Meine Pflanzen', + searchLexicon: 'Lexikon', + searchAiSection: 'AI Deep Search', + searchDeepAction: 'Deep Search (AI)', + searchNoLocalResults: 'Keine Treffer in deiner Sammlung.', + searchNoLexiconResults: 'Keine Treffer im Lexikon.', + searchAiLoading: 'AI durchsucht den Katalog...', + searchAiNoResults: 'AI hat keine passenden Pflanzen gefunden.', + searchAiUnavailable: 'AI-Suche ist aktuell nicht verfügbar.', + searchHistory: 'Suchverlauf', + clearHistory: 'Verlauf löschen', // Categories catCareEasy: "Pflegeleicht", @@ -37,6 +62,14 @@ export const translations = { catPetFriendly: "Tierfreundlich", catAirPurifier: "Luftreiniger", catFlowering: "Blühend", + catBrightLight: "Helles Licht", + catSun: "Sonnig", + catHighHumidity: "Hohe Luftfeuchte", + catHanging: "Hängend", + catPatterned: "Gemustert", + catTree: "Bäume", + catLarge: "Groß", + catMedicinal: "Heilpflanzen", // Dictionary lexiconTitle: "Pflanzen-Lexikon", @@ -52,12 +85,40 @@ export const translations = { scanner: 'Scanner', analyzing: 'Pflanze wird analysiert...', localProcessing: "Lokale Verarbeitung", + registerToSave: "Registrieren zum Speichern", // Scan Stages scanStage1: "Bildqualität wird geprüft...", scanStage2: "Blattstrukturen werden analysiert...", scanStage3: "Abgleich mit Pflanzendatenbank...", + // Dashboard + greetingMorning: 'Guten Morgen,', + greetingAfternoon: 'Guten Tag,', + greetingEvening: 'Guten Abend,', + creditsLabel: 'Credits', + needsWaterToday: 'Heute gießen', + viewSchedule: 'Plan anzeigen', + all: 'Alle', + today: 'Heute', + week: 'Woche', + healthy: 'Gesund', + dormant: 'Ruhe', + thirsty: 'Durstig', + healthyStatus: 'Gesund', + nextWaterLabel: 'Gießen', + noneInFilter: 'Keine Pflanzen in diesem Filter.', + reminderTitle: 'Erinnerungen', + reminderNone: 'Heute ist keine Pflanze fällig.', + reminderDue: '{0} Pflanzen brauchen heute Wasser.', + plantsThirsty: '{0} deiner Pflanzen brauchen heute Wasser!', + collectionCount: '{0} Pflanzen', + more: 'weitere', + collectionTitle: 'Sammlung', + emptyCollectionTitle: 'Deine Sammlung ist noch leer', + emptyCollectionHint: 'Scanne deine erste Pflanze und starte deine digitale Sammlung.', + scanFirstPlant: 'Erste Pflanze scannen', + // Plant Card / Detail / Result result: "Ergebnis", match: "Übereinstimmung", @@ -116,6 +177,37 @@ export const translations = { reminderOn: "Aktiviert", reminderOff: "Deaktiviert", reminderPermissionNeeded: "Berechtigung für Benachrichtigungen erforderlich.", + + // Gallery + galleryTitle: "Galerie", + addPhoto: "Foto hinzufügen", + noPhotos: "Noch keine Fotos", + + // Tour + tourFabTitle: "📷 Pflanze scannen", + tourFabDesc: "Tippe hier um eine Pflanze zu fotografieren — die KI erkennt sie sofort.", + tourSearchTitle: "🔍 Pflanzenlexikon", + tourSearchDesc: "Durchsuche tausende Pflanzen oder lass die KI nach der perfekten suchen.", + tourProfileTitle: "👤 Dein Profil", + tourProfileDesc: "Passe Design, Sprache und Benachrichtigungen ganz nach deinem Geschmack an.", + + // Onboarding + onboardingTitle1: "Pflanzen-Scanner", + onboardingTitle2: "Pflanzenpflege", + onboardingTitle3: "Dein Garten", + onboardingDesc1: "Scanne jede Pflanze und identifiziere sie sofort mit KI", + onboardingDesc2: "Erhalte personalisierte Pflegetipps und Gießerinnerungen", + onboardingDesc3: "Baue deine digitale Pflanzensammlung auf", + onboardingNext: "Weiter", + onboardingStart: "Los geht's", + onboardingTagline: "Deine Pflanzen. Deine Welt.", + onboardingFeatureScan: "Pflanzen scannen & erkennen", + onboardingFeatureReminder: "Gießerinnerungen & Pflege", + onboardingFeatureLexicon: "Digitales Pflanzen-Lexikon", + onboardingScanBtn: "Pflanze scannen", + onboardingRegister: "Registrieren", + onboardingLogin: "Anmelden", + onboardingDisclaimer: "Deine Daten bleiben privat und lokal auf deinem Gerät.", }, en: { tabPlants: 'Plants', @@ -126,13 +218,38 @@ export const translations = { settingsTitle: 'Settings', darkMode: 'Dark Mode', language: 'Language', + appearance: 'Appearance', + appearanceMode: 'Mode', + colorPalette: 'Color Palette', + themeSystem: 'System', + themeLight: 'Light', + themeDark: 'Dark', + paletteForest: 'Forest', + paletteOcean: 'Ocean', + paletteSunset: 'Sunset', + paletteMono: 'Mono', noPlants: 'No plants yet.', + nextStepsTitle: 'Your next steps', + stepScan: 'Scan first plant', + stepLexicon: 'Explore plant lexicon', + stepTheme: 'Customize design', allGood: 'All good', toWater: 'To water', searchPlaceholder: 'Search plants...', categories: 'Discover Categories', resultsInPlants: 'Results in "My Plants"', noResults: 'No plants found.', + searchMyPlants: 'My Plants', + searchLexicon: 'Lexicon', + searchAiSection: 'AI Deep Search', + searchDeepAction: 'Deep Search (AI)', + searchNoLocalResults: 'No matches in your collection.', + searchNoLexiconResults: 'No matches in the lexicon.', + searchAiLoading: 'AI is searching the catalog...', + searchAiNoResults: 'AI found no matching plants.', + searchAiUnavailable: 'AI search is currently unavailable.', + searchHistory: 'Search history', + clearHistory: 'Clear history', catCareEasy: "Easy Care", catSucculents: "Succulents", @@ -140,25 +257,61 @@ export const translations = { catPetFriendly: "Pet Friendly", catAirPurifier: "Air Purifier", catFlowering: "Flowering", + catBrightLight: "Bright Light", + catSun: "Sunny", + catHighHumidity: "High Humidity", + catHanging: "Hanging", + catPatterned: "Patterned", + catTree: "Trees", + catLarge: "Large", + catMedicinal: "Medicinal", lexiconTitle: "Plant Encyclopedia", lexiconDesc: "Browse our database and find the perfect addition for your home.", lexiconSearchPlaceholder: "Search encyclopedia...", browseLexicon: "Browse Encyclopedia", backToSearch: "Back to Search", - - comingSoon: 'Coming Soon', - gallery: 'Gallery', - help: 'Help', - scanner: 'Scanner', - analyzing: 'Analyzing plant...', - localProcessing: "Local Processing", +// Misc +comingSoon: 'Coming Soon', +gallery: 'Gallery', +help: 'Help', +scanner: 'Scanner', +analyzing: 'Analyzing plant...', +localProcessing: "Local Processing", +registerToSave: "Sign up to save", // Scan Stages scanStage1: "Checking image quality...", scanStage2: "Analyzing leaf structures...", scanStage3: "Matching with plant database...", + // Dashboard + greetingMorning: 'Good morning,', + greetingAfternoon: 'Good afternoon,', + greetingEvening: 'Good evening,', + creditsLabel: 'Credits', + needsWaterToday: 'Needs water today', + viewSchedule: 'View Schedule', + all: 'All', + today: 'Today', + week: 'Week', + healthy: 'Healthy', + dormant: 'Dormant', + thirsty: 'Thirsty', + healthyStatus: 'Healthy', + nextWaterLabel: 'Water', + noneInFilter: 'No plants in this filter.', + reminderTitle: 'Reminders', + reminderNone: 'No plants are due today.', + reminderDue: '{0} plants need water today.', + plantsThirsty: '{0} of your plants are feeling thirsty!', + collectionCount: '{0} plants', + more: 'more', + collectionTitle: 'Collection', + emptyCollectionTitle: 'Your collection is still empty', + emptyCollectionHint: 'Scan your first plant to start building your digital garden.', + scanFirstPlant: 'Scan first plant', + result: "Result", match: "Match", careCheck: "Care Check", @@ -212,6 +365,37 @@ export const translations = { reminderOn: "Enabled", reminderOff: "Disabled", reminderPermissionNeeded: "Notification permission required.", + + // Gallery + galleryTitle: "Gallery", + addPhoto: "Add Photo", + noPhotos: "No photos yet", + + // Tour + tourFabTitle: "📷 Scan Plant", + tourFabDesc: "Tap here to photograph a plant — the AI recognizes it instantly.", + tourSearchTitle: "🔍 Plant Encyclopedia", + tourSearchDesc: "Search thousands of plants or let the AI find the perfect one.", + tourProfileTitle: "👤 Your Profile", + tourProfileDesc: "Customize design, language, and notifications to your liking.", + + // Onboarding + onboardingTitle1: "Plant Scanner", + onboardingTitle2: "Plant Care", + onboardingTitle3: "Your Garden", + onboardingDesc1: "Scan any plant and identify it instantly with AI", + onboardingDesc2: "Get personalized care tips and watering reminders", + onboardingDesc3: "Build your digital plant collection", + onboardingNext: "Next", + onboardingStart: "Get Started", + onboardingTagline: "Your plants. Your world.", + onboardingFeatureScan: "Scan & identify plants", + onboardingFeatureReminder: "Watering reminders & care", + onboardingFeatureLexicon: "Digital plant encyclopedia", + onboardingScanBtn: "Scan Plant", + onboardingRegister: "Sign Up", + onboardingLogin: "Log In", + onboardingDisclaimer: "Your data stays private and local on your device.", }, es: { tabPlants: 'Plantas', @@ -222,13 +406,38 @@ export const translations = { settingsTitle: 'Ajustes', darkMode: 'Modo Oscuro', language: 'Idioma', + appearance: 'Apariencia', + appearanceMode: 'Modo', + colorPalette: 'Paleta', + themeSystem: 'Sistema', + themeLight: 'Claro', + themeDark: 'Oscuro', + paletteForest: 'Forest', + paletteOcean: 'Ocean', + paletteSunset: 'Sunset', + paletteMono: 'Mono', noPlants: 'Aún no hay plantas.', + nextStepsTitle: 'Tus próximos pasos', + stepScan: 'Escanear primera planta', + stepLexicon: 'Explorar enciclopedia', + stepTheme: 'Personalizar diseño', allGood: 'Todo bien', toWater: 'Regar', searchPlaceholder: 'Buscar plantas...', categories: 'Descubrir Categorías', resultsInPlants: 'Resultados en "Mis Plantas"', noResults: 'No se encontraron plantas.', + searchMyPlants: 'Mis Plantas', + searchLexicon: 'Enciclopedia', + searchAiSection: 'Busqueda profunda AI', + searchDeepAction: 'Busqueda profunda (AI)', + searchNoLocalResults: 'No hay coincidencias en tu coleccion.', + searchNoLexiconResults: 'No hay coincidencias en la enciclopedia.', + searchAiLoading: 'AI esta buscando en el catalogo...', + searchAiNoResults: 'AI no encontro plantas compatibles.', + searchAiUnavailable: 'La busqueda AI no esta disponible ahora.', + searchHistory: 'Busquedas recientes', + clearHistory: 'Borrar historial', catCareEasy: "Fácil Cuidado", catSucculents: "Suculentas", @@ -236,25 +445,61 @@ export const translations = { catPetFriendly: "Pet Friendly", catAirPurifier: "Purificador", catFlowering: "Con Flores", + catBrightLight: "Luz Brillante", + catSun: "Sol", + catHighHumidity: "Alta Humedad", + catHanging: "Colgante", + catPatterned: "Con Patrón", + catTree: "Árboles", + catLarge: "Grande", + catMedicinal: "Medicinal", lexiconTitle: "Enciclopedia", lexiconDesc: "Explora nuestra base de datos y encuentra la adición perfecta para tu hogar.", lexiconSearchPlaceholder: "Buscar en enciclopedia...", browseLexicon: "Explorar Enciclopedia", backToSearch: "Volver a Buscar", - - comingSoon: 'Próximamente', - gallery: 'Galería', - help: 'Ayuda', - scanner: 'Escáner', - analyzing: 'Analizando planta...', - localProcessing: "Procesamiento Local", +// Misc +comingSoon: 'Próximamente', +gallery: 'Galería', +help: 'Ayuda', +scanner: 'Escáner', +analyzing: 'Analizando planta...', +localProcessing: "Procesamiento Local", +registerToSave: "Regístrate para guardar", // Scan Stages scanStage1: "Verificando calidad de imagen...", scanStage2: "Analizando estructuras...", scanStage3: "Comparando con base de datos...", + // Dashboard + greetingMorning: 'Buenos dias,', + greetingAfternoon: 'Buenas tardes,', + greetingEvening: 'Buenas noches,', + creditsLabel: 'Creditos', + needsWaterToday: 'Necesitan agua hoy', + viewSchedule: 'Ver horario', + all: 'Todas', + today: 'Hoy', + week: 'Semana', + healthy: 'Saludables', + dormant: 'Dormantes', + thirsty: 'Sedienta', + healthyStatus: 'Saludable', + nextWaterLabel: 'Riego', + noneInFilter: 'No hay plantas en este filtro.', + reminderTitle: 'Recordatorios', + reminderNone: 'No hay plantas pendientes para hoy.', + reminderDue: '{0} plantas necesitan agua hoy.', + plantsThirsty: '¡{0} de tus plantas tienen sed hoy!', + collectionCount: '{0} plantas', + more: 'más', + collectionTitle: 'Coleccion', + emptyCollectionTitle: 'Tu coleccion esta vacia', + emptyCollectionHint: 'Escanea tu primera planta para empezar tu coleccion digital.', + scanFirstPlant: 'Escanear primera planta', + result: "Resultado", match: "Coincidencia", careCheck: "Chequeo de Cuidados", @@ -308,6 +553,37 @@ export const translations = { reminderOn: "Activado", reminderOff: "Desactivado", reminderPermissionNeeded: "Permiso de notificación requerido.", + + // Gallery + galleryTitle: "Galería", + addPhoto: "Añadir Foto", + noPhotos: "Sin fotos aún", + + // Tour + tourFabTitle: "📷 Escanear Planta", + tourFabDesc: "Toca aquí para fotografiar una planta — la IA la reconoce al instante.", + tourSearchTitle: "🔍 Enciclopedia", + tourSearchDesc: "Busca en miles de plantas o deja que la IA encuentre la perfecta.", + tourProfileTitle: "👤 Tu Perfil", + tourProfileDesc: "Personaliza diseño, idioma y notificaciones a tu gusto.", + + // Onboarding + onboardingTitle1: "Escáner de Plantas", + onboardingTitle2: "Cuidado de Plantas", + onboardingTitle3: "Tu Jardín", + onboardingDesc1: "Escanea cualquier planta e identifícala al instante con IA", + onboardingDesc2: "Obtén consejos de cuidado personalizados y recordatorios de riego", + onboardingDesc3: "Construye tu colección digital de plantas", + onboardingNext: "Siguiente", + onboardingStart: "Empezar", + onboardingTagline: "Tus plantas. Tu mundo.", + onboardingFeatureScan: "Escanea e identifica plantas", + onboardingFeatureReminder: "Recordatorios de riego y cuidado", + onboardingFeatureLexicon: "Enciclopedia digital de plantas", + onboardingScanBtn: "Escanear Planta", + onboardingRegister: "Registrarse", + onboardingLogin: "Iniciar sesión", + onboardingDisclaimer: "Tus datos permanecen privados y locales en tu dispositivo.", } }; diff --git a/vite.config.ts b/vite.config.ts deleted file mode 100644 index ee5fb8d..0000000 --- a/vite.config.ts +++ /dev/null @@ -1,23 +0,0 @@ -import path from 'path'; -import { defineConfig, loadEnv } from 'vite'; -import react from '@vitejs/plugin-react'; - -export default defineConfig(({ mode }) => { - const env = loadEnv(mode, '.', ''); - return { - server: { - port: 3000, - host: '0.0.0.0', - }, - plugins: [react()], - define: { - 'process.env.API_KEY': JSON.stringify(env.GEMINI_API_KEY), - 'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY) - }, - resolve: { - alias: { - '@': path.resolve(__dirname, '.'), - } - } - }; -});