Commit graph

9 commits

Author SHA1 Message Date
Doxa Maps
70ea389db3 Docs: "reusable by default" in the library guides, and Deep Research by its name
- library/components/WARNING.md, library/dashboards/README.md and
  documentation/contributing/README.md taught "graduate into the library at the second
  consumer". They now teach the plugin-designer skill's rule (section 3): a component that
  could serve more than one map is built once in library/, driven by props, and landed through
  the build owner; one-off or experimental pieces stay in a map's folder; a new pattern is a
  pilot, then approved, then rolled out. The contributing guide's "full reasoning" link pointed
  to an index without it; it now points to the skill.
- The app shell doxa-maps-spa is labelled Deep Research. Ten docs still called it the Research
  Gallery (15 mentions): DEPLOY.md, the desktop how-to, embeddability, develop-a-plugin,
  reference-universal-props, reference.md, the shell's EMBED.md, and the plugin-designer skill
  with two of its references. Identifiers (doxa-maps-spa, branch and route names) are unchanged;
  README.md is not touched.
2026-10-01 08:27:04 +00:00
Doxa Maps
c394533fc8 Research Gallery: Poster Design joins Prayer Mobilization
Prayer Mobilization now reads Prayer Progress, UPG 100 List Posters, Country Posters, then Poster Design.
The row mounts the Styles + Sizes composite (bundle poster-design, profile poster-design-mfe), uses the same
tab id as the Posterverse shell, and carries the same label and subtitle in all 11 languages. As a curated
row it never appears on the Experimental shelf.
2026-09-30 22:42:05 +00:00
Doxa Maps
f18aff662b Research Gallery: a "Back to homepage" link above Collapse, and the poster rows in Prayer Mobilization
The tab layout takes an optional homeHref and homeLabel from its host. When a URL is given it draws a
link directly above the rail's Collapse button, in the same box, and a phone shows it at the top of the
drawer. It mirrors in Arabic and slims with the rail. With no URL nothing changes, so the Plugin Studio
and every other host look exactly as before. A javascript:, data: or vbscript: URL is ignored.

The gallery accepts home-href and home-label (or profile-config homeHref and homeLabel) and passes them
on; its own "Back to homepage" is the fallback label in all 11 languages.

Prayer Mobilization now reads Prayer Progress, UPG 100 List Posters (renamed in all 11 languages), then
Country Posters, which mounts its composite view and leaves the Experimental shelf. Posterverse, the
second shell, is kept off this shelf so a shell never opens inside a shell.
2026-09-30 20:16:15 +00:00
doxa-maps-88655c70
9e43332aad EMBED.md: lead with the picture and an at-a-glance table
The embed guide opened with prose and a code block. It now leads with the
existing screenshot of the gallery embedded by script on a partner page,
then a two-column table (script vs iframe): what to paste, sizing,
language, deep link, keyless maps, and what the server must send. Every
row is behaviour measured this session. Then it names the seven
production maps in their sections.
2026-09-25 05:09:09 +00:00
doxa-maps-88655c70
5e7f73d0be VerticalTabsLayout mirrors for right-to-left, and the gallery sets its direction
Arabic did not flip the shell (reported by studio for matrix cell E). The
layout is written in physical terms: rail at left:0, content at left:256px,
translateX(-…) slides. So an Arabic gallery kept its rail on the left with
LTR geometry.

The layout now carries an additive :dir(rtl) mirror block, in BOTH copies
of its CSS (VTL_SHADOW_CSS and the style block). The rail anchors right,
content right:256px, the collapse and drawer slides go positive, the
collapsed paddings, auto-margins and text-align mirror, and the arrow SVGs
flip. translateX has no logical form, so this is a mirror block rather than
logical properties. LTR consumers match none of it.

The gallery sets dir (and lang) on the layout from its own language: rtl
for Arabic, ltr otherwise. So an English gallery on some other RTL page
keeps a Latin rail unmirrored.

Measured on the served built tree:
  1400px ar: rail [944,1200], content [0,944], text right; collapsed =
             a 72px rail on the right
  390px ar:  drawer parked off-canvas right, slides in to [944,1200]
  LTR:       studio, stack-demo and the gallery at 1400px geometry
             identical before and after. The 390px differences seen once
             were transition timing and did not reproduce.

The shared layout is compiled into doxa-maps-spa and plugin-studio, so
both bundles are rebuilt here. stack-demo's bundle came out byte-identical:
it does not compile the layout.
2026-09-25 04:41:01 +00:00
doxa-maps-88655c70
c8b13286f2 Research Gallery: speak the host page's language, and prove the composites' links
Language. The gallery fell back to the browser's language and forced it
onto every nested map through profile-config.locale, while its own rail
stayed English. Measured: a Spanish page viewed in a German browser showed
German maps under an English rail. It now follows the ladder every nested
map already uses: the `language` attribute, then ?lang=, then <html lang>
(watched live, so a host that switches language switches the gallery), then
English. The browser only counts once a visitor has used the gallery's own
switcher.

