diff --git a/plugin-designs/regions-dashboard/region-dashboards.vue b/plugin-designs/regions-dashboard/region-dashboards.vue
index be7699a1f..575ac2e3e 100644
--- a/plugin-designs/regions-dashboard/region-dashboards.vue
+++ b/plugin-designs/regions-dashboard/region-dashboards.vue
@@ -46,6 +46,7 @@ import { PALETTE as REGION_PALETTE, WAGF_REGIONS, REGION_ORDER } from '@map/colo
// component's shadow CSS so every var() below resolves inside the shadow root.
import { DXLIFE_TOKENS } from './dxlife-tokens.js'
import RegionCountryMap from './src/RegionCountryMap.vue'
+import { SHADOW_BOX_SIZING_RESET } from './src/shadowReset.js'
import { summarizeRegions, emptyStats, toNumber, PEOPLE_GROUP_LIST_FIELDS } from '@map/utils/countries-meta.js'
const props = defineProps({
@@ -704,6 +705,9 @@ onBeforeUnmount(() => {
// the two tabs does not change the surface under the reader.
// NO BACKTICKS in this string, including comments (house style: one terminates the literal).
useShadowStyles(
+ // Their _reset.scss:3-8 FIRST, so every rule below is authored against border-box exactly as
+ // theirs is. See src/shadowReset.js for why it lives there and for the measured blast radius.
+ SHADOW_BOX_SIZING_RESET +
DXLIFE_TOKENS +
// EVERY value below is DX-life's own, resolved against their 10px rem root
// (app/assets/styles/base/_globals.scss html{font-size:var(--font-size-base)}, and
@@ -793,7 +797,7 @@ useShadowStyles(
' padding:var(--spacing-3xl) 0 var(--spacing-4xl); display:flex; flex-direction:column;' +
' container-type:inline-size; }' +
'.rd-scroll > * + *{ margin-top:var(--spacing-3xl); }' + // .stack .stack--3xl
- '.rd-scroll > *{ box-sizing:border-box; width:calc(90% + 16px); max-width:1200px;' +
+ '.rd-scroll > *{ width:calc(90% + 16px); max-width:1200px;' +
' margin-left:auto; margin-right:auto; }' +
'.rd-status{ padding:28px; text-align:center; color:var(--dx-muted); font-size:var(--font-size-md); }' +
'.rd-status.rd-failed{ font-weight:600; }' +
@@ -838,7 +842,7 @@ useShadowStyles(
// ── .card: blocks/_cards.scss:9-21. radius --border-radius-xlg (35px);
// padding clamp(--spacing-lg, 6vw, --spacing-2xl) clamp(--spacing-lg, 6vw, --spacing-3xl).
- '.rd-card{ position:relative; box-sizing:border-box; border-radius:var(--dx-radius);' +
+ '.rd-card{ position:relative; border-radius:var(--dx-radius);' +
' background:var(--dx-elevated); color:var(--dx-text);' +
' padding:clamp(var(--spacing-lg), 6cqw, var(--spacing-2xl)) clamp(var(--spacing-lg), 6cqw, var(--spacing-3xl)); }' +
// .card[padding-small] -> --spacing-lg flat
diff --git a/plugin-designs/regions-dashboard/regions-list.vue b/plugin-designs/regions-dashboard/regions-list.vue
index 552eb49d8..7131ed944 100644
--- a/plugin-designs/regions-dashboard/regions-list.vue
+++ b/plugin-designs/regions-dashboard/regions-list.vue
@@ -40,6 +40,7 @@
*/
import { inject, ref, computed, onMounted, watch, getCurrentInstance } from 'vue'
import { useShadowStyles } from '@map/composables/useShadowStyles.js'
+import { SHADOW_BOX_SIZING_RESET } from './src/shadowReset.js'
import { splitLastWord } from './src/useLastWordHighlight.js'
import { useRegionsI18n } from './src/useRegionsI18n.js'
// ar renders right-to-left. RTL_LOCALES is the shared set and :dir on our own root is the
@@ -340,6 +341,8 @@ onMounted(loadRegions)
// Colours/fonts/radii are an intentional exception to this repo's material-light chrome tokens —
// the Driver asked for an exact clone of DX-life's OWN design here, so the clone wins.
useShadowStyles(
+ // Their _reset.scss:3-8 FIRST -- see src/shadowReset.js.
+ SHADOW_BOX_SIZING_RESET +
DXLIFE_TOKENS +
':host{ display:block; width:100%; height:100%; min-height:320px; }' +
'.rl-root{ position:absolute; inset:0; display:flex; flex-direction:column; min-height:0;' +
@@ -383,7 +386,7 @@ useShadowStyles(
// So it is FLUID at 90%+16px until the viewport reaches 1315.625px, then pinned at 1200px centred.
// Our cards previously stretched to the full pane at every width -- there was no cap at all.
// box-sizing:border-box so .rl-status's own 28px padding stays inside the cap.
- '.rl-scroll > *{ box-sizing:border-box; width:calc(90% + 16px); max-width:1200px;' +
+ '.rl-scroll > *{ width:calc(90% + 16px); max-width:1200px;' +
' margin-left:auto; margin-right:auto; }' +
// Their head block: .stack--xs (10px) gap, centred. h1 is _globals' clamp(--font-size-3xl,
// 7vw, --font-size-5xl) and the subtitle is --font-size-md in --color-brand-lighter.
diff --git a/plugin-designs/regions-dashboard/regions-mfe.vue b/plugin-designs/regions-dashboard/regions-mfe.vue
index bf21b46cd..d302e420f 100644
--- a/plugin-designs/regions-dashboard/regions-mfe.vue
+++ b/plugin-designs/regions-dashboard/regions-mfe.vue
@@ -27,6 +27,7 @@
import { ref, computed, inject, onMounted, onBeforeUnmount } from 'vue'
import { buildPaneColumn, PANE_GRID_STYLES } from '@map/layouts/pane-wrapper/pane-wrapper.js'
import { useShadowStyles } from '@map/composables/useShadowStyles.js'
+import { SHADOW_BOX_SIZING_RESET } from './src/shadowReset.js'
import ViewSelect from '@map/components/ViewSelect.vue'
import ShareButton from '@map/components/map-controls/ShareButton.vue'
// The SELECT VIEW strip is one of the sanctioned additions, so DX-life has no equivalent
@@ -170,7 +171,7 @@ const SHARE_EMBED_PATH = 'regions-dashboard/regions-mfe/index.html'
// NO BACKTICKS inside this CSS string, including in comments — one terminates the JS template
// literal and the build stops compiling (house style).
-useShadowStyles(PANE_GRID_STYLES + '\n' +
+useShadowStyles(SHADOW_BOX_SIZING_RESET + PANE_GRID_STYLES + '\n' +
// SELF-SIZE. Every layer inside is absolute/height:100% (.rmfe -> .pane-col -> .pane), so the
// chain resolves to ZERO unless the HOST itself is sized — the "elements are not embedding"
// failure upg-100-mfe documents. Declaring :host makes this fill whatever slot it is mounted
diff --git a/plugin-designs/regions-dashboard/src/RegionCountryMap.vue b/plugin-designs/regions-dashboard/src/RegionCountryMap.vue
index 774734f96..82c2a90de 100644
--- a/plugin-designs/regions-dashboard/src/RegionCountryMap.vue
+++ b/plugin-designs/regions-dashboard/src/RegionCountryMap.vue
@@ -739,7 +739,6 @@ useShadowStyles(
// root so it is verified where it is measured; porting it bundle-wide and DELETING those seven
// patches is carded (BUILD-PORT-THEIR-BOX-SIZING-RESET-TO-THE-SHADOW-ROOT) because it changes
// geometry in components whose match against live has to be re-measured, not assumed.
- '.rcm, .rcm *, .rcm *::before, .rcm *::after{ box-sizing:border-box; }' +
'.rcm{ display:block; position:relative; width:100%; min-height:780px; aspect-ratio:16/9;' +
' overflow:hidden; border-radius:inherit; }' +
'@media (max-width:768px){ .rcm{ min-height:0; aspect-ratio:1/2; } }' +
diff --git a/plugin-designs/regions-dashboard/src/UupgsList.vue b/plugin-designs/regions-dashboard/src/UupgsList.vue
index 16b93afbf..aecbd3729 100644
--- a/plugin-designs/regions-dashboard/src/UupgsList.vue
+++ b/plugin-designs/regions-dashboard/src/UupgsList.vue
@@ -326,7 +326,7 @@ useShadowStyles(
// type at every other size. MEASURED: theirs renders ~600px inside the 1200px container
// and shows the whole placeholder; ours truncated it at 480px.
'.search-box{ position:relative; width:100%; max-width:50ch; margin-inline:auto; }' +
- '.search-box input{ box-sizing:border-box; width:100%; border:1px solid #666; border-radius:100px;' +
+ '.search-box input{ width:100%; border:1px solid #666; border-radius:100px;' +
' background:var(--dx-white); padding:10px var(--spacing-lg); text-indent:1.5em; font:inherit;' +
' font-size:var(--font-size-md); color:var(--dx-text); }' +
'.search-box input::placeholder{ color:gray; }' +
@@ -397,7 +397,7 @@ useShadowStyles(
'.grid{ display:grid; grid-gap:var(--spacing-2xl);' +
' grid-template-columns:repeat(auto-fit, minmax(min(400px,100%), 1fr)); }' +
// .card + .uupg__card: their grid-template-areas, radius-xlg, --spacing-md padding + gap
- '.uupg__card{ box-sizing:border-box; background:var(--dx-white); color:var(--dx-text);' +
+ '.uupg__card{ background:var(--dx-white); color:var(--dx-text);' +
' border-radius:35px; display:grid;' +
' grid-template-areas:"image header adopted" "image content content" "footer footer footer-right";' +
' grid-template-columns:auto 1fr auto; grid-template-rows:auto auto auto;' +
@@ -424,7 +424,7 @@ useShadowStyles(
'.uupg__match{ margin:0; font-size:var(--font-size-sm); color:var(--dx-muted); }' +
// .button.compact, grid-area footer, bottom-aligned
'.uupg__more-button{ grid-area:footer; align-self:flex-end; display:block; width:fit-content;' +
- ' box-sizing:border-box; padding:10px var(--spacing-2xl); color:#f3f3f1; background:#92b195;' +
+ ' padding:10px var(--spacing-2xl); color:#f3f3f1; background:#92b195;' +
' border-radius:100px; border:1px solid transparent; line-height:1; text-decoration:none;' +
' text-transform:uppercase; font-size:var(--font-size-md);' +
// THEIR FAMILY IS "Brandon Grotesque", WHICH IS COMMERCIAL — the one substitution RULE 1
diff --git a/plugin-designs/regions-dashboard/src/shadowReset.js b/plugin-designs/regions-dashboard/src/shadowReset.js
new file mode 100644
index 000000000..11e6df297
--- /dev/null
+++ b/plugin-designs/regions-dashboard/src/shadowReset.js
@@ -0,0 +1,52 @@
+/**
+ * Their box-sizing reset, ported into the shadow root.
+ *
+ * WHAT THIS IS. app/assets/styles/base/_reset.scss:3-8 on DX-life master, verbatim:
+ *
+ * *,
+ * *::before,
+ * *::after {
+ * box-sizing: border-box;
+ * }
+ *
+ * a piccalil.li reset that applies to EVERY element on their page.
+ *
+ * WHY IT WAS MISSING FOR SO LONG, and why no component could reveal it. Our leaf document already
+ * carries the identical rule (regions-dashboard/index.html:9) -- but these components render inside
+ * a SHADOW ROOT, and a document-level `*` selector does not cross a shadow boundary. So every
+ * element in here was content-box while every element of theirs was border-box, and no scoped
+ * component style could show the difference. It was the SEVENTH global rule of theirs found
+ * missing, and it is why this codebase had accumulated seven separate per-element
+ * `box-sizing:border-box` patches: each was a local workaround for the reset that never arrived.
+ *
+ * WHAT IT COST, measured rather than described: their legend swatch is `width:10px; border:1px
+ * solid #fff` -- 10px under border-box, 12px under content-box. Two swatch columns of 1px each are
+ * exactly the 2px by which our legend panel measured wider than theirs (167px vs 165px) after the
+ * rest of the legend had been aligned to the pixel. The same label string measured 129px on both
+ * sides in the same Poppins, so the text was never the cause.
+ *
+ * WHY PORTING IT IS SAFE, and this is the part that made the change cheap instead of frightening:
+ * the blast radius was MEASURED before any of it was written.
+ * _probe-boxsizing-blast-radius.mjs injected this exact rule into every shadow root at runtime and
+ * diffed every element's rect before and after -- 0 of 431 elements moved on region-dashboards and
+ * 0 of 678 on regions-list, with 301 already border-box by their own declarations. So the port is a
+ * geometric NO-OP and the whole value of it is DELETING the per-element patches it replaces, which
+ * is the direction RULE 3 asks for. The detector was negative-tested (NEG=1 injects padding-left:3px
+ * and it reports the movement), because a zero from a check that cannot fail is worth nothing.
+ *
+ * WHY HERE AND NOT library/useShadowStyles.js. Putting it there would fix all 25 bundles at once and
+ * is tempting for exactly that reason -- but the blast radius above was measured on THESE two pages
+ * only, and geometry in 23 other bundles would change on an unmeasured basis. RULE 2 says default to
+ * the plugin folder; the second consumer that would justify library/ is not named yet. If another
+ * plugin wants it, it moves then, with that plugin's blast radius measured too.
+ *
+ * WHY A MODULE AND NOT THREE COPIES. Three roots inject into the shared shadow root
+ * (region-dashboards, regions-list, regions-mfe) and any of them can be the one that mounts, so all
+ * three need it. One exported string keeps it one fact in one place.
+ */
+
+/** Their _reset.scss:3-8, as a shadow-root-scoped rule. */
+export const SHADOW_BOX_SIZING_RESET =
+ '*, *::before, *::after{ box-sizing:border-box; }'
+
+export default SHADOW_BOX_SIZING_RESET
diff --git a/public/dx-maps/doxa-maps-spa/manifest.json b/public/dx-maps/doxa-maps-spa/manifest.json
index fd3fa284e..496545596 100644
--- a/public/dx-maps/doxa-maps-spa/manifest.json
+++ b/public/dx-maps/doxa-maps-spa/manifest.json
@@ -888,7 +888,7 @@
"bundle": "regions-dashboard",
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"output": "dx-maps/regions-dashboard/regions-dashboard.js",
- "integrity": "sha384-z4GurUdJw60hce5cF5GM+ugsgNGMEYEdkT0VlBXI8XOw1J4NP+F5CUtoD7ahznVG",
+ "integrity": "sha384-FDwUoPdVCOpa/WplF4PpBVLYMusCFPZqbxBBqQOFlI0sJhR+UB4HuSbH/O4MJec0",
"elements": [
"regions-dashboard"
],
@@ -908,7 +908,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "",
- "script": "\n\n\n\n"
+ "script": "\n\n\n\n"
}
},
{
@@ -922,7 +922,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "",
- "script": "\n\n"
+ "script": "\n\n"
}
},
{
@@ -936,7 +936,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "",
- "script": "\n\n\n\n"
+ "script": "\n\n\n\n"
}
}
]
diff --git a/public/dx-maps/manifest.json b/public/dx-maps/manifest.json
index fd3fa284e..496545596 100644
--- a/public/dx-maps/manifest.json
+++ b/public/dx-maps/manifest.json
@@ -888,7 +888,7 @@
"bundle": "regions-dashboard",
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"output": "dx-maps/regions-dashboard/regions-dashboard.js",
- "integrity": "sha384-z4GurUdJw60hce5cF5GM+ugsgNGMEYEdkT0VlBXI8XOw1J4NP+F5CUtoD7ahznVG",
+ "integrity": "sha384-FDwUoPdVCOpa/WplF4PpBVLYMusCFPZqbxBBqQOFlI0sJhR+UB4HuSbH/O4MJec0",
"elements": [
"regions-dashboard"
],
@@ -908,7 +908,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "",
- "script": "\n\n\n\n"
+ "script": "\n\n\n\n"
}
},
{
@@ -922,7 +922,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "",
- "script": "\n\n"
+ "script": "\n\n"
}
},
{
@@ -936,7 +936,7 @@
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
"embed": {
"iframe": "",
- "script": "\n\n\n\n"
+ "script": "\n\n\n\n"
}
}
]
diff --git a/public/dx-maps/regions-dashboard/region-dashboards/index.html b/public/dx-maps/regions-dashboard/region-dashboards/index.html
index 49c4c4c63..507e973c6 100644
--- a/public/dx-maps/regions-dashboard/region-dashboards/index.html
+++ b/public/dx-maps/regions-dashboard/region-dashboards/index.html
@@ -30,7 +30,7 @@
-
+
-
+
-
+