Changelog CannaCal

0.55.7 — 27.09.2026

Zurueckgenommen: die Reiter-Daempfung

Drei Anlaeufe (0.55.4 bis 0.55.6) haben nicht gegriffen. Die Reiter sind <a>,

und eine Link-Farbregel gewinnt in beiden Modi gegen jede Regel, die hier an den

Reitern ansetzt. Die Regeln standen wirkungslos in der Datei und sind wieder

raus — wirkungslose CSS ist schlimmer als keine, sie verspricht etwas.

Gemessener Stand, der bleibt: aktiv 6,49:1 hell und 5,43:1 dunkel, inaktiv

13,55:1 und 6,43:1. Lesbar ist alles; unterschieden werden die Reiter ueber die

Flaeche, nicht ueber die Schriftfarbe. Der naechste Anlauf muss an die

Link-Regel selbst.

0.55.6 — 27.09.2026

Dritter Anlauf, und diesmal mit der richtigen Diagnose: die Reiter sind <a>,

und die Link-Farbregel schlug jede Reiter-Regel — in beiden Modi, nicht nur

im dunklen. Der inaktive Reiter war also nie gedaempft, auch hell nicht. Mit

Elternklasse und :not(.is-active) reicht die Spezifitaet.

0.55.5 — 27.09.2026

0.55.4 hat den inaktiven Reiter auf --we-d-muted gesetzt — und damit auf ein

dunkles Gruen: gemessen oklab(0.55 -0.106 0.066), 1,46:1 gegen die Leiste. Das

Token traegt auf dieser Seite offenbar eine andere Rolle als in navweed. Jetzt

ein gemessener Festwert.

0.55.4 — 27.09.2026

Inaktive Reiter sind im Dunkelmodus jetzt gedaempft statt gruen wie die aktive

Kachel; im Hellmodus war das laengst so. Die Dark-Regel fuer .is-active steht

weiter oben und traegt dieselbe Struktur plus Klasse, gewinnt also — genau die

Spezifitaetsfalle aus 0.47.0, diesmal von vornherein beachtet.

0.55.3 — 27.09.2026

Die neuen Menues standen im Dunkelmodus als weisse Flaeche da — live gemessen

rgb(255, 255, 255). CannaCals Dark-Regeln weisen die Tokens nicht global um,

sondern je Komponente; die Menues hatten noch keine. Nachgereicht, inklusive

Hover, Loesch-Eintrag und Menue-Knopf.

0.55.2 — 27.09.2026

Reiter-Polster von .6 auf .3 rem, Beschriftung bricht nicht mehr um: mit dem

dritten Reiter und der Eintragszahl stand „Einträge (75)" auf zwei Zeilen und

die Leiste war 53 px hoch. Jetzt 33 px, gemessen auf 390 px. Unter 360 px faellt

die Schrift auf .78 rem, statt ueberzulaufen.

0.55.1 — 27.09.2026

„Weitere anzeigen" trug cd_view nicht mit und landete damit in der

Schreib-Ansicht, in der es gar keine Liste gibt.

0.55.0 — 27.09.2026

Variante B: Schreiben und Nachlesen sind getrennte Wege

Gemessen lagen auf dem Handy 1.416 px zwischen Titel und erstem Eintrag, davon

624 px das immer offene Formular, das vor der Liste stand. Das Tagebuch hat

jetzt drei Ansichten statt zwei, und „Neu" ist der Standard: es oeffnet zum

Schreiben, Nachlesen ist ein eigener Weg.

Dirks Entscheidung dazu, woertlich: „selbst wenn ich im laufenden grow nochmal

nachlesen möchte, hab ich so eine trennung zwischen eingabe und nachlesen."

Deshalb haengt der Standard nicht am Zustand des Grows — beendet wie

laufend landen auf derselben Ansicht.

Kein neuer Mechanismus: cd_view routet die Fotos-Ansicht seit jeher, die

Einträge bekommen mit cd_view=entries ihren eigenen Wert. In der Schreib-

Ansicht steht statt der Liste ein Link „N Einträge ansehen".

Der Kopf traegt nur noch das Noetige

* Vier Dauerknoepfe (Bearbeiten, Kalender, Teilen, Beenden) wurden ein

⋯-Menue, dasselbe Muster wie an den Eintraegen seit 0.54.0. Die Ausloeser

tragen data-open statt popovertarget und das JS oeffnet das Ziel selbst:

liegt ein popovertarget IM Menue, gilt das Ziel als verschachteltes Popover

und der Vorfahr bleibt offen stehen — in navweed 0.82.1 live gemessen.

* Run, Setup, Sorte, Tag und Eintragszahl stehen hinter „Details zum Grow".

Die Statuszeile mit Fortschrittsbalken bleibt sichtbar, sie ist die Angabe,

wegen der man das Tagebuch aufmacht.

Desktop bekommt dieselben drei Ansichten. Zwei Spalten mit Formular links und

Liste rechts waeren die Trennung, die Dirk ausdruecklich wollte, wieder los.

0.54.3 — 27.09.2026

Und der eigentliche Grund: Astras Knopf-Polster

Anklickbare Tage sind <button>, leere Tage <span>. Astra gibt jedem Knopf

padding: .6em 1em .4em, gemessen 12 / 24 px — deshalb standen Tage mit

Eintrag auf 50 x 50 px und alle anderen auf 41 x 41 in derselben Spur. Dasselbe

Polster war auch die Mindestbreite, an der die Spuren vor 0.54.1 auf 50 px

sprangen. padding: 0 auf der Kachel raeumt beides ab.

0.54.2 — 27.09.2026

Kalender: Tage mit Foto waren groesser als die anderen

Nach dem Rasterfix fiel der zweite Grund auf, warum die Heatmap unruhig

aussah: der Foto-Punkt stand im Textfluss und addierte 9 px Mindesthoehe.

Kacheln mit Foto massen 50 x 50 px, alle anderen 41 x 41 — in derselben

41-px-Spur. Benachbarte gruene Tage wirkten dadurch verschmolzen, die Reihe

ausgefranst. Der Punkt haengt jetzt absolut in der Kachel.

0.54.1 — 27.09.2026

Der Kalender lief aus dem Raster

Die Heatmap unter den Tagebuechern stand auf sieben Spalten zu je 50 px statt

41,28 px: die Reihe wurde 374 px breit in einem 313 px breiten Container, lief

23 px aus der Karte und passte auch nicht mehr zur Wochentags-Kopfzeile, die

korrekt bei 41,28 px stand.

Ursache ist eine Feinheit von 1fr: es bedeutet minmax(auto, 1fr), und die

automatische Mindestgroesse der Kacheln setzte sich gegen den fairen Anteil

durch. Das min-width: 0 auf der Kachel half nicht — erlauben muss es die Spur

selbst. Jetzt repeat(7, minmax(0, 1fr)) in Gitter und Kopfzeile.

0.54.0 — 27.09.2026

Variante A: der Grow-Bereich wird ruhiger

Dirk: „das interface ist erschlagend, wenn man es zu beginn sieht." Gemessen

auf 390 px liegen zwischen Titel und erstem Eintrag rund 1.416 px. Dieses

Release raeumt die drei gemeldeten Fehler ab; der grosse Umbau (Kopf eindampfen,

Formular falten, Einträge und Fotos als eigene Ansichten) folgt als Variante B.

* Trocknungs-Check lief ueber, er brach nicht schlecht um. .we-radio-row

hatte kein flex-wrap: die erste Antwortreihe misst 442 px in 311 px

Innenbreite, 131 px ragten aus der Karte, die Layoutbreite wuchs auf 496 px

und das Telefon zoomte die ganze Seite heraus. Jetzt flex-wrap: wrap plus

flex: 1 1 auto und 44 px Mindesthoehe je Antwort.

* Drei Dauerknoepfe je Eintrag wurden ein Menue. Sie belegten 139 der

313 px Kartenbreite und drueckten die Textspalte auf 144 px, mit Foto auf

73 px. Jetzt ein ⋯-Knopf, Bearbeiten/Teilen/Loeschen im Popover. Bewusst

Popover und nicht <details>: ein <details> im Formular hat in navweed

0.74.2 siebzehn Felder aus dem Absenden geworfen.

* „Probleme?" ist ein Textlink. Der Kommentar im Code sagte seit jeher, der

Block duerfe den Eintrag nicht dominieren — als 113 × 44 px grosser Knopf in

12 von 15 Karten tat er genau das.

* Nebenbei: „Außen trocken, innen leicht elastisch" heisst jetzt „Außen

trocken, innen elastisch". Nur der Anzeigetext, der Schluessel crisp bleibt.

Mockup mit allen drei Varianten und den Messwerten:

cannacal/docs/mockups/CannaCal_Mockup_Grow_Entschlacken_2026-09-27.html

0.53.0 — 27.09.2026

Altbestand-Bilder bekommen WebP-Ableitungen nachgereicht

Seit 0.46.2 entstehen die abgeleiteten Groessen neuer Tagebuch-Uploads als WebP.

Die vorher hochgeladenen Bilder blieben PNG/JPEG — gemessen am 27.09.2026 ueber

die Mediathek: 135 JPEG, 25 PNG, genau 1 WebP. WebpBackfill holt das nach.

Bewusst in Haeppchen ueber WP-Cron (5 Anhaenge je Durchlauf, ein Durchlauf je

Minute) statt in einem Rutsch: Bildverarbeitung ueber 160 Anhaenge laeuft in

jedes PHP-Zeitlimit. Jeder erledigte Anhang traegt _cannacal_webp_done, der

Lauf ist damit wiederholbar und fasst keine Datei zweimal an. Der Fortschritt

steht in der Option cannacal_webp_backfill.

Zwei bewusste Entscheidungen:

* Das Original bleibt unangetastet. Neu entstehen nur die abgeleiteten

Groessen — dieselbe Regel wie beim Upload.

* Die alten Ableitungen werden nicht geloescht. Fest in Beitragsinhalte

geschriebene Bild-URLs zeigen weiter auf sie; ein Aufraeumen wuerde genau

diese Bilder ins Leere laufen lassen. Kostet Plattenplatz, spart einen Bug.

0.52.0 — 14.09.2026

Nachernte an der Pflanze statt am Kalendertag

Alles nach der Ernte hing bisher am Tageszaehler seit Saatstart: Erntetag fest

auf 78, Fermentierungsstart fest auf 85. Wer drei Tage spaeter erntet, glast zu

feuchtes Material ein. Jetzt gibt es zwei echte Anker.

Anker als Aktions-Chips. harvested und jarred stehen als normale Chips

neben Gegossen und Geduengt. Haken setzen schreibt cc_harvest_date bzw.

cc_jar_date auf das Datum des Eintrags (Diary::syncAnchorsFromActions()),

auch nachtraeglich beim Bearbeiten. Ein zweiter Eintrag mit demselben Haken

verschiebt den Anker nicht. Der Grow ist damit geerntet, das Tagebuch bleibt

offen — bewusst getrennt von end_grow.

Plan loest relativ auf. Die sieben Nachernte-Events tragen anchor und

offset, GrowSchedule::resolveEvents() rechnet sie aus. Ohne Anker aendert

sich nichts: gemessen ueber alle Events, identisch zum Festplan. Ein

jar-Termin ohne Einglastag schaetzt sich aus Ernte + 7 Tagen — dieselben sieben

Tage, die vorher fest zwischen Tag 78 und 85 lagen.

ICS bekommt SEQUENCE. Ohne das darf ein Client ein geaendertes Datum unter

derselben UID ignorieren. Der Sprung geht genau einmal von 0 auf 1, weil ein

Anker nur gesetzt wird, wenn keiner steht. Die Anker haengen zusaetzlich in der

Cache-Signatur des Feeds.

Trocknungs-Check. Vier Antippfragen (Auffaelligkeiten, Knacktest, Griff,

Geruch) plus optionale Messwerte. DryCheck::evaluate() ist rein und kennt kein

WordPress, tests/drycheck-logik.php deckt sie mit 38 Pruefungen ab. Schimmel

schlaegt alles: sichtbarer Belag oder Ammoniak geben keinen Glas-Knopf.

Gespeichert werden die Beobachtungen, nicht das Urteil — bewertet wird beim

Anzeigen neu, damit eine spaeter geschaerfte Regel alte Eintraege nicht

verfaelscht.

Fuenfte Badge-Stufe (Keimling · Veg · Bluete · Trocknung · Curing). Die

Stufe entscheidet sich an den Meilensteinen, nicht am Phasennamen: ernte

beginnt im Bestandsplan schon Tag 70 mit den Vorkontrollen, da haengt noch

nichts. Der geschaetzte Glastag schiebt die Anzeige nicht ins Curing, solange

nichts im Glas ist.

Zielwerte korrigiert (Tage 78 und 82). Vorher 15–20 °C bei 50–55 % rF.

Jetzt 15–18 °C mit Toleranz bis ~24 °C, rund 60 % rF, getrennte Dauer fuer ganze

aufgehaengte Pflanzen (10–14 Tage) und einzelne Blueten (7–10). Neu im Text:

Absaugen kommt nie unter die Feuchte des Raums, in dem das Zelt steht, und die

taegliche Schimmelkontrolle gehoert in die dichten Colas, nicht an die

Oberflaeche.

Performance

  • cannadaily_prime_photos() laedt Foto-Attachments in einem Rutsch statt je Bild einzeln — Eintragsliste, Galerie und Dashboard-Grid. Das Grid primed das rohe cc_cover-Meta, weil coverPhotoId() die Datei selbst prueft.
  • Diary::countEntries() zaehlt per COUNT(*), statt alle IDs zu laden. Trifft die oeffentliche Share-Seite.
  • Diary::latestDryCheck() primed den Meta-Cache vor der Schleife (fields => 'ids' ueberspringt das Priming von WP_Query).

0.51.1 — 08.09.2026

