diff --git a/server/pruef-kalender.mjs b/server/pruef-kalender.mjs
index 516d49ac..fd4f4e30 100644
--- a/server/pruef-kalender.mjs
+++ b/server/pruef-kalender.mjs
@@ -197,7 +197,27 @@ const lesen = (seite) => seite.evaluate(() => ({
/* Eintraege */
pillen: [...document.querySelectorAll(".k-pille")].map((p) => ({
text: p.textContent,
- farbe: getComputedStyle(p).borderLeftColor,
+ /* DIE KENNUNG IST DER TITEL-TEXT, nicht der sichtbare Text: Bei
+ einem Zeitraum steht im sichtbaren Text "Tag 3/5 ..." und er ist
+ abgeschnitten.
+
+ DER `title` GEHT AUCH NICHT: Er endet bei einem Zeitraum mit
+ "(Tag 3 von 5)" und ist damit an jedem Tag ein anderer -- der
+ erste Versuch zaehlte deshalb weiter 14 statt 10.
+
+ Der VERWEIS bleibt gleich: `bereich.html?b=live&zeigen=eintrag-7`
+ zeigt an jedem der fuenf Tage auf denselben Eintrag. Wo es
+ keinen gibt (Fristen, Calls), tut es der Titel -- die sind immer
+ eintaegig. */
+ kennung: p.getAttribute("href") || p.title || p.textContent,
+ spanne: p.dataset.spanne || null,
+ /* DIE FARBE KOMMT AUS `--pfarbe`, NICHT AUS DER LINKEN KANTE.
+ Die Kante ist eine Darstellung und faellt weg, wo die Pille ein
+ Punkt ist (Handy) -- dann meldete diese Pruefung "1 Farbe" und
+ sah aus wie ein Befund am Kalender. Die Eigenschaft dagegen
+ steht auf jeder Pille, in jeder Ansicht. */
+ farbe: p.style.getPropertyValue("--pfarbe").trim()
+ || getComputedStyle(p).borderLeftColor,
brett: p.querySelector(".k-pille__brett")?.textContent || null,
zugesagt: !!p.querySelector('.k-pille__zusage'),
})),
@@ -258,9 +278,22 @@ for (const [breite, wie] of [[1440, "Computer"], [390, "Handy"]]) {
ok(r.heuteZellen === 1, `genau ein Tag ist "heute" (${r.heuteZellen})`);
ok(r.fremdZellen > 0, `die Nachbarmonatstage sind erkennbar (${r.fremdZellen})`);
- /* ---- Eintraege im Raster ---- */
- ok(r.pillen.length === ERWARTET.pillen,
- `alle ${ERWARTET.pillen} Einträge stehen im Raster (${r.pillen.length})`);
+ /* ---- Eintraege im Raster ----
+
+ EIN EINTRAG, NICHT EINE MARKE (berichtigt 21.09.2026).
+
+ Seit ein Termin von-bis ueber die ganze Spanne markiert wird
+ (Filipes Wunsch vom 21.09.), setzt ein Eintrag ueber fuenf Tage
+ auch FUENF Marken ins Raster. Diese Zeile zaehlte Marken und
+ meldete deshalb 14 statt 10 -- ohne dass am Kalender etwas kaputt
+ war. Dieselbe Falle wie eine feste Zahl, nur eine Ebene tiefer:
+ nicht die Erwartung war veraltet, sondern das, was gemessen wurde.
+
+ `kennung` ist fuer alle Tage desselben Eintrags gleich. */
+ const eintraege = (liste) => new Set(liste.map((x) => x.kennung)).size;
+ ok(eintraege(r.pillen) === ERWARTET.pillen,
+ `alle ${ERWARTET.pillen} Einträge stehen im Raster `
+ + `(${eintraege(r.pillen)} Einträge in ${r.pillen.length} Marken)`);
ok(r.pillen.some((p) => p.text.includes("Wochen-Call")), "der Call ist dabei");
ok(r.pillen.some((p) => p.text.includes("Thumbnail bauen")), "die Frist aus den Aufgaben auch");
/* Jede Art traegt ihre eigene Farbe. Zwei Calls, ein Termin, ein
@@ -291,8 +324,9 @@ for (const [breite, wie] of [[1440, "Computer"], [390, "Handy"]]) {
await seite.click('.k-chip:has-text("Call")');
await seite.waitForTimeout(250);
const nachFilter = await lesen(seite);
- ok(nachFilter.pillen.length === ERWARTET.ohneCalls,
- `Calls ausgeschaltet: ${ERWARTET.ohneCalls} Einträge übrig (${nachFilter.pillen.length})`);
+ ok(eintraege(nachFilter.pillen) === ERWARTET.ohneCalls,
+ `Calls ausgeschaltet: ${ERWARTET.ohneCalls} Einträge übrig `
+ + `(${eintraege(nachFilter.pillen)})`);
ok(new RegExp(`· ${ERWARTET.ohneCalls} Einträge`).test(nachFilter.unter),
`und die Kopfzeile zählt neu ("${nachFilter.unter}")`);
await seite.click('.k-chip:has-text("Call")');
@@ -704,6 +738,134 @@ console.log("\n=== Die gerechneten Tage");
}
}
+
+/* =======================================================================
+ AM HANDY WIRD AUS EINER PILLE EIN PUNKT
+ =======================================================================
+
+ Eine Monatszelle ist am Handy 42-49 px breit. Abzueglich Zellen- und
+ Pillenrand bleiben 16-23 px fuer Text -- anderthalb Buchstaben und
+ drei Punkte. "Content-Ideen sammeln" wurde zu "C…".
+
+ Seit dem 21.09.2026 wird daraus ein Punkt: Man sieht, DASS an dem
+ Tag etwas ist und wie viel, und tippt den Tag an, um zu lesen, was.
+ Ein Zeitraum bleibt ein durchgehender Balken -- sonst ginge genau
+ das verloren, wofuer er gebaut wurde.
+
+ WAS HIER GEMESSEN WIRD, und warum gerade das: Die Groesse allein
+ genuegt NICHT. Beim Bauen war die Pille bereits 8 x 8 gross und trug
+ trotzdem ihren Titel quer ueber die Nachbarzellen -- weil eine
+ Sammelregel aus start.css die Schriftgroesse zurueckholte. Die
+ Zahlen sagten "alles gut", das Bildschirmfoto sagte das Gegenteil.
+ Deshalb wird hier beides gefragt: die Groesse UND ob irgendetwas
+ ueber den Rand der Zelle hinausragt.
+ ======================================================================= */
+console.log("\n=== Am Handy wird aus einer Pille ein Punkt");
+{
+ const kPunkt = await browser.newContext({ viewport: { width: 390, height: 1100 } });
+ const sPunkt = await anmelden(kPunkt, "admin", "CODE-DOGI-0001");
+ try {
+ await sPunkt.goto(BASIS + "/workspace/kalender.html", { waitUntil: "networkidle" });
+ await sPunkt.waitForTimeout(900);
+
+ const lage = await sPunkt.evaluate(() => {
+ const raster = document.querySelector(".k-raster");
+ if (!raster) return null;
+ const zellen = [...document.querySelectorAll(".k-tag")];
+ const pillen = [...document.querySelectorAll(".k-tag .k-pille")];
+ const punkte = pillen.filter((p) => !p.dataset.spanne);
+ const balken = pillen.filter((p) => p.dataset.spanne);
+
+ /* RAGT IRGENDETWAS UEBER SEINE ZELLE HINAUS? Das ist die Frage,
+ an der es beim Bauen haengengeblieben ist. Zwei Pixel Luft --
+ Raender und Rundungen. */
+ const raus = [];
+ for (const z of zellen) {
+ const rz = z.getBoundingClientRect();
+ for (const e of z.querySelectorAll("*")) {
+ const r = e.getBoundingClientRect();
+ if (r.width < 1) continue;
+ if (r.right > rz.right + 2) {
+ raus.push(`${e.className}: ${Math.round(r.right - rz.right)}px ueber den Rand`);
+ }
+ }
+ }
+
+ const masse = (liste) => liste.map((p) => {
+ const r = p.getBoundingClientRect();
+ return { b: Math.round(r.width), h: Math.round(r.height),
+ zeiger: getComputedStyle(p).pointerEvents,
+ schrift: getComputedStyle(p).fontSize };
+ });
+
+ return {
+ raster: Math.round(raster.getBoundingClientRect().width),
+ zelle: zellen[0] ? Math.round(zellen[0].getBoundingClientRect().width) : 0,
+ punkte: masse(punkte), balken: masse(balken),
+ raus: raus.slice(0, 5),
+ /* Die Zelle muss antippbar bleiben -- der Punkt ist es nicht,
+ also muss es jemand sein. */
+ zelleKnopf: zellen.filter((z) => z.getAttribute("role") === "button").length,
+ zellen: zellen.length,
+ };
+ });
+
+ ok(!!lage, "das Monatsraster steht am Handy");
+ if (lage) {
+ console.log(` Raster ${lage.raster}px, Zelle ${lage.zelle}px, `
+ + `${lage.punkte.length} Punkte, ${lage.balken.length} Balken`);
+
+ /* DIE ZAHL GEHOERT IN DIE BEDINGUNG: Ohne Eintraege waere unten
+ alles gruen und nichts geprueft. */
+ ok(lage.punkte.length > 0,
+ `es gibt ueberhaupt Eintraege zu messen (${lage.punkte.length})`);
+ ok(lage.punkte.every((p) => p.b <= 12 && p.h <= 12),
+ `jeder Termin ist ein Punkt (${lage.punkte.map((p) => p.b + "x" + p.h).join(", ")})`);
+ ok(lage.punkte.every((p) => p.schrift === "0px"),
+ `und traegt keinen Text mehr (${[...new Set(lage.punkte.map((p) => p.schrift))].join(", ")})`);
+ ok(lage.punkte.every((p) => p.zeiger === "none"),
+ "ein 8-px-Punkt ist nicht einzeln antippbar -- der Tipp gehoert der Zelle");
+ ok(lage.zelleKnopf === lage.zellen,
+ `und jede Zelle IST antippbar (${lage.zelleKnopf} von ${lage.zellen})`);
+
+ /* DER EIGENTLICHE BEFUND VON DAMALS. */
+ ok(lage.raus.length === 0, lage.raus.length === 0
+ ? "nichts ragt ueber den Rand seiner Zelle hinaus"
+ : `ragt hinaus: ${lage.raus.join(" | ")}`);
+
+ /* Ein Zeitraum bleibt ein Balken -- breiter als ein Punkt. */
+ if (lage.balken.length) {
+ ok(lage.balken.every((b) => b.b > 12),
+ `ein Zeitraum bleibt ein durchgehender Balken (${lage.balken.map((b) => b.b + "px").join(", ")})`);
+ }
+ }
+
+ /* GEGENPROBE: Das Raster breiter machen, bis die Abfrage nicht mehr
+ greift -- dann muessen die Punkte wieder zu Pillen mit Text
+ werden. Ohne das waere oben nur bewiesen, dass es IRGENDEINE
+ Regel gibt, nicht dass sie an der Breite haengt. */
+ const gegen = await sPunkt.evaluate(() => {
+ const raster = document.querySelector(".k-raster");
+ if (!raster) return null;
+ const vorher = raster.style.width;
+ raster.style.width = "1200px";
+ /* Layout erzwingen, sonst misst man den Stand von davor. */
+ void raster.offsetWidth;
+ const p = document.querySelector(".k-tag .k-pille");
+ const st = p ? getComputedStyle(p) : null;
+ const aus = st ? { schrift: st.fontSize, zeiger: st.pointerEvents,
+ breite: Math.round(p.getBoundingClientRect().width) } : null;
+ raster.style.width = vorher;
+ return aus;
+ });
+ ok(gegen && gegen.schrift !== "0px" && gegen.zeiger === "auto",
+ `bei breitem Raster steht der Titel wieder da `
+ + `(${gegen ? gegen.schrift + ", " + gegen.breite + "px, " + gegen.zeiger : "nicht messbar"})`);
+ } finally {
+ await kPunkt.close();
+ }
+}
+
await browser.close();
/* Der Testordner bleibt manchmal gesperrt, weil der Server im selben
Prozess noch auf der Datenbank sitzt. Das ist kein Prüfergebnis --
diff --git a/workspace/anruf-probe.html b/workspace/anruf-probe.html
index e68ac40c..afe6f0d8 100644
--- a/workspace/anruf-probe.html
+++ b/workspace/anruf-probe.html
@@ -16,15 +16,15 @@
verdeckt. Gefunden hat es pruef-struktur.
Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. -->
-
-
+
+
-
+