From c2c5b25ab1acfb5ef3b663eed3753bda84bda70b Mon Sep 17 00:00:00 2001 From: jay Date: Sun, 21 Jun 2026 17:33:59 -0400 Subject: [PATCH] Art frames: add Black frame; thicker full-screen rail; rail-only top of thickness slider MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Black frame (no grain) added after Silver — a satin charcoal moulding in the metals family. - Full-screen rail bumped (clamp 18–36px) so the moulding reads as thick as the page view against the much larger image; mat held. - Thickness slider extended to 1.9× and the mat now caps at 1.5× (min()), so the top of the slider thickens only the wood while the white border stays put. Applies to the full-screen frame too. Co-Authored-By: Claude Opus 4.8 --- frontend/src/routes/art/+page.svelte | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/frontend/src/routes/art/+page.svelte b/frontend/src/routes/art/+page.svelte index 3407264..5f00f82 100644 --- a/frontend/src/routes/art/+page.svelte +++ b/frontend/src/routes/art/+page.svelte @@ -9,6 +9,7 @@ { id: 'mahogany', label: 'Mahogany' }, { id: 'gold', label: 'Gold' }, { id: 'silver', label: 'Silver' }, + { id: 'black', label: 'Black' }, { id: 'none', label: 'No frame' }, ]; @@ -16,7 +17,7 @@ let state = $state('loading'); // loading | ready | empty let zoom = $state(false); let frame = $state('walnut'); - let thickness = $state(1); // frame-scale multiplier, 0.7–1.5 + let thickness = $state(1); // frame-scale multiplier, 0.7–1.9 (mat caps at 1.5) let who = $derived( art ? [art.artist || 'Unknown artist', art.date_text].filter(Boolean) : [] @@ -27,7 +28,7 @@ const saved = localStorage.getItem('ub_art_frame'); if (saved && FRAMES.some((f) => f.id === saved)) frame = saved; const t = parseFloat(localStorage.getItem('ub_art_thickness')); - if (t >= 0.7 && t <= 1.5) thickness = t; + if (t >= 0.7 && t <= 1.9) thickness = t; } catch { /* private mode — defaults are fine */ } try { art = await getJSON('/api/art/today'); @@ -117,7 +118,7 @@ {#if frame !== 'none'}
Thickness -
{/if} @@ -204,8 +205,10 @@ switching frames never reflows the page. */ .frame { box-sizing: border-box; + /* Rail scales across the whole slider; the mat caps at scale 1.5 so the top of the + slider thickens only the moulding (wood), holding the white border steady. */ --rail: calc(clamp(11px, 2.3vw, 22px) * var(--frame-scale, 1)); - --mat: calc(clamp(10px, 2.4vw, 22px) * var(--frame-scale, 1)); + --mat: calc(clamp(10px, 2.4vw, 22px) * min(var(--frame-scale, 1), 1.5)); border: none; cursor: zoom-in; background: none; position: relative; line-height: 0; display: inline-block; max-width: 100%; border-radius: 4px; padding: var(--rail); @@ -241,6 +244,13 @@ inset 0 2px 3px rgba(255, 255, 255, 0.75), inset 0 -3px 9px rgba(60, 70, 85, 0.42); } + .frame--black { + background: linear-gradient(135deg, #2a2c30, #15171a 45%, #25282c 60%, #101113); + box-shadow: 0 24px 58px rgba(20, 30, 45, 0.30), + inset 0 0 0 1px rgba(255, 255, 255, 0.08), + inset 0 2px 3px rgba(255, 255, 255, 0.10), + inset 0 -3px 9px rgba(0, 0, 0, 0.60); + } /* Mitered (45°) corner joints for the woods — each seam runs from the outer corner to the mat, sized to the rail width so it tracks the thickness slider. */ @@ -310,6 +320,7 @@ .swatch--mahogany { background: linear-gradient(150deg, #5a241a, #7e3826 55%, #3a160e); } .swatch--gold { background: linear-gradient(150deg, #c79a45, #ecd293 55%, #a9772f); } .swatch--silver { background: linear-gradient(150deg, #aab1bb, #edf0f3 55%, #98a0ab); } + .swatch--black { background: linear-gradient(150deg, #34373c, #16181b 55%, #0c0d0f); } .swatch--none { background: linear-gradient(150deg, #ffffff, #ece6da); } .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); } @@ -333,8 +344,8 @@ framed piece — including the bottom rail — always fits on screen. */ .lb-frame { cursor: zoom-out; max-width: 92vw; - --rail: calc(clamp(14px, 1.4vw, 26px) * var(--frame-scale, 1)); - --mat: calc(clamp(16px, 1.6vw, 30px) * var(--frame-scale, 1)); + --rail: calc(clamp(18px, 1.9vw, 36px) * var(--frame-scale, 1)); + --mat: calc(clamp(16px, 1.6vw, 30px) * min(var(--frame-scale, 1), 1.5)); } .lb-frame.frame--none { --rail: 0px; --mat: 0px; } /* bare art fills the screen */ .lb-frame img { max-width: 86vw; max-height: 66vh; width: auto; height: auto; object-fit: contain; }