diff --git a/frontend/src/routes/art/+page.svelte b/frontend/src/routes/art/+page.svelte index dca7519..535083a 100644 --- a/frontend/src/routes/art/+page.svelte +++ b/frontend/src/routes/art/+page.svelte @@ -5,6 +5,7 @@ // Virtual frames the viewer can switch between — remembered locally, no account needed. const FRAMES = [ { id: 'walnut', label: 'Walnut' }, + { id: 'oak', label: 'Oak' }, { id: 'gold', label: 'Gold' }, { id: 'silver', label: 'Silver' }, { id: 'none', label: 'No frame' }, @@ -116,8 +117,10 @@ {#if zoom && art} - {/if} @@ -178,7 +181,7 @@ border-radius: 5px; box-shadow: 0 24px 58px rgba(20, 30, 45, 0.20), 0 3px 10px rgba(20, 30, 45, 0.10); } - .frame--walnut, .frame--gold, .frame--silver { padding: clamp(11px, 2.3vw, 22px); border-radius: 4px; } + .frame--walnut, .frame--oak, .frame--gold, .frame--silver { padding: clamp(11px, 2.3vw, 22px); border-radius: 4px; } .frame--walnut { background: linear-gradient(135deg, #5c3d26, #87592f 38%, #4d3220 68%, #76512f); box-shadow: 0 24px 58px rgba(20, 30, 45, 0.24), @@ -201,10 +204,33 @@ inset 0 -3px 9px rgba(60, 70, 85, 0.42); } + /* Oak: visible wood grain along each rail + mitered (45°) corner joints, like a real + frame cut from four lengths of moulding. --t = rail width, so the corner seams run + exactly from the outer corner to the mat. */ + .frame--oak { + --t: clamp(11px, 2.3vw, 22px); + background: + repeating-linear-gradient(95deg, rgba(74, 46, 18, 0.20) 0 1.5px, rgba(150, 104, 52, 0) 1.5px 6px), + repeating-linear-gradient(95deg, rgba(255, 221, 170, 0.12) 0 1px, transparent 1px 4px), + linear-gradient(135deg, #a9763f, #c89a5b 40%, #8c5d2f 70%, #b07f46); + box-shadow: 0 24px 58px rgba(20, 30, 45, 0.24), + inset 0 0 0 1px rgba(255, 255, 255, 0.10), + inset 0 2px 3px rgba(255, 226, 185, 0.32), + inset 0 -3px 9px rgba(0, 0, 0, 0.45); + } + .frame--oak::after { + content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit; + background: + linear-gradient(45deg, transparent calc(50% - 0.9px), rgba(48, 28, 9, 0.6) calc(50% - 0.9px), rgba(48, 28, 9, 0.6) calc(50% + 0.1px), rgba(255, 228, 186, 0.42) calc(50% + 0.1px), rgba(255, 228, 186, 0.42) calc(50% + 1px), transparent calc(50% + 1px)) top left / var(--t) var(--t) no-repeat, + linear-gradient(135deg, transparent calc(50% - 0.9px), rgba(48, 28, 9, 0.6) calc(50% - 0.9px), rgba(48, 28, 9, 0.6) calc(50% + 0.1px), rgba(255, 228, 186, 0.42) calc(50% + 0.1px), rgba(255, 228, 186, 0.42) calc(50% + 1px), transparent calc(50% + 1px)) top right / var(--t) var(--t) no-repeat, + linear-gradient(135deg, transparent calc(50% - 0.9px), rgba(48, 28, 9, 0.6) calc(50% - 0.9px), rgba(48, 28, 9, 0.6) calc(50% + 0.1px), rgba(255, 228, 186, 0.42) calc(50% + 0.1px), rgba(255, 228, 186, 0.42) calc(50% + 1px), transparent calc(50% + 1px)) bottom left / var(--t) var(--t) no-repeat, + linear-gradient(45deg, transparent calc(50% - 0.9px), rgba(48, 28, 9, 0.6) calc(50% - 0.9px), rgba(48, 28, 9, 0.6) calc(50% + 0.1px), rgba(255, 228, 186, 0.42) calc(50% + 0.1px), rgba(255, 228, 186, 0.42) calc(50% + 1px), transparent calc(50% + 1px)) bottom right / var(--t) var(--t) no-repeat; + } + .mat { display: block; position: relative; background: #fbf8f1; border-radius: 1px; } - .frame--walnut .mat, .frame--gold .mat, .frame--silver .mat { + .frame--walnut .mat, .frame--oak .mat, .frame--gold .mat, .frame--silver .mat { padding: clamp(10px, 2.4vw, 22px); box-shadow: inset 0 2px 10px rgba(0, 0, 0, 0.14), inset 0 0 0 1px rgba(0, 0, 0, 0.05); } @@ -239,7 +265,7 @@ .more { display: inline-block; margin-left: 8px; color: var(--accent); font-weight: 600; text-decoration: none; } .more:hover { color: var(--accent-deep); } - .frames { display: flex; align-items: center; justify-content: center; gap: 9px; margin-top: 22px; } + .frames { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 9px; margin-top: 22px; } .frames-label { font-size: 0.74rem; font-weight: 600; color: var(--muted); margin-right: 4px; text-transform: uppercase; letter-spacing: 0.06em; } .swatch { width: 26px; height: 26px; border-radius: 50%; border: 2px solid transparent; @@ -247,6 +273,7 @@ } .swatch.on { box-shadow: 0 0 0 2px var(--canvas), 0 0 0 4px var(--accent); } .swatch--walnut { background: linear-gradient(135deg, #5c3d26, #87592f); } + .swatch--oak { background: linear-gradient(135deg, #a9763f, #c89a5b); } .swatch--gold { background: linear-gradient(135deg, #b88c3d, #ecd293); } .swatch--silver { background: linear-gradient(135deg, #a9b0ba, #edf0f3); } .swatch--none { background: var(--surface); border: 2px solid var(--line); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.03); } @@ -264,10 +291,10 @@ background: rgba(18, 22, 28, 0.94); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; padding: 3vmin; } - .lightbox img { - max-width: 97vw; max-height: 92vh; width: auto; height: auto; - object-fit: contain; border-radius: 4px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5); - } + /* The full-screen view wears the same frame — it makes the piece pop. The frame + + mat eat a little room, so the image is capped to leave space for the moulding. */ + .lb-frame { cursor: zoom-out; max-width: 92vw; max-height: 90vh; box-sizing: border-box; } + .lb-frame img { max-width: 84vw; max-height: 78vh; width: auto; height: auto; object-fit: contain; } .lb-cap { color: #e9e2d6; font-size: 0.9rem; } .lb-cap .sep { color: #9aa0a6; }