Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 171 additions & 0 deletions app.css
Original file line number Diff line number Diff line change
Expand Up @@ -4856,3 +4856,174 @@ footer a:hover { color: var(--accent-2); }
.hi-section { padding: .4rem 1rem; }
.hi-overview { padding: .6rem 1rem; }
}

/* ── VideoGame β€” Steam store page ── */
.card.game-store {
background: #1b2838;
border-color: rgba(255,255,255,.06);
box-shadow:
0 2px 8px rgba(0,0,0,.4),
0 12px 40px rgba(0,0,0,.5);
overflow: hidden;
}
.card.game-store .hd.hidden { display: none; }

/* Banner with game art */
.gs-banner {
position: relative;
height: 360px;
overflow: hidden;
margin: 0;
}
.gs-banner-img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}

/* Dark gradient scrim for text legibility */
.gs-scrim {
position: absolute;
inset: 0;
background:
linear-gradient(to bottom,
rgba(27,40,56,0) 0%,
rgba(27,40,56,.15) 40%,
rgba(27,40,56,.7) 70%,
rgba(27,40,56,.97) 95%,
rgba(27,40,56,1) 100%
);
pointer-events: none;
}

/* Title + meta overlay on banner */
.gs-banner-overlay {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 0 1.5rem 1.2rem;
z-index: 2;
}
.gs-title {
font-size: 2.2rem;
font-weight: 800;
color: #fff;
line-height: 1.1;
letter-spacing: -.02em;
margin: 0 0 .35rem;
text-shadow: 0 2px 16px rgba(0,0,0,.6);
}
.gs-banner-meta {
font-size: .8rem;
color: rgba(255,255,255,.5);
letter-spacing: .03em;
}

/* Body area β€” dark Steam surface */
.card.game-store .bd {
background: #1b2838;
color: rgba(255,255,255,.8);
padding-top: .6rem;
}
.card.game-store .bd::before {
display: none;
}

/* Tag chips */
.gs-tags {
display: flex;
flex-wrap: wrap;
gap: .3rem;
margin-bottom: .8rem;
}
.gs-tag {
font-size: .72rem;
font-weight: 600;
padding: .25rem .6rem;
border-radius: 3px;
letter-spacing: .02em;
}
.gs-tag-genre {
background: rgba(102,192,244,.12);
color: #66c0f4;
border: 1px solid rgba(102,192,244,.2);
}
.gs-tag-platform {
background: rgba(255,255,255,.06);
color: rgba(255,255,255,.5);
border: 1px solid rgba(255,255,255,.08);
}

