Die Einblendung nimmt die Farbe des Bereichs an, in dem sie steht
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.
This commit is contained in:
+77
-10
@@ -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 <span> 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 <body>, 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?:\/\/[^/]+/, "")} `
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user