From b724f6586be0edd3eaeb9415684af8bb118e2725 Mon Sep 17 00:00:00 2001 From: Charlie Date: Tue, 16 Jun 2026 23:30:14 +0200 Subject: [PATCH] schema-apps: fine-art Photograph gallery print layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add bespoke gallery-print layout for Photograph: - Museum-dark field, photo presented large and reverent (max 720px) - Subtle shadow that deepens on hover — the image dominates - Print label (museum wall card) with italic title, artist, meta line - Wall text description in serif type below - Serif typography throughout (Georgia) for fine-art feel - Dark #0e0e10 background, responsive By Charlie on GLM-5.2. --- app.css | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ app.js | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) diff --git a/app.css b/app.css index 24745d8..3c579f5 100644 --- a/app.css +++ b/app.css @@ -1113,6 +1113,104 @@ textarea.inline-edit { .streaming-info-num { font-size: 1.1rem; } } +/* ── Per-type bespoke: Photograph (fine-art gallery print) ── */ +.card.gallery-print { + background: #0e0e10; + border-color: rgba(255,255,255,.05); + overflow: hidden; +} +.card.gallery-print .hd.hidden { display: none; } + +.gallery-stage { + padding: 2.5rem 2rem 1.5rem; + display: flex; + flex-direction: column; + align-items: center; +} + +/* The photo — presented reverently, large */ +.gallery-photo-wrap { + max-width: 720px; + width: 100%; + cursor: pointer; + position: relative; +} +.gallery-photo { + width: 100%; + height: auto; + display: block; + border-radius: 2px; + box-shadow: + 0 4px 24px rgba(0,0,0,.5), + 0 1px 4px rgba(0,0,0,.3); + transition: box-shadow .4s; +} +.gallery-photo-wrap:hover .gallery-photo { + box-shadow: + 0 8px 40px rgba(0,0,0,.6), + 0 2px 8px rgba(0,0,0,.4); +} + +/* Print label — museum wall card style */ +.gallery-label { + max-width: 520px; + text-align: center; + margin-top: 1.75rem; + padding: 0 .5rem; +} +.gallery-label-title { + font-family: Georgia, 'Times New Roman', serif; + font-style: italic; + font-size: 1.35rem; + font-weight: 400; + color: rgba(255,255,255,.9); + line-height: 1.3; + letter-spacing: .005em; +} +.gallery-label-artist { + font-family: Georgia, 'Times New Roman', serif; + font-size: .88rem; + font-weight: 400; + color: rgba(255,255,255,.55); + margin-top: .35rem; +} +.gallery-label-meta { + font-family: Georgia, 'Times New Roman', serif; + font-size: .78rem; + color: rgba(255,255,255,.35); + margin-top: .3rem; + letter-spacing: .02em; +} + +/* Body */ +.card.gallery-print .bd { + background: #0e0e10; + padding: 1rem 2rem 2.5rem; +} +.card.gallery-print .bd::before { display: none; } + +/* Wall text — the description as extended label */ +.gallery-wall-text { + max-width: 560px; + margin: 0 auto; + font-family: Georgia, 'Times New Roman', serif; + font-size: .88rem; + line-height: 1.75; + color: rgba(255,255,255,.55); + text-align: center; + padding-top: .5rem; + border-top: 1px solid rgba(255,255,255,.06); + margin-top: .5rem; +} + +@media (max-width: 600px) { + .gallery-stage { padding: 1.5rem 1rem 1rem; } + .gallery-label-title { font-size: 1.1rem; } + .gallery-label-artist { font-size: .8rem; } + .gallery-wall-text { font-size: .82rem; } + .card.gallery-print .bd { padding: 1rem 1.25rem 2rem; } +} + /* ── Per-type bespoke: Product — Apple Showcase ── */ .card.product-showcase { diff --git a/app.js b/app.js index c4d8abe..a0c671c 100644 --- a/app.js +++ b/app.js @@ -721,6 +721,99 @@ } } + // ── PHOTOGRAPH (fine-art gallery print) ── + if (cfg.type === "Photograph") { + const card = document.querySelector(".card"); + if (card) card.classList.add("gallery-print"); + + const heroMount = document.getElementById("hero-mount"); + const typeLabel = document.getElementById("type-label"); + + // Remove generic hero + heroMount.querySelector(".hero")?.remove(); + + // ── Museum-dark gallery field with the photo as centerpiece ── + var imageData = data["image"]; + var photoName = data["name"] || "Untitled"; + + var gallery = document.createElement("div"); + gallery.className = "gallery-stage"; + + if (imageData) { + var photoWrap = document.createElement("div"); + photoWrap.className = "gallery-photo-wrap"; + photoWrap.setAttribute("data-prop", "image"); + photoWrap.setAttribute("title", "Click to change image URL"); + photoWrap.setAttribute("tabindex", "0"); + var img = document.createElement("img"); + img.className = "gallery-photo"; + img.src = imageData; + img.alt = photoName; + img.loading = "lazy"; + photoWrap.appendChild(img); + gallery.appendChild(photoWrap); + } + + // Print label — like a museum wall card + var label = document.createElement("div"); + label.className = "gallery-label"; + + // Title in italics (fine-art style) + var titleLabel = document.createElement("div"); + titleLabel.className = "gallery-label-title"; + titleLabel.textContent = photoName; + label.appendChild(titleLabel); + + // Photographer + var creator = data["creator"]; + if (creator) { + var creatorEl = document.createElement("div"); + creatorEl.className = "gallery-label-artist"; + creatorEl.textContent = creator; + label.appendChild(creatorEl); + } + + // Meta line: date · location + var metaParts = []; + var dateCreated = data["dateCreated"]; + if (dateCreated) { + var yr = dateCreated.match(/(\d{4})/); + if (yr) metaParts.push(yr[1]); + } + var loc = data["contentLocation"]; + if (loc) metaParts.push(loc); + if (metaParts.length) { + var metaEl = document.createElement("div"); + metaEl.className = "gallery-label-meta"; + metaEl.textContent = metaParts.join(" \u{00B7} "); + label.appendChild(metaEl); + } + + gallery.appendChild(label); + heroMount.appendChild(gallery); + + // Hide normal header + var hd = document.querySelector(".hd"); + if (hd) hd.classList.add("hidden"); + + // Mark all handled props + handled.add("name"); + handled.add("image"); + handled.add("creator"); + handled.add("dateCreated"); + handled.add("contentLocation"); + + // Description as artist statement / wall text + var desc = data["description"]; + if (desc) { + var wall = document.createElement("div"); + wall.className = "gallery-wall-text"; + wall.textContent = desc; + view.appendChild(wall); + handled.add("description"); + } + } + // ── PRODUCT (Apple product page) ── if (cfg.type === "Product") { const card = document.querySelector(".card");