Zustandsregeln zurueckgeholt

Drei Dark-Regeln fuer Zustaende (.we-subtab.is-active, .we-cal-pop-link:hover,

.we-glossar-az a:hover) waren in 0.51.0 mitgeloescht worden, obwohl die

generische Dark-Regel derselben Familie stehenblieb — die hat hoehere

Spezifitaet und haette den Zustand ueberschrieben. Siehe navweed 0.74.1.

0.51.0 — 08.09.2026

Token-Set, Stufe 3 — Flip nutzen, Dark-Bloecke entfernen

53 Dark-Bloecke ersatzlos entfernt (diary.css 40, frontend.css 13) — alle

maschinell geprueft: nur was nach dem Flip denselben Wert liefert, faellt.

20 bzw. 8 bleiben stehen (Sonderfarben ausserhalb der Palette, bewusst

abweichende Faelle).

.we-cal-pop-grow, .we-lb-cap und .we-photo-x tragen jetzt

--we-on-fixed statt --we-on-accent: ihre Flaeche kippt nicht mit (feste

Grow-Farbe, halbtransparentes Overlay), die Schrift darf es deshalb auch nicht.

0.50.0 — 08.09.2026

Token-Set, Stufe 3 — Block 1: Basisregeln tokenisiert

259 Hex-Werte in Basisregeln (diary.css 166, frontend.css 93), die exakt

