legend: the height cap now derives from the offset instead of repeating it
Some checks are pending
build-gate / build (push) Waiting to run

THE LEGEND OVERFLOWED THE BOTTOM OF THE MAP because two numbers that had to
agree were written out twice.

.stl-panel is capped at calc(100% - var(--stl-top) - 12px), but this profile
set `top` DIRECTLY with !important instead of setting --stl-top. So the panel
moved down to 58px while the cap kept subtracting 8px, and the two silently
disagreed by exactly the difference.

  MEASURED at 390px in a 420px-tall host: top 58px, max-height calc(100% - 20px),
  panel bottom 458 in a 420px map -- 38px PAST the map. Same 38px at 560px,
  because the error is the mismatch, not the map's size. After: -12px, the
  intended bottom margin, at 390/420, 390/560 and 1440/500 alike.

Two more copies of the same mistake went with it. The mobile rule paired
top:64px with max-height:calc(100vh - 72px) -- a constant unrelated to the
offset, AND the wrong box: 100vh measures the VIEWPORT while the panel is
positioned inside the MAP. Those agree only when the map fills the screen,
which is true of every standalone leaf and false the moment a host puts a
header above it. .fit-content had the same fixed 72px. Both now derive from
--stl-top, so they cannot drift apart again.

★ THIS IS INVISIBLE ON EVERY PUBLISHED LEAF. A standalone leaf gives the map
the whole viewport, and a panel that overflows a full-height map is still on
screen. It only appears when the host makes the map SHORTER than the viewport
-- which is how the element is actually embedded. Verify in a constrained
host, never on the bare leaf.

The a11y half of this work is NOT here. I fixed the same two nameless legend
controls locally while the remote was unreachable, then found on rebase that
they were already fixed on main -- better, with the row's own label
interpolated ("Expand Africa" rather than a generic string), and in one
key namespace instead of the second one I had introduced. Took main's version
whole and dropped my duplicate locale keys; only the CSS above is mine.
This commit is contained in:
doxa-maps-88655c70 2026-09-24 21:40:26 +00:00
parent 608ef3dd56
commit 88a566f49d
8 changed files with 110 additions and 80 deletions

View file

