File: //tmp/bm_upload_patch.cjs
const fs = require('fs');
function replaceExact(file, from, to) {
let s = fs.readFileSync(file, 'utf8');
if (!s.includes(from)) throw new Error(`Missing expected text in ${file}: ${from.slice(0,120)}`);
s = s.replace(from, to);
fs.writeFileSync(file, s, 'utf8');
}
replaceExact('web/src/modules/photos/UploadPage.jsx',
" const heroPickerLabel = isRateContextEntry ? 'Jetzt Foto aus Galerie wählen' : 'Kamera oder Galerie öffnen';\n const heroPickerSubcopy = isRateContextEntry\n ? 'Erst lokale Vorschau. Keine Anmeldung, kein Upload und keine Veröffentlichung vor deiner Bestätigung.'\n : 'Der Klick öffnet nur den Systemdialog. Kein Upload, keine Veröffentlichung, solange du nicht speicherst.';\n const primaryPickerTitle = isRateContextEntry ? 'Foto aus Galerie wählen · erst nur Vorschau' : 'Foto auswählen · erst nur lokale Vorschau';\n const primaryPickerCta = isRateContextEntry ? 'Foto aus Galerie wählen und privat prüfen' : 'Kamera oder Galerie öffnen und Foto nur vormerken';",
" const heroPickerLabel = isRateContextEntry ? 'Galerie öffnen – Foto bleibt privat' : 'Kamera oder Galerie öffnen';\n const heroPickerSubcopy = isRateContextEntry\n ? 'Ein Tipp öffnet nur deine Fotoauswahl. Du kannst abbrechen; nichts wird übertragen.'\n : 'Ein Tipp öffnet nur den Systemdialog. Du kannst abbrechen; nichts wird übertragen.';\n const primaryPickerTitle = isRateContextEntry ? 'Foto aus Galerie wählen · erst nur Vorschau' : 'Foto auswählen · erst nur lokale Vorschau';\n const primaryPickerCta = isRateContextEntry ? 'Galerie öffnen und Foto nur lokal ansehen' : 'Kamera oder Galerie öffnen und Foto nur vormerken';");
replaceExact('web/src/modules/photos/UploadPage.jsx',
" <div className=\"mt-2 text-xs font-semibold text-white/70\">{heroPickerSubcopy}</div>\n <div className=\"mt-3 flex flex-wrap gap-2 text-sm md:mt-4\">",
" <div className=\"mt-2 text-xs font-semibold text-white/70\">{heroPickerSubcopy}</div>\n <div\n className=\"mt-3 grid gap-2 text-xs font-black text-white/85 sm:grid-cols-3\"\n data-growth-marker=\"upload-first-viewport-click-nudge\"\n >\n <span className=\"rounded-full border border-white/15 bg-white/10 px-3 py-2 text-center\">30 Sekunden bis zur Vorschau</span>\n <span className=\"rounded-full border border-white/15 bg-white/10 px-3 py-2 text-center\">Kein Account vor der Auswahl</span>\n <span className=\"rounded-full border border-white/15 bg-white/10 px-3 py-2 text-center\">Abbrechen bleibt folgenlos</span>\n </div>\n <div className=\"mt-3 flex flex-wrap gap-2 text-sm md:mt-4\">");
const smokeFiles = ['scripts/growth-smoke-check.mjs', 'scripts/growth-journey-smoke-check.mjs'];
for (const file of smokeFiles) {
let s = fs.readFileSync(file, 'utf8');
const anchor = "'upload-file-selection-decision-aid'";
if (!s.includes(anchor)) throw new Error(`Missing smoke anchor in ${file}`);
if (!s.includes("'upload-first-viewport-click-nudge'")) s = s.replace(anchor, `${anchor}, 'upload-first-viewport-click-nudge'`);
s = s.replaceAll("'Jetzt Foto aus Galerie wählen'", "'Galerie öffnen – Foto bleibt privat'");
s = s.replaceAll("'Foto aus Galerie wählen und privat prüfen'", "'Galerie öffnen und Foto nur lokal ansehen'");
if (!s.includes("'Abbrechen bleibt folgenlos'")) {
const titleAnchor = "'Fotoauswahl ohne Grübeln'";
if (!s.includes(titleAnchor)) throw new Error(`Missing title anchor in ${file}`);
s = s.replace(titleAnchor, `${titleAnchor}, 'Abbrechen bleibt folgenlos'`);
}
fs.writeFileSync(file, s, 'utf8');
}