diff --git a/app.css b/app.css
index 81ca47f..9a35fde 100644
--- a/app.css
+++ b/app.css
@@ -5540,3 +5540,187 @@ footer a:hover { color: var(--accent-2); }
.cc-salary-box { margin: 0 1rem .6rem; padding: .6rem .8rem; }
.cc-skill-section, .cc-qual-section, .cc-overview { padding-left: 1rem; padding-right: 1rem; }
}
+
+/* ── TouristTrip — Travel Itinerary ── */
+.card.itinerary-card {
+ border-color: rgba(13,148,136,.12);
+ overflow: hidden;
+}
+.card.itinerary-card .hd.hidden { display: none; }
+
+/* Hero header */
+.ti-hero {
+ position: relative;
+ height: 260px;
+ overflow: hidden;
+}
+.ti-hero-img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ display: block;
+}
+.ti-hero-scrim {
+ position: absolute;
+ inset: 0;
+ background: linear-gradient(to bottom,
+ rgba(0,0,0,0) 0%,
+ rgba(0,0,0,.1) 40%,
+ rgba(0,0,0,.6) 70%,
+ rgba(0,0,0,.88) 100%);
+ pointer-events: none;
+}
+.ti-hero-overlay {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding: 0 1.5rem 1.2rem;
+ z-index: 2;
+}
+.ti-hero-icon {
+ font-size: 1.5rem;
+ display: block;
+ margin-bottom: .2rem;
+}
+.ti-hero-title {
+ font-size: 1.6rem;
+ font-weight: 800;
+ color: #fff;
+ line-height: 1.2;
+ letter-spacing: -.015em;
+ margin: 0;
+ text-shadow: 0 2px 12px rgba(0,0,0,.5);
+}
+
+/* Trip-style chips */
+.ti-trip-chips {
+ display: flex;
+ flex-wrap: wrap;
+ gap: .35rem;
+ padding: .8rem 1.5rem .4rem;
+}
+.ti-trip-chip {
+ display: inline-flex;
+ align-items: center;
+ gap: .25rem;
+ font-size: .73rem;
+ font-weight: 600;
+ padding: .25rem .65rem;
+ border-radius: 4px;
+ background: rgba(13,148,136,.08);
+ color: #0d9488;
+ border: 1px solid rgba(13,148,136,.15);
+}
+.ti-chip-icon {
+ font-size: .8rem;
+}
+
+/* Section label */
+.ti-section-label {
+ font-size: .7rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ letter-spacing: .12em;
+ color: var(--muted-2);
+ margin-bottom: .4rem;
+}
+
+/* Vertical timeline */
+.ti-timeline {
+ padding: .6rem 1.5rem .4rem;
+ position: relative;
+}
+.ti-timeline::before {
+ content: "";
+ position: absolute;
+ left: calc(1.5rem + 14px);
+ top: 1.2rem;
+ bottom: .8rem;
+ width: 2px;
+ background: linear-gradient(to bottom, #0d9488, #f59e0b);
+ border-radius: 1px;
+}
+.ti-timeline-stop {
+ display: flex;
+ gap: 1rem;
+ padding-bottom: 1rem;
+ position: relative;
+}
+.ti-timeline-dot {
+ flex-shrink: 0;
+ width: 30px; height: 30px;
+ border-radius: 50%;
+ background: linear-gradient(135deg, #0d9488, #14b8a6);
+ color: #fff;
+ font-size: .72rem;
+ font-weight: 800;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 2px 6px rgba(13,148,136,.3);
+ border: 2px solid var(--card-bg, #fff);
+ z-index: 1;
+}
+.ti-timeline-content {
+ flex: 1;
+ padding-top: .15rem;
+}
+.ti-timeline-label {
+ font-size: .72rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ letter-spacing: .1em;
+ color: #0d9488;
+ margin-bottom: .2rem;
+}
+.ti-timeline-body {
+ font-size: .82rem;
+ line-height: 1.65;
+ color: var(--ink-2);
+ margin: 0;
+}
+
+/* Overview fallback */
+.ti-overview {
+ padding: .6rem 1.5rem .8rem;
+}
+.ti-overview-body {
+ font-size: .84rem;
+ line-height: 1.75;
+ color: var(--muted);
+ margin: 0;
+}
+
+/* Book CTA */
+.ti-book-cta {
+ display: inline-flex;
+ align-items: center;
+ gap: .35rem;
+ margin: .4rem 1.5rem 1rem;
+ padding: .6rem 1.4rem;
+ background: linear-gradient(135deg, #0d9488, #f59e0b);
+ color: #fff;
+ font-size: .85rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ letter-spacing: .03em;
+ border-radius: 6px;
+ text-decoration: none;
+ box-shadow: 0 3px 10px rgba(13,148,136,.3);
+ transition: filter .15s;
+}
+.ti-book-cta:hover {
+ filter: brightness(1.1);
+}
+
+@media (max-width: 480px) {
+ .ti-hero { height: 200px; }
+ .ti-hero-title { font-size: 1.25rem; }
+ .ti-hero-overlay { padding: 0 1rem .8rem; }
+ .ti-trip-chips { padding: .6rem 1rem .3rem; }
+ .ti-timeline { padding: .5rem 1rem .3rem; }
+ .ti-timeline::before { left: calc(1rem + 14px); }
+ .ti-overview { padding: .5rem 1rem .6rem; }
+ .ti-book-cta { margin: .3rem 1rem .8rem; }
+}
diff --git a/app.js b/app.js
index 8f14a68..5657357 100644
--- a/app.js
+++ b/app.js
@@ -3640,6 +3640,107 @@
}
}
+ // ── TOURISTTRIP (Travel Itinerary) ──
+ if (cfg.type === "TouristTrip") {
+ const card = document.querySelector(".card");
+ if (card) card.classList.add("itinerary-card");
+
+ // Hide normal header
+ const hd = document.querySelector(".hd");
+ if (hd) hd.classList.add("hidden");
+
+ // Remove generic hero
+ const heroMount = document.getElementById("hero-mount");
+ if (heroMount) heroMount.querySelector('.hero')?.remove();
+
+ // ── Hero header with trip name + image ──
+ const tiHeader = document.createElement("div"); tiHeader.className = "ti-hero";
+ const imgUrl = data["image"];
+ if (imgUrl) {
+ const img = document.createElement("img"); img.className = "ti-hero-img";
+ img.src = imgUrl; img.alt = data[cfg.titleProp] || "";
+ img.loading = "lazy";
+ tiHeader.appendChild(img);
+ const scrim = document.createElement("div"); scrim.className = "ti-hero-scrim";
+ tiHeader.appendChild(scrim);
+ handled.add("image");
+ }
+ const tiOverlay = document.createElement("div"); tiOverlay.className = "ti-hero-overlay";
+ const tiIcon = document.createElement("span"); tiIcon.className = "ti-hero-icon";
+ tiIcon.textContent = "\u{1F9C3}";
+ tiOverlay.appendChild(tiIcon);
+ const h1 = document.createElement("h1"); h1.className = "ti-hero-title";
+ h1.textContent = data[cfg.titleProp] || "";
+ tiOverlay.appendChild(h1);
+ tiHeader.appendChild(tiOverlay);
+ heroMount.appendChild(tiHeader);
+ handled.add("name");
+
+ // ── Trip-style chips from touristType ──
+ const touristType = data["touristType"];
+ if (touristType) {
+ const chipRow = document.createElement("div"); chipRow.className = "ti-trip-chips";
+ touristType.split(",").forEach(t => {
+ const chip = document.createElement("span"); chip.className = "ti-trip-chip";
+ chip.innerHTML = "\u{1F6E9}\uFE0F " + t.trim();
+ chipRow.appendChild(chip);
+ });
+ view.appendChild(chipRow);
+ handled.add("touristType");
+ }
+
+ // ── Day-by-day timeline from description ──
+ const desc = data["description"];
+ if (desc) {
+ // Parse "Day one: ... Day two: ..." or "Day 1: ... Day 2: ..." patterns
+ const dayParts = desc.split(/\s*Day\s+(?:one|two|three|four|five|six|seven|eight|1|2|3|4|5|6|7|8)[:.]?\s*/i)
+ .filter(s => s.trim());
+ const dayLabels = desc.match(/Day\s+(?:one|two|three|four|five|six|seven|eight|1|2|3|4|5|6|7|8)[:.]?/gi);
+
+ if (dayParts.length >= 2 && dayLabels && dayLabels.length >= 2) {
+ // Render as vertical timeline
+ const timeline = document.createElement("div"); timeline.className = "ti-timeline";
+ dayParts.forEach((text, i) => {
+ const stop = document.createElement("div"); stop.className = "ti-timeline-stop";
+ const dot = document.createElement("div"); dot.className = "ti-timeline-dot";
+ dot.textContent = String(i + 1);
+ stop.appendChild(dot);
+ const content = document.createElement("div"); content.className = "ti-timeline-content";
+ const label = document.createElement("div"); label.className = "ti-timeline-label";
+ label.textContent = dayLabels[i] ? dayLabels[i].replace(/[:.]?$/, "") : ("Day " + (i + 1));
+ content.appendChild(label);
+ const body = document.createElement("p"); body.className = "ti-timeline-body";
+ body.textContent = text.trim();
+ content.appendChild(body);
+ stop.appendChild(content);
+ timeline.appendChild(stop);
+ });
+ view.appendChild(timeline);
+ } else {
+ // No day pattern — show as overview
+ const overview = document.createElement("div"); overview.className = "ti-overview";
+ const label = document.createElement("div"); label.className = "ti-section-label";
+ label.textContent = "Trip Overview";
+ overview.appendChild(label);
+ const body = document.createElement("p"); body.className = "ti-overview-body";
+ body.textContent = desc;
+ overview.appendChild(body);
+ view.appendChild(overview);
+ }
+ handled.add("description");
+ }
+
+ // ── Book This Trip CTA ──
+ const url = data["url"];
+ if (url) {
+ const cta = document.createElement("a"); cta.className = "ti-book-cta";
+ cta.href = url; cta.target = "_blank"; cta.rel = "noopener";
+ cta.innerHTML = "\u2708\uFE0F Book This Trip \u2192";
+ view.appendChild(cta);
+ handled.add("url");
+ }
+ }
+
return handled;
}