@ -607,7 +607,10 @@ useShadowStyles(`
pointer-events: auto;
}
.stl-panel.closed { transform: translateX(-100%); opacity: 0; pointer-events: none; }
.stl-panel.fit-content { max-height: calc(100% - 72px); }
/* Derived from --stl-top for the same reason as the base rule above: a fixed 72px here overflowed
whenever the profile's real offset was larger (UPG-100 sets 58px + a 12px bottom margin = 70px of
required clearance, against 72px only by luck; at --stl-top:8px it wasted 64px of panel height). */
.stl-panel.fit-content { max-height: calc(100% - var(--stl-top, 60px) - 12px); }
.stl-titlebar {
display: flex; align-items: center; gap: 6px;
padding: 8px 12px; flex-shrink: 0;
@ -923,7 +926,21 @@ useShadowStyles(`
.stl-reopen-caret { color: #6e7681; flex-shrink: 0; }
.stl-reopen:hover .stl-reopen-caret { color: #c9d1d9; }
@media (max-width: 640px) {
.stl-panel { width: 92vw; max-width: 380px; top: 64px; max-height: calc(100vh - 72px); }
/* ⚠ TWO BUGS LIVED IN THIS ONE LINE, and both are the same mistake: a number that has to agree
with another number, written out twice.
1. THE CAP MEASURED THE WRONG BOX. calc(100vh - 72px) sizes the panel against the VIEWPORT,
while the panel is positioned inside the MAP (position:absolute within .upg-map{inset:0}).
Those agree only when the map fills the screen — true of every standalone leaf, false the
moment a host puts a header above the map or content below it, which is how the element is
actually embedded. 100% is the map's own box, the same reference the desktop rule uses.
2. THE OFFSET AND THE CAP DISAGREED. top:64px with max-height:calc(... - 72px) subtracts a
constant that has nothing to do with the offset above it. --stl-top makes one value drive
both, so they cannot drift apart again.
MEASURED 2026-09-24 at 390px in a 420px-tall host: the panel ran 38px past the bottom of the
map. Driver: "the upg 100 list legend on the map is overflowing beyond the height of the map." */
.stl-panel { width: 92vw; max-width: 380px; --stl-top: 64px; }
.stl-reopen { top: 64px; }
}
.stl-panel[data-theme="light"] .stl-inner {

View file

@ -515,8 +515,21 @@ useShadowStyles(
// Driver kept reporting. One host cannot be fixed by breaking the other, so the offset is
// conditional on the pill EXISTING: default raised to 8px (matching .stl-panel's own left
// inset), pushed down only when a rendered geocoder is actually in the tree.
'.stl-panel{top:8px!important}' +
'.upg-root:has(.mapboxgl-ctrl-geocoder) .stl-panel{top:58px!important}' +
// ★ SET --stl-top, DO NOT SET top DIRECTLY. The library caps the panel at
// calc(100% - var(--stl-top, 60px) - 12px) (SemanticTreeLegend.vue:605), so the offset and the
// height cap MUST come from one value. Overriding top alone moved the panel down while the cap
// kept subtracting the OLD offset, and the two silently disagreed.
// MEASURED 2026-09-24, upg-100-list hosted in a 420px-tall frame at 390px wide: top resolved to
// 58px while max-height resolved to calc(100% - 20px), so the panel ran to 458px in a 420px map
// and HUNG 38px PAST THE BOTTOM OF THE MAP — exactly 58 - 20. Same 38px at a 560px frame, because
// the error is the offset mismatch, not the map's size. Driver 2026-09-24: "the upg 100 list
// legend on the map is overflowing beyond the height of the map".
// ⚠ WHY THIS IS INVISIBLE ON EVERY PUBLISHED LEAF: a standalone leaf gives the map the FULL
// viewport, and a panel that overflows a full-height map is still inside the screen. It only
// shows when a host makes the map SHORTER than the viewport, which is how the element is really
// embedded. Verify in a constrained host, never on the bare leaf.
'.stl-panel{--stl-top:8px!important}' +
'.upg-root:has(.mapboxgl-ctrl-geocoder) .stl-panel{--stl-top:58px!important}' +
// Geocoder suggestion metadata layout (clone — bold field labels for PG rows).
'.dg-main{font:13px/1.3 ui-monospace,monospace}' +
'.dg-meta{margin-top:2px;font-size:11px;color:#475569;display:flex;flex-wrap:wrap;gap:8px}' +

File diff suppressed because one or more lines are too long

View file

@ -681,7 +681,7 @@
"bundle": "my-upg-100-list",
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"output": "doxa-maps/my-upg-100-list/my-upg-100-list.js",
"integrity": "sha384-4QjITklNF8dldIMyzCtJ89iM0orN98L0CNHUbBo04Vtis/xxe1qkkEFQkCF/04i7",
"integrity": "sha384-hBqkpEcVb+g3Pbin8O8dlRGJGUTfOGUoU5zCCQhr7wwWkDafVraBZCQfBItxRKcI",
"elements": [
"my-upg-100-list-map"
],
@ -701,7 +701,7 @@
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"embed": {
"iframe": "<iframe src=\"./my-upg-100-list/poster-wall/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-4QjITklNF8dldIMyzCtJ89iM0orN98L0CNHUbBo04Vtis/xxe1qkkEFQkCF/04i7\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-hBqkpEcVb+g3Pbin8O8dlRGJGUTfOGUoU5zCCQhr7wwWkDafVraBZCQfBItxRKcI\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
}
},
{
@ -715,7 +715,7 @@
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"embed": {
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-4QjITklNF8dldIMyzCtJ89iM0orN98L0CNHUbBo04Vtis/xxe1qkkEFQkCF/04i7\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-hBqkpEcVb+g3Pbin8O8dlRGJGUTfOGUoU5zCCQhr7wwWkDafVraBZCQfBItxRKcI\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
}
},
{
@ -729,7 +729,7 @@
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"embed": {
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-4QjITklNF8dldIMyzCtJ89iM0orN98L0CNHUbBo04Vtis/xxe1qkkEFQkCF/04i7\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-hBqkpEcVb+g3Pbin8O8dlRGJGUTfOGUoU5zCCQhr7wwWkDafVraBZCQfBItxRKcI\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
}
}
]

File diff suppressed because one or more lines are too long

View file

@ -26,7 +26,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <my-upg-100-list-map> custom element. -->
<script src="../my-upg-100-list.js" integrity="sha384-P80Is4VW2RBIxrqlYITNybtR8AiaxsbngqobOVFGhmc8IrGXraMzYexAuyZcTtVF" crossorigin="anonymous"></script>
<script src="../my-upg-100-list.js" integrity="sha384-hBqkpEcVb+g3Pbin8O8dlRGJGUTfOGUoU5zCCQhr7wwWkDafVraBZCQfBItxRKcI" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -29,7 +29,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <my-upg-100-list-map> custom element. -->
<script src="../my-upg-100-list.js" integrity="sha384-P80Is4VW2RBIxrqlYITNybtR8AiaxsbngqobOVFGhmc8IrGXraMzYexAuyZcTtVF" crossorigin="anonymous"></script>
<script src="../my-upg-100-list.js" integrity="sha384-hBqkpEcVb+g3Pbin8O8dlRGJGUTfOGUoU5zCCQhr7wwWkDafVraBZCQfBItxRKcI" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -40,7 +40,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <my-upg-100-list-map> custom element. -->
<script src="../my-upg-100-list.js" integrity="sha384-P80Is4VW2RBIxrqlYITNybtR8AiaxsbngqobOVFGhmc8IrGXraMzYexAuyZcTtVF" crossorigin="anonymous"></script>
<script src="../my-upg-100-list.js" integrity="sha384-hBqkpEcVb+g3Pbin8O8dlRGJGUTfOGUoU5zCCQhr7wwWkDafVraBZCQfBItxRKcI" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order: