<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0, viewport-fit=cover"
    />
    <title>ROUTS: Interactive Pathfinding on Real Maps | By Alatic</title>
    <meta
      name="description"
      content="ROUTS visualizes pathfinding on live OpenStreetMap roads. Compare A*, Dijkstra, bidirectional search, ALT, Prim’s, and Cascade: free in your browser. By Alatic."
    />
    <meta
      name="keywords"
      content="pathfinding, routing, A star, Dijkstra, OpenStreetMap, OSM, route visualization, shortest path, bidirectional search, map algorithms, ROUTS, Alatic"
    />
    <meta name="author" content="Alatic" />
    <meta name="creator" content="Alatic" />
    <meta name="publisher" content="Alatic" />
    <meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1" />
    <meta name="googlebot" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1" />
    <meta name="bingbot" content="index, follow" />
    <meta name="theme-color" content="#05070b" />
    <meta name="color-scheme" content="dark" />
    <meta name="application-name" content="ROUTS" />
    <meta name="apple-mobile-web-app-title" content="ROUTS" />
    <meta name="mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
    <meta name="format-detection" content="telephone=no" />
    <link rel="canonical" href="https://routs.dev/" />
    <link rel="alternate" hreflang="en" href="https://routs.dev/" />
    <link rel="alternate" hreflang="x-default" href="https://routs.dev/" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <link rel="apple-touch-icon" href="/og.png" />
    <link rel="manifest" href="/site.webmanifest" />
    <link rel="sitemap" type="application/xml" title="Sitemap" href="https://routs.dev/sitemap.xml" />
    <meta property="og:type" content="website" />
    <meta property="og:site_name" content="ROUTS" />
    <meta property="og:locale" content="en_US" />
    <meta property="og:url" content="https://routs.dev/" />
    <meta property="og:title" content="ROUTS: Interactive Pathfinding on Real Maps" />
    <meta
      property="og:description"
      content="Watch A*, Dijkstra, and more find routes on real OpenStreetMap streets. Free browser tool by Alatic."
    />
    <meta property="og:image" content="https://routs.dev/og.png" />
    <meta property="og:image:secure_url" content="https://routs.dev/og.png" />
    <meta property="og:image:type" content="image/png" />
    <meta property="og:image:width" content="1200" />
    <meta property="og:image:height" content="1200" />
    <meta property="og:image:alt" content="ROUTS: pathfinding on real maps" />
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:title" content="ROUTS: Interactive Pathfinding on Real Maps" />
    <meta
      name="twitter:description"
      content="Watch A*, Dijkstra, and more find routes on real OpenStreetMap streets. Free browser tool by Alatic."
    />
    <meta name="twitter:image" content="https://routs.dev/og.png" />
    <meta name="twitter:image:alt" content="ROUTS: pathfinding on real maps" />
    <script type="application/ld+json">
      {
        "@context": "https://schema.org",
        "@graph": [
          {
            "@type": "WebSite",
            "@id": "https://routs.dev/#website",
            "url": "https://routs.dev/",
            "name": "ROUTS",
            "description": "Interactive pathfinding on OpenStreetMap roads in the browser.",
            "inLanguage": "en",
            "publisher": { "@id": "https://routs.dev/#org" }
          },
          {
            "@type": "Organization",
            "@id": "https://routs.dev/#org",
            "name": "Alatic",
            "url": "https://routs.dev/",
            "logo": {
              "@type": "ImageObject",
              "url": "https://routs.dev/og.png"
            }
          },
          {
            "@type": "WebApplication",
            "@id": "https://routs.dev/#app",
            "name": "ROUTS",
            "url": "https://routs.dev/",
            "description": "Visualize and compare pathfinding algorithms on live OpenStreetMap road networks. Includes A*, Dijkstra, greedy best-first, ALT, bidirectional search, Prim’s, and Cascade.",
            "applicationCategory": "EducationalApplication",
            "applicationSubCategory": "Navigation",
            "operatingSystem": "Any",
            "browserRequirements": "Requires JavaScript. Modern browser with WebGL.",
            "inLanguage": "en",
            "isAccessibleForFree": true,
            "offers": {
              "@type": "Offer",
              "price": "0",
              "priceCurrency": "USD"
            },
            "image": "https://routs.dev/og.png",
            "screenshot": "https://routs.dev/og.png",
            "creator": { "@id": "https://routs.dev/#org" },
            "publisher": { "@id": "https://routs.dev/#org" },
            "featureList": [
              "A* pathfinding",
              "Dijkstra",
              "Bidirectional search",
              "ALT landmarks",
              "OpenStreetMap road loading",
              "City and country place search",
              "Route visualization and drive mode"
            ]
          },
          {
            "@type": "WebPage",
            "@id": "https://routs.dev/#webpage",
            "url": "https://routs.dev/",
            "name": "ROUTS: Interactive Pathfinding on Real Maps",
            "isPartOf": { "@id": "https://routs.dev/#website" },
            "about": { "@id": "https://routs.dev/#app" },
            "primaryImageOfPage": {
              "@type": "ImageObject",
              "url": "https://routs.dev/og.png"
            },
            "description": "ROUTS visualizes pathfinding on live OpenStreetMap roads. Compare classic routing algorithms in your browser."
          }
        ]
      }
    </script>
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=Manrope:wght@400;500;600;700;800&family=Syne:wght@600;700;800&display=swap"
      rel="stylesheet"
    />
    <script type="module" crossorigin src="/assets/index-DC6waIKo.js"></script>
    <link rel="stylesheet" crossorigin href="/assets/index-DUW0Itpq.css">
  </head>
  <body>
    <noscript>
      <main style="max-width:40rem;margin:2rem auto;padding:1rem;font-family:system-ui,sans-serif;color:#e8eef8;background:#05070b">
        <h1>ROUTS</h1>
        <p>
          Interactive pathfinding on OpenStreetMap: A*, Dijkstra, bidirectional search, and more.
          Enable JavaScript to use the map at
          <a href="https://routs.dev/" style="color:#3dd6c6">routs.dev</a>.
        </p>
        <p>By Alatic.</p>
      </main>
    </noscript>
    <div id="app">
      <div id="map"></div>
      <div class="ui-vignette" aria-hidden="true"></div>

      <div class="loading-overlay" id="loading-overlay">
        <div class="loading-card glass">
          <div class="loading-spinner"></div>
          <div id="loading-text">Loading map…</div>
        </div>
      </div>

      <div class="toast hidden" id="toast"></div>

      <header class="topbar glass">
        <div class="brand">
          <div class="brand-mark" aria-hidden="true">
            <span class="brand-mark-core"></span>
          </div>
          <div>
            <div class="brand-name">ROUTS</div>
            <div class="brand-sub">by Alatic</div>
          </div>
        </div>
        <div class="top-actions">
          <div class="mode-switch" id="data-mode">
            <button class="seg active" data-mode="demo">Los Angeles</button>
            <button class="seg" data-mode="osm">My Location</button>
          </div>
          <button class="btn ghost" id="btn-locate">Locate me</button>
          <button class="btn ghost" id="btn-info" title="Help">Info</button>
          <button
            type="button"
            class="btn ghost only-mobile"
            id="btn-toggle-panel"
            aria-controls="control-panel"
            aria-expanded="false"
          >
            Controls
          </button>
          <button
            type="button"
            class="btn ghost only-mobile"
            id="btn-more-top"
            aria-controls="top-more"
            aria-expanded="false"
          >
            More
          </button>
          <button class="btn ghost" id="btn-places" title="Go to a city or country">
            Places
          </button>
          <div class="top-more" id="top-more">
            <button class="btn ghost" id="btn-load-view" title="Fetch OSM roads for the current map view">
              Load this view
            </button>
            <button class="btn ghost" id="btn-custom-osm" title="Fetch a custom OpenStreetMap bounding box">
              Custom bbox
            </button>
            <button class="btn ghost" id="btn-race">Algorithm Race</button>
            <div class="fps" id="fps-counter" style="display: none">60 FPS</div>
          </div>
        </div>
      </header>

      <button
        type="button"
        class="mobile-fab only-mobile"
        id="btn-mobile-fab"
        aria-controls="control-panel"
        aria-expanded="false"
        title="Open controls"
      >
        Controls
      </button>

      <aside class="panel left-panel glass" id="control-panel">
        <button class="panel-collapse" id="collapse-left" title="Collapse">‹</button>
        <div class="sheet-grab only-mobile">
          <span class="sheet-grab-bar" aria-hidden="true"></span>
          <button type="button" class="btn ghost sheet-close" id="btn-sheet-close">Close</button>
        </div>
        <div class="panel-scroll">
          <section class="section">
            <h3>Route</h3>
            <div class="field">
              <label>Start</label>
              <input id="search-start" placeholder="Road name or click map…" />
            </div>
            <div class="field">
              <label>Destination</label>
              <input id="search-goal" placeholder="Road name or click map…" />
            </div>
            <div class="pick-hint" id="pick-hint">Click the map to set start (A) and destination (B)</div>
            <div class="route-summary" id="route-summary">
              <div><span>Distance</span><b id="sum-dist">-</b></div>
              <div><span>ETA</span><b id="sum-eta">-</b></div>
              <div><span>Segments</span><b id="sum-seg">-</b></div>
              <div><span>Intersections</span><b id="sum-nodes">-</b></div>
              <div><span>Avg speed</span><b id="sum-speed">-</b></div>
              <div><span>Traffic delay</span><b id="sum-traffic">-</b></div>
              <div><span>Alg. cost</span><b id="sum-cost">-</b></div>
            </div>
            <button class="btn accent xl" id="btn-start-viz">Start Visualization</button>
            <button class="btn primary xl" id="btn-find">Find Route</button>
          </section>

          <section class="section">
            <h3>Algorithm</h3>
            <select id="algorithm">
              <optgroup label="Classic">
                <option value="astar">A*</option>
                <option value="dijkstra">Dijkstra</option>
                <option value="greedy">Greedy Best First</option>
                <option value="alt">ALT / Landmark</option>
              </optgroup>
              <optgroup label="Bidirectional">
                <option value="bidirectional-astar" selected>Bidirectional A*</option>
                <option value="bidirectional-dijkstra">Bidirectional Dijkstra</option>
              </optgroup>
              <optgroup label="Tree / custom">
                <option value="prim">Prim’s tree growth</option>
                <option value="cascade">Cascade (ROUTS custom)</option>
              </optgroup>
            </select>

            <label class="field-label">Search direction</label>
            <div class="mode-switch dir-switch" id="search-direction">
              <button type="button" class="seg" data-dir="a-to-b">A → B</button>
              <button type="button" class="seg" data-dir="b-to-a">B → A</button>
              <button type="button" class="seg active" data-dir="meet">A ↔ B</button>
            </div>
            <p class="muted tiny" id="alg-blurb">
              Cyan from A + orange from B until the searches meet.
            </p>

            <label class="toggle"><input type="checkbox" id="turn-costs" checked /> Turn costs</label>
            <label class="toggle"><input type="checkbox" id="prefer-major" checked /> Prefer major roads</label>
          </section>

          <section class="section">
            <h3>Simulation</h3>
            <select id="sim-speed">
              <option value="0.1">0.1× slow-mo</option>
              <option value="0.25">0.25×</option>
              <option value="0.5">0.5×</option>
              <option value="1" selected>1× FAST</option>
              <option value="2">2×</option>
              <option value="5">5×</option>
              <option value="10">10×</option>
              <option value="25">25×</option>
              <option value="100">100×</option>
              <option value="10000">MAX / INSTANT</option>
            </select>
            <input type="range" id="speed-slider" min="0" max="9" step="1" value="3" />
            <div class="btn-row">
              <button class="btn" id="btn-play">Play</button>
              <button class="btn" id="btn-pause">Pause</button>
              <button class="btn" id="btn-restart">Restart</button>
            </div>
            <div class="btn-row">
              <button class="btn" id="btn-prev">◀ Step</button>
              <button class="btn" id="btn-next">Step ▶</button>
              <button class="btn" id="btn-skip">Skip</button>
            </div>
          </section>

          <section class="section">
            <h3>Traffic</h3>
            <label class="toggle"><input type="checkbox" id="traffic-enabled" checked /> Enable traffic</label>
            <label>Global intensity <span id="traffic-val">55%</span></label>
            <input type="range" id="traffic-intensity" min="0" max="100" value="55" />
            <div class="btn-row">
              <button class="btn" id="btn-traffic-rand">Randomize</button>
              <button class="btn" id="btn-traffic-regen">Regenerate</button>
            </div>

            <h4 class="subhead">Scatter incidents</h4>
            <p class="muted tiny">
              Set how many of each, then scatter into the loaded area (spaced out, major roads preferred).
            </p>
            <div class="incident-grid" id="incident-scatter">
              <div class="incident-row">
                <span>Crashes</span>
                <input type="number" id="cnt-crash" min="0" max="40" value="4" />
                <button class="btn" data-scatter="crash">Add random</button>
              </div>
              <div class="incident-row">
                <span>Traffic jams</span>
                <input type="number" id="cnt-congestion" min="0" max="40" value="7" />
                <button class="btn" data-scatter="congestion">Add random</button>
              </div>
              <div class="incident-row">
                <span>Closures</span>
                <input type="number" id="cnt-closure" min="0" max="40" value="1" />
                <button class="btn danger" data-scatter="closure">Add random</button>
              </div>
              <div class="incident-row">
                <span>Construction</span>
                <input type="number" id="cnt-construction" min="0" max="40" value="2" />
                <button class="btn" data-scatter="construction">Add random</button>
              </div>
              <div class="incident-row">
                <span>Lane close</span>
                <input type="number" id="cnt-lane_closure" min="0" max="40" value="2" />
                <button class="btn" data-scatter="lane_closure">Add random</button>
              </div>
            </div>
            <div class="btn-row">
              <button class="btn primary" id="btn-scatter-all">Scatter all counts</button>
              <button class="btn" id="btn-clear-incidents">Clear incidents</button>
            </div>

            <h4 class="subhead">Place on selected road</h4>
            <div class="btn-row wrap">
              <button class="btn danger" id="btn-incident-close">Close road</button>
              <button class="btn" id="btn-incident-crash">Crash</button>
              <button class="btn" id="btn-incident-build">Construction</button>
              <button class="btn" id="btn-incident-lane">Lane close</button>
              <button class="btn" id="btn-incident-jam">Traffic jam</button>
            </div>
          </section>

          <section class="section">
            <h3>Road Data</h3>
            <div class="muted" id="graph-meta">-</div>
            <label class="toggle"><input type="checkbox" id="overlay-traffic" /> Traffic colors</label>
            <label class="toggle"><input type="checkbox" id="overlay-speed" /> Speed limit colors</label>
            <label class="toggle"><input type="checkbox" id="show-speed-labels" /> Speed labels</label>
          </section>

          <section class="section">
            <h3>Visualization</h3>
            <div class="toggle-grid" id="viz-toggles">
              <label class="toggle"><input type="checkbox" data-viz="traffic" /> Traffic</label>
              <label class="toggle"><input type="checkbox" data-viz="searchNodes" checked /> Search Nodes</label>
              <label class="toggle"><input type="checkbox" data-viz="searchEdges" checked /> Search Edges</label>
              <label class="toggle"><input type="checkbox" data-viz="heatmap" /> Heatmap</label>
              <label class="toggle"><input type="checkbox" data-viz="finalRoute" checked /> Final Route</label>
              <label class="toggle"><input type="checkbox" data-viz="graphNodes" /> Graph Nodes</label>
              <label class="toggle"><input type="checkbox" data-viz="incidents" checked /> Incidents</label>
              <label class="toggle"><input type="checkbox" data-viz="fps" /> FPS Counter</label>
            </div>
          </section>

          <section class="section">
            <h3>Camera</h3>
            <div class="btn-row wrap">
              <button class="btn" id="cam-reset">Reset</button>
              <button class="btn" id="cam-top">Top-down</button>
              <button class="btn" id="cam-cine">Fit area</button>
              <button class="btn" id="cam-follow">Follow search</button>
              <button class="btn" id="cam-free">Free</button>
            </div>
          </section>

          <section class="section">
            <h3>Vehicle</h3>
            <button class="btn primary" id="btn-drive">Drive Route</button>
            <div class="btn-row wrap">
              <button class="btn" data-drive-cam="overhead">Overhead</button>
              <button class="btn" data-drive-cam="chase">Chase</button>
              <button class="btn" data-drive-cam="dash">Follow</button>
              <button class="btn" data-drive-cam="free">Free</button>
            </div>
            <button class="btn danger" id="btn-recalc-incident">Incident ahead + Recalc</button>
          </section>
        </div>
      </aside>

      <div class="map-layer-dock" id="map-layer-dock">
        <button
          type="button"
          class="map-sat-btn"
          id="btn-satellite"
          aria-pressed="false"
          title="Switch to satellite view"
        >
          <span class="map-sat-glyph" aria-hidden="true"></span>
          <span class="map-sat-text">
            <span class="map-sat-label">Satellite</span>
            <span class="map-sat-sub">Aerial view</span>
          </span>
        </button>
      </div>

      <aside class="panel right-panel glass" id="stats-panel">
        <h3>Live Statistics</h3>
        <div class="stat-grid" id="stats">
          <div class="stat"><span>Algorithm</span><b id="st-alg">A*</b></div>
          <div class="stat"><span>Status</span><b id="st-status">IDLE</b></div>
          <div class="stat"><span>Elapsed</span><b id="st-elapsed">0.000 s</b></div>
          <div class="stat"><span>Nodes Visited</span><b id="st-visited">0</b></div>
          <div class="stat"><span>Nodes Queued</span><b id="st-queued">0</b></div>
          <div class="stat"><span>Edges Checked</span><b id="st-edges">0</b></div>
          <div class="stat"><span>Paths Rejected</span><b id="st-reject">0</b></div>
          <div class="stat"><span>Current Best Cost</span><b id="st-best">-</b></div>
          <div class="stat"><span>Est. Remaining</span><b id="st-remain">-</b></div>
          <div class="stat"><span>Total Graph Nodes</span><b id="st-nodes">0</b></div>
          <div class="stat"><span>Total Graph Edges</span><b id="st-gedges">0</b></div>
          <div class="stat"><span>Memory Used</span><b id="st-mem">-</b></div>
          <div class="stat"><span>Ops / Second</span><b id="st-ops">0</b></div>
        </div>

        <h3 class="mt">Inspector</h3>
        <div class="inspector" id="inspector">
          <div class="muted">Click a road segment during search…</div>
        </div>

        <h3 class="mt">Charts</h3>
        <div class="charts">
          <canvas id="chart-nodes" width="280" height="80"></canvas>
          <canvas id="chart-queue" width="280" height="80"></canvas>
          <canvas id="chart-cost" width="280" height="80"></canvas>
        </div>

        <h3 class="mt">Alternatives</h3>
        <div id="alt-routes" class="alt-routes"></div>

        <div id="race-panel" class="race-panel hidden">
          <h3>Algorithm Race</h3>
          <div id="race-results"></div>
        </div>
      </aside>

      <div class="drive-hud glass hidden" id="drive-hud">
        <div><span>SPEED</span><b id="drv-speed">0</b><small>km/h</small></div>
        <div><span>LIMIT</span><b id="drv-limit">0</b><small>km/h</small></div>
        <div><span>ROAD</span><b id="drv-road">-</b></div>
        <div><span>ETA</span><b id="drv-eta">-</b></div>
        <div><span>LEFT</span><b id="drv-left">-</b></div>
        <div><span>TRAFFIC</span><b id="drv-traffic">-</b></div>
      </div>

      <div class="banner hidden" id="recalc-banner">RECALCULATING…</div>

      <footer class="timeline glass" id="timeline">
        <div class="timeline-head">
          <span>Algorithm Timeline</span>
          <span id="timeline-label">Ready</span>
        </div>
        <input type="range" id="timeline-scrub" min="0" max="1000" value="0" />
        <div class="milestones" id="milestones"></div>
        <p class="keys-hint">
          Space play/pause · ← → step · R restart · F follow · 1-9 speed
        </p>
      </footer>
    </div>

    <div class="modal hidden" id="places-modal" role="dialog" aria-labelledby="places-title" aria-modal="true">
      <div class="modal-card glass places-card">
        <div class="info-head">
          <div>
            <h2 id="places-title">Go to a place</h2>
            <p class="info-tagline">Cities, countries, or any named location</p>
          </div>
          <button class="btn ghost" id="places-close" aria-label="Close">Close</button>
        </div>
        <div class="field place-search-field">
          <label for="place-query">Search</label>
          <input
            id="place-query"
            type="search"
            autocomplete="off"
            spellcheck="false"
            placeholder="Tokyo, France, Cape Town…"
          />
        </div>
        <p class="muted tiny" id="place-status">Pick a popular city or search the world.</p>
        <div class="place-chips" id="place-chips"></div>
        <div class="place-results" id="place-results" role="listbox" aria-label="Search results"></div>
        <p class="muted info-note">
          Countries &amp; huge metros load a central street sample: pan and use <b>Load this view</b> to expand.
        </p>
        <div class="btn-row">
          <button class="btn" id="places-bbox">Custom coordinates…</button>
          <button class="btn" id="places-locate">My location</button>
        </div>
      </div>
    </div>

    <div class="modal hidden" id="osm-modal">
      <div class="modal-card glass">
        <h2>Custom bounding box</h2>
        <p>Fetch roads for an exact OSM bbox (advanced).</p>
        <div class="field-row">
          <label>South <input id="osm-s" type="text" inputmode="decimal" placeholder="south lat" value="" /></label>
          <label>West <input id="osm-w" type="text" inputmode="decimal" placeholder="west lon" value="" /></label>
          <label>North <input id="osm-n" type="text" inputmode="decimal" placeholder="north lat" value="" /></label>
          <label>East <input id="osm-e" type="text" inputmode="decimal" placeholder="east lon" value="" /></label>
        </div>
        <p class="muted" id="osm-status">Keep the box small (~2 km). Prefer Places search for cities.</p>
        <div class="btn-row">
          <button class="btn" id="osm-cancel">Cancel</button>
          <button class="btn" id="osm-use-location">Use my location</button>
          <button class="btn primary" id="osm-load">Fetch</button>
        </div>
      </div>
    </div>

    <div class="modal hidden" id="info-modal" role="dialog" aria-labelledby="info-title" aria-modal="true">
      <div class="modal-card glass info-card">
        <div class="info-head">
          <div>
            <h2 id="info-title">ROUTS</h2>
            <p class="info-tagline">Pathfinding on real maps · by Alatic</p>
          </div>
          <button class="btn ghost" id="info-close" aria-label="Close">Close</button>
        </div>

        <div class="info-tabs" id="info-tabs" role="tablist">
          <button class="info-tab active" role="tab" aria-selected="true" data-info-tab="howto">How to use</button>
          <button class="info-tab" role="tab" aria-selected="false" data-info-tab="algorithms">Algorithms</button>
          <button class="info-tab" role="tab" aria-selected="false" data-info-tab="controls">Controls</button>
          <button class="info-tab" role="tab" aria-selected="false" data-info-tab="about">About</button>
        </div>

        <div class="info-panels">
          <div class="info-panel active" data-info-panel="howto">
            <ol class="info-steps">
              <li>
                <b>Map</b>
                Defaults to Los Angeles. Use <b>Places</b> for any city/country, <b>My Location</b>, or
                <b>Load this view</b> while panning.
              </li>
              <li>
                <b>A / B</b>
                Click map for start then destination, or type a road name and press Enter.
              </li>
              <li>
                <b>Algorithm</b>
                Pick one and a search direction (A→B, B→A, or A↔B).
              </li>
              <li>
                <b>Run</b>
                <b>Find Route</b> for the result, or <b>Start Visualization</b> to watch the search.
              </li>
            </ol>
            <p class="muted info-note">Cyan branches = from A. Orange = from B. Blue = final route.</p>
          </div>

          <div class="info-panel" data-info-panel="algorithms">
            <dl class="info-dl">
              <div><dt>A*</dt><dd>Cost so far + estimate to goal. Good default.</dd></div>
              <div><dt>Dijkstra</dt><dd>Cheapest cost first. Optimal, explores more.</dd></div>
              <div><dt>Greedy Best First</dt><dd>Chases closest-looking node. Fast, not always optimal.</dd></div>
              <div><dt>ALT</dt><dd>A* with landmark distances for a tighter heuristic.</dd></div>
              <div><dt>Bidirectional A* / Dijkstra</dt><dd>Search from both ends until they meet.</dd></div>
              <div><dt>Prim’s</dt><dd>Grows a cheap-edge tree until B is reached.</dd></div>
              <div><dt>Cascade</dt><dd>Custom: Prim-like start, then bias toward B on major roads.</dd></div>
            </dl>
          </div>

          <div class="info-panel" data-info-panel="controls">
            <table class="info-table">
              <tbody>
                <tr><td>Click map</td><td>Set start / destination</td></tr>
                <tr><td>Drag / scroll</td><td>Pan / zoom</td></tr>
                <tr><td>Space</td><td>Play / pause</td></tr>
                <tr><td>← →</td><td>Step back / forward</td></tr>
                <tr><td>R</td><td>Restart</td></tr>
                <tr><td>F</td><td>Follow search</td></tr>
                <tr><td>1-9</td><td>Speed</td></tr>
                <tr><td>Timeline</td><td>Scrub search events</td></tr>
              </tbody>
            </table>
          </div>

          <div class="info-panel" data-info-panel="about">
            <p>
              Runs entirely in your browser. Nothing is sent to a ROUTS server: there isn’t one. GPS is only used if you
              ask for it (My Location / Locate me).
            </p>
            <p class="muted info-note">
              When you load roads, your map bbox is requested from public Overpass mirrors (and map tiles from Esri /
              similar). Those third parties can see the area you asked for: not a ROUTS backend.
            </p>
            <p class="info-credit">by Alatic · routs.dev</p>
          </div>
        </div>
      </div>
    </div>

  </body>
</html>
