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
146 changes: 146 additions & 0 deletions app.css
Original file line number Diff line number Diff line change
Expand Up @@ -3343,6 +3343,152 @@ footer a:hover { color: var(--accent-2); }
.quote-footnote { color: #666; border-top-color: #333; }
}


/* ── Per-type bespoke: Flight — boarding pass ── */

.card.boarding-pass { background: #fff; border-color: rgba(0,0,0,.1); }
.card.boarding-pass .hd.hidden { display: none; }
.card.boarding-pass .bd { padding: 0; background: #fff; }
.card.boarding-pass .bd::before { display: none; }

/* Top strip: airline + flight number */
.bp-strip {
display: flex;
justify-content: space-between;
align-items: center;
padding: .8rem 1.4rem;
background: #111;
color: #fff;
}
.bp-airline { font-size: .8rem; font-weight: 600; letter-spacing: .03em; text-transform: uppercase; }
.bp-flight-num { font-family: "SF Mono", "Fira Code", monospace; font-size: .85rem; font-weight: 700; letter-spacing: .05em; }

/* Route section */
.bp-route {
display: flex;
align-items: center;
justify-content: center;
padding: 1.8rem 1.4rem 1.4rem;
gap: 1rem;
}
.bp-airport-col {
display: flex;
flex-direction: column;
align-items: center;
min-width: 80px;
}
.bp-code {
font-size: 2.4rem;
font-weight: 800;
line-height: 1;
color: #111;
letter-spacing: .02em;
}
.bp-city {
font-size: .7rem;
color: #888;
margin-top: .2rem;
text-align: center;
max-width: 120px;
}
.bp-time {
font-size: .85rem;
font-weight: 600;
color: #444;
margin-top: .3rem;
}

/* Plane + dotted line */
.bp-arrow {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
min-width: 60px;
}
.bp-plane { font-size: 1.3rem; margin-bottom: .3rem; }
.bp-dots {
width: 100%;
height: 0;
border-top: 2.5px dotted rgba(0,0,0,.2);
}

/* Tear line */
.bp-tear {
position: relative;
border-top: 2px dashed rgba(0,0,0,.15);
margin: 0;
}
.bp-notch {
position: absolute;
width: 18px;
height: 18px;
border-radius: 50%;
background: var(--app-bg, #f0f0f0);
top: -10px;
}
.bp-notch:first-child { left: -10px; }
.bp-notch:last-child { right: -10px; }

/* Bottom section */
.bp-bottom {
padding: 1rem 1.4rem 1.2rem;
}

/* Fake barcode strip */
.bp-barcode {
height: 36px;
background: repeating-linear-gradient(
90deg,
#111 0px, #111 2px,
transparent 2px, transparent 4px,
#111 4px, #111 5px,
transparent 5px, transparent 8px,
#111 8px, #111 9px,
transparent 9px, transparent 11px,
#111 11px, #111 14px,
transparent 14px, transparent 16px
);
border-radius: 3px;
margin-bottom: .8rem;
opacity: .75;
}

.bp-desc {
font-size: .78rem;
line-height: 1.5;
color: #888;
margin: 0;
}

/* Dark mode boarding pass */
@media (prefers-color-scheme: dark) {
.card.boarding-pass { background: #1c1c1e; border-color: rgba(255,255,255,.06); }
.card.boarding-pass .bd { background: #1c1c1e; }
.bp-strip { background: #f5f5f5; color: #111; }
.bp-code { color: #f5f5f5; }
.bp-city { color: #666; }
.bp-time { color: #ccc; }
.bp-dots { border-top-color: rgba(255,255,255,.15); }
.bp-tear { border-top-color: rgba(255,255,255,.1); }
.bp-notch { background: #0d0d0d; }
.bp-barcode {
background: repeating-linear-gradient(
90deg,
#f5f5f5 0px, #f5f5f5 2px,
transparent 2px, transparent 4px,
#f5f5f5 4px, #f5f5f5 5px,
transparent 5px, transparent 8px,
#f5f5f5 8px, #f5f5f5 9px,
transparent 9px, transparent 11px,
#f5f5f5 11px, #f5f5f5 14px,
transparent 14px, transparent 16px
);
opacity: .6;
}
.bp-desc { color: #666; }
}

/* ──────────────────────────────────────────────
Responsive / Mobile — small-screen polish.
Stacks label/value grid, scales header,
Expand Down
82 changes: 82 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2268,6 +2268,88 @@
handled.add("text"); handled.add("author"); handled.add("dateCreated");
}

// ── FLIGHT (boarding pass) ──
if (cfg.type === "Flight") {
const card = document.querySelector(".card");
if (card) card.classList.add("boarding-pass");

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

// Remove generic hero if present
const heroMount = document.getElementById("hero-mount");
if (heroMount) heroMount.querySelector(".hero")?.remove();

// Helper: extract IATA code from string like "Name (CODE)"
const extractCode = (s) => { const m = (s || "").match(/\(([A-Z]{3})\)/); return m ? m[1] : s; };
const extractCity = (s) => { const m = (s || "").match(/^(.+?)\s*\([A-Z]{3}\)/); return m ? m[1].trim() : s; };

// Top strip: airline + flight number
const strip = document.createElement("div"); strip.className = "bp-strip";
const airline = data["provider"] || "";
const flightNum = data["flightNumber"] || "";
strip.innerHTML = "<span class=\"bp-airline\">" + airline + "</span><span class=\"bp-flight-num\">" + flightNum + "</span>";
view.appendChild(strip);

// Route section: DEPARTURE → ARRIVAL
const route = document.createElement("div"); route.className = "bp-route";

const depCode = extractCode(data["departureAirport"]);
const depCity = extractCity(data["departureAirport"]);
const depTime = data["departureTime"] || "";

const arrCode = extractCode(data["arrivalAirport"]);
const arrCity = extractCity(data["arrivalAirport"]);
const arrTime = data["arrivalTime"] || "";

// Departure column
const depCol = document.createElement("div"); depCol.className = "bp-airport-col";
depCol.innerHTML = "<div class=\"bp-code\">" + depCode + "</div><div class=\"bp-city\">" + depCity + "</div><div class=\"bp-time\">" + depTime + "</div>";
route.appendChild(depCol);

// Plane arrow in the middle
const arrow = document.createElement("div"); arrow.className = "bp-arrow";
arrow.innerHTML = "<span class=\"bp-plane\">\u2708\uFE0F</span><div class=\"bp-dots\"></div>";
route.appendChild(arrow);

// Arrival column
const arrCol = document.createElement("div"); arrCol.className = "bp-airport-col";
arrCol.innerHTML = "<div class=\"bp-code\">" + arrCode + "</div><div class=\"bp-city\">" + arrCity + "</div><div class=\"bp-time\">" + arrTime + "</div>";
route.appendChild(arrCol);

view.appendChild(route);

// Dashed tear line
const tear = document.createElement("div"); tear.className = "bp-tear";
const notchL = document.createElement("span"); notchL.className = "bp-notch";
const notchR = document.createElement("span"); notchR.className = "bp-notch";
tear.append(notchL, notchR);
view.appendChild(tear);

// Bottom: barcode strip + description
const bottom = document.createElement("div"); bottom.className = "bp-bottom";

// Fake barcode via CSS
const barcode = document.createElement("div"); barcode.className = "bp-barcode";
bottom.appendChild(barcode);

// Description as small text
const desc = data["description"];
if (desc) {
const descEl = document.createElement("p"); descEl.className = "bp-desc";
descEl.textContent = desc;
bottom.appendChild(descEl);
}

view.appendChild(bottom);

handled.add("name"); handled.add("image"); handled.add("description");
handled.add("flightNumber"); handled.add("provider");
handled.add("departureAirport"); handled.add("arrivalAirport");
handled.add("departureTime"); handled.add("arrivalTime");
}

return handled;
}

Expand Down
Loading