- {/* Owner subtitle */}
+ {/* Owner subtitle. `flex min-w-0` (not inline-flex) so a long owner
+ name truncates within the card instead of overflowing ~11px on
+ the narrowest mobile widths (R2). */}
{yacht.currentOwnerName ? (
-
+
{yacht.currentOwnerName}
diff --git a/tests/e2e/matrix/responsive-overflow.spec.ts b/tests/e2e/matrix/responsive-overflow.spec.ts
index c8333dc8..8981fb2e 100644
--- a/tests/e2e/matrix/responsive-overflow.spec.ts
+++ b/tests/e2e/matrix/responsive-overflow.spec.ts
@@ -82,13 +82,39 @@ test.describe('Responsive overflow sweep', () => {
// Elements whose right edge runs past the viewport by > 2px and are
// actually visible (have size, not display:none).
const offscreen: { tag: string; cls: string; right: number; text: string }[] = [];
+ const SVG_INTERNAL = new Set([
+ 'svg',
+ 'g',
+ 'ellipse',
+ 'path',
+ 'circle',
+ 'rect',
+ 'line',
+ 'polyline',
+ 'polygon',
+ ]);
const els = document.querySelectorAll('body *');
for (const el of els) {
+ const tag = el.tagName.toLowerCase();
+ // Skip SVG internals (icons, the react-grab dev overlay, chart guts)
+ // — not layout-cutoff signal.
+ if (SVG_INTERNAL.has(tag)) continue;
const r = (el as HTMLElement).getBoundingClientRect();
if (r.width === 0 || r.height === 0) continue;
if (r.right > vpWidth + 2 && r.left < vpWidth) {
- // overflowing the right edge (partially clipped)
- const tag = el.tagName.toLowerCase();
+ // Skip elements inside a horizontal-scroll container (data tables
+ // etc. scroll on purpose) — that's intended, not a clip.
+ let p: HTMLElement | null = el.parentElement;
+ let inScroll = false;
+ while (p) {
+ const ox = getComputedStyle(p).overflowX;
+ if (ox === 'auto' || ox === 'scroll') {
+ inScroll = true;
+ break;
+ }
+ p = p.parentElement;
+ }
+ if (inScroll) continue;
const cls = ((el as HTMLElement).className || '').toString().slice(0, 40);
const text = (el.textContent || '').trim().slice(0, 30);
offscreen.push({ tag, cls, right: Math.round(r.right), text });