From 6b79d13f24a27221d005a936270e3c7fa8cfd3a3 Mon Sep 17 00:00:00 2001 From: swift-river542 Date: Thu, 17 Sep 2026 02:19:59 -0500 Subject: [PATCH] The map slot paints its own rounded corners over whatever it holds, so a canvas or an iframe can never square them --- app/components/DoxaMapSlot.vue | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/app/components/DoxaMapSlot.vue b/app/components/DoxaMapSlot.vue index e3f5ef46..816d775b 100644 --- a/app/components/DoxaMapSlot.vue +++ b/app/components/DoxaMapSlot.vue @@ -57,6 +57,32 @@ const isSimple = props.bundle === 'simple-map' will-change: transform; transform: translateZ(0); } + +/* THE CORNERS ARE PAINTED, NOT ONLY CLIPPED. + A map canvas and an iframe are composited layers: on a real GPU they are not reliably + clipped by an ancestor's radius, which is why the corners went square the moment a map + finished loading (Firefox, reported 2026-09-17). Clipping the canvas itself breaks + Mapbox's own transforms, so the slot instead paints the four corner wedges in the page + colour ON TOP of whatever it holds. Ordinary painting — no compositor can escape it, and + it works the same for a canvas, an iframe or an image. Per-corner radii so a card can be + square along one edge (the research card on phones). */ +.doxa-map-slot::after { + content: ''; + position: absolute; + inset: 0; + pointer-events: none; + z-index: 3; + --corner-tl: var(--slot-radius, 0px); + --corner-tr: var(--slot-radius, 0px); + --corner-br: var(--slot-radius, 0px); + --corner-bl: var(--slot-radius, 0px); + --corner-bg: var(--slot-corner-bg, var(--color-surface-default, #F3F3F1)); + background: + radial-gradient(circle at 100% 100%, #0000 calc(var(--corner-tl) - 0.5px), var(--corner-bg) var(--corner-tl)) left top / var(--corner-tl) var(--corner-tl) no-repeat, + radial-gradient(circle at 0 100%, #0000 calc(var(--corner-tr) - 0.5px), var(--corner-bg) var(--corner-tr)) right top / var(--corner-tr) var(--corner-tr) no-repeat, + radial-gradient(circle at 0 0, #0000 calc(var(--corner-br) - 0.5px), var(--corner-bg) var(--corner-br)) right bottom / var(--corner-br) var(--corner-br) no-repeat, + radial-gradient(circle at 100% 0, #0000 calc(var(--corner-bl) - 0.5px), var(--corner-bg) var(--corner-bl)) left bottom / var(--corner-bl) var(--corner-bl) no-repeat; +} /* One corner size for every map card, and the element's own radius is pinned to the same token so it can never disagree with the clip (the page's utility class sets its own). */ .doxa-map-slot.rounded-md { --slot-radius: var(--border-radius-lg); border-radius: var(--slot-radius); } @@ -71,6 +97,7 @@ const isSimple = props.bundle === 'simple-map' clip-path: inset(0 round 0 0 var(--slot-radius) var(--slot-radius)); --map-radius-corners: 0 0 var(--slot-radius) var(--slot-radius); } + .doxa-map-slot.rounded-xlg::after { --corner-tl: 0px; --corner-tr: 0px; } .doxa-map-slot { min-height: 0; /* Phone height: twice as tall as wide (~734px on a 390px phone) — 80px more map than the