From 89987b8316c35df0250c74c01fb452be715d3dc3 Mon Sep 17 00:00:00 2001 From: jay Date: Tue, 23 Jun 2026 21:09:28 -0400 Subject: [PATCH] /art: thickness affects rotated fullscreen; collapsible writeup on mobile - Fullscreen (rotated landscape view) ignored the thickness slider because I'd hard-coded the frame rail/mat to fit after rotation. Let them scale with thickness again and pull the image's short-edge cap in (60vw) so the whole frame still fits even at max thickness. - Mobile: the writeup is now a collapsible "About this piece" accordion between the artwork and the controls (open by default). Collapse it and the frame / thickness / palette controls rise up beside the artwork, so you can see frame changes live. Desktop unchanged (writeup always shown in the left column). Co-Authored-By: Claude Opus 4.8 --- frontend/src/routes/art/+page.svelte | 48 +++++++++++++++++++++------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/frontend/src/routes/art/+page.svelte b/frontend/src/routes/art/+page.svelte index a13369b..fc4eb24 100644 --- a/frontend/src/routes/art/+page.svelte +++ b/frontend/src/routes/art/+page.svelte @@ -82,6 +82,8 @@ }); let dlName = $derived(art ? `${(art.title || 'artwork').replace(/[^\w \-]+/g, '').trim()}.jpg` : 'artwork.jpg'); + let detailsOpen = $state(true); // mobile: collapse the writeup to bring the controls up near the art + let copied = $state(false); async function share() { const url = art?.source_url || location.href; @@ -127,14 +129,24 @@ {#if attribution}

{attribution}

{/if}
- {#if art.blurb}

{art.blurb}

{/if} -
-
Collection{art.museum}
- {#if art.license}
Rights{art.license}
{/if} + +
+ {#if art.blurb}

{art.blurb}

{/if} +
+
Collection{art.museum}
+ {#if art.license}
Rights{art.license}
{/if} +
+ {#if art.source_url} + View at {art.museum} → + {/if}
- {#if art.source_url} - View at {art.museum} → - {/if}
@@ -270,7 +282,9 @@ box-shadow: 0 16px 40px -22px rgba(120, 95, 50, 0.32); } .left { flex: 1; min-width: 0; padding: clamp(28px, 4vw, 50px) clamp(24px, 3.4vw, 46px); display: flex; flex-direction: column; justify-content: center; } - .head, .body { display: flex; flex-direction: column; } /* so .cta align-self works (no overlap) */ + .head, .body, .body-content { display: flex; flex-direction: column; } /* so .cta align-self works */ + .details-toggle { display: none; } /* desktop: the writeup is always shown in the left column */ + .chev { transition: transform 0.2s ease; } .kicker { display: inline-flex; align-items: center; gap: 9px; font-family: 'Space Mono', monospace; font-size: 12px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent); } .kicker-rule { width: 18px; height: 2px; background: var(--accent); border-radius: 2px; } .art-title { font-family: 'Newsreader', Georgia, serif; font-weight: 500; font-size: clamp(2rem, 4.2vw, 2.9rem); line-height: 1.05; letter-spacing: -0.01em; color: var(--ink); margin: 14px 0 0; } @@ -313,7 +327,17 @@ .left, .right { display: contents; } /* promote head/body/art-stage/controls */ .head { order: 1; padding: clamp(22px, 5vw, 28px) clamp(18px, 5vw, 22px) 14px; } .art-stage { order: 2; background: var(--art-band); padding: 22px 18px; box-sizing: border-box; } - .body { order: 3; padding: 20px clamp(18px, 5vw, 22px) 4px; } + .body { order: 3; padding: 6px clamp(18px, 5vw, 22px) 4px; } + /* writeup collapses (tap "About this piece") so the controls rise up beside the art */ + .details-toggle { + display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%; + background: none; border: none; cursor: pointer; padding: 14px 0; + font-family: 'Space Mono', monospace; font-size: 11px; letter-spacing: 0.14em; + text-transform: uppercase; color: var(--label); -webkit-tap-highlight-color: transparent; + border-top: 1px solid rgba(120, 95, 50, 0.16); + } + .chev.open { transform: rotate(180deg); } + .body-content.collapsed { display: none; } .controls { order: 4; width: auto; max-width: none; box-sizing: border-box; margin: 16px clamp(14px, 4vw, 18px) clamp(20px, 5vw, 24px); background: #fff; border: 1px solid #ece3d0; border-radius: 16px; padding: 18px 16px; } @@ -513,8 +537,10 @@ /* The image's SHORT edge + the frame's rail/mat map to the phone's narrow width, so cap it there (max-height, pre-rotation) with a modest fixed frame so the whole moulding always fits; the long edge (max-width → screen height) stays generous. */ - .lightbox.rotate .lb-frame { max-width: 92vh; --rail: 16px; --mat: 16px; } - .lightbox.rotate .lb-frame img { max-width: 88vh; max-height: 74vw; } + .lightbox.rotate .lb-frame { max-width: 92vh; } /* rail/mat keep scaling with thickness */ + /* short edge (→ screen width after rotation) capped low enough that the frame fits even + at max thickness; the long edge stays generous */ + .lightbox.rotate .lb-frame img { max-width: 88vh; max-height: 60vw; } .lightbox.rotate .lb-frame.frame--none img { max-width: 94vh; max-height: 92vw; } }