diff --git a/src/web-ui/src/app/components/NavPanel/NavPanel.scss b/src/web-ui/src/app/components/NavPanel/NavPanel.scss index e5f59c8b76..f38d9a2490 100644 --- a/src/web-ui/src/app/components/NavPanel/NavPanel.scss +++ b/src/web-ui/src/app/components/NavPanel/NavPanel.scss @@ -1391,10 +1391,14 @@ $_section-header-height: 22px; > svg { flex-shrink: 0; // A line box is split by the font's ascent and descent, not by the glyphs - // drawn in it, so centring the mark on that box leaves its ink about a pixel - // above the text's own ink centre. One pixel, measured in the browser, puts - // the two on one optical centre. - transform: translateY(1px); + // drawn in it, so the mark was once pushed down a pixel to follow the text. + // Measured against the face this row actually renders (HarmonyOS Sans: + // 92.8%/24.4% against a cap ink of 74.5%/1.5%), centring the mark on that box + // already leaves it 0.03em below a caps label's ink centre and 0.05em below a + // Chinese one, and a device name is one of those two. The nudge therefore read + // as the mark sitting low. A mark whose own mass is off-centre still states its + // correction in `deviceSystemMarks`, which moves the drawn mass rather than the + // box. } &:hover, diff --git a/src/web-ui/src/font-profiles/harmony-bundled.css b/src/web-ui/src/font-profiles/harmony-bundled.css index 98a63a3cb3..fc451cea9b 100644 --- a/src/web-ui/src/font-profiles/harmony-bundled.css +++ b/src/web-ui/src/font-profiles/harmony-bundled.css @@ -13,6 +13,34 @@ font-style: normal; font-weight: 400 700; font-display: swap; + /* + * The zh-CN profile puts this face in front of all body text, so it is the face + * Chinese copy is centred by. HarmonyOS Sans splits its line box as 92.8% + * ascent / 24.4% descent, but its ideographs draw from 84.5% above the baseline + * to 7.5% below it, which leaves the box about 0.043em more room under the + * glyphs than over them: a selected line reads as an uneven band and message + * text sits high in its bubble. Splitting the same 117.2% as 97.1% / 20.1% + * moves the shared baseline down by exactly that 0.043em, before the glyphs are + * painted and without touching any box the product lays out. + * + * Keeping the sum is what contains the blast radius. `line-height: normal` and + * `1lh` both resolve to it, and the product sets an explicit numeric leading on + * every other text it lays out, so a line box only follows the split where the + * leading is intrinsic. Chromium on Windows rounds each metric to whole pixels, + * which at 13px, 14px and 20px turns the split into a one pixel `normal` box + * change and a half pixel baseline move; the design system's text overflow + * primitive is the only consumer of that intrinsic leading, and its block + * padding and centred grid absorb the pixel. + * + * The descent is deliberately tighter than the deepest Latin descender (24.5%): + * one reaches 0.044em past the content box, which is the same block padding. + * + * The Latin-first base face above keeps its own metrics: Latin ink brackets that + * split from both sides (lowercase 52%, sentence case 53%, cap labels 73%), so + * shifting it would trade one class of text for the other. + */ + ascent-override: 97.1%; + descent-override: 20.1%; } @font-face {