diff --git a/app.css b/app.css
index d01a3a8..a0daa54 100644
--- a/app.css
+++ b/app.css
@@ -5027,3 +5027,142 @@ footer a:hover { color: var(--accent-2); }
.gs-banner-overlay { padding: 0 1rem .8rem; }
.gs-blurb { padding: .4rem 0 .8rem; }
}
+
+/* ── SportsEvent — Matchday Scoreboard ── */
+.card.scoreboard {
+ border-color: rgba(22,163,74,.15);
+ overflow: hidden;
+}
+.card.scoreboard .hd.hidden { display: none; }
+
+/* Header band — bold competition name */
+.sb-header-band {
+ display: flex;
+ align-items: center;
+ gap: .4rem;
+ padding: .8rem 1.5rem;
+ background: linear-gradient(135deg, #14532d 0%, #166534 50%, #15803d 100%);
+ color: #fff;
+}
+.sb-header-icon {
+ font-size: 1.1rem;
+}
+.sb-header-title {
+ font-size: 1rem;
+ font-weight: 800;
+ letter-spacing: .01em;
+ text-shadow: 0 1px 4px rgba(0,0,0,.3);
+}
+
+/* VS row — big centered matchup */
+.sb-vs-row {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 1.5rem;
+ padding: 2rem 1.5rem 1.5rem;
+}
+.sb-team {
+ font-size: 1.4rem;
+ font-weight: 800;
+ color: var(--ink);
+ text-align: center;
+ flex: 1;
+ line-height: 1.2;
+}
+.sb-team-home { text-align: right; }
+.sb-team-away { text-align: left; }
+.sb-vs-badge {
+ flex: 0 0 auto;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 3rem; height: 3rem;
+ border-radius: 50%;
+ background: #166534;
+ color: #fff;
+ font-size: .75rem;
+ font-weight: 900;
+ letter-spacing: .05em;
+ box-shadow: 0 2px 8px rgba(22,101,52,.4);
+}
+.sb-event-big {
+ font-size: 1.6rem;
+ font-weight: 800;
+ color: var(--ink);
+ text-align: center;
+ line-height: 1.2;
+}
+
+/* Fixture info strip */
+.sb-fixture-strip {
+ display: flex;
+ flex-direction: column;
+ gap: .4rem;
+ padding: .6rem 1.5rem 1rem;
+ border-top: 1px solid var(--line);
+ border-bottom: 1px solid var(--line);
+ background: rgba(22,163,74,.03);
+}
+.sb-fixture-row {
+ display: flex;
+ align-items: center;
+ gap: .5rem;
+ font-size: .82rem;
+ color: var(--ink-2);
+}
+.sb-fixture-icon {
+ font-size: .9rem;
+ width: 1.4rem;
+ text-align: center;
+}
+
+/* Get Tickets CTA */
+.sb-tickets-cta {
+ display: inline-flex;
+ align-items: center;
+ gap: .3rem;
+ margin: .6rem 1.5rem;
+ padding: .55rem 1.4rem;
+ background: linear-gradient(to bottom, #16a34a 5%, #15803d 95%);
+ color: #fff;
+ font-size: .85rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ letter-spacing: .03em;
+ border-radius: 4px;
+ text-decoration: none;
+ box-shadow: 0 2px 6px rgba(22,101,52,.3);
+ transition: background .15s;
+}
+.sb-tickets-cta:hover {
+ background: linear-gradient(to bottom, #22c55e 5%, #16a34a 95%);
+}
+
+/* Match overview */
+.sb-overview {
+ padding: .4rem 1.5rem 1rem;
+}
+.sb-overview-label {
+ font-size: .9rem;
+ font-weight: 700;
+ color: var(--ink);
+ margin-bottom: .4rem;
+}
+.sb-overview-body {
+ font-size: .84rem;
+ line-height: 1.7;
+ color: var(--muted);
+ margin: 0;
+}
+
+@media (max-width: 480px) {
+ .sb-header-band { padding: .6rem 1rem; }
+ .sb-header-title { font-size: .85rem; }
+ .sb-vs-row { gap: .8rem; padding: 1.5rem 1rem 1rem; }
+ .sb-team { font-size: 1.1rem; }
+ .sb-vs-badge { width: 2.5rem; height: 2.5rem; font-size: .65rem; }
+ .sb-fixture-strip { padding: .5rem 1rem .8rem; }
+ .sb-tickets-cta { margin: .5rem 1rem; }
+ .sb-overview { padding: .4rem 1rem .8rem; }
+}
diff --git a/app.js b/app.js
index d4cb26e..a998b5d 100644
--- a/app.js
+++ b/app.js
@@ -3280,6 +3280,114 @@
}
}
+ // ── SPORTSEVENT (Matchday Scoreboard) ──
+ if (cfg.type === "SportsEvent") {
+ const card = document.querySelector(".card");
+ if (card) card.classList.add("scoreboard");
+
+ // Hide normal header
+ const hd = document.querySelector(".hd");
+ if (hd) hd.classList.add("hidden");
+
+ // Remove generic hero — we build our own
+ const heroMount = document.getElementById("hero-mount");
+ if (heroMount) heroMount.querySelector('.hero')?.remove();
+
+ // ── Bold header band with competition name ──
+ const eventName = data[cfg.titleProp] || "";
+ const headerBand = document.createElement("div"); headerBand.className = "sb-header-band";
+ const iconSpan = document.createElement("span"); iconSpan.className = "sb-header-icon";
+ iconSpan.textContent = (cfg.icon || "⚽") + " ";
+ headerBand.appendChild(iconSpan);
+ const bandTitle = document.createElement("span"); bandTitle.className = "sb-header-title";
+ bandTitle.textContent = eventName;
+ headerBand.appendChild(bandTitle);
+ heroMount.appendChild(headerBand);
+ handled.add("name"); handled.add("image");
+
+ // ── Big centered VS row ──
+ // Try to infer home vs away from the name (e.g. "Team A vs Team B")
+ let homeName = "", awayName = "";
+ const vsMatch = eventName.match(/(.+?)\s+(?:vs?\.?|[:–\-])\s+(.+)/i);
+ if (vsMatch) {
+ homeName = vsMatch[1].trim();
+ awayName = vsMatch[2].trim();
+ }
+ const vsRow = document.createElement("div"); vsRow.className = "sb-vs-row";
+ if (homeName && awayName) {
+ const homeEl = document.createElement("div"); homeEl.className = "sb-team sb-team-home";
+ homeEl.textContent = homeName;
+ const vsBadge = document.createElement("div"); vsBadge.className = "sb-vs-badge";
+ vsBadge.textContent = "VS";
+ const awayEl = document.createElement("div"); awayEl.className = "sb-team sb-team-away";
+ awayEl.textContent = awayName;
+ vsRow.append(homeEl, vsBadge, awayEl);
+ } else {
+ // No VS pattern — just show the event name large
+ const eventEl = document.createElement("div"); eventEl.className = "sb-event-big";
+ eventEl.textContent = eventName;
+ vsRow.appendChild(eventEl);
+ }
+ view.appendChild(vsRow);
+
+ // ── Fixture info strip: date + venue + organizer ──
+ const fixtureStrip = document.createElement("div"); fixtureStrip.className = "sb-fixture-strip";
+
+ const startDate = data["startDate"];
+ if (startDate) {
+ const d = new Date(startDate);
+ const dateStr = isNaN(d.getTime()) ? startDate : d.toLocaleDateString("en-GB", { weekday: "short", day: "numeric", month: "short", year: "numeric" });
+ const timeStr = isNaN(d.getTime()) ? "" : d.toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit" });
+ const dateRow = document.createElement("div"); dateRow.className = "sb-fixture-row";
+ dateRow.innerHTML = "Ὄ5 " + dateStr + (timeStr ? " · " + timeStr : "") + "";
+ fixtureStrip.appendChild(dateRow);
+ handled.add("startDate");
+ }
+ const endDate = data["endDate"];
+ if (endDate) handled.add("endDate");
+
+ const loc = data["location"];
+ if (loc) {
+ const locRow = document.createElement("div"); locRow.className = "sb-fixture-row";
+ locRow.innerHTML = "📍 " + loc + "";
+ fixtureStrip.appendChild(locRow);
+ handled.add("location");
+ }
+
+ const org = data["organizer"];
+ if (org) {
+ const orgRow = document.createElement("div"); orgRow.className = "sb-fixture-row";
+ orgRow.innerHTML = "🎫 " + org + "";
+ fixtureStrip.appendChild(orgRow);
+ handled.add("organizer");
+ }
+ if (fixtureStrip.children.length) view.appendChild(fixtureStrip);
+
+ // ── Get Tickets CTA ──
+ const url = data["url"];
+ if (url) {
+ const cta = document.createElement("a"); cta.className = "sb-tickets-cta";
+ cta.href = url; cta.target = "_blank"; cta.rel = "noopener";
+ cta.innerHTML = "Get Tickets →";
+ view.appendChild(cta);
+ handled.add("url");
+ }
+
+ // ── Description as match overview ──
+ const desc = data["description"];
+ if (desc) {
+ const overview = document.createElement("div"); overview.className = "sb-overview";
+ const label = document.createElement("div"); label.className = "sb-overview-label";
+ label.textContent = "Match Overview";
+ overview.appendChild(label);
+ const body = document.createElement("p"); body.className = "sb-overview-body";
+ body.textContent = desc;
+ overview.appendChild(body);
+ view.appendChild(overview);
+ handled.add("description");
+ }
+ }
+
return handled;
}