Its own words (rail, sections, hints, badges, notice) now ship in all 11
locales, in a private src/strings.js that reuses the library's terms.
Rail sweep, 11 locales at 1400px and 390px: 21 of 22 clean. The one clip,
Italian 'Avanzamento della preghiera' (191px in a 176px slot), now uses the
rail form 'Avanzamento preghiera'. A live <html lang> switch from en to
pt-BR re-renders the rail.

Interop (matrix cell D). check:gallery-embed gains a `linked` phase that
drives each composite's real control INSIDE a gallery tab:
- Big Picture: a facet shows "Showing 1,309" in the grid.
- Simple Research: a grid search narrows 2107 → 3. Its halves are
  independent by design.
- Regions: clicking "Africa" in the list retitles the dashboard "Africa".
- UPG-100: "Show on map" brings the map.
UPG-100's missing zone selection is an owned, printed LINKED_KNOWN entry.
Full gate: js 13, iframe 13, neighbour 13, linked 4.
2026-09-25 04:22:54 +00:00
doxa-maps-88655c70
86fb6e750b Research Gallery: a good guest on the partner's page
Embedded below the fold on a phone-width host page, the gallery disturbed
the page it was a guest on:

- The host's inherited typography flowed into the gallery. Shadow DOM
  isolates selectors, not inheritance, so a host with body{font:20px/3;
  letter-spacing:2px} re-flowed every rail row and legend (root measured at
  20px / 60px / 2px). :host now resets the inherited text properties to the
  gallery's own defaults (16px / normal / normal). Direction still inherits,
  so RTL hosts stay RTL.
- Nested maps wrote the host's URL and title. The gallery now tells every
  child urlSync:false. Regions needs to honour it (routed).

check:gallery-embed gains a good-neighbour phase: phone width, gallery
below the fold, hostile host CSS, the host's own #anchor and <title>. After
load and after every tab it asserts no host scroll, an unchanged URL, an
unchanged title, and no inherited typography. Two nested-plugin violations
are listed, owned and printed in NEIGHBOUR_KNOWN until their owners fix
them (same contract as MAPBOX_KNOWN):
- research-map.vue:647's scrollIntoView jumps the host to y=640 on load on
  a phone.
- Regions' unconditional URL/title sync.

A boot timeout is now a named FAIL instead of an uncaught crash. The gate
caught a real one on the way: a rebuilt bundle whose leaf page still
pinned the old SRI hash.
2026-09-25 03:37:26 +00:00
doxa-maps-88655c70
3a4f065ec5 Research Gallery: a host that asks for maplibre gets maplibre in every tab
The shell forwarded tk, tokenUrl, locale and treeBase to each nested map,
but not the engine. So <doxa-maps-spa provider="maplibre"> still loaded
mapbox-gl and Mapbox styles. On a keyless host, that is the embed failing.

The shell now forwards `provider` in each child's profile-config, validated
to the two known engines. That fixed the simple map tabs, but not the
composites: they mount their inner maps without passing the provider on.
Measured with one tab per clean page: Big Picture made 19 api.mapbox.com
requests, Regions 17, UPG-100 15, Simple Research 14. So when a host asks
for an engine, the shell also sets window.MAP_PROVIDER (only if the page
hasn't). That is rung 3 of every map's own ladder, so it reaches maps
nested at any depth. After it, all four composites make 0 Mapbox requests.

check:gallery-embed:maplibre runs the cross-origin gate with a keyless
provider and fails on any api.mapbox.com request, attributed to the tab
that was open. Before this change, js mode failed with 20 URLs. It has one
named, printed exemption: upg-100-list.vue pins a token-free mapbox-gl.css.
That belongs to the upg100 plugin and is routed there.
2026-09-24 19:57:23 +00:00
doxa-maps-88655c70
3a2cf0e8f2 Research Gallery: embed on someone else's page, in both modes
The gallery is going onto the DX-life research page, and nothing had tried
it on a page it didn't generate. From a second origin, a bare
<script> + <doxa-maps-spa> drew over the host's header, and 8 of 13 tabs
showed an error card.

Three causes, each fixed in the shell:

- No :host box. The layout root is position:absolute, so it anchored to the
  viewport instead of the element. :host is now a positioned block with a
  default height the host can override.
- A foreign page sets none of the globals a leaf page bakes. Every data call
  hit the host's own origin and got HTML back. The manifest now publishes a
  `runtime` block (apiBaseUrl + the public token every leaf already carries).
  The shell fills window.MAP_APP_API_URL / window.MAP_TOKEN only when the page
  hasn't set them, and forwards tk in profile-config.
- Nested elements resolved assets to <tree>/../assets, a sibling pool the
  publisher doesn't ship (404 live). The shell now forwards an absolute
  <tree>/assets. This also fixes the iframe mode, where Cities with Internet
  and Gospel Resources were failing the same way.

Also adds a `tab` attribute (plus ?tab=) to deep-link into one map, and a
`tab-change` event for the host.

check:gallery-embed drives every tab in both modes from a second origin. It
passes here and fails on the previous tree (7 findings).

EMBED.md documents the contract. The Traefik template now sends CORS for the
whole tree: live manifest.json answers without Access-Control-Allow-Origin.
2026-09-24 19:03:37 +00:00