/* Price box + Add to Cart */
.gs-price-box {
display: flex;
align-items: center;
justify-content: flex-end;
padding: .4rem 0 .8rem;
}
.gs-cart-btn {
display: inline-flex;
align-items: center;
gap: .4rem;
background: linear-gradient(to bottom, #75b022 5%, #588a1b 95%);
color: #d2efa0;
font-size: .85rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: .03em;
padding: .55rem 1.4rem;
border: none;
border-radius: 2px;
cursor: pointer;
text-shadow: 0 1px 2px rgba(0,0,0,.3);
box-shadow: 0 2px 6px rgba(0,0,0,.3);
transition: background .15s;
}
.gs-cart-btn:hover {
background: linear-gradient(to bottom, #8ed629 5%, #6ba022 95%);
color: #fff;
}
.gs-cart-icon {
font-size: .9rem;
}

/* Store blurb */
.gs-blurb {
padding: .6rem 0 1rem;
}
.gs-blurb-label {
font-size: .9rem;
font-weight: 700;
color: #fff;
margin-bottom: .5rem;
letter-spacing: .01em;
}
.gs-blurb-body {
font-size: .84rem;
line-height: 1.75;
color: rgba(255,255,255,.65);
margin: 0;
}

/* Edit/JSON-LD disclosure in dark theme */
.card.game-store details {
border-color: rgba(255,255,255,.08);
}
.card.game-store summary {
color: rgba(255,255,255,.4);
}
.card.game-store .row .k {
color: rgba(255,255,255,.4);
}
.card.game-store .row .v {
color: rgba(255,255,255,.75);
}

@media (max-width: 480px) {
.gs-banner { height: 240px; }
.gs-title { font-size: 1.5rem; }
.gs-banner-overlay { padding: 0 1rem .8rem; }
.gs-blurb { padding: .4rem 0 .8rem; }
}
109 changes: 109 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3171,6 +3171,115 @@
handled.add("answerCount"); handled.add("acceptedAnswer");
}

// ── VIDEOGAME (Steam store page) ──
if (cfg.type === "VideoGame") {
const card = document.querySelector(".card");
if (card) card.classList.add("game-store");

// Hide normal header
const hd = document.querySelector(".hd");
if (hd) hd.classList.add("hidden");

// Remove generic hero β€” we build our own banner
const heroMount = document.getElementById("hero-mount");
if (heroMount) heroMount.querySelector('.hero')?.remove();

// ── Game art banner with title overlay ──
const imgUrl = data["image"];
if (imgUrl) {
const banner = document.createElement("div"); banner.className = "gs-banner";
const img = document.createElement("img"); img.className = "gs-banner-img";
img.src = imgUrl; img.alt = data[cfg.titleProp] || "";
img.loading = "lazy";
banner.appendChild(img);

// Scrim for legibility
const scrim = document.createElement("div"); scrim.className = "gs-scrim";
banner.appendChild(scrim);

// Title overlay
const titleOverlay = document.createElement("div"); titleOverlay.className = "gs-banner-overlay";
const h1 = document.createElement("h1"); h1.className = "gs-title";
h1.textContent = data[cfg.titleProp] || "";
titleOverlay.appendChild(h1);

// Release year + publisher as small meta inside banner
const metaParts = [];
const pub = data["publisher"];
if (pub) metaParts.push(pub);
const rel = data["datePublished"];
if (rel) {
const d = new Date(rel);
const yr = isNaN(d.getTime()) ? rel : d.toLocaleDateString("en-GB", { day: "numeric", month: "short", year: "numeric" });
metaParts.push(yr);
}
if (metaParts.length) {
const meta = document.createElement("div"); meta.className = "gs-banner-meta";
meta.textContent = metaParts.join(" Β· ");
titleOverlay.appendChild(meta);
}

banner.appendChild(titleOverlay);
heroMount.appendChild(banner);
handled.add("image");
handled.add("name");
handled.add("publisher");
handled.add("datePublished");
}

// ── Tag chips: genre + platform ──
const tagItems = [];
const genre = data["genre"];
if (genre) {
genre.split(",").forEach(g => tagItems.push({ label: g.trim(), cls: "gs-tag-genre" }));
}
const platform = data["gamePlatform"];
if (platform) {
platform.split(",").forEach(p => tagItems.push({ label: p.trim(), cls: "gs-tag-platform" }));
}
if (tagItems.length) {
const tags = document.createElement("div"); tags.className = "gs-tags";
tagItems.forEach(t => {
const tag = document.createElement("span"); tag.className = "gs-tag " + t.cls;
tag.textContent = t.label;
tags.appendChild(tag);
});
view.appendChild(tags);
handled.add("genre");
handled.add("gamePlatform");
}

// ── Price box + Add to Cart ──
const priceBox = document.createElement("div"); priceBox.className = "gs-price-box";
const url = data["url"];
// Use the URL as a link wrapper if available
const cartBtn = document.createElement("button"); cartBtn.className = "gs-cart-btn";
cartBtn.type = "button";
cartBtn.innerHTML = "<span class=\"gs-cart-icon\">πŸ›’</span> Add to Cart";
priceBox.appendChild(cartBtn);
view.appendChild(priceBox);
if (url) {
// Make the whole price box clickable
priceBox.style.cursor = "pointer";
priceBox.addEventListener("click", () => window.open(url, "_blank"));
handled.add("url");
}

// ── Description as store blurb ──
const desc = data["description"];
if (desc) {
const blurb = document.createElement("div"); blurb.className = "gs-blurb";
const label = document.createElement("div"); label.className = "gs-blurb-label";
label.textContent = "About This Game";
blurb.appendChild(label);
const body = document.createElement("p"); body.className = "gs-blurb-body";
body.textContent = desc;
blurb.appendChild(body);
view.appendChild(blurb);
handled.add("description");
}
}

return handled;
}

Expand Down
Loading