einem kanonischen Token entsprechen, laufen jetzt ueber var(--token, #hex).

Der Inline-Fallback traegt den Originalwert — optischer Nulleffekt per

Konstruktion. Vorarbeit fuer den Dark-Flip: erst wenn die Basisregel ein Token

benutzt, darf der zugehoerige Dark-Block entfallen.

Rollenbewusst: color: #fff wird --we-on-accent (Schrift auf Akzentflaeche),

nicht --we-surface.

0.49.0 — 08.09.2026

Token-Set, Stufe 1 (optischer Nulleffekt)

  • --we-ink-muted ist jetzt definiert. Es wurde in diary.css fuenfmal benutzt, stand aber in keiner Datei — nur der Inline-Fallback #5b6b5e hat es getragen. Definition liegt in we-core.css (Child-Theme), Wert unveraendert.
  • Der gedaempfte Punkt der PlantCheck-Liste lief auf --we-ink-muted, also auf einem Schriftfarb-Token hinter background. Neu --we-badge-muted-bg, Wert unveraendert #5b6b5e.
  • we-core wird bedingt mitgezogen. CannaCal rendert durchgaengig gegen --we-* und --we-d-*, registrierte seine Styles aber mit leerer Dependency-Liste. Bewusst keine harte Dependency: fehlt ein Dependency-Handle, druckt WordPress das Stylesheet gar nicht — CannaCal waere dann ohne jedes CSS statt nur ohne Tokens. Stattdessen wp_style_is()-Pruefung und mitziehen.
  • CI-Schritt Token-Rollen pruefen (tools/token-rollen.sh) setzt die Rollenregel bei jedem Deploy durch.

0.48.0 — Status statt Zahlenreihe: Phase, Fortschritt, Stille

  • Die Uebersichtskarten zeigten nur „Run #9 · Tag 70 · 14 Eintraege". Alle Karten hatten dasselbe Gewicht, egal ob der Grow lief, stockte oder laengst geerntet war. Neu auf jeder laufenden Karte: der Phasenname (Keimling / Veg / Bluete / Curing) plus derselbe Vier-Segment-Balken wie in der Detailansicht. Quelle ist unveraendert cannadaily_get_current_stage() → GrowSchedule, es wird nichts neu gerechnet.
  • „Letzter Eintrag vor N Tagen" erscheint ab drei Tagen Stille, ab vierzehn Tagen in Warnfarbe. Das ist die Information, wegen der man die App ueberhaupt oeffnet. Dafuer gibt es Diary::lastEntryDatesBulk() — eine Abfrage fuer die ganze Uebersicht statt eines N+1 ueber alle Tagebuecher.
  • Der Fortschrittsbalken der Detailansicht steht jetzt unter der Metazeile statt unter dem Speichern-Knopf. „Tag 83 · Curing" ist die wichtigste Statusangabe eines Tagebuchs und gehoert in den Kopf, nicht ans Formularende.
  • Beendete Tagebuecher behalten ihr „🏁 Beendet"-Badge und bekommen keinen Fortschritt — sie sind fertig, nicht bei 100 %.

0.47.0 — Dunkelmodus: vier Stellen waren nie dunkel gestylt

Mit navweed 0.63.0 folgt der Dunkelmodus jetzt der Systemeinstellung und

ueberlebt den Seitenwechsel. Damit wurde er zum ersten Mal wirklich benutzt —

und legte vier Kontrastfehler frei, die vorher niemand sehen konnte.

Gemessen auf der Tagebuchseite, WCAG AA verlangt 4,5:1:

  • .we-photo-title stand bei 1,00:1. Der Text „Foto aufnehmen" war buchstaeblich unsichtbar: var(--we-ink) (fast schwarz) auf dunkler Karte.
  • .we-subtab.is-active bei 1,87:1. Die Regel setzte background: var(--we-d-ink) — aber --we-d-ink ist die *helle Schriftfarbe* (#e8ece8), keine Flaeche. Der aktive Tab leuchtete deshalb weiss. Jetzt --we-d-green-soft.
  • .we-btn--secondary bei 2,06:1. Gar keine Dunkel-Regel vorhanden. Betraf „Galerie" und jeden einzelnen „Probleme?"-Knopf der Eintragsliste.
  • .we-entry-date bei 2,21:1. Dunkelgruen auf dunklem Panel.

0.46.2 — Groessere Trefferflaechen auf Touch-Geraeten

  • Gemessen mit aktivem pointer: coarse: die drei Aktions-Knoepfe pro Eintrag standen auf 32 px, die Subtabs („Eintraege" / „Fotos") auf 33 px, die Rueckmeldungs-Pillen der KI-Analyse auf 27 px. WCAG 2.5.8 verlangt 24 px, Apples HIG empfiehlt 44 px. Auf Touch-Geraeten jetzt: Aktions-Knoepfe 40 px (44 px sprengt die enge Eintragszeile aus Vorschaubild, Datum und drei Knoepfen auf 390 px), Subtabs, Pillen, Knoepfe und Eingabefelder 44 px. Mit Maus bleibt alles unveraendert.
  • Zur Klarstellung des Befunds vom 08.09.2026: die zunaechst gemeldeten „65 Icon-Knoepfe ohne Beschriftung" waren ein Messfehler. Die Zaehlung lief ohne Touch-Emulation und zaehlte <form>-Elemente mit; die Rueckmeldungs-Pillen galten als unbeschriftet, weil sie im zugeklappten Aufklapper stehen und innerText dort leer ist. Nachgemessen mit pointer: coarse: kein einziger Knopf ohne zugaengliche Beschriftung.

0.46.1 — Nachtrag: das "auto" vor sizes musste weg

  • WordPress stellt seit 6.7 jedem sizes-Wert eines lazy geladenen Bildes ein auto, voran und ueberlaesst dem Browser die Herleitung der Anzeigebreite. Beim 61 px breiten Vorschaubild lag der Browser damit um Groessenordnungen daneben und lud weiter die 1024er-Variante — 250 KB statt 12 KB pro Eintrag. Ein Filter auf wp_get_attachment_image_attributes (nur fuer .we-entry-thumb) setzt sizes jetzt hart auf (max-width: 600px) 61px, 92px. srcset bleibt, damit Retina-Displays die 300er-Variante bekommen.

0.46.0 — Tagebuch laedt 38 MB weniger, Eintraege kommen portionsweise

  • Ein Tagebuch mit 61 Eintraegen lud 38 MB Bilder. Gemessen am 08.09.2026 bei kaltem Cache, 390 px Viewport, DPR 2: 38.894 KB Transfer, DOMContentLoaded nach 6,6 s. Ursache war das Vorschaubild: es ist 61 px breit (Handy) bzw. 92 px (Desktop), ausgeliefert wurde es aber mit `sizes="auto, (max-width: 300px) 100vw, 300px". Das auto gilt nur fuer loading="lazy"`, und WordPress hatte dem ersten Bild loading="eager" samt fetchpriority="high" verpasst — also rechnete der Browser mit 300 px Anzeigebreite, verdoppelte fuer das Retina- Display und griff zur 1152-px-Variante mit 3,5 MB pro Eintrag. Jetzt wird die thumbnail-Groesse mit sizes="(max-width: 600px) 61px, 92px" ausgeliefert. Wirkt sofort auch fuer alle bestehenden Fotos, ohne Neu-Generierung.
  • Neue Fotos werden als WebP abgeleitet. Handyfotos kommen regelmaessig als PNG an; ein Foto in 1152 px Breite wiegt als PNG rund 3,5 MB, als WebP etwa ein Zehntel. Diary::handlePhotoUpload() setzt image_editor_output_format nur fuer den eigenen Upload — das Original bleibt unangetastet, die Mediathek insgesamt unveraendert. Bestehende Fotos werden nicht nachtraeglich konvertiert.
  • Die Eintragsliste kommt portionsweise. Bisher standen alle 61 Eintraege im DOM, die Seite war 10.587 px hoch. Sichtbar sind jetzt 15, der Rest kommt ueber einen normalen Link (?cd_show=) nach — kein JavaScript, cachebar, funktioniert ohne Skripte. Schrittweite ueber den Filter cannacal_entry_page_size.
  • Der Zurueck-Link stand doppelt. „← Alle Tagebuecher" erschien ein zweites Mal wenige Pixel unter dem gleichlautenden Link ueber der Kopfzeile.
  • Der Minify-Schritt laeuft jetzt in der GitHub-Action. Genau die Falle vom 07.09.2026, als diary.min.css zwoelf Tage aelter war als ihre Quelle und 29 Selektoren live fehlten. Geprueft: frische esbuild-Laeufe ueber alle fuenf Quelldateien sind byte-identisch mit den eingecheckten Builds.

0.45.0 — Kein Reinzoomen beim Tippen, Hinweis statt Querformat

  • iOS zoomte beim Antippen des Textfelds hinein. Safari auf dem iPhone vergroessert jedes Eingabefeld, dessen Schrift kleiner als 16 px ist, und laesst die Seite danach quer verschoben stehen. Das „Was faellt dir auf?"-Feld erbte font-size:.78rem von .we-share-pop .we-input, einer Regel fuer Link-Felder. Alle Felder im Tagebuch stehen jetzt auf 1rem, das Textfeld ausserdem wieder auf der normalen Schrift statt Monospace.
  • Querformat wird abgeblendet. Ein Website kann das Drehen nicht verbieten: screen.orientation.lock() hat auf iOS keine Wirkung, und die Manifest-Angabe orientation greift nur in installierten PWAs. Auf flachen Touch-Geraeten (quer, hoechstens 500 px hoch, grober Zeiger) wird das Tagebuch deshalb ausgeblendet und durch die Bitte ersetzt, zurueck ins Hochformat zu drehen. Tablets und Notebooks sind ausgenommen.

0.44.0 — KI-Analyse klappt zu, Rueckmeldung als Pillen

  • Bericht ist ein Aufklapper. Ausgeklappt nahm die Analyse den halben Eintrag ein. Zugeklappt steht jetzt eine Zeile da: „KI-Analyse" plus Ampel, also Unauffaellig / Beobachten / Handeln. Wer mehr will, tippt drauf. Ein gerade angeforderter Bericht (juenger als zwei Minuten) steht offen da — nach dem Absenden laedt die Seite neu, und dann will man das Ergebnis sehen.
  • „war zutreffend" / „lag daneben" sind Pillen mit Daumen-Icon. Vorher zwei breite Geisterknoepfe, die auf dem Handy uebereinander brachen. Die abgegebene Rueckmeldung erscheint danach als eingefaerbte Pille, gruen oder rot.

0.43.2 — Ausgelieferte CSS holt die letzten zwei Wochen nach

  • Der eigentliche Fehler: diary.min.css war vom 25.08., die Quelle vom 06.09. Ausgeliefert wird die minifizierte Datei. Alles, was seither dazukam, fehlte im Browser: die komplette PlantCheck-Oberflaeche (29 Selektoren, .we-pc-*) und der aufklappbare Setup-Kasten (.we-setup-*). Neu gebaut mit npx esbuild assets/css/diary.css --minify --outfile=assets/css/diary.min.css.
  • Berichtskarte lief seitlich aus dem Eintrag heraus. .we-pc-karte traegt zusaetzlich .we-info-card, und die steht in frontend.css auf display:flex; align-items:center — also eine Zeile. Ampel, Befundliste, Rueckmeldung und Fussnote standen damit nebeneinander statt untereinander und schoben die Seite quer. .we-pc-karte setzt jetzt display:block und overflow-wrap:anywhere.
  • Eingabefelder waren breiter als ihr Kasten. .we-input hatte width:100% ohne box-sizing:border-box; Innenabstand und Rahmen kamen oben drauf. Auf dem Handy ergab das einen waagerechten Scrollbalken. Ergaenzt um box-sizing:border-box und max-width:100%.
  • Bericht stand in einer 130-px-Spalte. Die Berichtskarte hing im Textblock des Eintrags, neben Vorschaubild und den drei Aktions-Knoepfen. Sie sitzt jetzt als eigener Block unter der Eintragszeile und nutzt die volle Breite.
  • Einsames „·" am Zeilenende. Die Meta-Zeile des Tagebuchs (Indoor · Sorte · Tag · Eintraege · Beendet) war ein Fliesstext mit Trennzeichen. Beim Umbruch blieb ein Trenner allein am Zeilenende stehen. Jedes Stueck ist jetzt ein eigenes .we-meta-item; der Trenner haengt per ::before am folgenden Stueck.

0.43.1 — Fotozahl pro Rueckblick ist einstellbar

  • Neuer Filter cannacal_video_max_photos (Vorgabewert 8, geklemmt auf 2 bis 20), bekommt die Grow-ID als zweites Argument. Jedes zusaetzliche Foto ist ein weiterer Kling-Clip: +5 Sekunden Laufzeit, +0,35 USD, groessere Datei (40 Sekunden waren rund 44 MB). Der Vorgabewert bleibt bei 8, damit nicht jeder Rueckblick teurer wird; fuer einen einzelnen Grow laesst er sich anheben:

add_filter('cannacal_video_max_photos', fn($max, $growId) => 12, 10, 2);

Die Obergrenze 20 verhindert, dass ein einzelnes Video das Monatsbudget von

50 USD sprengt.

0.43.0 — Ein gescheiterter Clip wirft nicht mehr den ganzen Rueckblick weg

  • Teilerfolg statt Totalausfall. Bisher galt ein Lauf als failed, sobald ein einziger Kling-Job scheiterte — beobachtet am 06.09.2026: sechs von sieben Clips fertig und bezahlt, das Video trotzdem nicht gebaut. Jetzt entsteht aus den vorhandenen Clips ein Film, und die Statusantwort nennt unter fehlende, wie viele Clips Kling nicht geliefert hat.
  • Nachschlag statt Neustart. Ein erneuter Start erzeugt nur die fehlenden Clips. Die bereits erzeugten werden ueber ihren Paar-Index wiederverwendet, abgesichert durch eine Signatur ueber die ausgewaehlten Fotos: aendert sich die Auswahl, wird sauber neu begonnen. Das Budget reserviert nur noch fuer die Clips, die tatsaechlich neu erzeugt werden.
  • Der 409-Riegel greift praeziser. Er blockiert nur noch, solange wirklich ein Job offen ist, statt nach jedem abgeschlossenen Lauf jeden weiteren Versuch abzuweisen.
  • Jobs werden jetzt unter ihrem Paar-Index gespeichert statt fortlaufend angehaengt. Uebersprang die Schleife ein Foto-Paar, verschob sich sonst die Zuordnung von Job zu Clip.

0.42.0 — Intro- und Outro-Karten sind zurueck, mit KI-Kennzeichnung

  • Der Karten-Blocker vom 03.09.2026 ist geloest. fal-Compose kann Standbilder und Clips weiterhin nicht in einer Timeline mischen — ein image-Track zaehlt intern als zweiter Video-Track und wird mit `Multiple video tracks are not supported abgelehnt. Auch ein gemischter Track mit frames/duration` half nicht: das Ergebnis hatte zwei Frames und eine Dauer von 1003 Sekunden. Der Weg, der funktioniert, laeuft ueber einen bisher ungenutzten Endpoint: ffmpeg-api/images-to-video macht aus jeder Karte ein eigenes kurzes MP4 (60 Frames bei 24 fps = 2,5 s), danach verkettet merge-videos Intro, Clips und Outro. Am 06.09.2026 gegen die echte API verifiziert.
  • Neue Stufe cardsStage() in der Zustandsmaschine, mit derselben 10-Minuten-Grenze wie die Compose-Stufe. Scheitert eine Karte, laeuft das Video ohne Karten weiter statt gar nicht.
  • KI-Kennzeichnung nach Art. 50 Abs. 4 KI-VO, Pflicht seit 02.08.2026: Der Hinweis „KI-generiert" steht unten rechts auf jedem Frame und jeder Karte, an der Stelle des frueheren Domain-Wasserzeichens. Feste Position, nicht ueberlagerbar, in jeder Darstellung sichtbar.
  • Branding aufgeraeumt. Die obere Leiste nennt nur noch WEEDERKENNEN.DE statt CANNACAL · WEEDERKENNEN.DE, die Outro-Karte nur noch weederkennen.de statt „Getrackt mit CannaCal auf weederkennen.de". Die Domain steht damit genau einmal im Bild.

0.41.0 — Kill-Switch offen: der KI-Pflanzenbericht ist freigegeben

  • CANNACAL_PLANTCHECK_ENABLED steht als Vorgabewert jetzt auf true. Damit sehen alle Premium-Mitglieder den Knopf „Probleme?", nicht mehr nur die Allowlist. Die drei Blocker davor sind abgearbeitet: AutoPots-Gegenprobe bestanden (Eintrag 99461 empfiehlt keine Giessmenge mehr, sondern Tankstand), Model Training im OpenRouter-Konto nachweislich aus, KI-Kennzeichnungspflicht gegen das eRecht24-Handout geprueft (Textberichte an den eigenen Nutzer sind nicht kennzeichnungspflichtig).
  • Das Feature bleibt doppelt gesichert. Ohne Premium und ohne Webhook plus Secret passiert weiterhin nichts. Zum Schliessen genuegt ein define('CANNACAL_PLANTCHECK_ENABLED', false); in wp-config.php; die Datei laedt vor den Plugins und gewinnt gegen den Vorgabewert.
  • Stand beim Oeffnen: zwei Nutzer tragen die Rolle „Weederkennen Mitglied", dieselben zwei, die schon auf der Allowlist standen. Der Schalter wirkt praktisch erst fuer die naechsten Mitglieder.

0.40.4 — Fix: Umlaute im Bericht waren zerstoert

  • Jeder erzeugte Pflanzenbericht zeigte Blu00e4tter statt Blätter. wp_json_encode() escapt Umlaute zu \u00e4, und update_post_meta() ruft intern wp_unslash() auf — der Backslash fiel weg, das u00e4 blieb als Klartext stehen. Betroffen war der gesamte Modelltext (Begruendung, Massnahme, Verlauf, naechstes Foto) in App und Mail; die von WordPress selbst gerenderten Teile wie der Schimmel-Satz waren sauber, was den Fehler lange verdeckt hat. Gefunden bei der AutoPots-Gegenprobe an Eintrag 99461. Neuer Helfer PlantCheck::metaJson() legt mit wp_slash() die Ebene vor, die die Meta-API wieder abzieht — das deckt neben \uXXXX auch \" und \\ ab, anders als JSON_UNESCAPED_UNICODE. Vier neue Tests (jetzt 57).
  • Bereits gespeicherte Berichte bleiben kaputt. Der Schaden steckt im gespeicherten Text; nur ein neu erzeugter Bericht ist wieder lesbar.

0.40.3 — Duengerfeld fragt nach der Linie, nicht nach der Gabe

  • Feldbezeichnung von „Duenger" auf „Duengerlinie" geaendert, Platzhalter und Hinweis angepasst: gefragt ist die ueber den Grow genutzte Linie, der Zeitpunkt kommt weiter aus der Eintragsaktion „Geduengt". Grundlage war die Messung an 10 Verlaufseintraegen mit 0 gesetzten Aktionen (Spec Abschnitt 15).

0.40.2 — Fix: Grows aelter als 30 Tage waren nicht mehr speicherbar

  • Echter Bug, unabhaengig vom Pflanzenbericht. Das Startdatum-Feld im Grow-Formular trug min="heute minus 30 Tage". Beim Bearbeiten eines aelteren Grows blockte der Browser das Formular deshalb mit „Wert muss groesser oder gleich … sein" — ein im Juni gestarteter Grow liess sich im September nicht mehr speichern. Betroffen war jede Aenderung an einem Grow, der aelter als einen Monat ist, nicht nur die neuen Setup-Felder. Die Grenze gilt jetzt nur noch beim Anlegen; im Bearbeiten-Modus wird sie auf den vorhandenen Startwert aufgeweicht.
  • Die Setup-Angaben sehen jetzt nach einem Aufklapper aus. Ein nacktes <details> war auf dem Handy nicht als solches erkennbar: eigener Rahmen, sichtbares Dreieck, 44 px Touch-Ziel, Fokus-Ring.

0.40.1 — Der Webhook antwortet sofort

  • Konstruktionsfehler behoben. Der n8n-Webhook antwortete bisher erst, wenn der komplette Lauf durch war. Ein Aufruf am 06.09. brauchte 17,1 Sekunden; nginx warf beim Rauchtest einen 504, und bei ueber 20 Sekunden haette WordPress den Job faelschlich als gescheitert markiert, obwohl er noch lief — der Bericht waere dann im Callback auf einen Job getroffen, den WordPress schon abgeschrieben hat.
  • Der Webhook laeuft jetzt auf responseMode: onReceived und antwortet sofort mit HTTP 202. Der Modellaufruf passiert danach. Der respondToWebhook- Knoten entfaellt, die Kette endet beim Callback an WordPress.
  • WordPress' wp_remote_post-Timeout sinkt von 20 auf 8 Sekunden: Es wartet nur noch auf die Annahme, nicht mehr auf das Modell. Damit ist die Wartezeit von der Modelllaufzeit entkoppelt, so wie es im Konzept immer gemeint war.

0.40.0 — Setup-Daten des Grows (Stufe 6)

Anlass, gemessen an sechs echten Berichten: Substrat wurde in 6 von 6 erwaehnt,

Licht in 3, Bewaesserung, Duenger und pH in je 2 — alles Daten, die das Modell

nicht hatte. Bei einem AutoPots-Grow wurde daraus falscher Rat: Zwei Berichte

empfahlen „weniger giessen", obwohl die Anlage die Wassermenge selbst reguliert.

  • Fuenf neue Felder am cc_grow, einmal beim Anlegen ausgefuellt und in jedem spaeteren Bericht dieses Grows wirksam: cc_bewaesserung (Auswahl aus Diary::BEWAESSERUNG), cc_substrat, cc_topfvolumen, cc_licht, cc_duenger. Alle optional; ein leeres Feld wird geloescht statt als Leerstring gespeichert, damit „nicht angegeben" im Kontext eindeutig bleibt.
  • Am cc_entry bewusst keine neuen Felder. Ueber 98 Eintraege werden nicht einmal die vier vorhandenen Aktionen zuverlaessig gepflegt. Zehn neue Tagesfelder waeren zehn leere Felder.
  • Eine Ausnahme: neue Eintragsaktion substrat_gewechselt. Einmal pro Grow geklickt, liefert sie den genauen Zeitpunkt des Wechsels; das Freitextfeld am Grow nennt nur die Namen.
  • Der Systemprompt (Testharness) richtet Massnahmen jetzt nach der Bewaesserungsart: Bei AutoPots, Blumat, Troepfchen oder Hydro sind Tankstand, Schwimmerventil, Tropfer und Naehrloesung die pruefbaren Punkte, nicht die Giessmenge. Fehlt die Angabe, darf keine Annahme getroffen werden.

0.39.5 — Einwilligung wird protokolliert

  • Beim ersten Absenden im „Probleme?"-Panel werden **Zeitpunkt und Fassung des Hinweistextes** als cc_plantcheck_consent festgehalten. Die Fassung steckt in PlantCheck::EINWILLIGUNG_FASSUNG und wird erhoeht, sobald sich der Text inhaltlich aendert — sonst waere im Nachhinein nicht erkennbar, wem was vorgelegen hat. Bewusst keine IP-Adresse: zusaetzliche Datensammlung ohne Nutzen fuer den Nachweis.
  • Der Nachweis geht in den DSGVO-Datenexport und wird beim Loeschen mit entfernt, ebenso cc_premium und das Monatskontingent.

0.39.4 — Bericht als HTML-Mail, lesbare Befundnamen

  • HTML-Mail statt reinem Text. Tabellenlayout mit Inline-Styles, weil Mailclients weder Flexbox noch <style>-Bloecke zuverlaessig unterstuetzen. Keine externen Bilder und keine Webfonts — beides wird oft blockiert und macht die Mail zum Tracking-Verdachtsfall. Die Textfassung bleibt als AltBody erhalten, nicht als Ersatz: Textclients und Screenreader bekommen sie.
  • Fix: der rohe Enum-Wert landete beim Nutzer. Das Modell legte im ersten echten Bericht naehrstoff ins Feld bezeichnung, die Mail zeigte genau das. Neu sind klasseText() und befundName(): Ist die Bezeichnung leer oder nur die Klasse wiederholt, greift der lesbare deutsche Name. Gilt fuer Mail und UI.
  • Zusaetzlich im Systemprompt (Testharness, eigenes Repo): bezeichnung muss ein Name in normalem Deutsch sein, und ab Tag 60 sowie in Ernte/Curing sind Duengeempfehlungen untersagt — der erste Bericht empfahl an Tag 74 eine „milde Duengergabe", was so kurz vor der Ernte mehr schadet als nutzt.
  • 53 Logiktests (vorher 39), darunter: kein Enum-Wert in der Ausgabe, HTML ist escaped, keine externen Ressourcen in der Mail.

0.39.3 — Kein Mailversprechen ohne Mailversand

  • Gemessen am 2026-09-05: wp_mail() scheitert auf weederkennen.de mit „Die E-Mail-Funktion konnte nicht instanziiert werden". Im Container gibt es kein PHP mail(), und es ist kein SMTP-Plugin installiert. Betroffen ist damit die gesamte WordPress-Mail der Seite (auch Passwort-Reset und Registrierung), nicht nur dieses Feature.
  • Neue Probe im Admin-Endpunkt (POST /plantcheck/config mit mailtest), die wp_mail() ruft und zusaetzlich wp_mail_failed abfaengt. Ihr Ergebnis landet in der Option cannacal_mail_moeglich.
  • Der Einwilligungstext verspricht keine Mail mehr, solange die Probe negativ ist. Ein Versprechen, das nicht eingeloest wird, ist schlimmer als eine fehlende Funktion. Der Bericht erscheint am Eintrag; sobald ein Versandweg steht, ergaenzt sich der Satz von selbst.
  • mailSenden() versucht es erst gar nicht, wenn kein Versandweg bekannt ist.

0.39.2 — Mailversand-Probe im Admin-Endpunkt

  • Siehe 0.39.3, dort ist der Befund dokumentiert.

0.39.1 — Fix: wp_tempnam() im REST-Kontext

  • PlantCheck::bildAlsDataUrl() nutzte wp_tempnam(). Die Funktion lebt in wp-admin/includes/file.php und ist bei einem REST-Aufruf nicht geladen — der erste echte Start endete mit HTTP 500 (Call to undefined function). Ersetzt durch get_temp_dir() plus wp_generate_uuid4(), beides aus wp-includes. Derselbe Stolperstein wie 0.38.4 bei wp_read_video_metadata().

0.39.0 — KI-Pflanzenbericht „Probleme?" (Stufe 2 + 3, noch abgeklemmt)

  • Neue Klasse Premium: Zugang zu kostenpflichtigen Features haengt jetzt an der Capability cannacal_premium, nicht mehr an einem User-Meta. Dazu die additive Rolle weederkennen_member, die bei der Aktivierung angelegt wird, und der Filter cannacal_ist_premium als Andockpunkt fuer ein spaeteres Abrechnungssystem (WooCommerce Memberships oder ein eigenes Entitlement). Premium::grant() / revoke() machen einen Bestell-Hook zur Einzeiler-Sache. VideoGen delegiert dorthin, Signaturen unveraendert.
  • Neue Klasse PlantCheck: Nutzer klickt am Tagebucheintrag auf „Probleme?", schreibt optional dazu, was ihm auffaellt, und bekommt einen strukturierten Bericht zu Naehrstoffmangel, Schaedlingen, Schimmel und Umweltstress — in der App und per E-Mail. Ablauf asynchron ueber n8n; REST-Routen /plantcheck/<id>, /status, /feedback und /callback. Kontingent 20 Berichte je Kalendermonat, fehlgeschlagene Laeufe kosten nichts. Haengende Jobs laufen nach 15 Minuten in einen Timeout, statt den Eintrag dauerhaft zu blockieren.
  • Der Schimmel-Hinweis kommt aus dem Pflichtfeld, nie aus dem Prosatext. Im Modellvergleich vom 2026-09-05 schrieb das gewaehlte Modell in 10 von 20 Berichten Entwarnungen in den Fliesstext, obwohl das strukturierte Feld korrekt gesetzt war. Ueber das Feld ist die Sicherheitsaussage von der Formulierungsqualitaet des Modells entkoppelt.
  • Callback-Absicherung ohne HMAC: n8n laeuft als Community Edition, eine Signatur haette crypto und damit eine Container-Variable gebraucht. Der Endpunkt prueft stattdessen das Shared Secret UND dass die job_id zu einem eigenen, noch offenen Job gehoert. Erst beides zusammen.
  • DSGVO: Der Bericht samt Modell, Rueckmeldung und Nachtrag geht in den Datenexport. Beim Loeschen verschwindet das Monatskontingent aus der usermeta mit — die uebrigen Meta haengen am cc_entry und gehen ohnehin mit.
  • Standardmaessig aus. CANNACAL_PLANTCHECK_ENABLED ist false; ohne CANNACAL_PLANTCHECK_WEBHOOK und _SECRET in der wp-config.php antwortet der Start-Endpunkt mit 503. Freischaltung im Testbetrieb ueber CANNACAL_PLANTCHECK_ALLOWED_USERS.

0.38.0 — Rückblick-Video 2.0: 9:16-Morph-Film mit eingebrannten Stats

  • Neues Videoformat: Hochformat 9:16 (1080×1920). Neue Klasse VideoFrames (GD) rendert pro Clip Start-/Endframe: Tagebuchfoto quadratisch mittig, unscharfer Foto-Hintergrund, Stats-Leisten eingebrannt (Sorte, „Tag X → Y", Phase, Datum, Fortschrittsbalken, Ernte-Countdown). Fonts: DejaVu Sans (gebündelt unter assets/fonts/, freie Lizenz).
  • Morph-Übergänge: Kling 2.6 bekommt start_image_url + end_image_url (Foto N → Foto N+1) — die Pflanze wächst sichtbar von Bild zu Bild. Schema-Update: duration '5' (3 war nie gültig), generate_audio false, negative_prompt gegen Text-Artefakte; Prompt phasenabhängig (Keimling/Wachstum/Blüte). count-1 Clips statt count.
  • Compose-Stufe: Nach den Clips fügt fal-ai/ffmpeg-api/compose Intro-Karte + Clips + Outro-Karte zu EINEM MP4 zusammen (cc_video_final). Fallback-Kette: ohne Karten → aufgeben (Clips bleiben als ZIP). Frontend zeigt MP4-Download primär, ZIP sekundär.
  • Admin-Test-Endpoint: POST/GET cannacal/v1/rueckblick/test (manage_options) erzeugt einen einzelnen Testclip aus zwei Attachment-IDs (~$0,35) zur Verifikation von Schema und Textstabilität.

0.37.0 — Rückblick-Video: Per-User-Allowlist

  • Neue Konstante CANNACAL_VIDEO_ALLOWED_USERS (Komma-separierte User-IDs, Default 1,2, via wp-config.php überschreibbar): freigeschaltete User sehen den Video-CTA und dürfen Videos erzeugen, obwohl der globale Kill-Switch CANNACAL_VIDEO_FEATURE_ENABLED aus bleibt. Allowlist-User werden fürs Video-Feature wie Premium behandelt (isPremium). Gates in diary.php und VideoGen::restSubmit() prüfen jetzt VideoGen::isVideoEnabledFor($userId).

0.36.2 — Fix: Pinch-Zoom in der Lightbox

  • Lightbox-Overlay und Bild auf touch-action: none; zusätzlich werden Multi-Touch-Moves und iOS-Gesture-Events im Overlay abgefangen — kein Pinch-Zoom mehr in der Lightbox, Swipe-Blättern bleibt.

0.36.1 — Fix: Doppeltipp-Zoom in der Lightbox

  • touch-action: manipulation auf Lightbox, Bild, Buttons und Thumbnails — Doppeltipp löst auf iOS keinen Browser-Zoom mehr aus; Swipe-Blättern bleibt.

0.36.0 — Fotos-Reiter: flache Galerie statt KW-Timeline

  • Fotos-Reiter zeigt jetzt die flache Foto-Galerie (alt → jung, Datum als Caption, Lightbox) — derselbe Baustein wie auf der geteilten Grow-Seite.
  • Die nach ISO-Woche gruppierte Timeline (cannadaily_gallery_html_grouped()) ist entfernt, inkl. zugehöriger .we-timeline-*-CSS-Regeln.
  • Die Fotostrecke über der Einträge-Liste entfällt — Fotos leben nur noch im Fotos-Reiter.

0.35.0 — Grow beenden, Export & KI-Rückblick-Video

  • Grow beenden: neuer Status cc_status (aktiv/beendet) mit optionalen Ernte-Daten (Ertrag in g, Abschlussnotiz) und erneuter Katalog-Opt-in-Abfrage beim Beenden.
  • Export: beendete Tagebücher lassen sich als HTML+ZIP (Timeline + alle Fotos) herunterladen.
  • KI-Rückblick-Video (Premium, cc_premium-Flag): bis zu 8 Tagebuchfotos werden per fal.ai/Kling animiert und als ZIP mit einzelnen Clips ausgeliefert. Harter Monats-Budget-Deckel (Default 50 USD, Filter cannacal_video_monthly_cap_cents).

0.34.3 — Performance: Kalender-Monatsansicht, Dashboard-Grid, Seiten-Erkennung

Aus dem Performance-Review vom 13.08.2026:

  • Kalender-Heatmap ([canna_daily_calendar]): lud bisher pro Monatswechsel die komplette Tagebuch-Historie aller Grows und filterte den angezeigten Monat erst in PHP heraus. Je länger ein Nutzer sein Tagebuch führt, desto teurer wurde jeder Kalenderaufruf. Neue Methode Diary::getEntriesInMonth() grenzt die Query direkt per meta_query auf den angezeigten Monat ein.
  • Tagebuch-Dashboard: zählte die Einträge jeder Grow-Karte einzeln (countEntries() pro Karte → eine Query pro Tagebuch, N+1 bei N Tagebüchern). Neue Methode Diary::countEntriesBulk() holt alle Zählungen in einer gruppierten Query.
  • Seiten-Erkennung (cannacal_calendar_page_url(), cannadaily_page_url_by_shortcode()): scannte bei kaltem Options-Cache potenziell alle veröffentlichten Seiten der Website. Jetzt auf 500 Seiten begrenzt statt unbegrenzt.

0.34.2 — Fix: Toter Klick auf „Heute" im Grow-Kalender

Live gemeldet: Tippen auf den heutigen Tag im Monats-Heatmap-Kalender

([canna_daily_calendar]) tat nichts, wenn heute noch kein Eintrag geloggt

war. Root Cause: cannadaily_render_calendar_shortcode() rendert Tageszellen

nur dann als <button> mit Popover, wenn $level > 0 (also Log-Aktivität an

dem Tag existiert) — bei 0 Einträgen (der Normalfall für „heute", solange man

noch nichts eingetragen hat) blieb die Zelle eine reine, nicht interaktive

<span>. Fix: die is-today-Zelle ist jetzt immer ein Button; bei 0 Einträgen

öffnet sie ein Popover mit „Heute noch keine Einträge." + einem

„Eintrag hinzufügen →"-Link zum passenden Tagebuch (direkt zum einzigen Grow,

falls nur einer existiert, sonst zur Grow-Übersicht) — die Formular-Seite

befüllt das Datumsfeld dort ohnehin bereits automatisch mit heute.

0.34.1 — Polish-Pass: Tagebuch/Grow-Kalender

Gegen das neu erstellte DESIGN.md geprüft (Projekt-Root, gemeinsames System mit

NavWeed). Kein Feature-/Funktionsumfang geändert.

  • Aktions-Tags am Eintrag repariert: wurden mit der falschen CSS-Klasse (.we-tag/.we-tag-row, nie definiert) gerendert statt der bereits vorhandenen, vollständig gestylten .we-chip/.we-chip-row-Pillen — zeigten bislang unformatierten Rohtext statt Chips.
  • Schwebende Overlays vereinheitlicht: Kalender-Popover, Foto-Lightbox-Popover, Teilen-Popover, Speichern-Toast und Kamera-Dialog hatten fünf verschiedene Ad-hoc-Schattenwerte (eine davon: gar keinen) — jetzt durchgängig 0 20px 60px rgba(0,0,0,.3), wie im übrigen System für Modals/Popovers.
  • Danger-Rot vereinheitlicht + Dark-Mode ergänzt: Foto-Warnung und „Tagebuch löschen"-Link nutzten ein anderes Rot als der Rest des Systems und hatten keine Dark-Mode-Variante.
  • Fokus-Ringe ergänzt für Icon-Buttons (.we-act), Buttons, Sub-Tabs und Chips — bislang nur auf Texteingaben vorhanden.
  • Desktop-Breakpoint auf 782px vereinheitlicht (vorher 900px, s. 0.34.0): deckt sich jetzt mit --we-bp-lg, dem kanonischen Desktop-Breakpoint des restlichen App-Shells (Bottom-Nav→Rail wechselt ebenfalls bei 782px) — vorher blieb das Tagebuch zwischen 782–900px einspaltig, obwohl die Nav schon auf Desktop-Layout umgeschaltet hatte. Sidebar-Spalte dafür von 360px auf 320px verschmälert.
  • Stage-Bar barrierefrei: aktives Segment trägt jetzt aria-current="step", die Gruppe einen Tag/Phase-tragenden aria-label statt nur des benachbarten Texts.

0.34.0 — Grow-Tagebuch: 2-Spalten-Desktop-Layout, Katalog-Foto-Opt-in

  • Desktop-Layout: Ab 900px Breite steht das "Neuer Eintrag"-Formular jetzt sticky neben dem Grow-Log statt darüber/darunter — kein Hin-und-Herscrollen mehr beim Nacheintragen mehrerer Tage. Mobile (<900px) bleibt unverändert einspaltig. Siehe .we-diary-layout in assets/css/diary.css.
  • Katalog-Foto-Opt-in: neue Checkbox im Eintragsformular — Grower können ihr Titelbild für den NavWeed-Sorten-Katalog freigeben (cc_catalog_optin Meta, Diary::catalogOptIn()/setCatalogOptIn()). Getrennt vom bestehenden Share-Token-Mechanismus, da öffentlicher Katalog ein anderer Sichtbarkeits-Kontext ist als ein privater Share-Link.

0.33.1 — Tagebuch-Formular: kein Pflicht-Scroll mehr, Hinweistext, Sorten-Link

  • "Neuer Eintrag"-Formular (Foto-first Capture) erscheint jetzt direkt nach Titel/Tab-Umschalter statt erst nach dem Fortschrittsbalken — auf Mobile war bislang ein Scroll nötig, bevor Kamera/ Notizfeld sichtbar wurden. Fortschrittsbalken rückt dafür hinter das Formular.
  • Neuer Hinweistext im Formular: "Foto oder Notiz reicht — beides ist nicht Pflicht." (macht die bereits bestehende Server-Validierung sichtbar, Diary::addEntry() unverändert).
  • Sortenname im Tagebuch (Übersichtskarten + Grow-Detailseite) ist jetzt anklickbar und führt zur NavWeed-Sortenseite (Specs + dortiger HOS-Shop-Link).

0.33.0 — Dashboard-Redesign: Stat-Karten unter der Kalender-Heatmap (MacroFactor-Pattern)

Der Grow-Kalender ([canna_daily_calendar]) endete bisher direkt nach der Heatmap-Legende.

Ergänzt um eine Stat-Karten-Reihe (.we-result-info mit drei .we-info-cards: Log-Einträge,

Aktive Tage, Fotos — alle aus den ohnehin berechneten $activity-Daten des angezeigten

Monats, keine zusätzliche Query) nach dem Vorbild von MacroFactors Dashboard (Referenz-Recherche

via Mobbin, siehe Projekt-Memory). Dieselben Klassen kommen jetzt auch im NavWeed-Monats-Digest

zum Einsatz — geteiltes Stat-Karten-Pattern über beide Plugins hinweg.

0.32.2 — Fix: Kalender-Kacheln zu groß, Spalten nicht mehr unter Wochentagen

Live entdeckt: Grid-Items haben implizit min-width: auto (= Content-Mindestgröße), das

zwang die 1fr-Spalten in .we-heat-grid in Kombination mit aspect-ratio: 1 auf

.we-heat-cell über ihren fairen Anteil hinaus (65.5px statt 54px pro Spalte) — die

Kalender-Kacheln liefen aus dem Container und die Tages-Spalten passten nicht mehr zur

Wochentags-Kopfzeile (Mo/Di/Mi/…) darüber. Fix: min-width: 0; min-height: 0; auf

.we-heat-cell.

0.32.1 — Fix: ungewollte Abstände unter Untertiteln/Legende/Stage-Label

Live auf weederkennen.de entdeckt (Live-Inspektion via Browser-DevTools): dieselbe

Ursache wie im NavWeed-Fix 0.53.1 — Astras .entry-content p { margin-bottom: 1.6em }

gewann gegen .we-subtitle, .we-subtitle--detail, .we-stage-label und

.we-heat-legend/.we-cal-daypop-date (einzelne Klasse schlägt gegen

Klasse+Element-Selektor). Fix: jeweils Ancestor-Klasse (.we-widget, .we-stage,

.we-cal-daypop) vorangestellt, kein !important nötig.

0.32.0 — UI-Redesign: echter Grow-Kalender statt Konsum-Tagebuch-Optik

Erste Umsetzungsrunde des App-Redesigns (Referenz: Planta/GrowBuddy-Muster). CannaCal

bekommt sein eigenes, domänengerechtes Framing statt generischer Journal-App-Optik.

  • Stage-Fortschritt: neue cannadaily_get_current_stage()-Hilfsfunktion leitet aus cc_start + dem bestehenden GrowSchedule-Zeitplan die aktuelle Phase (Keimling/Veg/Blüte/Curing) ab; als 4-Segment-Fortschrittsbalken + "Tag N"-Anzeige oben im Tagebuch sichtbar. Bekannte Grenze: GrowSchedule bildet weiterhin nur eine feste Autoflower-Zeitlinie ab, keine Photoperiod-Sorten.
  • Aktions-Tags pro Eintrag: neues cc_actions-Meta-Feld (Gegossen/Gedüngt/ Getrimmt/Umgetopft) als Chip-Auswahl im Eintragsformular, sichtbar als Mini-Tags in der Liste.
  • Foto-first Erfassung + Wochen-Timeline: die Foto-/Kamera-Aufnahme (Funktion war bereits vorhanden) steht jetzt als erstes, großes Element im Formular statt als Neben-Icon. Neue cannadaily_gallery_html_grouped() gruppiert die Grow-Fotos nach ISO-Woche (neueste zuerst) als eigene "Fotos"-Ansicht neben den Einträgen.
  • Kalender als Monats-Heatmap: [canna_daily_calendar] zeigt jetzt ein 7-Spalten-Raster mit Einfärbung nach Log-Aktivität des Tages (0/1/2+ Einträge, Foto vorhanden) statt der vorherigen Agenda-/FullCalendar-Ansicht; aktive Tage öffnen ein natives Popover mit den Einträgen des Tages.

0.31.0 — Security- & Performance-Audit: Sharepic-Härtung, Feed-Caching, Conditional Assets

Ergebnis eines vollständigen Audits (Security + Performance) beider Plugins.

Security

  • Sharepics gehärtet: Dateinamen enthalten jetzt ein nicht erratbares, vom Share-Token abgeleitetes Segment (share-{typ}-{id}-{hash}.png) — vorher waren die PNGs (Foto + Notiz-Auszug) allein über die enumerierbare Post-ID abrufbar. Beim **Zurückziehen des Teilens, Bearbeiten/Löschen von Einträgen, Cover-Wechsel und Grow-Löschung** werden die Dateien jetzt gelöscht (Share::deleteSharepics(), inkl. Alt-Dateien ohne Hash).
  • Rate-Limiting auf den öffentlichen Token-Routen (/grow-kalender/…, /geteilt/…): max. 20 ungültige Tokens pro IP in 10 min, danach 429.
  • Foto-Upload: Datei-Inhalt wird per wp_getimagesize als echtes Bild verifiziert (vorher nur Endungs-Check via wp_check_filetype).
  • Mastodon-Token verschlüsselt in User-Meta (AES-256-GCM, Schlüssel aus wp_salt); Legacy-Klartext wird beim nächsten Speichern migriert.
  • SSRF-Härtung Mastodon: Instanz-Angabe muss ein plain Hostname sein und darf nicht auf private/link-local IPs auflösen.
  • Privacy-Hinweis präzisiert: Tagebuch-Formular verspricht nicht mehr absolute Privatheit (Fotos sind als Uploads über ihren direkten Datei-Link erreichbar).

Performance

  • Assets nur noch auf Plugin-Seiten (Shortcodes/Blöcke/Share-Seiten) statt global auf jeder Seite; CSS/JS minifiziert (*.min.*, ~71 KB → ~48 KB). Gast-Nonces entfernt (Full-Page-Caching möglich); CannaDaily-REST-Nonce nur noch für eingeloggte Nutzer.
  • Sharepics werden nicht mehr bei jedem Seitenaufruf neu gerendert (file_exists-Guard; vorher 2 GD-Renderings pro View inkl. OG-Crawler).
  • Grow-Feed: Token→ID- und ICS-Ergebnis-Caching (Transients, Invalidierung bei Eintrags-Änderungen), ETag/304 + Cache-Control: private statt no-store.
  • Öffentlicher Kalender (/kalender/…): ICS-Transient + `Cache-Control: public, max-age=3600 + ETag`/304 (Inhalt ist generisch, voll cachebar).
  • Mastodon-Post entkoppelt (Single-Event via WP-Cron) — blockierte vorher das Eintrag-Speichern mit bis zu 40 s externen Requests; Wetter-Timeout 8 s → 4 s.
  • DB: Diary::getEntries() mit Per-Request-Memoization; coverPhotoId() lädt nur noch den neuesten Eintrag mit Foto statt aller Einträge; GrowSchedule::getEvents() (30-KB-Literal) einmal pro Request; cannacal_user_strain_photo() memoized; neuer Helper cannadaily_next_planned_event() für das NavWeed-Dashboard (kein Einträge-Volllast).
  • Autoload-Flags korrigiert (einmalige Migration beim Update): kleine Per-Request- Optionen (Seiten-IDs, Rewrite-Marker) → autoload, große Admin-Inhalte (Infotainment/Werbepartner-JSON) → kein autoload.

0.30.0 — Foto-Galerie: Wischen in der Lightbox (Mobil)

Die Vollbild-Lightbox der Grow-Foto-Galerie (Detail- und geteilte Seite) reagiert jetzt auf

Touch-Wischgesten: horizontal wischen blättert zum vorigen/nächsten Foto. Schwelle 40px,

horizontale Bewegung muss die vertikale übersteigen — so bleibt vertikales Scrollen/Schließen

unberührt. Rein additiv zu den bestehenden ‹ ›-Buttons, Pfeiltasten und dem Zähler; kein CSS,

kein neues Markup.

0.29.0 — Foto-Upload: Live-Kamera im Eintragsformular (In-Page-Sucher)

Instagram-artiger Aufnahme-Flow, im Rahmen dessen, was das Web hergibt: das Mediathek-Grid

liefert der native Foto-Picker (Galerie-Button, unverändert), neu ist der Live-Sucher in der Seite.

  • Live-Kamera als natives <dialog> (#cd-camera): getUserMedia-Viewfinder mit großem Auslöser (Kamera-App-Optik, dunkles Umfeld), Kamera-Wechsel vorn/hinten (Frontkamera in der Vorschau gespiegelt, Aufnahme ungespiegelt), Schließen/Esc stoppt den Stream sauber (Track-Cleanup).
  • Aufnahme → bestehende Pipeline: der Auslöser zeichnet den Video-Frame auf ein Canvas (JPEG 0.92 — toBlob-WebP kann Safari nicht überall), legt die Datei per DataTransfer ins bestehende cd_photo-Input und feuert change — **Optimierung (1600px/WebP/EXIF-Strip) und Sofort-Vorschau laufen unverändert mit** (ein Codepfad für Kamera + Galerie).
  • Robuster Fallback: ohne getUserMedia/<dialog>/Secure Context oder bei verweigerter Berechtigung öffnet der Kamera-Button wie bisher die native Kamera-App (capture-Attribut, wird nach Gebrauch entfernt, damit der Galerie-Button sauber bleibt).
  • Edit-Modus: „Foto entfernen" ist jetzt ein ✕ direkt auf dem Bestandsfoto (Tap togglet, ↩ macht rückgängig; Foto wird ausgegraut). Die Checkbox bleibt als Formularfeld erhalten (visuell versteckt) — kein Server-Change.
  • A11y: Vorschau-Box mit aria-live="polite" („Bild wird optimiert …"/„✅ bereit"), Hinweiszeile im Dialog als role="status", Auslöser-Animation respektiert prefers-reduced-motion, Safe-Area-Padding unter den Controls.

0.28.0 — Eigene Tagebuch-Ansicht bekommt die Foto-Galerie

  • Die eigene Tagebuch-Seite zeigt jetzt dieselbe Foto-Galerie (Grid + JS-Lightbox, alt → jung) wie die geteilte Seite — als gemeinsamer Baustein cannadaily_gallery_html() (ein Codepfad, Share-Seite + Eigen-Ansicht).
  • Formular „Neuer Eintrag" bleibt oben; die per-Eintrag-Aktionen (Bearbeiten/Teilen/Löschen, Titelbild setzen) bleiben in der Liste darunter erhalten.

0.27.0 — Auto-Post neuer Einträge auf Mastodon (Opt-in pro Grow)

  • Mastodon-Auto-Post: Ist bei einem Grow „automatisch posten" aktiv, löst jeder neue Eintrag einen öffentlichen Mastodon-Post aus (Grow-Name/Run + Notiz + Link zum geteilten Eintrag + Foto als Medium).
  • Konto pro User: Instanz + Zugangstoken werden als User-Meta gespeichert (einmal im Grow-Setup gesetzt, gilt für alle eigenen Tagebücher). Token maskiert; leer lassen behält den bestehenden.
  • Direkt aus WordPress (includes/Mastodon.php): Medien-Upload (v2) + Status (v1), fire-and-forget, kurzer Timeout, Doppelpost-Marker (cc_mastodon_posted). Fehler blockieren das Speichern nicht.
  • Beim Posten wird der Eintrag automatisch geteilt, damit der Link öffentlich funktioniert.

0.26.5 — Lightbox nutzt Design-System-Buttons + Hero volle Breite

  • Lightbox-Buttons verwenden jetzt die vorhandene Icon-Button-Komponente .we-act (statt eigener Styles) — behebt die ovalen Buttons (Astras globale button-Regeln blähten die feste Größe auf) und ist konsistent zum Styleguide.
  • .we-share-hero ohne max-width — das Sharepic oben nutzt die volle Breite.

0.26.4 — Sharepic-Feinschliff + Lightbox-Look + WP-Standard-Bilder

  • Sharepic: Kicker „WEEDERKENNEN" (statt CANNADAILY); Titel überlappt den Kicker nicht mehr (mehr Abstand, Foto etwas kleiner); Sorte inkl. Breeder (nw_breeder); Anzahl Einträge entfernt; **Run # steht jetzt in derselben Zeile wie die Domain** (Footer).
  • Galerie/Lightbox nutzt WordPress-Standardbilder: Thumbnails über wp_get_attachment_image (responsive srcset + lazy), Lightbox lädt die Größe large statt des Originals → deutlich schneller.
  • Lightbox-Look überarbeitet: runde Buttons, Pfeile seitlich, Schließen oben rechts, Bildunterschrift als Pille unten.

0.26.3 — Sharepic wie navweed + JS-Lightbox

  • Sharepic: nutzt jetzt navweeds gebündelte Font + Schriftgrößen (behebt das Mojibake, das vom System-Font-Fallback kam — rohes UTF-8 wie navweed statt Entity-Trick). Einzelbild (neuestes Foto) statt 2×2-Collage. Auf der Seite ganz oben als Hero.
  • Galerie-Reihenfolge alt → jung, damit das Durchblättern den Verlauf zeigt.
  • Lightbox neu (JS): sauberes Overlay mit Vor/Zurück, Pfeiltasten (←/→), Esc/Backdrop zum Schließen, Positionsanzeige. Behebt den Bug, dass „✕" vorwärts blätterte (native Popover-Navigation ersetzt).

0.26.2 — Geteilte Grow-Seite: Feinschliff

  • Sharepic wieder sichtbar auf der Seite (eigener Abschnitt „Sharepic" unter der Galerie), zusätzlich zu og:image + Download.
  • Lightbox zum Durchklicken: Vor/Zurück/Schließen direkt in der Foto-Lightbox (natives Popover mit Umlauf, kein JS), inkl. Positionsanzeige (z. B. „3/10").
  • Mehr Abstand über der Headline (Kopfbereich war zu knapp).
  • Strain verlinkt: Der Sortenname in der Meta-Zeile führt jetzt zur Sorten-Seite.

0.26.0 — Geteilte Grow-Seite: Galerie + Sharepic-Fix, Tagebuch-Löschen als Button

  • Öffentliche Grow-Seite (/geteilt/grow/…) neu: zeigt jetzt eine Galerie aller Grow-Fotos (Grid + native Popover-Lightbox) statt nur eines Bildes + leerer Datumszeilen. „Verlauf" listet nur Einträge mit Notiz. Layout über das we--Design-System statt Inline-CSS.
  • Sharepic (GD-Grafik) aufgehübscht: Mojibake behoben (·/Eintrâ → korrekte Umlaute/Trennzeichen via mb_encode_numericentity vor imagettftext); größeres Foto-Band; für Grows 2×2-Collage der neuesten Fotos statt einzelnem Cover; kompaktes Info-Band ohne die frühere Riesenlücke. Bleibt als og:image + Download.
  • Tagebuch löschen ist jetzt ein sichtbarer Secondary-Button (statt blassem Textlink); Bestätigungsdialog bleibt.

0.25.0 — Tagebuch: Speicher-Feedback + letztes Foto als Titel

  • Speicher-Loader: Beim Absenden eines Eintrags erscheint ein Overlay („Wird gespeichert …"), das bis zum Neuladen sichtbar bleibt — zeigt klar, wann Upload/Speichern abgeschlossen ist. Während der clientseitigen Bildoptimierung ist der Speichern-Button gesperrt (kein Original-Upload).
  • Letztes Bild = Titelbild: addEntry setzt cc_cover jetzt aktiv auf das neu hochgeladene Foto (vorher nur Anzeige-Fallback). Das neueste Foto wird automatisch zum Titelbild des Grows.
  • Nach dem Speichern zu den Einträgen: Redirect springt per Anker #cd-entries direkt zur Einträge-Liste. Darüber eine Zeile: links „← Alle Tagebücher", rechts die Bestätigung „✅ Eintrag gespeichert". Die Eintrags-Meldung wandert von oben in diese Zeile.

0.24.1 — Fix: Fatal bei doppeltem Plugin-Verzeichnis

  • Doppel-Last-Schutz in cannacal.php: Lädt WordPress versehentlich zwei Kopien des Plugins (z. B. cannacal und cannacal-1, wie es beim Hochladen eines Zips ohne umschließenden Ordner entstehen kann), bricht der zweite Ladevorgang jetzt sauber ab (if (defined('CANNACAL_VERSION')) return;). Vorher: „Constant already defined"-Warnungen + Fatal, weil CANNACAL_DIR der einen Kopie auf die andere zeigte.
  • Zip-Struktur korrigiert: Das Release-Zip enthält die Dateien jetzt im umschließenden Ordner cannacal/, damit WordPress beim Installieren/Aktualisieren kein zweites Verzeichnis cannacal-1 anlegt.

0.24.0 — DSGVO: Tagebücher beim Konto-Löschen entfernen

  • Löschfunktion (includes/Privacy.php): cannadaily_delete_user_data() löscht alle Tagebücher + Einträge + zugehörige Foto-Dateien eines Nutzers (unwiderruflich). Strains bleiben unberührt.
  • Registriert einen WP-Privacy-Eraser (Admin: Tools → Daten löschen). Die Self-Service-Konto-Löschung (navweed) ruft dieselbe Funktion auf.

0.23.0 — DSGVO: Datenexport (Tagebücher + Fotos)

  • Datensammlung für den Export (includes/Privacy.php): cannadaily_export_user_data() liefert alle Tagebücher des Nutzers mit Einträgen (Datum/Notiz/Wetter) + die zugehörigen Foto-Dateien.
  • Registriert einen WP-Privacy-Exporter (Admin: Tools → Daten exportieren). Der eigentliche Self-Service-Download (ZIP mit Fotos) liegt im navweed-Plugin (Konto-Seite) und holt sich diese Daten per function_exists() — lose gekoppelt.

0.22.0 — Farbe pro Tagebuch (Kalenderansicht)

  • Jedes Tagebuch hat jetzt eine wählbare Farbe (Farbfeld im Tagebuch-Formular, neu + bearbeiten). Sie markiert die Termine/Einträge dieses Tagebuchs im Grow-Kalender — praktisch bei mehreren Tagebüchern.
  • Auflösung über Helper cannadaily_grow_color(): gewählte cc_color (Hex) oder sonst eine stabile Palette-Farbe pro Grow. Speicherung sicher per sanitize_hex_color().

0.21.5 — Titelbild standardmäßig das letzte Foto

  • Tagebuch-Titelbild ist jetzt standardmäßig das neueste Eintrags-Foto — kein manuelles Setzen mehr nötig. Auflösung beim Anzeigen: manuell gewähltes cc_cover (falls die Datei noch existiert) hat Vorrang, sonst automatisch das letzte Foto (Helper Diary::coverPhotoId()). Greift auch für bestehende Tagebücher und fängt gelöschte Titelbilder ab. Die Lightbox-Auswahl „★ Als Titelbild verwenden" bleibt als Override.

0.21.4 — Fix: Grow-Seite (Slug grow-beta) wird erkannt

  • Mobile-Menü „Übersicht"/„Dashboard" zeigte nicht auf die Grow-Seite: cannadaily_grow_page_url() suchte nur Slug grow/Titel Grow — die Seite heißt aber grow-beta („Grow (beta)"). Die Auflösung scheiterte → Fallback aufs Bewertungs-Dashboard. Jetzt werden Slugs grow/grow-beta/grow-bereich und Titel Grow/Grow (beta)/Grow-Bereich geprüft (per Filter weiterhin überschreibbar).

0.21.3 — Changelog neueste-zuerst

  • CHANGELOG.md strikt absteigend sortiert (neueste Version oben) und das array_reverse in der Changelog-Ausgabe entfernt — die On-Site-Anzeige zeigt jetzt korrekt die aktuellste Version zuerst.

0.21.2 — Fix: diary.css wurde nicht geladen (Handle-Kollision)

  • Regression aus dem we--Rename behoben: frontend.css/frontend.js und diary.css/diary.js hatten nach der Umbenennung dasselbe Enqueue-Handle (we-frontend) — WordPress verwarf das zweite, also diary.css/diary.js. Folge: auf den Grow-Seiten fehlten die Diary-Styles (doppelte „Tagebuch"-Überschrift, Karten gestapelt statt im Raster). Jetzt eindeutige Handles: we-cal (Generator) und we-diary (Tagebuch).
  • Damit greifen wieder Astra-Titel-Unterdrückung, Karten-Raster, Eintrags-Styles, Foto-Lightbox + JS-Resize.

0.21.1 — Foto-Upload optimiert + Titelbild per Lightbox

  • Clientseitige Bild-Optimierung vor dem Upload: Fotos werden im Browser auf max. 1600 px verkleinert und als WebP (Q 0.82) exportiert, bevor sie hochgeladen werden. Spart auf dem Handy massiv Zeit (Voll-Auflösung 5–12 MB → ~200–400 KB); EXIF/GPS fällt beim Reencode automatisch weg. Server akzeptiert WebP bereits. Fallback: bei fehlender WebP-Unterstützung das Original.
  • Titelbild jetzt über eine Foto-Lightbox: Tippen aufs Eintragsfoto öffnet ein Popover mit großem Bild und großem Button „★ Als Titelbild verwenden" (statt des winzigen ☆ auf dem Thumbnail). Das aktuelle Titelbild wird mit einem ★-Badge markiert.

0.21.0 — Design-System Stufe C–E: ein Namensraum we- + Dark-Mode CSS-only

  • Alle Klassen auf .we-* (vorher cannadaily-/cannacal-): einheitlicher Namensraum über beide Plugins, Markup + CSS + JS im Gleichschritt, inkl. Element-IDs (Kalender) + Handles. Look unverändert (per-Page-Isolation).
  • Dark-Mode CSS-only: keine JS-Theme-Umschaltung mehr. Dark greift über html:has(#we-theme-dark:checked); ein verstecktes Checkbox (Footer, von Weederkennen) + <label>-Toggle schalten um. 2 Modi (Hell/Dunkel), ohne Persistenz (Reset je Seitenwechsel) — bewusst so gewählt.
  • Token-Quelle bleibt --we-* (we-core). Hinweis: das alte data-nw-theme-Attribut entfällt; einige Kontrast-Regeln bleiben inert (Kontrast-Modus entfällt im CSS-only-Schalter).

0.20.3 — Design-System Stufe B: Buttons auf .we-btn

  • Alle Button-Klassen (cannadaily-btn*, cannacal-btn*) in Markup und CSS auf .we-btn/.we-btn--* (BEM) vereinheitlicht. Look unverändert (Regeln im Gleichschritt umbenannt). we-core stylt Buttons vorerst nicht (kein Lade-Order-Konflikt); die Zusammenführung auf eine Definition folgt.

0.20.2 — Design-System Stufe A: Token-Vokabular vereinheitlicht

  • CSS-Tokens --nw-* → --we-* (Weederkennen). Reine Umbenennung über alle CSS-Dateien, identische Werte + Fallbacks → kein optischer Bruch. Eine Quelle der Wahrheit (Child-Theme we-core.css/tokens.css).
  • Vorbereitung für die folgende Klassen-Vereinheitlichung auf den we--Präfix (eigene Stufen, mit Vorschau).
  • Hinweis: das Dark-Mode-Attribut data-nw-theme bleibt vorerst; es wird mit den Klassen umbenannt.

0.20.1 — Kalender mobil als Liste + schmaleres Datums-Feld

  • Mein Grow-Kalender startet auf Mobil (≤ 640 px) direkt in der Listen-Ansicht (listMonth) statt im Monats-Grid, das auf kleinen Screens kaum lesbar ist. Umschalter Liste/Monat bleibt.
  • „Dein persönlicher Grow-Kalender": das Datums-Feld zieht sich auf Mobil **nicht mehr über die volle Breite** (linksbündig, inhaltsbreit) — der „Kalender erstellen"-Button bleibt voll.

0.20.0 — Kopfzeilen aufgeräumt (eigener Seitentitel, Icons statt Emojis)

  • Eigene Seiten-Kopfzeile statt Astra-H1. Auf den CannaDaily-Seiten wird der Astra-Seitentitel per CSS unterdrückt (Body-Class cannadaily-page); der Shortcode rendert die Überschrift selbst.
  • Grow-Liste: „📓 Meine Grow-Tagebücher / CannaDaily · privat" entfällt; Titel „Tagebuch" links, „Neues Tagebuch" als Icon-Button oben rechts.
  • Tagebuch-Detail: Grow-Titel als Überschrift, rechts daneben **Bearbeiten/Kalender/Teilen nur als Icons** (.cannadaily-act, mit Tooltip/aria-label), Meta („Run #… · …") darunter. Eintragsformular steht als erstes im Kasten.
  • Emojis → SVG-Icons überall im Tagebuch-Kopf, im „Neuer Eintrag"-Titel, in den Popover-Titeln und bei den Foto-Buttons (Kamera/Galerie), die jetzt linksbündig sind. Neue Icons: camera, image, plus.
  • Mobile: Eintrags-Thumbnails ~1/3 kleiner (92→61 px).
  • „Übersicht"/„Alle Tagebücher" zeigen jetzt auf die „Grow"-Seite (Helper cannadaily_grow_page_url(), Auflösung Slug grow → Titel „Grow" → Fallback Dashboard).
  • Auch die Neu-/Bearbeiten-Formulare (Grow + Eintrag) nutzen die neue, emojifreie Kopfzeile.

0.19.4 — Eintragszeile kompakter (Datum + Wetter neben das Bild)

  • Die separate Kopfzeile (Datum links / Icons rechts) entfällt. Die Eintragszeile ist jetzt Thumbnail | Body | Icons: im Body stehen Datum und Wetter nebeneinander (.cannadaily-entry-meta), darunter die Notiz. Das leere Mittelfeld verschwindet, auch bei Einträgen ohne Foto.
  • Icons (Bearbeiten/Teilen/Löschen) bleiben oben rechts, oben ausgerichtet.
  • Aufräumen: tote .cannadaily-entry-head-CSS-Regeln entfernt.

0.19.3 — Aktionsleiste als Button-Reihe + SVG-Icons

  • Bearbeiten / Kalender abonnieren / Tagebuch teilen sitzen jetzt nebeneinander in einer Button-Reihe (.cannadaily-toolbar, flex + wrap) statt untereinander.
  • Emojis → SVG-Icons: die drei Buttons nutzen das vorhandene Icon-Set (cannadaily_share_svg); neues calendar-Icon ergänzt. Konsistent mit den Eintrags-Aktionen (Bearbeiten/Teilen/Löschen).
  • Die zwei aufklappbaren Boxen (Abonnieren, Teilen) sind jetzt Popovers (Wiederverwendung von .cannadaily-share-pop wie beim Eintrag-Teilen) — kein Inline-Aufklappen mehr, das die Reihe sprengt.
  • Fix: SVG in Buttons mit flex: 0 0 auto, damit Astra das Icon nicht auf Breite 0 schrumpft.

0.19.2 — Klapp-Header als Buttons

  • „Tagebuch bearbeiten", „Kalender abonnieren", „Ganzes Tagebuch teilen" nutzen jetzt die bestehende Button-Optik (.cannadaily-btn-secondary) statt Text-Link/Klappkasten — konsistent mit den übrigen Buttons. Die <details>-Boxen verlieren ihren Doppel-Rahmen; der Inhalt klappt unter dem Button auf.

0.19.1 — Eintrags-Icons + Versatz (im echten Browser verifiziert)

  • Leere Teilen-/Löschen-Icons behoben: Astra quetschte das SVG im <button> per Flexbox auf Breite 0 (Höhe blieb) — der Bearbeiten-Link (<a>) war nicht betroffen, daher nur er sichtbar. Fix: flex: 0 0 auto + erzwungene SVG-Breite und Button-Größe. (Live per DevTools bestätigt: Button-SVG 0px → 19px.)
  • Versatz behoben: Astra setzte 20px padding-left aufs ul.cannadaily-entries → mit padding: 0 !important überschrieben.

0.19.0 — Tagebuch bearbeiten

  • Bestehendes Tagebuch bearbeiten: neuer Link „✏️ Tagebuch bearbeiten" im Kopf der Detailseite öffnet das Setup-Formular vorbefüllt (Name, In-/Outdoor, Sorte, Standort, Run, Startdatum). Speichern über die neue Aktion update_grow (Diary::updateGrow, mit Eigentümer-Prüfung).
  • Alles editierbar inkl. Startdatum (verschiebt bewusst Plan/Kalender). Beim Wechsel **Outdoor → Indoor bleiben die Standortdaten erhalten** (nur die Wetter-Anzeige pausiert) — sie werden nur im Outdoor-Modus überschrieben.

0.18.2 — Tagebuch-Detail aufgeräumt

  • Datum/Icons fluchten jetzt: Der Eintrags-Kopf (Datum + Icons) sitzt über der Foto-Zeile und ist immer volle Breite — vorher rutschte er bei Einträgen mit Foto nach rechts (Versatz zu Einträgen ohne Foto).
  • Klarere Abgrenzung: Überschriften „✏️ Neuer Eintrag" und „Bisherige Einträge (N)" (mit Trennlinie) trennen Eingabe von der Liste.
  • Icons sichtbar (zweiter Anlauf): Icon-Farbe wird jetzt mit !important erzwungen — das Theme (Astra) überschrieb die Button-Textfarbe und machte die SVGs unsichtbar. Löschen rot, beides auch im Dark-Theme.

0.18.1 — Eintrags-Icons: Fixes

  • Leere Icons behoben: Die Aktions-<button> erbten die (weiße) Button-Textfarbe des Themes → Icons unsichtbar (nur der „Bearbeiten"-Link war grün). Icon-Farbe wird jetzt auf .cannadaily-act svg hart gesetzt; Löschen rot.
  • Aktionsreihe entzerrt: nur noch 3 Icons (Bearbeiten/Teilen/Löschen), kleiner (32px) und umbruchsicher → läuft auf dem Handy nicht mehr aus dem Eintrag.
  • Titelbild-Stern als Overlay direkt auf dem Foto (★ = aktuelles Titelbild, ☆ = als Titelbild setzen) statt als eigenes Icon in der Reihe.

0.18.0 — Kompakte Tagebuch-Einträge

  • Einträge als kompakte Liste statt hoher Karten: quadratisches Foto-Thumbnail links (object-fit: cover, 1:1 gecroppt; Tippen öffnet das Bild groß), rechts Datum/Notiz/Wetter.
  • Aktionen als Icons (wie im Bewertungs-Dashboard): ✎ Bearbeiten, ↗ Teilen, 🗑 Löschen und ★ Titelbild.
  • Teilen als Popover (native Popover-API) statt aufgeklappter Box — öffnet Link/X/Mastodon/Sharepics bzw. „Teilen aktivieren". Backend (Löschen, Teilen, Titelbild) unverändert; reiner Frontend-Umbau.

0.17.0 — Mobile Grow-Navigation + Foto-Auswahl

  • Helfer für die kontextabhängige Mobil-Navigation (von Weederkennen genutzt, lose gekoppelt): cannadaily_is_grow_page(), cannadaily_grow_entry_url() und cannadaily_nav_entry_data() (liefert je nach Anzahl Tagebücher den Modus neu/direkt/Auswahl + die Tagebuch-Liste). Das Eintragsformular hat jetzt einen Anker #cd-entry für den Direktsprung.
  • Foto-Upload „Instagram-like": statt des nackten Datei-Felds zwei Buttons 📷 Kamera und 🖼️ Galerie, die denselben (versteckten) cd_photo-Input auslösen — Kamera mit capture="environment", Galerie ohne. Sofort-Vorschau, Server-Validierung und EXIF-Strippung unverändert. Ein Foto pro Eintrag wie bisher.

0.16.1 — Kalender-Popover: Fixes

  • Pointer-Cursor auf Kalender-Events: FullCalendar setzt bei eventClick (statt url) keinen Hand-Cursor – jetzt per CSS ergänzt, damit Events sichtbar klickbar wirken.
  • Kodierung repariert: Tagebuch-Name/Titel zeigten texturierte Entities (– statt „–"), weil get_the_title() durch wptexturize läuft und die Werte per textContent ausgegeben werden. Jetzt serverseitig via html_entity_decode() zu echten UTF-8-Zeichen dekodiert (Name, Plan-Titel, Eintragszeile).

0.16.0 — Web-Kalender: Event-Popover

  • Klick auf einen Kalender-Eintrag öffnet ein Popover (FullCalendar-eventClick) mit Titel, Datum, Tagebuch-Badge und Typ (📋 Plan-Schritt / 📓 Tagebuch-Eintrag) sowie einem Button „Zum Tagebuch öffnen" (Detailseite des jeweiligen Grows via ?cd_grow=ID). Schließt bei Außenklick/ESC, bleibt im Viewport.
  • Dafür tragen die Kalender-Events jetzt growId + Detail-URL in extendedProps. Dynamische Texte werden per textContent gesetzt (kein innerHTML), da Titel aus Nutzer-Notizen stammen. Styling über --nw-*-Tokens inkl. Dark-Theme.

0.15.0 — Grow-Glossar

  • Neuer Shortcode [canna_glossar]: öffentliches Endnutzer-Fachlexikon für den Autoflower-Anbau (Pflanzentypen, Phasen, Licht/Klima, Training, Pflanzenteile, Substrat/Nährstoffe, Recht/KCanG) aus der mitgelieferten GLOSSAR.md. Alphabetisch sortiert, A–Z-Sprungnavigation, Live-Suchfilter und Anker je Begriff (Deep-Link, z. B. …/glossar/#term-autoflower).
  • Eigenständig, keine Kopplung an navweed (eigene Datei, eigener Inhalt). Styling über die --nw-*-Tokens inkl. Dark-Theme; standalone greifen die Fallback-Farben. Inhalt in GLOSSAR.md jederzeit erweiterbar.

0.14.6 — FullCalendar update-sicher laden

  • Der Web-Kalender ([canna_daily_calendar]) sucht die self-hosted FullCalendar-Datei jetzt zuerst im Plugin (assets/vendor/) und sonst in wp-content/uploads/cannacal/ — letzteres überlebt Plugin-Updates (im Plugin-Ordner würde die Datei bei jedem Update überschrieben). Gilt auch für die Locales-Datei.
  • Admin-Hinweis + READ_ME aktualisiert (empfohlener Ablageort = uploads/cannacal/).

0.14.5 — CannaDaily-Teilen mit Social-Icon-Reihe

  • In der Teilen-Box (Eintrag & Grow) jetzt die gleiche Icon-Reihe wie bei navweed: **Kopieren · X · Mastodon · Sharepic 1:1 · 4:5** (Icons 1.9rem, Buttons 44px). Kopieren/Mastodon via kleinem JS (diary.js).
  • Sharepics (1:1 + 4:5) werden beim Teilen erzeugt (Share::buildSharepics), damit die Download-Links sofort funktionieren; URL-Helper Share::sharepicUrl().

0.14.4 — Sharepic-Text repariert + Layout + Sorten-Vorbefüllung

  • Sharepic-Text gefixt: HTML-Entities (z. B. – → „–") werden dekodiert, Emojis/Symbole entfernt (GD-Schrift hat dafür keine Glyphen → vorher Müllzeichen wie „đ"/„Ś"), sauberes Kürzen ohne kaputte Zeichen.
  • Layout/Schrift: Kicker „CANNADAILY" + großer Titel + Akzent-Subzeile (wie bei den Reviews), deutlich größere Schrift; Bug behoben (Sorte im Grow-Sharepic). Footer „weederkennen.de".
  • Setup-Vorbefüllung: kommt der Nutzer über „Jetzt growen" von einer Sorte (?cd_strain_pre=ID), ist die Sorte im Tagebuch-Setup bereits ausgewählt.

0.14.3 — Sharepic sichtbar machen

  • Auf der geteilten Seite (/geteilt/…) wird das Sharepic jetzt inline angezeigt (1:1 als Hero-Bild), nicht nur als Download. Die 4:5-Variante bleibt als Download.
  • In der Teilen-Box im Tagebuch gibt es einen klaren Link „👁️ Vorschau & Sharepic öffnen ↗" zum geteilten Link — so findet man das Bild sofort.

0.14.2 — Sharepic auch im Hochformat (4:5)

  • Zusätzlich zum quadratischen Sharepic (1:1) gibt es jetzt eine 4:5-Variante (1080×1350) je geteiltem Eintrag/Grow. Auf der geteilten Seite stehen beide als Download („Quadrat (1:1)" · „Hochformat (4:5)").
  • Share::sharepic($type, $post, $ratio) mit square|portrait; Foto-Band + Textbereich passen sich der Höhe an.

0.14.1 — Foto-Upload: Sofort-Vorschau

  • Beim Tagebuch-Eintrag zeigt das Foto-Feld jetzt direkt nach der Auswahl ein Thumbnail + Dateiname/Größe (assets/js/diary.js), mit „✕ Foto entfernen". Der Upload passiert weiterhin beim Speichern — aber der Nutzer sieht sofort, dass ein Bild gewählt ist.
  • Client-Warnung bei falschem Typ (nur JPG/PNG/WebP) oder > 5 MB, damit nicht still verworfen wird.

0.14.0 — Tagebuch teilen (Eintrag & Grow, mit Bild)

  • Öffentliches Teilen wie bei Reviews (includes/Share.php): pro Element ein geheimer Token + Opt-in (cc_shared), Route /geteilt/(eintrag|grow)/{token}/ mit öffentlicher Seite + OG-Tags + GD-Sharepic.
  • Einheit: beides — einzelner Eintrag (Datum, Notiz, Foto, Wetter; Foto-Option cc_share_photo) und ganzes Tagebuch/Grow (Titelbild, Sorte, Run, Stats, letzte Einträge).
  • Teilen-UI im Tagebuch: je Eintrag „🔗 Eintrag teilen" (mit „Foto mitteilen") und „🔗 Ganzes Tagebuch teilen"; jeweils Link anzeigen + „Nicht mehr teilen" (zieht den öffentlichen Zugriff zurück).
  • Sharepic: 1080², Foto als Cover-Band oben + Text (TTF mit System-Font-Fallback), Footer „weederkennen.de".
  • Hinweis: Geteilte Links sind über das Token öffentlich erreichbar (kein Login) — bewusst, wie bei den Reviews. Nach Update den Permalink-Cache ggf. einmal neu speichern (neue Route).

0.13.2 — Changelog-Anzeige: neueste Version oben

  • [cannacal_changelog] rendert die Versionen jetzt neueste zuerst (Sektionen werden im Renderer umgedreht; die Datei bleibt chronologisch, neue Einträge weiterhin unten anhängbar).

0.13.1 — Härtung: persönliche Seiten leiten auf Login

  • Gäste werden auf [canna_daily] / [canna_daily_dashboard] / [canna_daily_calendar]-Seiten jetzt **hart zur Login-Seite umgeleitet** (auth_redirect auf template_redirect), statt nur eine Hinweis-Zeile zu zeigen.
  • Kein bekanntes Datenleck vorher: anonyme Abrufe zeigten bereits nur den Login-Hinweis (Shortcodes prüfen Login), Seiten sind noindex,nofollow. Diese Änderung macht das Verhalten konsistent mit dem Weederkennen-Katalog und robuster gegenüber Caching.
  • Hinweis: Nach Deploy den Seiten-Cache leeren (PWA/Cache-Plugin), damit eine evtl. gecachte Hinweis-Seite durch den Redirect ersetzt wird.

0.13.0 — Changelog-Shortcode/Block

  • Neuer Shortcode [cannacal_changelog] + Block „CannaCal Changelog" (includes/Changelog.php): rendert diese CHANGELOG.md als HTML (Überschriften, Listen, fett, code). Vorher gab es das nur als Datei – der Shortcode wurde daher nicht interpretiert. Pendant zu Weederkennens [navweed_changelog].

0.12.0 — Feinschliff CannaDaily

  • Button-Schrift weiß: Anchor-Buttons (z. B. „Neues Tagebuch") erzwingen jetzt weiße Schrift auf Grün — die Theme-Linkfarbe (blau) wurde per Spezifität überschrieben.
  • Redirect nach Eintrag: zeigt zuverlässig zurück auf die Grow-Tagebuchseite (deterministisch über die Detailseiten-URL) statt über Referer/Home auf dem Weederkennen-Dashboard zu landen. Nach „Tagebuch löschen" → Übersichtsseite.
  • Grow-Run-Nummer: Setup-Feld „Dein Grow-Run (Nummer)" (Auto-Vorschlag = nächster Lauf, anpassbar), gespeichert als cc_run; Anzeige als „Run #N" auf Dashboard-Karte und Tagebuch-Kopf.
  • Plan-Abgleich: Unter der Eintrags-Eingabe erscheint der heutige Plan-Hinweis, wenn für den Grow-Tag eine Aufgabe ansteht (z. B. Düngen) — „📋 Heute im Plan (Tag X): …" (aus dem GrowSchedule).

0.11.0 — Web-Kalender (Gesamt-Kalender im Frontend, iCal optional)

  • Neuer Shortcode [canna_daily_calendar] + Block „CannaDaily Kalender": zeigt den Gesamt-Kalender des Nutzers direkt auf der Website — alle Tagebücher (Anbau-Plan ab jeweiligem Start + alle Einträge), farbig je Grow. Damit wird das iCal-Abo optional (bleibt aber bestehen).
  • Renderer: FullCalendar v6 (MIT), self-hosted unter assets/vendor/fullcalendar.min.js (assets/js/calendar.js, Monats-/Listen-Ansicht). Events werden serverseitig aggregiert und inline geliefert (kein externer Request, nur eigene Daten, login-gated).
  • Graceful Fallback: fehlt die FullCalendar-Datei, rendert PHP automatisch eine Agenda-Liste (kommende Termine) — nie leer. Admin-Hinweis + Anleitung unter assets/vendor/READ_ME_FULLCALENDAR.txt.
  • Die FullCalendar-Datei kann ich nicht mitliefern (MIT-Lizenz, aber aus der Build-Umgebung nicht beschaffbar); einmalig herunterladen + ablegen (Pfad/Anleitung beigelegt).

0.10.0 — Seiten-Split: Übersicht vs. Detailseite

  • Neuer Übersichts-Shortcode [canna_daily_dashboard] + Block „CannaDaily Übersicht": zeigt nur die Tagebuch-Karten. Damit kannst du eine Übersichtsseite bauen mit [autoflower_calendar] + [canna_daily_dashboard] (Kalender + alle Tagebücher nebeneinander).
  • Die Karten verlinken auf die Detailseite mit [canna_daily] (auto-erkannt über den Shortcode, Option-Cache). Das einzelne Tagebuch + Einträge + Bearbeiten leben dort.
  • Back-Links („← Alle Tagebücher") führen zur Übersichtsseite, sofern vorhanden.
  • [canna_daily] bleibt abwärtskompatibel: ohne Übersichtsseite zeigt es weiterhin selbst das Dashboard.

0.9.0 — Pro-Grow-Kalenderfeed (Einträge im Kalender)

  • Neuer privater, tokengeschützter ICS-Feed je Tagebuch: Route /grow-kalender/{token}/ (includes/GrowFeed.php). Enthält Anbau-Schema (ab dem Startdatum dieses Grows) + Tagebuch-Einträge als Termine + die wöchentliche Erinnerung.
  • ICalBuilder erweitert: setDiaryEntries() (Einträge als VEVENTs) und setUidSalt() — Letzteres gibt jedem Grow eindeutige Event-UIDs, damit zwei Grows mit gleichem Startdatum (z. B. dieselbe Sorte in- & outdoor) sich in Kalender-Apps nicht überlagern.
  • Abo-Link in der Tagebuchseite (aufklappbar). Token = Bearer-Geheimnis (Tagebuch ist privat → Link nicht öffentlich teilen). Rewrite-Regel wird nach dem Update einmalig automatisch geflusht.
  • Der bestehende anonyme Datums-Kalender (/kalender/{base64}/) bleibt unverändert.

0.8.0 — Mehrere Tagebücher, Dashboard, editierbare Einträge (Refactor)

  • Einträge sind jetzt ein eigener CPT cc_entry (post_parent = Tagebuch) statt JSON-Meta — Grundlage für Bearbeiten pro Eintrag und späteres Teilen (analog Reviews). Einmalige, idempotente Migration der alten JSON-Einträge (cc_entries) in cc_entry-Posts; Roh-JSON bleibt als Fallback erhalten.
  • Mehrere Tagebücher parallel je Nutzer (z. B. gleiche Sorte in- & outdoor).
  • [canna_daily] ist jetzt ein Router: ohne Auswahl → Dashboard (Karten je Tagebuch mit Cover, „Tag X" seit Keimstart und Eintrags-Anzahl, Button „Neues Tagebuch"); ?cd_grow=ID → Tagebuchseite (changelog-artige Eintragsliste); ?cd_grow=ID&cd_edit=ENTRY → Eintrag bearbeiten; sonst Setup.
  • Jeder Eintrag editierbar (Datum, Notiz, Foto ersetzen/entfernen) und einzeln löschbar; Titelbild weiterhin pro Tagebuch markierbar. Alle Aktionen führen die konkrete Grow-/Eintrags-ID mit (Eigentümer-geprüft).
  • Read-API cannacal_user_strain_photo() und DSGVO-Eraser auf cc_entry umgestellt; Foto-Upload/EXIF-Strip/ Wetter-Stempel unverändert, hängen jetzt am Eintrag.
  • Teilen pro Eintrag ist damit vorbereitet, aber noch nicht gebaut (Folge-Schritt).

0.7.0 — Gutenberg-Blöcke (neben den Shortcodes)

  • Zwei dynamische Blöcke als dünne Hülle um die bestehenden Shortcodes (kein Markup-Duplikat, kein Build-Step – reines wp.*-JS): includes/Blocks.php + assets/js/blocks.js.
  • „CannaCal Grow-Kalender" (cannacal/calendar, render = cannacal_render_shortcode), mit optionalem Überschrift-Attribut.
  • „CannaDaily Tagebuch" (cannacal/diary, render = cannadaily_render_shortcode).
  • Im Editor je ein Platzhalter (Live-Vorschau nicht sinnvoll: Kalender braucht JS, Tagebuch Login); das Frontend rendert das echte Widget. Shortcodes bleiben unverändert nutzbar.

0.6.0 — CannaDaily Phase 2a: Fotos + Sorten-Verknüpfung (Quelle)

  • Foto-Upload pro Eintrag (media_handle_upload, multipart): Typ (jpg/png/webp) + Größe (≤ 5 MB) serverseitig geprüft, Attachment am Grow. Abonnenten-Upload via temporär gewährtem upload_files.
  • EXIF/GPS-Strip beim Upload (GD-Neukodierung) — kein Grow-Standort in den Metadaten.
  • Grow ↔ Sorte: cc_strain_ref (nw_strain-ID), Sortenwahl im Setup per Weederkennen-REST-Autocomplete (/wp-json/navweed/v1/strains, diary.js). Nur wenn Weederkennen aktiv (sonst Feld ausgeblendet → standalone).
  • Titelbild: Nutzer markiert ein Eintrags-Foto (cc_cover, Aktion set_cover, Eigentümer-geprüft).
  • Read-API cannacal_user_strain_photo($userId, $strainId) (global, helpers.php): liefert Titelbild, sonst neuestes Foto — Grundlage für Phase 2b (Anzeige in Weederkennen-Review + Sharepic).
  • DSGVO: Grow-Attachments werden bei „Grow löschen" und im Personal-Data-Eraser mitgelöscht.
  • Noch offen (2b): Anzeige des Fotos in der Weederkennen-Review und auf dem Sharepic (Opt-in) — separater Schritt im navweed-Plugin.

0.5.0 — CannaDaily: Standort (Photon) + DWD-Wetter

  • Standort-Autocomplete im Setup (outdoor): custom Photon-Feld (OpenStreetMap, kein Key, kein Google), assets/js/diary.js. Auswahl speichert Ort-Label + lat/lng (+ PLZ) ins Meta — datensparsam, debounced (ab 3 Zeichen). Ausrichtung (Himmelsrichtung) bleibt separat. Bewusst kein ACF (komplett custom).
  • DWD-Wetter pro Eintrag: neuer WeatherProvider (includes/WeatherProvider.php) holt das Tageswetter via Bright Sky (DWD Open Data) für die Koordinaten des Grows und stempelt es an jeden neuen Outdoor-Eintrag (Emoji + Lage + Temperatur + Luftfeuchte). Transient-Cache (6 h) pro Ort/Tag, graceful: kein/kaputtes Ergebnis → Eintrag ohne Wetter.
  • Anzeige: Wetter-Chip je Eintrag; Pflicht-Attribution „DWD via Bright Sky · OpenStreetMap/Photon".
  • Hinweis: Photon/Bright Sky sind öffentliche Dritt-Instanzen (Rate-Limit, self-hostbar) — für DSGVO/Last ggf. später Self-Host. Foto-Upload weiterhin offen (Phase 2).

0.4.0 — CannaDaily: Grow-Tagebuch (MVP, ohne Wetter)

  • Neues, eigenständiges Tagebuch auf WP-Core (CPT cc_grow, post_author = Nutzer; Einträge als JSON-Meta cc_entries). Kein eigenes Login, keine Weederkennen-Kopplung. (includes/Diary.php)
  • Shortcode [canna_daily] (frontend/diary.php): nur eingeloggt; Setup (indoor/outdoor; bei outdoor PLZ + Ausrichtung; Startdatum rückdatierbar bis 30 Tage), datierte Text-Einträge, Eintragsliste (neueste zuerst), „Grow löschen". Formulare per Nonce + PRG-Redirect.
  • CSS assets/css/diary.css in den Weederkennen-Tokens (--nw-* mit Fallbacks) inkl. Dunkel-Mode.
  • Wöchentliche Tagebuch-Erinnerung im Kalender-Feed: wiederkehrendes Event (RRULE:FREQ=WEEKLY;COUNT=16) ab Tag 7 — zustandslos, in jedem generierten ICS (ICalBuilder).
  • DSGVO: in den WP-Personal-Data-Eraser eingehängt (löscht alle Grows eines Nutzers).
  • Bewusst noch NICHT enthalten: Wetter-Stempel (DWD). Grund: das im Konzept geplante Bündeln der PLZ→Koordinaten-CSV ist aus der Build-Umgebung nicht möglich → Geocoding-Quelle muss vor 0.5.0 entschieden werden (siehe CannaCal_Konzept_Tagebuch.md). Foto-Upload ebenfalls Phase 2.

0.3.1 — Startdatum: Rückdatieren möglich

  • Startdatum-Feld erlaubt jetzt Vergangenheitsdaten bis 30 Tage zurück („schon angesetzt"), statt nur ab heute (shortcode.php: min = heute−30). Label klarer: „Wann hast du die Samen angesetzt – oder wann planst du es?".
  • Bewusst keine separate Checkbox: das Datum kodiert geplant (Zukunft) vs. bereits gestartet (Vergangenheit) — keine redundante zweite Bedienlogik.
  • Hinweis: Rückdatieren verkürzt die verbleibende Link-Gültigkeit (145 Tage ab Startdatum).

0.3.0 — Nachernte: Fermentierung + Curing (+4 Wochen)

  • Schema um eine zweistufige Nachernte verlängert (Tag 85 → ~113):
  • Stufe 1 Fermentierung (Tag 85 Start, Tag 92 Woche 1, tägliches Burpen).
  • Stufe 2 Curing (Tag 99 Beginn, Tag 106 Woche 3, Tag 113 abgeschlossen).
  • Neue Phasen fermentation + curing (GrowSchedule::getPhases()), Emoji 🫙 in ICalBuilder.
  • Der „nächster Zyklus"-Hinweis + §34-Hinweis wandern ans neue Ende (Tag 113).
  • Gekoppelter Pflicht-Fix: Abo-Ablauf von 90 → 145 Tage angehoben (Server::EXPIRY_DAYS, genutzt in isExpired, PROPFIND-Fenster und Fehlertext) — sonst stürben die Curing-Events hinter der alten 90-Tage-Grenze. Frontend (frontend.js EXPIRY_DAYS, Shortcode-Anzeige „145 Tage", Termin-Zähler) synchron nachgezogen.

0.2.0 — Weederkennen-Integration (Phase 1a + 1b)

Design (1a)

  • assets/css/frontend.css komplett von der eigenen --cc-*-Glassmorphism-Optik auf die Weederkennen-Tokens (--nw-green, --nw-line, --nw-surface-soft, --nw-ink, --nw-star, --nw-radius*) umgestellt — flach, ohne Gradients/Glow/Float-Animation.
  • Tokens werden per var(--nw-*, fallback) referenziert: mit aktivem Weederkennen erbt das Widget dessen Marke; Dunkel-Mode via html[data-nw-theme="dark"]-Overrides; standalone greifen die Fallbacks.

Branding (1a)

  • iCal-Feed rebranded: PRODID, X-WR-CALNAME, UID-Domain (@weederkennen.de) und Footer (🌐 weederkennen.de) in ICalBuilder.php; PROPFIND-displayname/-Beschreibung + ICS-Dateiname in CalDAV/Server.php; Legal-Footer-Link im Shortcode (cannacal.io → weederkennen.de).
  • Naming „CannaCal" → „Weederkennen Grow" (im Feed/Abo sichtbar).

Kopplung (1b)

  • Neuer globaler Helper cannacal_calendar_page_url(int $strainId = 0) (frontend/helpers.php, bewusst global für function_exists()-Detection durch Weederkennen): findet die Seite mit dem [autoflower_calendar]-Shortcode (Option-Cache + Revalidierung), hängt optional ?nw_strain=ID an.
  • Shortcode nimmt den Sorten-Kontext (?nw_strain) auf und zeigt ihn als Chip „Für deine Sorte: …"; cached zugleich die eigene Seiten-ID für den Helper.
  • Gegenstück in Weederkennen (strain-view.php, ab navweed 0.35.7): CTA „🌱 Grow-Kalender starten" nur auf Autoflower-Sorten, function_exists()-gekapselt.

0.1.0 — Erststand (Bestandsaufnahme)

  • Autoflower-Grow-Kalender als CalDAV/ICS-Abo.
  • Rewrite-Route /kalender/{base64-datum}/; CalDAV-Server (GET/HEAD/OPTIONS/PROPFIND), Slug- Decode + checkdate-Validierung, 90-Tage-Ablauf (410).
  • RFC-5545-iCal: All-Day-VEVENTs, 24h-VALARM, Text-Escaping, 75-Oktett-Folding, Europe/Berlin.
  • Statisches Schema (GrowSchedule): ~25 Events, Phasen Vorbereitung→Ernte, Biobizz-Düngung, Ernte-Fenster Tag 70–85 (bewusst beibehalten).
  • Per-Tag-Content-Blöcke infotainment + werbepartner (JSON in wp_options); basis = Event- eigene Beschreibung (die separate basis-Option ist vestigial/ungenutzt).
  • Shortcode [autoflower_calendar] (Datum → URL, Kopieren, Plattform-Tabs); Admin mit 2 Tabs.
  • Moderne Code-Basis: Namespace CannaCal\, declare(strict_types=1), OOP/Singleton.

Was willst du anlegen?

Sorte bewertenGrow starten
Nach oben scrollen