Book a callGitHub10

Kyoto, three days

Sat 15 to Mon 17 Nov · 2 travellers · 9 stops

Arrive in Kyoto

  1. Train to KyotoTokyo to Kyoto · car 7, seat 12DConfirmation JR-58214
  2. Bedroom with a wooden bed and a garden view
    Check in at Kanbe House2 nights · Gion · key code at the doorConfirmation KH-3390
  3. Bowl of ramen with egg, chili and scallions
    Dinner at Sobaya RitsuTable for 2 · counter seatsConfirmation R-1147

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.

Source
<!-- 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>

More like this

ConsumerFriendly · Games

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.

B2BDense · Finance

Selectable table

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.

B2BQuiet · Finance

Approval panel

One bill waiting for approval: the amount, the policy that applies, who has approved so far, and what the balance will be after paying.

Your kit

Nothing here yet. Add parts with Add to kit, and a look if you want the whole system.

    Parts
    0
    Files to fetch
    0 KB
    Licence
    MIT
    Total
    Free, now and later

    How do you want it?

    Your prompt

    No sign-up. Nothing leaves your browser until you paste it.

    Free