diff --git a/library/composables/useDocumentFont.js b/library/composables/useDocumentFont.js index 86c3e07d2..916ee0963 100644 --- a/library/composables/useDocumentFont.js +++ b/library/composables/useDocumentFont.js @@ -101,3 +101,28 @@ export const POPPINS_FACES = [ { weight: '700', src: 'fonts/poppins/poppins-700-latin.woff2', unicodeRange: POPPINS_LATIN }, { weight: '700', src: 'fonts/poppins/poppins-700-latin-ext.woff2', unicodeRange: POPPINS_LATIN_EXT }, ] + +// Oswald, as DX-life serves it for CYRILLIC HEADINGS. base/_globals.scss:35-44 switches every +// h1/h2/h3 to --font-family-cyrillic under [lang="ru-RU"], because Bebas Neue has no Cyrillic +// glyphs at all — without the switch a Russian heading leaves the family entirely. Google's own +// unicode-range values (css2 v57), carried verbatim so only the needed subset is fetched; latin and +// latin-ext are included because a Russian heading routinely contains Latin characters and a +// Cyrillic-only face would drop those back to the fallback mid-word. +export const OSWALD_FACES = [ + { + src: 'fonts/oswald/oswald-400-cyrillic.woff2', + unicodeRange: 'U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116', + }, + { + src: 'fonts/oswald/oswald-400-cyrillic-ext.woff2', + unicodeRange: 'U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F', + }, + { + src: 'fonts/oswald/oswald-400-latin.woff2', + unicodeRange: 'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD', + }, + { + src: 'fonts/oswald/oswald-400-latin-ext.woff2', + unicodeRange: 'U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF', + }, +] diff --git a/plugin-designs/regions-dashboard/region-dashboards.vue b/plugin-designs/regions-dashboard/region-dashboards.vue index 06105fce0..3f18b3998 100644 --- a/plugin-designs/regions-dashboard/region-dashboards.vue +++ b/plugin-designs/regions-dashboard/region-dashboards.vue @@ -28,7 +28,7 @@ import { useShadowStyles } from '@map/composables/useShadowStyles.js' // house pattern (doxa-simple-map.vue:18, :246, :1346) — an EMBEDDED element must not reach for // document.documentElement.dir, which belongs to the host page. import { RTL_LOCALES } from '@map/i18n/index.js' -import { useDocumentFont, BEBAS_NEUE_FACES, POPPINS_FACES, FIGTREE_FACES } from '@map/composables/useDocumentFont.js' +import { useDocumentFont, BEBAS_NEUE_FACES, POPPINS_FACES, FIGTREE_FACES, OSWALD_FACES } from '@map/composables/useDocumentFont.js' import FilterDropdown from '@map/components/search/FilterDropdown.vue' import UupgsList from './src/UupgsList.vue' // Their strings, via their own English keys (see src/useRegionsI18n.js). The goal sentences, @@ -105,6 +105,12 @@ useDocumentFont('Poppins', POPPINS_FACES, assetsBase.value) // giveaway (Driver, 2026-09-24). @font-face is DOCUMENT-scoped, so it registers here beside // the other two rather than inside the shadow root that uses it. useDocumentFont('Figtree', FIGTREE_FACES, assetsBase.value) +// Oswald, for CYRILLIC HEADINGS ONLY. base/_globals.scss:35-44 switches every h1/h2/h3 to +// --font-family-cyrillic under [lang="ru-RU"], because BEBAS NEUE HAS NO CYRILLIC GLYPHS — their +// heading face cannot render Russian at all, so without the switch the heading leaves the family. +// We ship a `ru` locale and had neither the rule nor the font, so every Russian heading here was +// rendering in whatever condensed system face the browser picked. +useDocumentFont('Oswald', OSWALD_FACES, assetsBase.value) // ── state ─────────────────────────────────────────────────────────────────── const { t, tf , locale } = useRegionsI18n() @@ -824,6 +830,19 @@ useShadowStyles( ' font-family:"Bebas Neue","Arial Narrow",BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;' + ' font-weight:400; }' + '.rd-h2--start{ text-align:start; }' + + // ★ CYRILLIC HEADINGS SWITCH FACE, as theirs do. base/_globals.scss:35-44: + // h1,h2,h3 { [lang="ru-RU"] & { font-family: var(--font-family-cyrillic); letter-spacing: -0.02em } } + // and --font-family-cyrillic is Oswald. The switch is not decoration: BEBAS NEUE HAS NO CYRILLIC + // GLYPHS, so a Russian heading in it leaves the family entirely and lands on whatever condensed + // system face the browser picks. We ship a `ru` locale and had neither the rule nor the font. + // ONLY the headings, exactly as theirs — their .region-stat__value is a

and keeps Bebas even in + // Russian, which is their behaviour and so is ours. + // BOTH TAG FORMS, deliberately: their site tags the document ru-RU while our i18n locale is `ru`, + // and a host page embedding this element may set either. A selector that matched only one would + // work on their site and fail on ours, or the reverse, depending on who set the attribute. + '[lang="ru"] .rd-title, [lang="ru-RU"] .rd-title,' + + '[lang="ru"] .rd-h2, [lang="ru-RU"] .rd-h2{ font-family:"Oswald","Arial Narrow",BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;' + + ' letter-spacing:-0.02em; }' + // .font-size-4xl .font-weight-medium / .font-size-lg // Their .font-size-4xl (var(--font-size-4xl)) verified live. Same substitution consequence as the h2: // in our wider stand-in face 'Adoption Progress' 21 / 2,107 breaks after the slash inside a @@ -912,7 +931,11 @@ useShadowStyles(