` elements.");
lines.push("However, if you have **non-image elements** with negative z-index (e.g. `-z-10` on a `` used as a background layer), they may become invisible.");
lines.push("");
lines.push("**Why it breaks:** In TanStack Start/React, section wrappers (``) or parent elements can create");
lines.push("CSS stacking contexts (via `animation`, `transform`, `will-change`, `filter`, `isolation`, etc.).");
lines.push("A child with negative z-index gets trapped inside that stacking context and renders behind the parent's background — making it invisible.");
lines.push("");
lines.push("**How to fix:**");
lines.push("1. Replace `-z-{n}` with `z-0` on the background element");
lines.push("2. Content siblings render on top naturally via DOM order (they come after in the HTML)");
lines.push("3. If needed, add `relative z-10` to content siblings to ensure they stay above");
lines.push("");
lines.push("**How to detect:** Search for remaining negative z-index: `grep -rn '\\-z-' src/ --include='*.tsx'`");
lines.push("");
lines.push("### Opacity utility classes");
lines.push("");
lines.push("Tailwind v4 removed `bg-opacity-{n}`, `text-opacity-{n}`, etc. The script converts them to");
lines.push("the modifier syntax (e.g. `bg-black bg-opacity-20` → `bg-black/20`). If a color and its opacity");
lines.push("are not in the same className string (e.g. set via different conditional branches), the script");
lines.push("flags them for manual review.");
lines.push("");
lines.push("**How to detect:** `grep -rn 'opacity-' src/ --include='*.tsx'`");
lines.push("");
// Framework findings
lines.push("## Framework Findings");
lines.push("");
lines.push(
"> These are patterns found during migration that should eventually be handled by `@decocms/blocks` instead of being duplicated in every site.",
);
lines.push("");
for (const finding of ctx.frameworkFindings) {
lines.push(`- ${finding}`);
}
lines.push("");
// Next steps
lines.push("## Next Steps");
lines.push("");
lines.push("```bash");
lines.push("# 1. Install dependencies (bun is the canonical PM)");
lines.push("bun install");
lines.push("");
lines.push("# 2. Generate CMS artifacts (blocks, sections, loaders, schema)");
lines.push("bun run generate");
lines.push("");
lines.push("# 3. Generate routes");
lines.push("bunx tsr generate");
lines.push("");
lines.push("# 4. Type check");
lines.push("bunx tsc --noEmit");
lines.push("");
lines.push("# 5. Find unused code");
lines.push("bun run knip");
lines.push("");
lines.push("# 6. Run dev server");
lines.push("npm run dev");
lines.push("");
lines.push("# 7. (Once wrangler.jsonc is wired) enable CF-native observability");
lines.push("# Adds the canonical `observability` block to wrangler.jsonc so the");
lines.push("# Cloudflare runtime captures console.* logs and auto-instrumented");
lines.push("# traces directly into the CF dashboard (Workers & Pages -> ");
lines.push("# -> Observability). No external destination required — the CF");
lines.push("# dashboard is the destination.");
lines.push("#");
lines.push("# Forwarding to a future ClickHouse-backed OTel collector is on the");
lines.push("# roadmap (placeholder lives at");
lines.push("# @decocms/blocks/sdk/otelAdapters/clickhouseCollector); when it");
lines.push("# ships, the codemod gains a `--destination-logs` /");
lines.push("# `--destination-traces` flag to point at it.");
lines.push("npx -p @decocms/blocks-cli deco-cf-observability # dry-run");
lines.push("npx -p @decocms/blocks-cli deco-cf-observability --write # apply");
lines.push("```");
lines.push("");
const content = lines.join("\n");
if (ctx.dryRun) {
console.log("\n" + content);
} else {
const reportPath = path.join(ctx.sourceDir, "MIGRATION_REPORT.md");
fs.writeFileSync(reportPath, content, "utf-8");
console.log(` Report written to MIGRATION_REPORT.md`);
}
// Print summary to console
console.log(`\n === Migration ${ctx.dryRun ? "(DRY RUN)" : "COMPLETE"} ===`);
console.log(` Scaffolded: ${ctx.scaffoldedFiles.length}`);
console.log(` Transformed: ${ctx.transformedFiles.length}`);
console.log(` Deleted: ${ctx.deletedFiles.length}`);
console.log(` Moved: ${ctx.movedFiles.length}`);
console.log(` Manual review: ${ctx.manualReviewItems.length}`);
}