=== JS diff (app.js only, should be sidebar fix + logo badge) === 60a61,66 > } else if (opts.body && typeof opts.body === "object" && > !(opts.body instanceof FormData) && !(opts.body instanceof Blob) && > !(opts.body instanceof URLSearchParams) && !(opts.body instanceof ArrayBuffer)) { > // plain object → JSON body (guards against accidental "[object Object]" sends) > headers["Content-Type"] = "application/json"; > opts.body = JSON.stringify(opts.body); 71,72c77,89 < const detail = data && (data.detail?.message || data.detail || data.error); < const err = new Error(typeof detail === "string" ? detail : (res.status + " " + res.statusText)); --- > let detail = data && (data.detail?.message || data.detail || data.error); > // Pydantic 422: detail is [{loc:[...], msg:'...'}] — surface the msg > if (Array.isArray(detail)) { > detail = detail.map(e => { > let field = Array.isArray(e?.loc) ? e.loc.filter(x => typeof x === "string").join(".") : ""; > field = field.replace(/^body\./, ""); > let msg = e?.msg || String(e); > msg = msg.replace(/^Value error,\s*/i, ""); > return (field ? field + ": " : "") + msg; > }).join("; "); > } > if (detail && typeof detail === "object") detail = JSON.stringify(detail); > const err = new Error(typeof detail === "string" && detail ? detail : (res.status + " " + res.statusText)); 182a200,206 > // The login page has its own full-page layout (no sidebar chrome) even > // for an already-authenticated session that happens to land here. > if (location.pathname.startsWith("/login")) { > if (window.pageBoot) window.pageBoot(me); > return me; > } > 185,186c209,210 < el("span", { class: "brand-badge" }, "M"), < el("span", {}, "Bulk Mailer"))); --- > el("span", { class: "brand-badge", html: 'Ravan Mailer' }), > el("span", { class: "brand-name" }, "Ravan Mailer"))); === CSS diff line count === 106 === confirm no python files touched === Files /tmp/orig_check/bulkmailer/app/api/routers/attachments.py and /workspace/bulkmailer/app/api/routers/attachments.py differ Files /tmp/orig_check/bulkmailer/app/api/routers/auth.py and /workspace/bulkmailer/app/api/routers/auth.py differ Files /tmp/orig_check/bulkmailer/app/api/routers/campaigns.py and /workspace/bulkmailer/app/api/routers/campaigns.py differ Files /tmp/orig_check/bulkmailer/app/api/routers/logs.py and /workspace/bulkmailer/app/api/routers/logs.py differ Files /tmp/orig_check/bulkmailer/app/api/routers/phones.py and /workspace/bulkmailer/app/api/routers/phones.py differ Files /tmp/orig_check/bulkmailer/app/api/routers/subjects.py and /workspace/bulkmailer/app/api/routers/subjects.py differ Files /tmp/orig_check/bulkmailer/app/api/routers/templates.py and /workspace/bulkmailer/app/api/routers/templates.py differ Files /tmp/orig_check/bulkmailer/app/main.py and /workspace/bulkmailer/app/main.py differ Files /tmp/orig_check/bulkmailer/app/services/gmail_service.py and /workspace/bulkmailer/app/services/gmail_service.py differ Files /tmp/orig_check/bulkmailer/app/services/message_builder.py and /workspace/bulkmailer/app/services/message_builder.py differ Files /tmp/orig_check/bulkmailer/app/tasks/send_tasks.py and /workspace/bulkmailer/app/tasks/send_tasks.py differ