diff --git a/apps/web/src/styles/editor-typography.test.mjs b/apps/web/src/styles/editor-typography.test.mjs index e015399a..08ab3f57 100644 --- a/apps/web/src/styles/editor-typography.test.mjs +++ b/apps/web/src/styles/editor-typography.test.mjs @@ -46,12 +46,28 @@ describe("editor typography contract", () => { expect(placeholderRules).toMatch(/line-height\s*:\s*inherit/); }); - test("keeps bold text visibly distinct across platform font fallbacks", () => { + test("keeps bold and italic text visible across platform font fallbacks", () => { const globals = readStyle("./globals.css"); + const mobileEditor = readStyle("./mobile-markdown-editor.css"); const defaultBoldRules = declarationsForSelector(globals, ".ProseMirror strong"); + const defaultItalicRules = declarationsForSelector(globals, ".ProseMirror em"); + const mobileBoldRules = declarationsForSelector( + mobileEditor, + ".edgeever-mobile-tiptap-content strong", + ); + const mobileItalicRules = declarationsForSelector( + mobileEditor, + ".edgeever-mobile-tiptap-content em", + ); - expect(defaultBoldRules).toMatch(/font-synthesis\s*:\s*weight/); + expect(defaultBoldRules).toMatch(/font-synthesis\s*:\s*weight style/); expect(defaultBoldRules).toMatch(/font-weight\s*:\s*800/); + expect(defaultItalicRules).toMatch(/font-synthesis\s*:\s*weight style/); + expect(defaultItalicRules).toMatch(/font-style\s*:\s*italic/); + expect(mobileBoldRules).toMatch(/font-synthesis\s*:\s*weight style/); + expect(mobileBoldRules).toMatch(/font-weight\s*:\s*800/); + expect(mobileItalicRules).toMatch(/font-synthesis\s*:\s*weight style/); + expect(mobileItalicRules).toMatch(/font-style\s*:\s*italic/); for (const filename of PRESET_THEME_FILES) { const source = readStyle(`./editor-themes/${filename}`); diff --git a/apps/web/src/styles/globals.css b/apps/web/src/styles/globals.css index 1777212d..f3575d85 100644 --- a/apps/web/src/styles/globals.css +++ b/apps/web/src/styles/globals.css @@ -601,15 +601,22 @@ textarea { padding: 0; } -/* Do not rely on the browser's relative `bolder` mapping here. Linux Chrome - * can render CJK fallback fonts with too little contrast between regular and - * bold, especially when the installed family has no matching bold face. */ +/* The root deliberately disables synthetic font faces for the application UI, + * but rich-text emphasis must remain visible when a platform fallback font has + * no matching bold or italic face. Allow both forms here so nested bold-italic + * marks work regardless of their DOM order. */ .ProseMirror strong, .ProseMirror b { - font-synthesis: weight; + font-synthesis: weight style; font-weight: 800; } +.ProseMirror em, +.ProseMirror i { + font-synthesis: weight style; + font-style: italic; +} + /* External hyperlinks (default theme). * Tailwind preflight resets to inherit color/decoration, so without this * rule links are indistinguishable from body text. Note/attachment chips below diff --git a/apps/web/src/styles/mobile-markdown-editor.css b/apps/web/src/styles/mobile-markdown-editor.css index 727d6f7e..6510ca4f 100644 --- a/apps/web/src/styles/mobile-markdown-editor.css +++ b/apps/web/src/styles/mobile-markdown-editor.css @@ -483,6 +483,20 @@ input { white-space: pre-wrap; } +/* Keep semantic emphasis visible even though the standalone shell disables + * synthetic font faces globally. Both values preserve nested bold-italic text. */ +.edgeever-mobile-tiptap-content strong, +.edgeever-mobile-tiptap-content b { + font-synthesis: weight style; + font-weight: 800; +} + +.edgeever-mobile-tiptap-content em, +.edgeever-mobile-tiptap-content i { + font-synthesis: weight style; + font-style: italic; +} + /* External hyperlinks — match desktop default ProseMirror link styling. */ .edgeever-mobile-tiptap-content a { color: #00751f;