From 721c7593046635b8871112fabf371e3bb4fb6aa5 Mon Sep 17 00:00:00 2001 From: Charlie Date: Tue, 16 Jun 2026 23:37:01 +0200 Subject: [PATCH] schema-apps: bold Brand identity hero card Add bespoke brand-hero layout for Brand: - Accent-color gradient block with dot-grid texture + sheen overlay - Logo in a rounded framed mark, brand name HUGE (3rem 900-weight) - Italic slogan as hero tagline - Type badge, body with brand story + accent-colored website CTA - Like a brand style-guide hero By Charlie on GLM-5.2. --- app.css | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ app.js | 93 +++++++++++++++++++++++++++++++++++ 2 files changed, 241 insertions(+) diff --git a/app.css b/app.css index 3c579f5..7154a04 100644 --- a/app.css +++ b/app.css @@ -1113,6 +1113,154 @@ textarea.inline-edit { .streaming-info-num { font-size: 1.1rem; } } +/* ── Per-type bespoke: Brand (bold brand identity hero) ── */ +.card.brand-hero { + overflow: hidden; + border-color: color-mix(in oklab, var(--accent) 40%, var(--line)); +} +.card.brand-hero .hd.hidden { display: none; } + +.brand-block { + position: relative; + padding: 3.5rem 2.5rem 3rem; + background: + linear-gradient(135deg, + var(--accent) 0%, + color-mix(in oklab, var(--accent) 80%, #000) 100%); + color: #fff; + text-align: center; + overflow: hidden; +} +/* Dot-grid texture */ +.brand-block::before { + content: ""; + position: absolute; + inset: 0; + background-image: radial-gradient(rgba(255,255,255,.08) 1px, transparent 1px); + background-size: 20px 20px; + pointer-events: none; +} +/* Sheen */ +.brand-block::after { + content: ""; + position: absolute; + inset: 0; + background: radial-gradient(120% 120% at 20% 0%, rgba(255,255,255,.18), transparent 55%); + pointer-events: none; +} + +.brand-logo-wrap { + position: relative; + z-index: 1; + display: inline-block; + width: 88px; + height: 88px; + border-radius: 20px; + overflow: hidden; + background: rgba(255,255,255,.15); + border: 1px solid rgba(255,255,255,.2); + box-shadow: 0 4px 16px rgba(0,0,0,.2); + cursor: pointer; + margin-bottom: 1.25rem; + transition: transform .3s; +} +.brand-logo-wrap:hover { + transform: scale(1.05); +} +.brand-logo { + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} + +.brand-name { + position: relative; + z-index: 1; + margin: 0; + font-size: 3rem; + font-weight: 900; + letter-spacing: -.04em; + line-height: 1; + text-shadow: 0 2px 12px rgba(0,0,0,.2); +} + +.brand-slogan { + position: relative; + z-index: 1; + margin: .6rem 0 0; + font-size: 1.05rem; + font-weight: 400; + font-style: italic; + opacity: .82; + letter-spacing: .01em; +} + +.brand-type-badge { + position: relative; + z-index: 1; + display: inline-block; + margin-top: 1.25rem; + padding: .3rem .7rem; + border-radius: 4px; + background: rgba(255,255,255,.15); + border: 1px solid rgba(255,255,255,.18); + font-size: .6rem; + font-weight: 700; + letter-spacing: .12em; + text-transform: uppercase; + opacity: .7; +} + +/* Body */ +.card.brand-hero .bd { + padding: 1.75rem 2.5rem 2.5rem; +} +.card.brand-hero .bd::before { display: none; } + +/* Brand story */ +.brand-story { + font-size: .92rem; + line-height: 1.75; + color: var(--ink-2); + max-width: 620px; +} + +/* CTA */ +.brand-cta-wrap { + margin-top: 1.5rem; +} +.brand-cta { + display: inline-flex; + align-items: center; + gap: .4rem; + padding: .7rem 1.5rem; + border-radius: 8px; + background: var(--accent); + color: #fff; + font-size: .88rem; + font-weight: 700; + text-decoration: none; + transition: transform .2s, box-shadow .2s, opacity .2s; + box-shadow: 0 2px 8px color-mix(in oklab, var(--accent) 30%, transparent); +} +.brand-cta:hover { + transform: translateY(-2px); + box-shadow: 0 4px 16px color-mix(in oklab, var(--accent) 40%, transparent); + opacity: .95; +} +.brand-cta:active { + transform: translateY(0); +} + +@media (max-width: 600px) { + .brand-block { padding: 2.5rem 1.5rem 2rem; } + .brand-name { font-size: 2.2rem; } + .brand-slogan { font-size: .95rem; } + .brand-logo-wrap { width: 72px; height: 72px; } + .card.brand-hero .bd { padding: 1.25rem 1.5rem 2rem; } +} + /* ── Per-type bespoke: Photograph (fine-art gallery print) ── */ .card.gallery-print { background: #0e0e10; diff --git a/app.js b/app.js index a0c671c..7b58255 100644 --- a/app.js +++ b/app.js @@ -721,6 +721,99 @@ } } + // ── BRAND (bold brand identity hero) ── + if (cfg.type === "Brand") { + const card = document.querySelector(".card"); + if (card) card.classList.add("brand-hero"); + + const heroMount = document.getElementById("hero-mount"); + const typeLabel = document.getElementById("type-label"); + + // Remove generic hero + heroMount.querySelector(".hero")?.remove(); + + // ── Color block using accent as brand color ── + var brandBlock = document.createElement("div"); + brandBlock.className = "brand-block"; + + // Logo/image if present — rendered as a framed mark + var imageData = data["image"]; + if (imageData) { + var logoWrap = document.createElement("div"); + logoWrap.className = "brand-logo-wrap"; + logoWrap.setAttribute("data-prop", "image"); + logoWrap.setAttribute("title", "Click to change image URL"); + logoWrap.setAttribute("tabindex", "0"); + var img = document.createElement("img"); + img.className = "brand-logo"; + img.src = imageData; + img.alt = data["name"] || "Brand logo"; + img.loading = "lazy"; + logoWrap.appendChild(img); + brandBlock.appendChild(logoWrap); + } + + // Brand name HUGE + var nameEl = document.createElement("h1"); + nameEl.className = "brand-name"; + nameEl.textContent = data["name"] || ""; + brandBlock.appendChild(nameEl); + + // Slogan as hero tagline + var slogan = data["slogan"]; + if (slogan) { + var sloganEl = document.createElement("p"); + sloganEl.className = "brand-slogan"; + sloganEl.textContent = slogan; + brandBlock.appendChild(sloganEl); + } + + // Type badge + var badge = document.createElement("span"); + badge.className = "brand-type-badge"; + badge.textContent = "\u{2122}\u{00A0}" + (typeLabel ? typeLabel.textContent : "Brand"); + brandBlock.appendChild(badge); + + heroMount.appendChild(brandBlock); + + // Hide normal header + var hd = document.querySelector(".hd"); + if (hd) hd.classList.add("hidden"); + + // Mark handled props + handled.add("name"); + handled.add("image"); + handled.add("slogan"); + + // ── Body: description + website CTA ── + + // Description as brand story + var desc = data["description"]; + if (desc) { + var story = document.createElement("div"); + story.className = "brand-story"; + story.textContent = desc; + view.appendChild(story); + handled.add("description"); + } + + // Website CTA + var url = data["url"]; + if (url) { + var ctaWrap = document.createElement("div"); + ctaWrap.className = "brand-cta-wrap"; + var cta = document.createElement("a"); + cta.className = "brand-cta"; + cta.href = url; + cta.target = "_blank"; + cta.rel = "noopener"; + cta.textContent = "\u{1F310} Visit website"; + ctaWrap.appendChild(cta); + view.appendChild(ctaWrap); + handled.add("url"); + } + } + // ── PHOTOGRAPH (fine-art gallery print) ── if (cfg.type === "Photograph") { const card = document.querySelector(".card");