Leaderboard
A game or challenge leaderboard: a calm podium of the top three with photos and a crown for first, ranked rows with photos and how far each moved up or down, your own row pinned and highlighted, and a this week or all time switch.
Sat 15 to Mon 17 Nov · 2 travellers · 9 stops
Arrive in Kyoto
Shrines and tea
Home
It is live: hover, focus and its own controls respond. Actions that would change data (approve, send, delete) are for your app to wire. The width is a real 390 px, 768 px or 1280 px box, shrunk to fit your screen.
<!-- Icons: Lucide (lucide.dev), ISC licence -->
<style>
.odl-itinerary { box-sizing: border-box; inline-size: 100%; max-inline-size: 52rem; margin-inline: auto; container-type: inline-size; color: var(--ds-color-text-primary); font: var(--ds-text-body-md); text-wrap: pretty; }
.odl-itinerary *, .odl-itinerary *::before, .odl-itinerary *::after { box-sizing: border-box; }
.odl-itinerary .odl-head { display: grid; gap: var(--ds-space-stack-xs); margin-block-end: var(--ds-space-stack-lg); }
.odl-itinerary h3 { margin: 0; font: var(--ds-text-title-lg); }
.odl-itinerary .odl-sub { margin: 0; color: var(--ds-color-text-secondary); font: var(--ds-text-body-md); }
.odl-itinerary .odl-tabs { display: flex; gap: var(--ds-space-inline-sm); margin-block-end: var(--ds-space-stack-lg); overflow-x: auto; scrollbar-width: none; }
.odl-itinerary .odl-tabs button { display: grid; flex: 1 1 0; justify-items: start; align-content: center; gap: var(--ds-space-2); min-inline-size: max-content; min-block-size: max(var(--ds-size-control-lg), var(--ds-size-target-min)); padding: var(--ds-space-inset-xs) var(--ds-space-inset-md);
border: var(--ds-border-width-default) solid var(--ds-color-border-default); border-radius: var(--ds-radius-control); background: var(--ds-color-surface-raised); color: var(--ds-color-text-primary);
font: var(--ds-text-label-lg); text-align: start; cursor: pointer; transition: background-color var(--ds-motion-duration-short) var(--ds-motion-easing-standard); }
.odl-itinerary .odl-tabs b { font: inherit; }
.odl-itinerary .odl-tabs small { color: var(--ds-color-text-secondary); font: var(--ds-text-label-md); white-space: nowrap; }
.odl-itinerary .odl-tabs button:hover { border-color: var(--ds-color-border-strong); }
.odl-itinerary .odl-tabs button[aria-selected="true"] { background: var(--ds-color-bg-inverse); border-color: var(--ds-color-bg-inverse); color: var(--ds-color-text-inverse); }
.odl-itinerary .odl-tabs button[aria-selected="true"] small { color: var(--ds-color-text-inverse); }
.odl-itinerary .odl-grid { display: grid; gap: var(--ds-space-stack-lg); }
.odl-itinerary .odl-tabs::-webkit-scrollbar { display: none; }
.odl-itinerary .odl-map { border-radius: var(--ds-radius-container); overflow: hidden; border: var(--ds-border-width-default) solid var(--ds-color-border-subtle); background: var(--ds-color-success-light-2); }
.odl-itinerary .odl-map svg { display: block; inline-size: 100%; block-size: auto; aspect-ratio: 2 / 1; max-block-size: 16rem; }
.odl-itinerary .m-park { fill: var(--ds-color-success-light-4); }
.odl-itinerary .m-block { fill: var(--ds-color-neutral-light-3); }
.odl-itinerary .m-river { fill: none; stroke: var(--ds-color-info-light-6); stroke-width: 14; stroke-linecap: round; }
.odl-itinerary .m-road { fill: none; stroke: var(--ds-color-white); stroke-width: 5; stroke-linecap: round; }
.odl-itinerary .m-road.is-small { stroke-width: 2.5; }
.odl-itinerary .m-route { fill: none; stroke: var(--ds-color-accent-light-9); stroke-width: 2.5; stroke-dasharray: 5 5; stroke-linecap: round; stroke-linejoin: round; }
.odl-itinerary .m-pin path { fill: var(--ds-color-accent-light-9); stroke: var(--ds-color-white); stroke-width: 2; }
.odl-itinerary .m-pin text { fill: var(--ds-color-white); font: var(--ds-text-label-sm); font-weight: var(--ds-font-weight-heading); }
.odl-itinerary .m-pin.is-on path { fill: var(--ds-color-neutral-light-12); }
.odl-itinerary .m-pin { transition: transform var(--ds-motion-duration-short) var(--ds-motion-easing-standard); }
.odl-itinerary .odl-dayname { margin: 0 0 var(--ds-space-stack-md); font: var(--ds-text-title-md); }
.odl-itinerary .odl-panel[hidden], .odl-itinerary .odl-pins[hidden] { display: none; }
/* The time leads each stop's card; the node and line run down the left. */
.odl-itinerary .odl-line { --node: var(--ds-size-control-md); display: grid; margin: 0; padding: 0; list-style: none; }
.odl-itinerary .odl-line li { position: relative; display: grid; grid-template-columns: var(--node) minmax(0, 1fr); column-gap: var(--ds-space-inline-md); padding-block-end: var(--ds-space-stack-md); }
.odl-itinerary .odl-line li:last-child { padding-block-end: 0; }
.odl-itinerary .odl-line li::before { content: ""; position: absolute; inset-block: calc(var(--node) + var(--ds-space-stack-xs)) var(--ds-space-stack-xs); inset-inline-start: calc(var(--node) / 2); inline-size: var(--ds-border-width-emphasis);
transform: translateX(-50%); border-radius: var(--ds-radius-full); background: var(--ds-color-border-subtle); }
.odl-itinerary .odl-line li:last-child::before { display: none; }
.odl-itinerary .odl-time { color: var(--ds-color-text-secondary); font: var(--ds-text-label-md); font-variant-numeric: tabular-nums; }
.odl-itinerary .odl-node { display: grid; place-items: center; inline-size: var(--node); block-size: var(--node); border-radius: var(--ds-radius-full);
background: var(--ds-color-surface-sunken); border: var(--ds-border-width-default) solid var(--ds-color-border-subtle); color: var(--ds-color-icon-default); }
.odl-itinerary .odl-node svg { inline-size: var(--ds-size-icon-sm); block-size: var(--ds-size-icon-sm); stroke-width: var(--ds-icon-stroke-md); }
.odl-itinerary .odl-stop { --pad: var(--ds-space-inset-md); position: relative; display: flex; align-items: flex-start; gap: var(--ds-space-inline-md); padding: var(--pad); background: var(--ds-color-surface-raised);
border: var(--ds-border-width-default) solid var(--ds-color-border-subtle); border-radius: var(--ds-radius-container); }
.odl-itinerary .odl-stop img { flex: none; display: block; inline-size: var(--ds-size-control-lg); block-size: var(--ds-size-control-lg); border-radius: max(0px, calc(var(--ds-radius-container) - var(--pad) - var(--ds-border-width-default))); object-fit: cover; background: var(--ds-color-surface-sunken); }
.odl-itinerary .odl-txt { display: grid; flex: 1; justify-items: start; gap: var(--ds-space-stack-xs); min-inline-size: 0; }
.odl-itinerary .odl-txt b { font: var(--ds-text-label-lg); }
.odl-itinerary .odl-txt small { color: var(--ds-color-text-secondary); font: var(--ds-text-label-md); }
.odl-itinerary .odl-code { margin-block-start: var(--ds-space-stack-xs); padding: var(--ds-space-2) var(--ds-space-inset-xs); border-radius: var(--ds-radius-control-sm); background: var(--ds-color-bg-neutral-subtle); color: var(--ds-color-text-secondary);
font: var(--ds-text-code-sm); letter-spacing: var(--ds-text-label-sm-tracking); }
/* The stop's number, matching its pin on the map; pressing it highlights the pin. */
.odl-itinerary .odl-top { display: flex; justify-self: stretch; align-items: center; justify-content: space-between; gap: var(--ds-space-inline-sm); }
.odl-itinerary .odl-pin { flex: none; display: grid; place-items: center; inline-size: var(--ds-size-target-min); block-size: var(--ds-size-target-min); margin: calc((var(--ds-size-control-sm) - var(--ds-size-target-min)) / 2); padding: 0; border: 0;
border-radius: var(--ds-radius-full); background: transparent; color: var(--ds-color-text-secondary); font: var(--ds-text-label-md); font-variant-numeric: tabular-nums; cursor: pointer; isolation: isolate; position: relative; }
.odl-itinerary .odl-pin::before { content: ""; position: absolute; z-index: -1; inset: 50% auto auto 50%; inline-size: var(--ds-size-control-sm); aspect-ratio: 1; transform: translate(-50%, -50%); border-radius: var(--ds-radius-full);
border: var(--ds-border-width-default) solid var(--ds-color-border-default); background: var(--ds-color-surface-raised); transition: background-color var(--ds-motion-duration-short) var(--ds-motion-easing-standard); }
.odl-itinerary .odl-pin:hover::before { background: var(--ds-color-bg-neutral-subtle); }
.odl-itinerary .odl-pin[aria-pressed="true"] { color: var(--ds-color-text-on-accent); }
.odl-itinerary .odl-pin[aria-pressed="true"]::before { background: var(--ds-color-bg-accent-bold); border-color: var(--ds-color-bg-accent-bold); }
.odl-itinerary button:focus-visible { outline: var(--ds-focus-ring-width) solid var(--ds-color-border-focus); outline-offset: var(--ds-focus-ring-offset); }
.odl-itinerary .odl-sr { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
@container (min-width: 36rem) { .odl-itinerary .odl-stop { --pad: var(--ds-space-inset-lg); } }
@container (min-width: 48rem) {
.odl-itinerary .odl-grid { grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr); align-items: start; column-gap: var(--ds-space-section-sm); }
.odl-itinerary .odl-grid { align-items: stretch; }
.odl-itinerary .odl-map { grid-column: 2; grid-row: 1; display: grid; min-block-size: 18rem; }
.odl-itinerary .odl-map svg { block-size: 100%; aspect-ratio: auto; max-block-size: none; }
.odl-itinerary .odl-tabs button { flex: 0 0 11rem; }
}
@media (prefers-reduced-motion: reduce) { .odl-itinerary, .odl-itinerary *, .odl-itinerary *::before { transition: none !important; animation: none !important; } }
</style>
<section class="odl-itinerary" aria-labelledby="odl-it-title">
<div class="odl-head">
<h3 id="odl-it-title">Kyoto, three days</h3>
<p class="odl-sub">Sat 15 to Mon 17 Nov · 2 travellers · 9 stops</p>
</div>
<div class="odl-tabs" role="tablist" aria-label="Days"><button type="button" role="tab" id="odl-it-t1" aria-controls="odl-it-p1" aria-selected="true" tabindex="0"><b>Day 1</b><small>Sat 15 Nov</small></button><button type="button" role="tab" id="odl-it-t2" aria-controls="odl-it-p2" aria-selected="false" tabindex="-1"><b>Day 2</b><small>Sun 16 Nov</small></button><button type="button" role="tab" id="odl-it-t3" aria-controls="odl-it-p3" aria-selected="false" tabindex="-1"><b>Day 3</b><small>Mon 17 Nov</small></button></div>
<div class="odl-grid">
<div class="odl-map" aria-hidden="true">
<svg viewBox="0 0 400 400" preserveAspectRatio="xMidYMid slice">
<rect class="m-park" x="30" y="250" width="120" height="70" rx="14"/><rect class="m-park" x="300" y="70" width="80" height="60" rx="12"/><rect class="m-park" x="40" y="20" width="90" height="50" rx="12"/><rect class="m-park" x="270" y="330" width="100" height="50" rx="12"/>
<rect class="m-block" x="160" y="80" width="60" height="40" rx="5"/><rect class="m-block" x="160" y="170" width="50" height="40" rx="5"/><rect class="m-block" x="280" y="190" width="80" height="34" rx="5"/>
<rect class="m-block" x="50" y="110" width="80" height="50" rx="5"/><rect class="m-block" x="280" y="250" width="60" height="40" rx="5"/><rect class="m-block" x="170" y="300" width="60" height="50" rx="5"/><rect class="m-block" x="50" y="340" width="70" height="40" rx="5"/>
<path class="m-river" d="M232 -10C220 80 250 150 236 220S250 330 240 410"/>
<path class="m-road" d="M-10 200H410M140 -10V410M340 -10 355 410"/>
<path class="m-road is-small" d="M-10 90H410M-10 280H410M-10 360H410M70 -10V410M265 -10V410"/>
<g class="odl-pins" data-day="1"><path class="m-route" d="M128 216 L207 173 L242 207"/><g class="m-pin" data-pin="1" transform="translate(128 216)"><path d="M0 0c-7-8-11-12-11-17a11 11 0 0 1 22 0c0 5-4 9-11 17z"/><text x="0" y="-13.5" text-anchor="middle">1</text></g><g class="m-pin" data-pin="2" transform="translate(207 173)"><path d="M0 0c-7-8-11-12-11-17a11 11 0 0 1 22 0c0 5-4 9-11 17z"/><text x="0" y="-13.5" text-anchor="middle">2</text></g><g class="m-pin" data-pin="3" transform="translate(242 207)"><path d="M0 0c-7-8-11-12-11-17a11 11 0 0 1 22 0c0 5-4 9-11 17z"/><text x="0" y="-13.5" text-anchor="middle">3</text></g></g><g class="odl-pins" data-day="2" hidden><path class="m-route" d="M148 242 L218 160 L182 194"/><g class="m-pin" data-pin="1" transform="translate(148 242)"><path d="M0 0c-7-8-11-12-11-17a11 11 0 0 1 22 0c0 5-4 9-11 17z"/><text x="0" y="-13.5" text-anchor="middle">1</text></g><g class="m-pin" data-pin="2" transform="translate(218 160)"><path d="M0 0c-7-8-11-12-11-17a11 11 0 0 1 22 0c0 5-4 9-11 17z"/><text x="0" y="-13.5" text-anchor="middle">2</text></g><g class="m-pin" data-pin="3" transform="translate(182 194)"><path d="M0 0c-7-8-11-12-11-17a11 11 0 0 1 22 0c0 5-4 9-11 17z"/><text x="0" y="-13.5" text-anchor="middle">3</text></g></g><g class="odl-pins" data-day="3" hidden><path class="m-route" d="M207 173 L138 229 L272 250"/><g class="m-pin" data-pin="1" transform="translate(207 173)"><path d="M0 0c-7-8-11-12-11-17a11 11 0 0 1 22 0c0 5-4 9-11 17z"/><text x="0" y="-13.5" text-anchor="middle">1</text></g><g class="m-pin" data-pin="2" transform="translate(138 229)"><path d="M0 0c-7-8-11-12-11-17a11 11 0 0 1 22 0c0 5-4 9-11 17z"/><text x="0" y="-13.5" text-anchor="middle">2</text></g><g class="m-pin" data-pin="3" transform="translate(272 250)"><path d="M0 0c-7-8-11-12-11-17a11 11 0 0 1 22 0c0 5-4 9-11 17z"/><text x="0" y="-13.5" text-anchor="middle">3</text></g></g>
</svg>
</div>
<div class="odl-panels"><div class="odl-panel" role="tabpanel" id="odl-it-p1" aria-labelledby="odl-it-t1"><p class="odl-dayname">Arrive in Kyoto</p><ol class="odl-line"><li><span class="odl-node" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 3.1V7a4 4 0 0 0 8 0V3.1"/><path d="m9 15-1-1"/><path d="m15 15 1-1"/><path d="M9 19c-2.8 0-5-2.2-5-5v-4a8 8 0 0 1 16 0v4c0 2.8-2.2 5-5 5Z"/><path d="m8 19-2 3"/><path d="m16 19 2 3"/></svg></span><div class="odl-stop"><div class="odl-txt"><div class="odl-top"><time class="odl-time">13:20</time><button type="button" class="odl-pin" data-pin="1" aria-pressed="false" aria-label="Show Train to Kyoto on the map">1</button></div><b>Train to Kyoto</b><small>Tokyo to Kyoto · car 7, seat 12D</small><span class="odl-code"><span class="odl-sr">Confirmation </span>JR-58214</span></div></div></li><li><span class="odl-node" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 4v16"/><path d="M2 8h18a2 2 0 0 1 2 2v10"/><path d="M2 17h20"/><path d="M6 8v9"/></svg></span><div class="odl-stop"><img src="https://images.unsplash.com/photo-1611892440504-42a792e24d32?w=112&h=112&fit=crop&auto=format&q=70" alt="Bedroom with a wooden bed and a garden view" width="56" height="56" loading="lazy" decoding="async"><div class="odl-txt"><div class="odl-top"><time class="odl-time">16:00</time><button type="button" class="odl-pin" data-pin="2" aria-pressed="false" aria-label="Show Check in at Kanbe House on the map">2</button></div><b>Check in at Kanbe House</b><small>2 nights · Gion · key code at the door</small><span class="odl-code"><span class="odl-sr">Confirmation </span>KH-3390</span></div></div></li><li><span class="odl-node" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 2v7c0 1.1.9 2 2 2h4a2 2 0 0 0 2-2V2"/><path d="M7 2v20"/><path d="M21 15V2a5 5 0 0 0-5 5v6c0 1.1.9 2 2 2h3Zm0 0v7"/></svg></span><div class="odl-stop"><img src="https://images.unsplash.com/photo-1612927601601-6638404737ce?w=112&h=112&fit=crop&auto=format&q=70" alt="Bowl of ramen with egg, chili and scallions" width="56" height="56" loading="lazy" decoding="async"><div class="odl-txt"><div class="odl-top"><time class="odl-time">19:30</time><button type="button" class="odl-pin" data-pin="3" aria-pressed="false" aria-label="Show Dinner at Sobaya Ritsu on the map">3</button></div><b>Dinner at Sobaya Ritsu</b><small>Table for 2 · counter seats</small><span class="odl-code"><span class="odl-sr">Confirmation </span>R-1147</span></div></div></li></ol></div><div class="odl-panel" role="tabpanel" id="odl-it-p2" aria-labelledby="odl-it-t2" hidden><p class="odl-dayname">Shrines and tea</p><ol class="odl-line"><li><span class="odl-node" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 16v-2.38C4 11.5 2.97 10.5 3 8c.03-2.72 1.49-6 4.5-6C9.37 2 10 3.8 10 5.5c0 3.11-2 5.66-2 8.68V16a2 2 0 1 1-4 0Z"/><path d="M20 20v-2.38c0-2.12 1.03-3.12 1-5.62-.03-2.72-1.49-6-4.5-6C14.63 6 14 7.8 14 9.5c0 3.11 2 5.66 2 8.68V20a2 2 0 1 0 4 0Z"/><path d="M16 17h4"/><path d="M4 13h4"/></svg></span><div class="odl-stop"><img src="https://images.unsplash.com/photo-1503614472-8c93d56e92ce?w=112&h=112&fit=crop&auto=format&q=70" alt="Wooded mountain scenery" width="56" height="56" loading="lazy" decoding="async"><div class="odl-txt"><div class="odl-top"><time class="odl-time">08:30</time><button type="button" class="odl-pin" data-pin="1" aria-pressed="false" aria-label="Show Fushimi Inari walk on the map">1</button></div><b>Fushimi Inari walk</b><small>Go early · about 2 hours to the top</small></div></div></li><li><span class="odl-node" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 2v2"/><path d="M14 2v2"/><path d="M16 8a1 1 0 0 1 1 1v8a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1h14a4 4 0 1 1 0 8h-1"/><path d="M6 2v2"/></svg></span><div class="odl-stop"><img src="https://images.unsplash.com/photo-1616141037618-d671075fd1a1?w=112&h=112&fit=crop&auto=format&q=70" alt="Wooden table and chairs by a window" width="56" height="56" loading="lazy" decoding="async"><div class="odl-txt"><div class="odl-top"><time class="odl-time">13:00</time><button type="button" class="odl-pin" data-pin="2" aria-pressed="false" aria-label="Show Tea class with Yuki Mori on the map">2</button></div><b>Tea class with Yuki Mori</b><small>Gion · 90 minutes · English host</small><span class="odl-code"><span class="odl-sr">Confirmation </span>AS-0261</span></div></div></li><li><span class="odl-node" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 2v7c0 1.1.9 2 2 2h4a2 2 0 0 0 2-2V2"/><path d="M7 2v20"/><path d="M21 15V2a5 5 0 0 0-5 5v6c0 1.1.9 2 2 2h3Zm0 0v7"/></svg></span><div class="odl-stop"><img src="https://images.unsplash.com/photo-1601042879364-f3947d3f9c16?w=112&h=112&fit=crop&auto=format&q=70" alt="Wet street at night with neon reflections" width="56" height="56" loading="lazy" decoding="async"><div class="odl-txt"><div class="odl-top"><time class="odl-time">18:00</time><button type="button" class="odl-pin" data-pin="3" aria-pressed="false" aria-label="Show Nishiki night stalls on the map">3</button></div><b>Nishiki night stalls</b><small>Walk from Kanbe House · 12 min</small></div></div></li></ol></div><div class="odl-panel" role="tabpanel" id="odl-it-p3" aria-labelledby="odl-it-t3" hidden><p class="odl-dayname">Home</p><ol class="odl-line"><li><span class="odl-node" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 4v16"/><path d="M2 8h18a2 2 0 0 1 2 2v10"/><path d="M2 17h20"/><path d="M6 8v9"/></svg></span><div class="odl-stop"><img src="https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=112&h=112&fit=crop&auto=format&q=70" alt="Made bed in a guest room" width="56" height="56" loading="lazy" decoding="async"><div class="odl-txt"><div class="odl-top"><time class="odl-time">10:00</time><button type="button" class="odl-pin" data-pin="1" aria-pressed="false" aria-label="Show Check out of Kanbe House on the map">1</button></div><b>Check out of Kanbe House</b><small>Leave bags at the front desk until 12:00</small><span class="odl-code"><span class="odl-sr">Confirmation </span>KH-3390</span></div></div></li><li><span class="odl-node" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 3.1V7a4 4 0 0 0 8 0V3.1"/><path d="m9 15-1-1"/><path d="m15 15 1-1"/><path d="M9 19c-2.8 0-5-2.2-5-5v-4a8 8 0 0 1 16 0v4c0 2.8-2.2 5-5 5Z"/><path d="m8 19-2 3"/><path d="m16 19 2 3"/></svg></span><div class="odl-stop"><div class="odl-txt"><div class="odl-top"><time class="odl-time">12:10</time><button type="button" class="odl-pin" data-pin="2" aria-pressed="false" aria-label="Show Train to Kansai Airport on the map">2</button></div><b>Train to Kansai Airport</b><small>Haruka express · 75 min</small><span class="odl-code"><span class="odl-sr">Confirmation </span>JR-60477</span></div></div></li><li><span class="odl-node" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 22h20"/><path d="M6.36 17.4 4 17l-2-4 1.1-.55a2 2 0 0 1 1.8 0l.17.1a2 2 0 0 0 1.8 0L8 12 5 6l.9-.45a2 2 0 0 1 2.09.2l4.02 3a2 2 0 0 0 2.1.2l4.19-2.06a2.41 2.41 0 0 1 1.73-.17L21 7a1.4 1.4 0 0 1 .87 1.99l-.38.76c-.23.46-.6.84-1.07 1.08L7.58 17.2a2 2 0 0 1-1.22.18Z"/></svg></span><div class="odl-stop"><div class="odl-txt"><div class="odl-top"><time class="odl-time">15:40</time><button type="button" class="odl-pin" data-pin="3" aria-pressed="false" aria-label="Show Flight VA 483 to Lisbon on the map">3</button></div><b>Flight VA 483 to Lisbon</b><small>KIX terminal 1 · bag drop closes 14:40</small><span class="odl-code"><span class="odl-sr">Confirmation </span>K7XQ2M</span></div></div></li></ol></div></div>
</div>
</section>
<script>
document.querySelectorAll(".odl-itinerary").forEach((root) => {
if (root.dataset.odlReady) return; // wire once, even if the file is pasted twice
root.dataset.odlReady = "1";
const tabs = [...root.querySelectorAll('[role="tab"]')], panels = root.querySelectorAll('[role="tabpanel"]'), groups = root.querySelectorAll(".odl-pins");
const select = (t) => {
tabs.forEach((x, i) => { const on = x === t; x.setAttribute("aria-selected", String(on)); x.tabIndex = on ? 0 : -1;
if (panels[i]) panels[i].hidden = !on; if (groups[i]) groups[i].toggleAttribute("hidden", !on); }); // by order, not id: a preview copy has no ids
root.querySelectorAll(".m-pin").forEach((p) => p.classList.remove("is-on"));
root.querySelectorAll(".odl-pin").forEach((b) => b.setAttribute("aria-pressed", "false"));
};
tabs.forEach((t, i) => {
t.addEventListener("click", () => select(t));
t.addEventListener("keydown", (e) => { const d = e.key === "ArrowRight" ? 1 : e.key === "ArrowLeft" ? -1 : 0;
if (d) { const n = tabs[(i + d + tabs.length) % tabs.length]; select(n); n.focus(); } });
});
root.querySelectorAll(".odl-panel").forEach((panel, i) => {
const btns = panel.querySelectorAll(".odl-pin");
btns.forEach((b) => b.addEventListener("click", () => {
const on = b.getAttribute("aria-pressed") !== "true";
btns.forEach((x) => x.setAttribute("aria-pressed", String(x === b && on)));
groups[i].querySelectorAll(".m-pin").forEach((p) => p.classList.toggle("is-on", on && p.dataset.pin === b.dataset.pin));
}));
});
});
</script>
A game or challenge leaderboard: a calm podium of the top three with photos and a crown for first, ranked rows with photos and how far each moved up or down, your own row pinned and highlighted, and a this week or all time switch.
A dense table with row checkboxes, status pills and a bar of bulk actions that appears, with a live count, as soon as a row is picked.
One bill waiting for approval: the amount, the policy that applies, who has approved so far, and what the balance will be after paying.