From 6261d548d0b138f52e35057a373cf001ececa74d Mon Sep 17 00:00:00 2001 From: Dogfather Date: Sun, 27 Sep 2026 19:37:06 +0200 Subject: [PATCH] Die Einblendung nimmt die Farbe des Bereichs an, in dem sie steht MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Filipe, 27.09.2026: „nimm dann doch die seiten vom community bereich ne?" Er hatte recht, und es war derselbe Fehler noch einmal. Beim ersten Mal stand die Buehne in einer Farbe aus einem fremden Bereich (#9cde90, die Notizen-Kachel aus dem Team). Beim zweiten Mal stand sie in EINER Farbe fuer alles -- und jeder Bereich des Treffs hat seine eigene: Rudel-Chat #5499ff Wunschliste #abff96 Highlights #f60684 Dogi-Media #918a01 Anschlagbrett #ffabff Mitmachen #577ecc Was ansteht #2dc9ba Unterstuetzen #e76006 Ein Video ueber Dogi-Media mit violetten Einblendungen sind zwei Sachen nebeneinander. Mit der Farbe des Bereichs ist es eine. ABGELESEN, NICHT ABGESCHRIEBEN Die Buehne fragt nach jedem Seitenwechsel `getComputedStyle(document.body).--ton` -- genau den Wert, den die Seite selbst benutzt. Eine Liste hier waere eine zweite Wahrheit, die irgendwann von der ersten abweicht; tools/treff-farben.mjs liest dieselben zwei Quellen (workspace.js fuer die Nummer, start.css fuer den Farbwert), wenn man sie nachsehen will. AUFGEHELLT, BIS ES LESBAR IST #918a01 ist als Flaeche schoen und als Schrift auf dunklem Grund unlesbar (1,9:1). Die Buehne mischt Weiss dazu, bis 4,5:1 erreicht sind -- dieselbe Rechnung wie bei den Namen im Chat. Balken, Schein und Vorhang bekommen den rohen Ton, die brauchen keinen Kontrast. DER ABSPANN BLEIBT MARKE Er ist in allen vier Videos derselbe und faellt deshalb auf --violett/--akzent zurueck, egal auf welcher Seite er steht. Wer drei Videos gesehen hat, soll den vierten am Schluss wiedererkennen. UND EIN EIGENER FEHLER, GEMESSEN STATT UEBERSEHEN Das Ablesen stand zuerst in `auf()` -- und `auf()` laeuft vor jeder Karte, jedem Untertitel und jedem Rollen. Ueber hundert zusaetzliche Wege in den Browser fuer eine Antwort, die sich nur beim Seitenwechsel aendern kann. Video 1 wuchs dadurch von 32,9 auf 36,1 s. Jetzt wird beim Seitenwechsel gelesen: 32,0 s. Alle vier neu gedreht: 24 bis 34 s, 1080x1920. --- server/tiktok-videos.mjs | 87 +++++++++++++++++++++++++++++++++++----- tools/treff-farben.mjs | 36 +++++++++++++++++ 2 files changed, 113 insertions(+), 10 deletions(-) create mode 100644 tools/treff-farben.mjs diff --git a/server/tiktok-videos.mjs b/server/tiktok-videos.mjs index 1d6fbac8..b83be982 100644 --- a/server/tiktok-videos.mjs +++ b/server/tiktok-videos.mjs @@ -561,7 +561,14 @@ function BUEHNE(blendeZu) { + "filter='url(%23n)'/%3E%3C/svg%3E\")"; const css = [ - '#tk-buehne{position:fixed;inset:0;z-index:2147483000;pointer-events:none;', + /* Zwei Regler: `--tk-ton` ist die rohe Bereichsfarbe (Balken, + Schein, Vorhang), `--tk-ton-text` dieselbe Farbe so weit + aufgehellt, dass man sie LESEN kann. Vorgabe sind die + Hausfarben -- solange keine Seite geladen ist, gibt es keinen + Bereich, dessen Farbe man nehmen koennte. */ + '#tk-buehne{--tk-ton:' + VIOLETT + ';--tk-ton-text:' + VIOLETT + ';', + ' --tk-hell:' + AKZENT + ';', + ' position:fixed;inset:0;z-index:2147483000;pointer-events:none;', ' font-family:"Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif;', ' -webkit-font-smoothing:antialiased}', @@ -594,11 +601,11 @@ function BUEHNE(blendeZu) { zwei Striche, ein Wort dazwischen, weit gesperrt. */ '#tk-karte .kicker{display:flex;align-items:center;justify-content:center;gap:9px;', ' font-size:9px;font-weight:700;letter-spacing:.38em;text-transform:uppercase;', - ' color:' + VIOLETT + ';opacity:0;transform:translateY(10px);', + ' color:var(--tk-ton-text);opacity:0;transform:translateY(10px);', ' transition:opacity .42s ease .04s,transform .42s cubic-bezier(.16,.8,.3,1) .04s}', '#tk-karte .kicker i{display:block;width:22px;height:1px;', - ' background:linear-gradient(90deg,rgba(169,139,255,0),' + VIOLETT + ')}', - '#tk-karte .kicker i + i{background:linear-gradient(90deg,' + VIOLETT + ',rgba(169,139,255,0))}', + ' background:linear-gradient(90deg,transparent,var(--tk-ton-text))}', + '#tk-karte .kicker i + i{background:linear-gradient(90deg,var(--tk-ton-text),transparent)}', '#tk-karte.an .kicker{opacity:.92;transform:none}', /* `text-wrap: balance` verteilt die Woerter selbst auf die Zeilen. @@ -614,8 +621,8 @@ function BUEHNE(blendeZu) { /* Wenig Schein, dafuer ein enger dunkler Schatten: Ein breiter Schein frisst die Kanten der Buchstaben, und im Video wird daraus Matsch. */ - '#tk-karte p b{color:' + AKZENT + ';font-weight:800;', - ' text-shadow:0 1px 2px rgba(3,2,8,.85),0 0 16px rgba(142,201,255,.30)}', + '#tk-karte p b{color:var(--tk-ton-text);font-weight:800;', + ' text-shadow:0 1px 2px rgba(3,2,8,.85)}', /* Der Abspann bekommt mehr Gewicht als die Zwischenkarten: Er ist das Einzige, was der Mensch danach noch tun soll. */ @@ -623,6 +630,11 @@ function BUEHNE(blendeZu) { ' radial-gradient(100% 52% at 50% 6%, rgba(169,139,255,.36), rgba(0,0,0,0) 66%),', ' radial-gradient(130% 62% at 50% 94%, rgba(142,201,255,.22), rgba(0,0,0,0) 64%),', ' linear-gradient(180deg,#120e27 0%,#0a0817 56%,#050409 100%)}', + /* Der Abspann ist in allen vier Videos derselbe und soll auch so + aussehen -- er faellt deshalb auf die Hausfarben zurueck, egal + auf welcher Seite er steht. */ + '#tk-karte.ende{--tk-ton-text:' + AKZENT + '}', + '#tk-karte.ende .kicker{color:' + VIOLETT + '}', '#tk-karte.ende p{font-size:32px}', /* `display:block` ist nicht Zierde: Ein ist inline, und dort gelten Hoehe, Breite und margin:auto nicht. Der Strich war @@ -645,10 +657,11 @@ function BUEHNE(blendeZu) { '#tk-satz span{display:flex;align-items:stretch;gap:11px;', ' background:rgba(10,8,22,.80);backdrop-filter:blur(14px) saturate(1.25);', ' -webkit-backdrop-filter:blur(14px) saturate(1.25);', - ' border:1px solid rgba(169,139,255,.26);border-radius:15px;padding:11px 14px;', + ' border:1px solid color-mix(in srgb,var(--tk-ton) 34%,transparent);', + ' border-radius:15px;padding:11px 14px;', ' box-shadow:0 20px 44px -20px #000,inset 0 1px 0 rgba(255,255,255,.07)}', '#tk-satz i{flex:none;width:3px;border-radius:3px;', - ' background:linear-gradient(180deg,' + VIOLETT + ',' + AKZENT + ')}', + ' background:linear-gradient(180deg,var(--tk-ton),var(--tk-hell))}', '#tk-satz em{font-style:normal;font-weight:700;font-size:19px;line-height:1.32;', ' letter-spacing:-.006em;color:#ece8fa}', @@ -658,7 +671,8 @@ function BUEHNE(blendeZu) { fertigen Video -- das sieht nach Bildschirmaufnahme aus und nicht nach Film. */ '#tk-blende{position:absolute;inset:0;transform:translateY(102%);', - ' background:linear-gradient(180deg,' + VIOLETT + ' 0%,#4b3fa8 34%,#0b0918 78%,' + TINTE + ' 100%)}', + ' background:linear-gradient(180deg,var(--tk-ton) 0%,', + ' color-mix(in srgb,var(--tk-ton) 45%,#0b0918) 34%,#0b0918 78%,' + TINTE + ' 100%)}', '#tk-blende.zu{transform:translateY(0);', ' transition:transform .34s cubic-bezier(.66,0,.34,1)}', '#tk-blende.auf{transform:translateY(-102%);', @@ -773,15 +787,67 @@ function buehneFuer(seite) { was sie zudecken sollte. Der Zustand lebt deshalb hier und nicht im Browser. */ let vorhangZu = false; + + /* Die Bereichsfarbe wird ABGELESEN, nicht gefuehrt: Jede Seite des + Treffs setzt `--ton` auf ihrem , und genau dieser Wert geht + an die Buehne. Eine Liste hier waere eine zweite Wahrheit, die + irgendwann von der ersten abweicht. */ + const TON_LESEN = () => { + const b = document.getElementById("tk-buehne"); + if (!b) return null; + const roh = getComputedStyle(document.body).getPropertyValue("--ton").trim(); + if (!/^#[0-9a-f]{6}$/i.test(roh)) return null; + + /* Aufhellen, bis man es lesen kann -- dieselbe Rechnung wie bei + den Namen im Chat. #918a01 (Dogi-Media) kommt als Schrift auf + dunklem Grund sonst auf 1,9:1. */ + const teile = (h) => [1, 3, 5].map((i) => parseInt(h.substr(i, 2), 16) / 255); + const gerade = (c) => (c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)); + const leucht = (v) => 0.2126 * gerade(v[0]) + 0.7152 * gerade(v[1]) + 0.0722 * gerade(v[2]); + const abstand = (x, y) => { + const a = leucht(x); const b2 = leucht(y); + const hoch = Math.max(a, b2); const tief = Math.min(a, b2); + return (hoch + 0.05) / (tief + 0.05); + }; + const grund = [0.043, 0.035, 0.094]; /* #0b0918 */ + const f = teile(roh); + let text = "#f1edff"; + for (let t = 0; t <= 0.92; t += 0.04) { + const m = f.map((c) => c + (1 - c) * t); + if (abstand(m, grund) >= 4.5) { + text = "rgb(" + m.map((c) => Math.round(c * 255)).join(",") + ")"; + break; + } + } + b.style.setProperty("--tk-ton", roh); + b.style.setProperty("--tk-ton-text", text); + b.style.setProperty("--tk-hell", text); + return roh; + }; + + /* DIE FARBE WIRD BEIM SEITENWECHSEL GELESEN, NICHT BEI JEDEM + HANDGRIFF (27.09.2026). + + Erst stand das Ablesen in `auf()` -- und `auf()` laeuft vor jeder + Karte, jedem Untertitel und jedem Rollen. Das waren ueber + hundert zusaetzliche Wege in den Browser und drei Sekunden mehr + je Video, fuer eine Antwort, die sich nur beim Seitenwechsel + aendern kann. Gemessen: Video 1 wuchs von 32,9 auf 36,1 s. */ const auf = () => seite.evaluate(BUEHNE, vorhangZu); + const tonLesen = () => seite.evaluate(TON_LESEN).catch(() => null); /* Der Wiederaufbau haengt hier und nicht beim Aufrufer: Er braucht `vorhangZu`, und ein Zustand, den zwei Stellen fuehren, laeuft auseinander. */ - seite.on("load", () => { seite.evaluate(BUEHNE, vorhangZu).catch(() => {}); }); + seite.on("load", () => { + seite.evaluate(BUEHNE, vorhangZu) + .then(() => seite.evaluate(TON_LESEN)) + .catch(() => {}); + }); return { auf, + tonLesen, /** Vorhang zu. Danach darf navigiert werden. */ async zu(ms = 380) { @@ -1100,6 +1166,7 @@ for (const nr of liste) { es kurz still -- 450 ms reichten nicht, der Vorhang ging in dieser Stille auf. Kommt der Hinweis doch noch, faengt die Uhr von vorn an. */ + await b.tonLesen(); const still = await ruhig(seite); if (!still) { console.warn(` Hinweis: ${String(a[0]).replace(/^https?:\/\/[^/]+/, "")} ` diff --git a/tools/treff-farben.mjs b/tools/treff-farben.mjs new file mode 100644 index 00000000..c30d657c --- /dev/null +++ b/tools/treff-farben.mjs @@ -0,0 +1,36 @@ +/* Welche Farbe traegt jede Kachel des Community-Bereichs? + * + * Gelesen wird aus den zwei Stellen, die es wirklich entscheiden: + * workspace.js sagt, welche TON-NUMMER eine Kachel hat, start.css + * sagt, welcher Farbwert hinter der Nummer steht. Abgeschrieben wird + * nichts -- eine Liste, die niemand pflegt, kann nicht veralten. + * + * node tools/treff-farben.mjs + */ +import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import { dirname, join } from "node:path"; + +const HIER = dirname(fileURLToPath(import.meta.url)); +const js = readFileSync(join(HIER, "..", "server", "workspace.js"), "utf8"); +const css = readFileSync(join(HIER, "..", "workspace", "assets", "css", "start.css"), "utf8"); + +const hex = new Map(); +for (const m of css.matchAll(/\[data-ton="(\d+)"\]\s*\{\s*--ton:\s*(#[0-9a-fA-F]{6})/g)) { + hex.set(m[1], m[2]); +} + +/* Die Kacheln des Treffs stehen alle mit `...TREFF_GRUPPE` davor -- + daran sind sie erkennbar, ohne sie einzeln aufzuzaehlen. */ +const treffer = [...js.matchAll( + /\.\.\.TREFF_GRUPPE,\s*name:\s*"([^"]+)"[\s\S]{0,400}?ton:\s*(\d+)/g)]; + +console.log("KACHEL TON FARBE"); +for (const [, name, ton] of treffer) { + console.log(name.padEnd(20) + String(ton).padEnd(6) + (hex.get(ton) || "?")); +} +console.log("\n" + treffer.length + " Kacheln im Community-Bereich gefunden."); +if (!treffer.length) { + console.error("KEINE gefunden -- die Erkennung passt nicht mehr zum Quelltext."); + process.exit(1); +}