{"id":105,"date":"2026-06-08T08:44:12","date_gmt":"2026-06-08T08:44:12","guid":{"rendered":"https:\/\/metros.co.ke\/NairobiMatatu\/?page_id=105"},"modified":"2026-06-10T09:49:01","modified_gmt":"2026-06-10T09:49:01","slug":"nairobi-matatu-routes","status":"publish","type":"page","link":"https:\/\/metros.co.ke\/NairobiMatatu\/","title":{"rendered":"Nairobi Matatu Routes"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"105\" class=\"elementor elementor-105\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e33b209 e-con e-atomic-element e-flexbox-base e-a25edb0 \" data-id=\"e33b209\" data-element_type=\"e-flexbox\" data-e-type=\"e-flexbox\" data-interaction-id=\"e33b209\" data-e-type=\"e-flexbox\" data-id=\"e33b209\">\n    \t\t<div class=\"elementor-element elementor-element-1c9b6e7 elementor-widget elementor-widget-html\" data-id=\"1c9b6e7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n<meta charset=\"UTF-8\">\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n<a href=\"https:\/\/metros.co.ke\/\"><img decoding=\"async\" src=\"https:\/\/metros.co.ke\/wp-content\/uploads\/2026\/06\/metroskenya.png\"width=\"200\" height=\"100\"><\/a>\r\n<html lang=\"en\">\r\n<head>\r\n<meta charset=\"UTF-8\"\/>\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\/>\r\n<title>Nairobi Matatu Route Finder<\/title>\r\n<link rel=\"stylesheet\" href=\"https:\/\/cdn.jsdelivr.net\/npm\/@tabler\/icons-webfont@3.19.0\/dist\/tabler-icons.min.css\"\/>\r\n<style>\r\n  :root {\r\n    --color-text-primary: #1a1a1a;\r\n    --color-text-secondary: #6b7280;\r\n    --color-text-tertiary: #9ca3af;\r\n    --color-background-primary: #ffffff;\r\n    --color-background-secondary: #f9fafb;\r\n    --color-border-secondary: #d1d5db;\r\n    --color-border-tertiary: #e5e7eb;\r\n    --border-radius-md: 8px;\r\n    --border-radius-lg: 12px;\r\n    --font-sans: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\r\n  }\r\n  @media (prefers-color-scheme: dark) {\r\n    :root {\r\n      --color-text-primary: #f3f4f6;\r\n      --color-text-secondary: #9ca3af;\r\n      --color-text-tertiary: #6b7280;\r\n      --color-background-primary: #111827;\r\n      --color-background-secondary: #1f2937;\r\n      --color-border-secondary: #374151;\r\n      --color-border-tertiary: #2d3748;\r\n    }\r\n  }\r\n  * { box-sizing: border-box; margin: 0; padding: 0; }\r\n  body { font-family: var(--font-sans); background: var(--color-background-secondary); color: var(--color-text-primary); min-height: 100vh; padding: 0 1rem 2rem; }\r\n  .container { max-width: 860px; margin: 0 auto; }\r\n  .hero { text-align: center; padding: 2rem 1rem 1.25rem; }\r\n  .hero h1 { font-size: 28px; font-weight: 600; color: var(--color-text-primary); line-height: 1.2; }\r\n  .hero h1 span { color: #0F6E56; }\r\n  .hero p { font-size: 13px; color: var(--color-text-secondary); margin-top: 6px; }\r\n  .tabs { display: flex; border: .5px solid var(--color-border-secondary); border-radius: var(--border-radius-md); overflow: hidden; max-width: 340px; margin: 1rem auto 1.5rem; }\r\n  .tab { flex: 1; padding: 8px 0; font-size: 13px; text-align: center; cursor: pointer; color: var(--color-text-secondary); background: transparent; border: none; transition: background .15s, color .15s; font-family: var(--font-sans); }\r\n  .tab.active { background: #0F6E56; color: white; font-weight: 500; }\r\n  .panel { display: none; }\r\n  .panel.active { display: block; }\r\n  .search-wrap { position: relative; margin-bottom: .625rem; }\r\n  .search-wrap .ico { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); font-size: 15px; color: var(--color-text-tertiary); pointer-events: none; }\r\n  input[type=text] { width: 100%; padding: 9px 12px 9px 34px; font-size: 13px; border-radius: var(--border-radius-lg); border: .5px solid var(--color-border-secondary); background: var(--color-background-primary); color: var(--color-text-primary); font-family: var(--font-sans); }\r\n  input[type=text]:focus { outline: none; border-color: #0F6E56; }\r\n  .filter-row { display: flex; gap: 5px; flex-wrap: wrap; margin-bottom: .75rem; }\r\n  .fb { font-size: 12px; padding: 3px 10px; border-radius: 20px; border: .5px solid var(--color-border-secondary); background: transparent; color: var(--color-text-secondary); cursor: pointer; font-family: var(--font-sans); }\r\n  .fb.active { background: #0F6E56; color: white; border-color: #0F6E56; }\r\n  .sh { display: flex; justify-content: space-between; align-items: baseline; margin: .5rem 0; }\r\n  .sh h2 { font-size: 13px; font-weight: 500; color: var(--color-text-primary); }\r\n  .sh span { font-size: 12px; color: var(--color-text-secondary); }\r\n  .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 8px; }\r\n  .card { background: var(--color-background-primary); border: .5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); padding: .7rem .875rem; cursor: pointer; position: relative; overflow: hidden; transition: border-color .15s; }\r\n  .card:hover { border-color: var(--color-border-secondary); }\r\n  .ctb { position: absolute; top: 0; left: 0; right: 0; height: 3px; }\r\n  .ch { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 3px; }\r\n  .ctr { display: flex; align-items: center; gap: 7px; }\r\n  .badge { width: 21px; height: 21px; border-radius: 4px; display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 500; flex-shrink: 0; }\r\n  .cname { font-size: 13px; font-weight: 500; color: var(--color-text-primary); }\r\n  .csub { font-size: 11px; color: var(--color-text-secondary); margin-bottom: 5px; }\r\n  .rrow { display: flex; flex-wrap: wrap; gap: 3px; margin-bottom: 5px; }\r\n  .rp { font-size: 10px; color: var(--color-text-secondary); background: var(--color-background-secondary); border: .5px solid var(--color-border-tertiary); border-radius: 3px; padding: 1px 5px; }\r\n  .rp.more { color: var(--color-text-tertiary); }\r\n  .meta { display: flex; flex-direction: column; gap: 2px; border-top: .5px solid var(--color-border-tertiary); padding-top: 5px; }\r\n  .mrow { display: flex; align-items: center; gap: 5px; font-size: 11px; color: var(--color-text-secondary); }\r\n  .mrow i { font-size: 12px; color: var(--color-text-tertiary); flex-shrink: 0; }\r\n  .mrow strong { font-weight: 500; color: var(--color-text-primary); }\r\n  .tag { display: inline-flex; align-items: center; gap: 2px; font-size: 10px; padding: 1px 5px; border-radius: 3px; font-weight: 500; }\r\n  .tag-green { background: #E1F5EE; color: #085041; }\r\n  .tag-amber { background: #FAEEDA; color: #633806; }\r\n  .tag-red { background: #FCEBEB; color: #791F1F; }\r\n  .detail { background: var(--color-background-secondary); border-radius: var(--border-radius-lg); padding: 1rem 1.125rem; margin-top: .875rem; border: .5px solid var(--color-border-tertiary); }\r\n  .detail h3 { font-size: 13px; font-weight: 500; color: var(--color-text-primary); margin-bottom: .625rem; display: flex; align-items: center; gap: 6px; }\r\n  .dg { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 7px; margin-bottom: .625rem; }\r\n  .mc { background: var(--color-background-primary); border-radius: var(--border-radius-md); padding: .5rem .625rem; border: .5px solid var(--color-border-tertiary); }\r\n  .mc .ml { font-size: 10px; color: var(--color-text-secondary); margin-bottom: 2px; }\r\n  .mc .mv { font-size: 15px; font-weight: 500; color: var(--color-text-primary); }\r\n  .mc .ms { font-size: 10px; color: var(--color-text-secondary); }\r\n  .tip { font-size: 12px; color: var(--color-text-secondary); background: var(--color-background-primary); border: .5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); padding: .45rem .625rem; display: flex; gap: 6px; align-items: flex-start; margin-bottom: 5px; }\r\n  .tip i { font-size: 13px; color: #0F6E56; flex-shrink: 0; margin-top: 1px; }\r\n  .empty { text-align: center; padding: 1.5rem; color: var(--color-text-secondary); font-size: 13px; }\r\n  .jp-wrap { background: var(--color-background-primary); border: .5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); padding: 1rem 1.125rem; }\r\n  .jp-row { display: grid; grid-template-columns: 1fr 40px 1fr; gap: 8px; align-items: flex-end; margin-bottom: .875rem; }\r\n  .swap-btn { width: 36px; height: 36px; border-radius: 50%; border: .5px solid var(--color-border-secondary); background: var(--color-background-secondary); cursor: pointer; display: flex; align-items: center; justify-content: center; color: var(--color-text-secondary); font-size: 16px; transition: background .15s; margin: 0 auto; }\r\n  .swap-btn:hover { background: var(--color-background-primary); color: var(--color-text-primary); }\r\n  select { width: 100%; padding: 8px 10px; font-size: 13px; border-radius: var(--border-radius-md); border: .5px solid var(--color-border-secondary); background: var(--color-background-primary); color: var(--color-text-primary); cursor: pointer; font-family: var(--font-sans); }\r\n  select:focus { outline: none; border-color: #0F6E56; }\r\n  .sel-label { font-size: 11px; color: var(--color-text-secondary); margin-bottom: 4px; }\r\n  .route-card { background: var(--color-background-secondary); border-radius: var(--border-radius-lg); padding: .875rem 1rem; margin-bottom: .625rem; border: .5px solid var(--color-border-tertiary); }\r\n  .route-card.direct { border-color: #0F6E56; }\r\n  .rc-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: .5rem; }\r\n  .rc-title { font-size: 13px; font-weight: 500; color: var(--color-text-primary); display: flex; align-items: center; gap: 6px; }\r\n  .leg-bar { flex: 1; height: 3px; border-radius: 2px; min-width: 24px; }\r\n  .leg-detail { background: var(--color-background-primary); border-radius: var(--border-radius-md); padding: .4rem .625rem; margin-top: 5px; font-size: 12px; color: var(--color-text-secondary); border: .5px solid var(--color-border-tertiary); }\r\n  .leg-detail strong { color: var(--color-text-primary); font-weight: 500; }\r\n  .no-route { text-align: center; padding: 1.25rem; color: var(--color-text-secondary); font-size: 13px; }\r\n  .ask-btn { font-size: 12px; padding: 6px 14px; border-radius: var(--border-radius-md); cursor: pointer; background: #0F6E56; color: white; border: none; font-family: var(--font-sans); margin-top: 6px; }\r\n  .ask-btn:hover { background: #085041; }\r\n  .ask-btn.secondary { background: transparent; border: .5px solid var(--color-border-secondary); color: var(--color-text-secondary); }\r\n  .ask-btn.secondary:hover { border-color: #0F6E56; color: #0F6E56; }\r\n<\/style>\r\n<\/head>\r\n<body>\r\n<div class=\"container\">\r\n\r\n<div class=\"hero\">\r\n  <h1>Nairobi <span>Matatu Guide<\/span><\/h1>\r\n  <p>Browse 20 corridors \u00b7 fare estimates \u00b7 operating hours \u00b7 journey planner<\/p>\r\n<\/div>\r\n\r\n<div class=\"tabs\">\r\n  <button class=\"tab active\" onclick=\"switchTab('browse')\"><i class=\"ti ti-map-2\" style=\"font-size:13px;vertical-align:-1px\"><\/i> Browse corridors<\/button>\r\n  <button class=\"tab\" onclick=\"switchTab('plan')\"><i class=\"ti ti-route\" style=\"font-size:13px;vertical-align:-1px\"><\/i> Plan journey<\/button>\r\n<\/div>\r\n\r\n<!-- BROWSE PANEL -->\r\n<div id=\"panel-browse\" class=\"panel active\">\r\n  <div class=\"search-wrap\">\r\n    <i class=\"ico ti ti-search\"><\/i>\r\n    <input type=\"text\" id=\"search\" placeholder=\"Route number, destination, or road\u2026\" autocomplete=\"off\"\/>\r\n  <\/div>\r\n  <div class=\"filter-row\" id=\"frow\"><\/div>\r\n  <div class=\"sh\"><h2 id=\"slabel\">All corridors<\/h2><span id=\"clabel\"><\/span><\/div>\r\n  <div class=\"grid\" id=\"grid\"><\/div>\r\n  <div class=\"empty\" id=\"bempty\" style=\"display:none\">No corridors match \u2014 try a route number or area name.<\/div>\r\n  <div id=\"detailBox\" style=\"display:none\"><\/div>\r\n<\/div>\r\n\r\n<!-- PLAN PANEL -->\r\n<div id=\"panel-plan\" class=\"panel\">\r\n  <div class=\"jp-wrap\">\r\n    <div class=\"jp-row\">\r\n      <div>\r\n        <div class=\"sel-label\"><i class=\"ti ti-circle-dot\" style=\"font-size:11px;vertical-align:-1px;color:#0F6E56\"><\/i> From<\/div>\r\n        <select id=\"fromSel\" onchange=\"planJourney()\"><\/select>\r\n      <\/div>\r\n      <div style=\"display:flex;align-items:flex-end;padding-bottom:2px\">\r\n        <button class=\"swap-btn\" onclick=\"swapAreas()\" title=\"Swap origin and destination\">\r\n          <i class=\"ti ti-switch-horizontal\"><\/i>\r\n        <\/button>\r\n      <\/div>\r\n      <div>\r\n        <div class=\"sel-label\"><i class=\"ti ti-map-pin\" style=\"font-size:11px;vertical-align:-1px;color:#A32D2D\"><\/i> To<\/div>\r\n        <select id=\"toSel\" onchange=\"planJourney()\"><\/select>\r\n      <\/div>\r\n    <\/div>\r\n    <div id=\"jp-result\"><\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<\/div><!-- \/container -->\r\n\r\n<script>\r\nconst C=[\r\n  {id:1,name:\"Thika Road\",routes:[\"44\",\"45\",\"46\",\"49\",\"237\",\"48\",\"50\",\"51\",\"52\",\"53\"],stops:[\"Githurai\",\"Roysambu\",\"Roasters\",\"Muthaiga North\",\"Kasarani\"],color:\"#1D9E75\",badge:\"#E1F5EE\",bt:\"#085041\",fareMin:30,fareMax:80,peakFare:100,hours:\"5:00 AM \u2013 11:00 PM\",freq:\"3\u20138 min\",peak:\"7\u20139 AM, 5\u20137 PM\",tips:[\"One of Nairobi's busiest corridors \u2014 avoid peak hours if possible\",\"Routes 44 and 45 go furthest to Thika Town\",\"Touts at Githurai stage can be pushy; know your fare\"]},\r\n  {id:2,name:\"Mombasa Road\",routes:[\"110\",\"111\",\"33A\",\"34A\",\"19\",\"34\",\"35\"],stops:[\"Airport\",\"Syokimau\",\"Mlolongo\",\"Imara Daima\",\"Athi River\"],color:\"#D85A30\",badge:\"#FAECE7\",bt:\"#712B13\",fareMin:30,fareMax:120,peakFare:150,hours:\"4:30 AM \u2013 10:30 PM\",freq:\"5\u201315 min\",peak:\"6\u20139 AM, 4\u20138 PM\",tips:[\"Long-distance routes to Athi River\/Kitengela can cost up to KSh 150\",\"Traffic near Airport junction adds 30+ min at peak\",\"Route 110\/111 most reliable for Airport North area\"]},\r\n  {id:3,name:\"Nairobi Expressway\",routes:[\"Kitengela\",\"Athi\",\"Mlolongo\",\"Airport\",\"Long-distance\"],stops:[\"Kitengela\",\"Athi River\",\"Mlolongo\",\"Airport\"],color:\"#534AB7\",badge:\"#EEEDFE\",bt:\"#3C3489\",fareMin:50,fareMax:200,peakFare:250,hours:\"5:00 AM \u2013 10:00 PM\",freq:\"10\u201325 min\",peak:\"6\u20139 AM, 5\u20138 PM\",tips:[\"Expressway tolls may be added to fare\",\"Long-distance matatus depart from Machakos Country Bus\",\"Book early for Kitengela routes on Friday evenings\"]},\r\n  {id:4,name:\"Waiyaki Way\",routes:[\"105\",\"106\",\"107\",\"115\",\"114\",\"108\"],stops:[\"Westlands\",\"Kangemi\",\"Kikuyu\",\"Kinoo\",\"Limuru Rd\"],color:\"#185FA5\",badge:\"#E6F1FB\",bt:\"#0C447C\",fareMin:30,fareMax:70,peakFare:90,hours:\"5:30 AM \u2013 10:30 PM\",freq:\"4\u201310 min\",peak:\"7\u20139 AM, 5\u20137:30 PM\",tips:[\"Route 105 is the workhorse \u2014 very frequent\",\"Westlands stage congested; alight at Museum Hill for faster CBD access\",\"Fares rise significantly during evening peak\"]},\r\n  {id:5,name:\"Outer Ring Road\",routes:[\"32\",\"33A\",\"34A\",\"23\",\"17\",\"36\"],stops:[\"Ruai\",\"Tena\",\"Kayole\",\"Utawala\",\"Komarock\"],color:\"#D4537E\",badge:\"#FBEAF0\",bt:\"#72243E\",fareMin:30,fareMax:60,peakFare:80,hours:\"5:00 AM \u2013 10:00 PM\",freq:\"5\u201312 min\",peak:\"6\u20139 AM, 5\u20138 PM\",tips:[\"Good bypass option to avoid CBD\",\"Route 33A connects to both Eastlands and South B\",\"Road condition varies \u2014 some sections are rough\"]},\r\n  {id:6,name:\"Jogoo Road\",routes:[\"33A\",\"33B\",\"32\",\"34\",\"17\"],stops:[\"Donholm\",\"Komarock\",\"Soweto\",\"Makadara\",\"Umoja\"],color:\"#0F6E56\",badge:\"#E1F5EE\",bt:\"#04342C\",fareMin:30,fareMax:50,peakFare:60,hours:\"5:00 AM \u2013 11:00 PM\",freq:\"3\u20137 min\",peak:\"7\u20139 AM, 5\u20137 PM\",tips:[\"High-frequency corridor \u2014 rarely wait more than 5 min\",\"Route 33B goes deep into Umoja estates\",\"Avoid Makadara junction at school hours\"]},\r\n  {id:7,name:\"Ngong Road\",routes:[\"111\",\"46\",\"24\",\"125\",\"126\"],stops:[\"Dagoretti\",\"Karen\",\"Ngong\",\"Rongai\",\"Kibera\"],color:\"#3B6D11\",badge:\"#EAF3DE\",bt:\"#173404\",fareMin:30,fareMax:100,peakFare:130,hours:\"5:30 AM \u2013 10:00 PM\",freq:\"5\u201315 min\",peak:\"7\u20139 AM, 5\u20137:30 PM\",tips:[\"Routes to Ngong\/Karen are less frequent\",\"Karen-bound matatus fill up fast at Kencom stage\",\"Route 111 overlaps with Waiyaki Way routes\"]},\r\n  {id:8,name:\"Lang'ata Road\",routes:[\"15\",\"4W\",\"Rongai\",\"Karen\"],stops:[\"Langata\",\"Karen\",\"Hardy\",\"Rongai\",\"Bomas\"],color:\"#BA7517\",badge:\"#FAEEDA\",bt:\"#412402\",fareMin:40,fareMax:120,peakFare:150,hours:\"5:30 AM \u2013 9:30 PM\",freq:\"8\u201320 min\",peak:\"7\u20139 AM, 5\u20137 PM\",tips:[\"Rongai routes notorious for Langata Road traffic\",\"4W goes to Wilson Airport area\",\"Less frequent \u2014 plan around timetables\"]},\r\n  {id:9,name:\"Northern Bypass\",routes:[\"44\",\"45\",\"100\",\"101\",\"107\",\"102\",\"103\",\"104\"],stops:[\"Githurai 44\",\"Kahawa West\",\"Kiambu Rd Jcn\",\"Ruiru\"],color:\"#5F5E5A\",badge:\"#F1EFE8\",bt:\"#2C2C2A\",fareMin:40,fareMax:90,peakFare:110,hours:\"5:30 AM \u2013 9:30 PM\",freq:\"8\u201318 min\",peak:\"6:30\u20139 AM, 5\u20137:30 PM\",tips:[\"Bypass routes avoid CBD entirely\",\"Routes 100\/101 run to Kiambu town\",\"Less congested than main Thika Road\"]},\r\n  {id:10,name:\"Eastern Bypass\",routes:[\"34A\",\"34B\",\"33A\",\"33B\",\"32\",\"36\",\"37\",\"38\",\"39\",\"40\"],stops:[\"Ruai Jcn\",\"Kangundo Rd Jcn\",\"Kamakis\",\"Utawala\"],color:\"#A32D2D\",badge:\"#FCEBEB\",bt:\"#501313\",fareMin:40,fareMax:90,peakFare:110,hours:\"5:00 AM \u2013 9:30 PM\",freq:\"10\u201320 min\",peak:\"6\u20139 AM, 5\u20137:30 PM\",tips:[\"Good for avoiding Jogoo\/Mombasa Rd congestion\",\"Routes to Kamakis infrequent in evenings\",\"Useful for Airport trips from Eastlands\"]},\r\n  {id:11,name:\"Southern Bypass\",routes:[\"102\",\"103\",\"105\",\"111\",\"115\",\"112\",\"113\",\"114\"],stops:[\"Kikuyu\",\"Gitaru\",\"Dagoretti Corner\",\"Karen\"],color:\"#7F77DD\",badge:\"#EEEDFE\",bt:\"#26215C\",fareMin:30,fareMax:80,peakFare:100,hours:\"5:30 AM \u2013 9:30 PM\",freq:\"8\u201320 min\",peak:\"7\u20139 AM, 5\u20137 PM\",tips:[\"Links Westlands to Karen\/Rongai without CBD\",\"Less traffic but fewer matatus\",\"Route 105 most frequent on this bypass\"]},\r\n  {id:12,name:\"Western Bypass\",routes:[\"105\",\"102\",\"103\",\"115\",\"114\",\"106\",\"107\",\"108\",\"109\",\"110\",\"111\",\"112\"],stops:[\"Kinoo\",\"Kikuyu\",\"Wangige\",\"Ruaka\"],color:\"#5DCAA5\",badge:\"#E1F5EE\",bt:\"#04342C\",fareMin:30,fareMax:70,peakFare:90,hours:\"5:30 AM \u2013 9:30 PM\",freq:\"8\u201318 min\",peak:\"7\u20139 AM, 5\u20137:30 PM\",tips:[\"Links Westlands to Kiambu Road without going through town\",\"Ruaka routes expanded with new estates\",\"Good for Ridgeways\/Runda commuters\"]},\r\n  {id:13,name:\"Uhuru Highway\",routes:[\"105\",\"23\",\"111\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"10\",\"11\",\"12\"],stops:[\"Kencom\",\"Archives\",\"GPO\",\"Railways\",\"Haile Selassie\"],color:\"#378ADD\",badge:\"#E6F1FB\",bt:\"#042C53\",fareMin:20,fareMax:50,peakFare:60,hours:\"5:00 AM \u2013 11:30 PM\",freq:\"2\u20136 min\",peak:\"7\u20139 AM, 4:30\u20137 PM\",tips:[\"CBD corridor \u2014 extremely high frequency\",\"Lowest fares from KSh 20 for short CBD hops\",\"Kencom is the main hub \u2014 multiple routes depart here\"]},\r\n  {id:14,name:\"Murang'a Road\",routes:[\"25\",\"29\/30\",\"42\",\"44\",\"45\",\"46\",\"47\",\"48\",\"49\",\"50\",\"51\"],stops:[\"Pangani\",\"Ngara\",\"Kariobangi\",\"Dandora\",\"Githurai\"],color:\"#639922\",badge:\"#EAF3DE\",bt:\"#173404\",fareMin:30,fareMax:80,peakFare:100,hours:\"5:00 AM \u2013 10:30 PM\",freq:\"4\u201310 min\",peak:\"6:30\u20139 AM, 5\u20137 PM\",tips:[\"Pangani stage is a major interchange\",\"Routes 29\/30 loop through Ngara\",\"Dandora routes congested near the market\"]},\r\n  {id:15,name:\"Kiambu Road\",routes:[\"100\",\"101\",\"102\",\"106\",\"107\",\"103\",\"104\",\"105\",\"108\",\"109\",\"110\",\"111\",\"112\"],stops:[\"Muthaiga\",\"Ridgeways\",\"Kiambu Town\",\"Garden City\"],color:\"#EF9F27\",badge:\"#FAEEDA\",bt:\"#412402\",fareMin:40,fareMax:110,peakFare:140,hours:\"5:30 AM \u2013 9:30 PM\",freq:\"6\u201315 min\",peak:\"7\u20139 AM, 5\u20137 PM\",tips:[\"Route 100 goes to Kiambu Town \u2014 scenic but slow\",\"Garden City Mall is a popular stop\",\"Fares to Kiambu town rise sharply during rains\"]},\r\n  {id:16,name:\"Enterprise Road\",routes:[\"19\",\"33\",\"34\",\"35\",\"60\",\"36\",\"37\",\"38\",\"39\",\"40\",\"41\",\"42\",\"43\"],stops:[\"Muthurwa\",\"Industrial Area\",\"CBD\",\"Enterprise\"],color:\"#993C1D\",badge:\"#FAECE7\",bt:\"#4A1B0C\",fareMin:30,fareMax:60,peakFare:70,hours:\"5:00 AM \u2013 9:30 PM\",freq:\"5\u201312 min\",peak:\"6\u20139 AM, 4\u20137 PM\",tips:[\"Industrial Area routes peak at factory shift times\",\"Route 19 connects Eastleigh to Industrial Area\",\"Muthurwa stage \u2014 watch your belongings\"]},\r\n  {id:17,name:\"Likoni Road\",routes:[\"6\",\"19\",\"33\",\"34\",\"35\",\"36\",\"37\",\"38\",\"39\",\"40\",\"41\",\"42\",\"43\"],stops:[\"South B\",\"South C\",\"Mombasa Rd\",\"Hazina\"],color:\"#888780\",badge:\"#F1EFE8\",bt:\"#2C2C2A\",fareMin:30,fareMax:50,peakFare:60,hours:\"5:00 AM \u2013 10:00 PM\",freq:\"5\u201312 min\",peak:\"7\u20139 AM, 5\u20137 PM\",tips:[\"Key connector for South B and South C estates\",\"Route 6 is the most reliable\",\"Short CBD hops cost KSh 30\u201340\"]},\r\n  {id:18,name:\"Airport North Road\",routes:[\"33H\",\"33UTW\",\"33B\",\"33J\",\"33FED\",\"34\",\"35\",\"36\",\"37\",\"38\"],stops:[\"Pipeline\",\"Embakasi\",\"CBD\",\"Utawala\",\"Airport North\"],color:\"#185FA5\",badge:\"#E6F1FB\",bt:\"#042C53\",fareMin:40,fareMax:90,peakFare:120,hours:\"4:30 AM \u2013 10:30 PM\",freq:\"6\u201315 min\",peak:\"5\u20138 AM, 4\u20138 PM\",tips:[\"33H and 33UTW best for JKIA connections\",\"Early morning services from 4:30 AM\",\"Heavy traffic near Airport North 7\u20139 AM weekdays\"]},\r\n  {id:19,name:\"Limuru Road\",routes:[\"114\",\"115\",\"116\",\"118\",\"119\",\"120\",\"121\",\"122\",\"123\",\"124\",\"125\"],stops:[\"Kangemi\",\"Uthiru\",\"Lower Kabete\",\"Limuru\"],color:\"#1D9E75\",badge:\"#E1F5EE\",bt:\"#04342C\",fareMin:30,fareMax:130,peakFare:160,hours:\"5:30 AM \u2013 9:00 PM\",freq:\"8\u201320 min\",peak:\"7\u20139 AM, 5\u20137 PM\",tips:[\"Limuru town matatus depart from Koja\/Githurai stages\",\"Route 114 most used \u2014 goes to Lower Kabete\",\"Some evening services end early \u2014 confirm before 8 PM\"]},\r\n  {id:20,name:\"James Gichuru Road\",routes:[\"48A\",\"48B\",\"48K\",\"46\",\"2\",\"47\",\"48\",\"49\",\"50\",\"51\"],stops:[\"Lavington\",\"Kawangware\",\"Dagoretti\",\"Ruthimitu\"],color:\"#D4537E\",badge:\"#FBEAF0\",bt:\"#4B1528\",fareMin:30,fareMax:70,peakFare:90,hours:\"5:30 AM \u2013 10:00 PM\",freq:\"5\u201315 min\",peak:\"7\u20139 AM, 5\u20137 PM\",tips:[\"48A\/48B serve Lavington and Kawangware heavily\",\"Good connector from Westlands to Dagoretti\",\"Kawangware stage very busy on market days (Mon, Thu)\"]},\r\n];\r\n\r\nconst AREAS=[\r\n  {name:\"CBD \/ City Centre\",corridors:[13,14,16,17,6]},\r\n  {name:\"Westlands\",corridors:[4,12,20,11]},\r\n  {name:\"Eastlands\",corridors:[5,6,10,16]},\r\n  {name:\"Thika Road \/ Kasarani\",corridors:[1,9,14]},\r\n  {name:\"South B \/ South C \/ Langata\",corridors:[7,8,11,17]},\r\n  {name:\"Karen \/ Ngong\",corridors:[7,8,11]},\r\n  {name:\"Westlands \/ Lavington\",corridors:[20,4,12]},\r\n  {name:\"Kiambu Road \/ Ridgeways\",corridors:[15,9,12]},\r\n  {name:\"Mombasa Road \/ Airport\",corridors:[2,3,18]},\r\n  {name:\"Embakasi \/ Pipeline\",corridors:[18,10,5]},\r\n  {name:\"Industrial Area \/ Enterprise\",corridors:[16,2,17]},\r\n  {name:\"Limuru \/ Kikuyu\",corridors:[19,11,12,4]},\r\n  {name:\"Murang'a \/ Kariobangi\",corridors:[14,5,6]},\r\n  {name:\"Northern Bypass \/ Ruiru\",corridors:[9,15,1]},\r\n  {name:\"Eastern Bypass \/ Kamakis\",corridors:[10,5]},\r\n];\r\n\r\nconst JP_DATA={\r\n  \"CBD \/ City Centre|Thika Road \/ Kasarani\":{direct:[1,14],via:null,note:\"Board route 44\/45 from Kencom or Archives stage \u2014 very frequent.\"},\r\n  \"CBD \/ City Centre|Eastlands\":{direct:[6,5,16],via:null,note:\"Jogoo Road matatus from Kencom are the fastest option. Route 33A\/33B for deep Eastlands.\"},\r\n  \"CBD \/ City Centre|Westlands\":{direct:[4,13],via:null,note:\"Route 105 from Kencom is the quickest. Very high frequency throughout the day.\"},\r\n  \"CBD \/ City Centre|Mombasa Road \/ Airport\":{direct:[2,18],via:null,note:\"Route 34A or 33H for Airport. Board from Kencom or Railways stage.\"},\r\n  \"CBD \/ City Centre|South B \/ South C \/ Langata\":{direct:[17,7,8],via:null,note:\"Route 6 or 33 from CBD to South B\/C. For Rongai\/Karen, board at Kencom.\"},\r\n  \"CBD \/ City Centre|Karen \/ Ngong\":{direct:[7,8],via:null,note:\"Board at Kencom \u2014 routes 111 or 24. Karen matatus fill up fast in evenings.\"},\r\n  \"CBD \/ City Centre|Kiambu Road \/ Ridgeways\":{direct:[15,9],via:null,note:\"Route 100\/101 from Kencom. Northern Bypass routes also serve this area.\"},\r\n  \"CBD \/ City Centre|Embakasi \/ Pipeline\":{direct:[18,10],via:null,note:\"Route 33H or 33UTW from Railways stage for Pipeline\/Embakasi.\"},\r\n  \"CBD \/ City Centre|Murang'a \/ Kariobangi\":{direct:[14,6],via:null,note:\"Board at Pangani from CBD. Route 42\/46 serves Kariobangi.\"},\r\n  \"CBD \/ City Centre|Limuru \/ Kikuyu\":{direct:[19,4],via:null,note:\"Route 114\/115 from Kencom or Koja for Limuru road destinations.\"},\r\n  \"CBD \/ City Centre|Industrial Area \/ Enterprise\":{direct:[16,17],via:null,note:\"Route 19 or 33 from Muthurwa stage. Very frequent during factory shift changes.\"},\r\n  \"CBD \/ City Centre|Westlands \/ Lavington\":{direct:[20,13],via:null,note:\"Routes 48A\/48B from Kencom to Lavington and Kawangware.\"},\r\n  \"Westlands|Karen \/ Ngong\":{direct:[11],via:[[4,13],[7,8]],note:\"Southern Bypass (route 102\/105) avoids CBD entirely. Alternatively, go via CBD and board a Karen matatu at Kencom.\"},\r\n  \"Westlands|Thika Road \/ Kasarani\":{direct:null,via:[[4,13],[1,14]],note:\"No direct route. Change at CBD \u2014 alight at Kencom from Westlands matatu, then board a Thika Road matatu.\"},\r\n  \"Westlands|Kiambu Road \/ Ridgeways\":{direct:[12,15],via:null,note:\"Western Bypass connects directly without going through CBD. Route 102\/106.\"},\r\n  \"Westlands|Mombasa Road \/ Airport\":{direct:null,via:[[11,4],[2,18]],note:\"Change at CBD or use Southern Bypass to Langata\/Mombasa Rd junction.\"},\r\n  \"Westlands|South B \/ South C \/ Langata\":{direct:[11],via:[[4,13],[17,8]],note:\"Southern Bypass is your best bet \u2014 no need to go through CBD.\"},\r\n  \"Westlands|Eastlands\":{direct:null,via:[[4,13],[6,5]],note:\"No direct link. Change at CBD (Kencom) \u2014 board Westlands matatu then switch to a Jogoo\/Outer Ring Road matatu.\"},\r\n  \"Thika Road \/ Kasarani|Kiambu Road \/ Ridgeways\":{direct:[9,15],via:null,note:\"Northern Bypass links these two corridors directly. Routes 100\/101\/107.\"},\r\n  \"Thika Road \/ Kasarani|Eastlands\":{direct:null,via:[[1,14],[6,5]],note:\"Change at CBD. Alight at Pangani or Archives, then board an Eastlands matatu.\"},\r\n  \"Thika Road \/ Kasarani|Mombasa Road \/ Airport\":{direct:null,via:[[1,14],[2,18]],note:\"Change at CBD (Archives\/Kencom), then board a Mombasa Road\/Airport matatu.\"},\r\n  \"Thika Road \/ Kasarani|South B \/ South C \/ Langata\":{direct:null,via:[[1,14],[7,17]],note:\"Change at CBD. Alight at Kencom, then take a South B or Langata matatu.\"},\r\n  \"Eastlands|Mombasa Road \/ Airport\":{direct:[10,5,18],via:null,note:\"Eastern Bypass connects Eastlands to Airport area. Routes 33H, 34A, or bypass options.\"},\r\n  \"Eastlands|South B \/ South C \/ Langata\":{direct:[5,17],via:[[6],[17]],note:\"Outer Ring Road or Likoni Road. Some 33A routes connect directly.\"},\r\n  \"Eastlands|Kiambu Road \/ Ridgeways\":{direct:null,via:[[6,13],[15,9]],note:\"Change at CBD. No direct bypass route currently.\"},\r\n  \"South B \/ South C \/ Langata|Mombasa Road \/ Airport\":{direct:[2,17],via:null,note:\"Mombasa Road corridor runs along this route. Alight at Airport turnoff from South C.\"},\r\n  \"South B \/ South C \/ Langata|Karen \/ Ngong\":{direct:[7,8,11],via:null,note:\"Ngong Road and Lang'ata Road both serve this connection directly.\"},\r\n  \"Kiambu Road \/ Ridgeways|Eastlands\":{direct:null,via:[[15,9],[1,14],[6,5]],note:\"Change at CBD or via Thika Road. No direct bypass.\"},\r\n  \"Murang'a \/ Kariobangi|Eastlands\":{direct:[14,5,6],via:null,note:\"Routes along Outer Ring Road or Jogoo Road connect these areas.\"},\r\n  \"Embakasi \/ Pipeline|Mombasa Road \/ Airport\":{direct:[18,2],via:null,note:\"Airport North Road runs directly from Pipeline through to JKIA. Routes 33H\/33UTW.\"},\r\n  \"Industrial Area \/ Enterprise|Mombasa Road \/ Airport\":{direct:[2,16],via:null,note:\"Mombasa Road runs through Industrial Area. Routes 34\/35 serve both.\"},\r\n  \"Limuru \/ Kikuyu|Karen \/ Ngong\":{direct:[11],via:[[19,4],[7,8]],note:\"Southern Bypass links Kikuyu to Karen\/Ngong without going through CBD.\"},\r\n  \"Limuru \/ Kikuyu|Westlands\":{direct:[4,12,19],via:null,note:\"Waiyaki Way and Western Bypass both connect Limuru Rd to Westlands.\"},\r\n  \"Northern Bypass \/ Ruiru|Kiambu Road \/ Ridgeways\":{direct:[9,15],via:null,note:\"Northern Bypass directly links Ruiru\/Githurai 44 to Kiambu Road corridor.\"},\r\n};\r\n\r\nconst BROWSE_AREAS=[\"All\",\"CBD\",\"Westlands\",\"Eastlands\",\"Southlands\",\"Northlands\",\"Airport\",\"Bypass\"];\r\nconst AREA_MAP={Westlands:[4,8,19,20],CBD:[6,13,16,17,2],Eastlands:[5,6,10,16,17,18],Southlands:[7,8,11],Northlands:[1,9,14,15,19],Airport:[2,3,18],Bypass:[9,10,11,12]};\r\n\r\nlet activeArea=\"All\", query=\"\", openId=null;\r\n\r\nfunction switchTab(t){\r\n  document.querySelectorAll(\".tab\").forEach((el,i)=>el.classList.toggle(\"active\",[\"browse\",\"plan\"][i]===t));\r\n  document.querySelectorAll(\".panel\").forEach(el=>el.classList.remove(\"active\"));\r\n  document.getElementById(\"panel-\"+t).classList.add(\"active\");\r\n}\r\n\r\nfunction busyTag(c){\r\n  const h=new Date().getHours();\r\n  if((h>=7&&h<9)||(h>=17&&h<19)) return '<span class=\"tag tag-red\"><i class=\"ti ti-alert-triangle\" style=\"font-size:10px\"><\/i> Peak now<\/span>';\r\n  if(h>=5&&h<=22) return '<span class=\"tag tag-green\"><i class=\"ti ti-circle-check\" style=\"font-size:10px\"><\/i> Running<\/span>';\r\n  return '<span class=\"tag tag-amber\"><i class=\"ti ti-moon\" style=\"font-size:10px\"><\/i> Limited<\/span>';\r\n}\r\n\r\nfunction renderFilters(){\r\n  document.getElementById(\"frow\").innerHTML=BROWSE_AREAS.map(a=>\r\n    `<button class=\"fb${a===activeArea?\" active\":\"\"}\" onclick=\"setArea('${a}')\">${a}<\/button>`\r\n  ).join(\"\");\r\n}\r\nfunction setArea(a){activeArea=a;openId=null;renderBrowse();}\r\n\r\nfunction renderDetail(c){\r\n  return `<div class=\"detail\">\r\n    <h3><div class=\"badge\" style=\"background:${c.badge};color:${c.bt};width:20px;height:20px;border-radius:4px;font-size:10px;display:inline-flex;align-items:center;justify-content:center\">${c.id}<\/div>${c.name}<\/h3>\r\n    <div class=\"dg\">\r\n      <div class=\"mc\"><div class=\"ml\"><i class=\"ti ti-currency-dollar\" style=\"font-size:11px;vertical-align:-1px\"><\/i> Typical fare<\/div><div class=\"mv\">KSh ${c.fareMin}\u2013${c.fareMax}<\/div><div class=\"ms\">Peak: KSh ${c.peakFare}<\/div><\/div>\r\n      <div class=\"mc\"><div class=\"ml\"><i class=\"ti ti-clock\" style=\"font-size:11px;vertical-align:-1px\"><\/i> Hours<\/div><div class=\"mv\" style=\"font-size:13px\">${c.hours}<\/div><div class=\"ms\">Every ${c.freq}<\/div><\/div>\r\n      <div class=\"mc\"><div class=\"ml\"><i class=\"ti ti-alert-triangle\" style=\"font-size:11px;vertical-align:-1px\"><\/i> Peak times<\/div><div class=\"mv\" style=\"font-size:13px\">${c.peak}<\/div><div class=\"ms\">Higher fares<\/div><\/div>\r\n    <\/div>\r\n    ${c.tips.map(t=>`<div class=\"tip\"><i class=\"ti ti-bulb\"><\/i><span>${t}<\/span><\/div>`).join(\"\")}\r\n  <\/div>`;\r\n}\r\n\r\nfunction renderBrowse(){\r\n  const q=query.toLowerCase().trim();\r\n  let filtered=C.filter(c=>{\r\n    const mA=activeArea===\"All\"||(AREA_MAP[activeArea]||[]).includes(c.id);\r\n    if(!mA)return false;\r\n    if(!q)return true;\r\n    return c.name.toLowerCase().includes(q)||c.routes.some(r=>r.toLowerCase().includes(q))||(c.stops||[]).some(s=>s.toLowerCase().includes(q));\r\n  });\r\n  renderFilters();\r\n  document.getElementById(\"clabel\").textContent=filtered.length+\" corridor\"+(filtered.length!==1?\"s\":\"\");\r\n  document.getElementById(\"slabel\").textContent=activeArea===\"All\"?\"All corridors\":activeArea+\" corridors\";\r\n  const grid=document.getElementById(\"grid\");\r\n  const bempty=document.getElementById(\"bempty\");\r\n  const detail=document.getElementById(\"detailBox\");\r\n  if(!filtered.length){grid.innerHTML=\"\";bempty.style.display=\"block\";detail.style.display=\"none\";return;}\r\n  bempty.style.display=\"none\";\r\n  grid.innerHTML=filtered.map(c=>{\r\n    const sr=c.routes.slice(0,5),mr=c.routes.length-5;\r\n    const ph=sr.map(r=>`<span class=\"rp\">${r}<\/span>`).join(\"\")+(mr>0?`<span class=\"rp more\">+${mr}<\/span>`:\"\");\r\n    const isOpen=openId===c.id;\r\n    return `<div class=\"card\" onclick=\"toggleCard(${c.id})\" style=\"${isOpen?\"border-color:\"+c.color+\";border-width:1px\":\"\"}\">\r\n      <div class=\"ctb\" style=\"background:${c.color}\"><\/div>\r\n      <div class=\"ch\"><div class=\"ctr\"><div class=\"badge\" style=\"background:${c.badge};color:${c.bt}\">${c.id}<\/div><div><div class=\"cname\">${c.name}<\/div><div class=\"csub\">${c.routes.length} routes<\/div><\/div><\/div><i class=\"ti ti-chevron-${isOpen?\"up\":\"down\"}\" style=\"font-size:12px;color:var(--color-text-tertiary)\"><\/i><\/div>\r\n      <div class=\"rrow\">${ph}<\/div>\r\n      <div class=\"meta\">\r\n        <div class=\"mrow\"><i class=\"ti ti-currency-dollar\"><\/i><strong>KSh ${c.fareMin}\u2013${c.fareMax}<\/strong><span style=\"color:var(--color-text-tertiary)\"> \u00b7 peak KSh ${c.peakFare}<\/span><\/div>\r\n        <div class=\"mrow\"><i class=\"ti ti-clock\"><\/i>${c.hours}<\/div>\r\n        <div class=\"mrow\"><i class=\"ti ti-refresh\"><\/i>Every ${c.freq} &nbsp;${busyTag(c)}<\/div>\r\n      <\/div>\r\n    <\/div>`;\r\n  }).join(\"\");\r\n  if(openId!==null&&filtered.find(x=>x.id===openId)){\r\n    const oc=C.find(x=>x.id===openId);\r\n    if(oc){detail.style.display=\"block\";detail.innerHTML=renderDetail(oc);}\r\n  } else {detail.style.display=\"none\";}\r\n}\r\n\r\nfunction toggleCard(id){\r\n  openId=openId===id?null:id;\r\n  renderBrowse();\r\n  if(openId!==null) setTimeout(()=>{const d=document.getElementById(\"detailBox\");if(d)d.scrollIntoView({behavior:\"smooth\",block:\"nearest\"});},50);\r\n}\r\n\r\ndocument.getElementById(\"search\").addEventListener(\"input\",e=>{query=e.target.value;openId=null;renderBrowse();});\r\n\r\nfunction getJPKey(a,b){\r\n  if(JP_DATA[a+\"|\"+b]) return {key:a+\"|\"+b,flipped:false};\r\n  if(JP_DATA[b+\"|\"+a]) return {key:b+\"|\"+a,flipped:true};\r\n  return null;\r\n}\r\n\r\nfunction getCorridor(id){return C.find(x=>x.id===id);}\r\n\r\nfunction populateSelects(){\r\n  const opts=AREAS.map((a,i)=>`<option value=\"${i}\">${a.name}<\/option>`).join(\"\");\r\n  document.getElementById(\"fromSel\").innerHTML=opts;\r\n  document.getElementById(\"toSel\").innerHTML=opts;\r\n  document.getElementById(\"toSel\").value=\"1\";\r\n}\r\n\r\nfunction planJourney(){\r\n  const fi=parseInt(document.getElementById(\"fromSel\").value);\r\n  const ti=parseInt(document.getElementById(\"toSel\").value);\r\n  const from=AREAS[fi], to=AREAS[ti];\r\n  const res=document.getElementById(\"jp-result\");\r\n  if(fi===ti){res.innerHTML=`<div class=\"no-route\"><i class=\"ti ti-info-circle\" style=\"font-size:20px;color:var(--color-text-tertiary);display:block;margin:0 auto 6px\"><\/i>Choose different origin and destination areas.<\/div>`;return;}\r\n\r\n  const match=getJPKey(from.name,to.name);\r\n  let html=\"\";\r\n\r\n  if(match){\r\n    const d=JP_DATA[match.key];\r\n    const fromA=match.flipped?to:from;\r\n    const toA=match.flipped?from:to;\r\n\r\n    if(d.direct&&d.direct.length){\r\n      const cList=d.direct.map(id=>{const c=getCorridor(id);return c?`<span style=\"display:inline-flex;align-items:center;gap:4px;margin-right:6px\"><span class=\"badge\" style=\"background:${c.badge};color:${c.bt};width:18px;height:18px;border-radius:3px;font-size:9px\">${c.id}<\/span><strong style=\"font-size:12px;color:var(--color-text-primary)\">${c.name}<\/strong><\/span>`:\"\"}).join(\"\");\r\n      const fMin=Math.min(...d.direct.map(id=>{const c=getCorridor(id);return c?c.fareMin:999;}));\r\n      const fMax=Math.max(...d.direct.map(id=>{const c=getCorridor(id);return c?c.fareMax:0;}));\r\n      const fc=getCorridor(d.direct[0]);\r\n      html+=`<div class=\"route-card direct\">\r\n        <div class=\"rc-head\"><div class=\"rc-title\"><i class=\"ti ti-route\" style=\"font-size:14px;color:#0F6E56\"><\/i> Direct route<\/div><span class=\"tag tag-green\">No change<\/span><\/div>\r\n        <div style=\"display:flex;align-items:center;gap:8px;margin-bottom:8px;font-size:12px\">\r\n          <span style=\"font-weight:500;color:var(--color-text-primary)\">${from.name}<\/span>\r\n          <div class=\"leg-bar\" style=\"background:${fc?fc.color:'#0F6E56'}\"><\/div>\r\n          <span style=\"font-weight:500;color:var(--color-text-primary)\">${to.name}<\/span>\r\n        <\/div>\r\n        <div style=\"margin-bottom:6px\">${cList}<\/div>\r\n        <div class=\"leg-detail\"><strong>Fare: KSh ${fMin}\u2013${fMax}<\/strong> \u00b7 Board at main stage for this corridor<\/div>\r\n        ${d.note?`<div class=\"tip\" style=\"margin-top:6px;margin-bottom:0\"><i class=\"ti ti-bulb\"><\/i><span>${d.note}<\/span><\/div>`:\"\"}\r\n      <\/div>`;\r\n    }\r\n\r\n    if(d.via&&d.via.length){\r\n      d.via.forEach(legs=>{\r\n        const c1=getCorridor(legs[0]),c2=legs[1]?getCorridor(legs[1]):null;\r\n        if(!c1)return;\r\n        const fMin=(c1?c1.fareMin:0)+(c2?c2.fareMin:0);\r\n        const fMax=(c1?c1.fareMax:0)+(c2?c2.fareMax:0);\r\n        html+=`<div class=\"route-card\">\r\n          <div class=\"rc-head\"><div class=\"rc-title\"><i class=\"ti ti-transfer\" style=\"font-size:14px;color:var(--color-text-secondary)\"><\/i> Via ${c2?\"CBD \/ interchange\":\"CBD\"}<\/div><span class=\"tag tag-amber\">${c2?\"1 change\":\"1 leg\"}<\/span><\/div>\r\n          <div style=\"display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:8px;font-size:12px\">\r\n            <span style=\"font-weight:500;color:var(--color-text-primary)\">${from.name}<\/span>\r\n            <div class=\"leg-bar\" style=\"background:${c1.color}\"><\/div>\r\n            ${c2?`<span style=\"color:var(--color-text-secondary)\">CBD<\/span><div class=\"leg-bar\" style=\"background:${c2.color}\"><\/div>`:\"\"}\r\n            <span style=\"font-weight:500;color:var(--color-text-primary)\">${to.name}<\/span>\r\n          <\/div>\r\n          <div style=\"display:flex;gap:8px;flex-wrap:wrap;margin-bottom:6px\">\r\n            <span style=\"display:inline-flex;align-items:center;gap:4px\"><span class=\"badge\" style=\"background:${c1.badge};color:${c1.bt};width:18px;height:18px;border-radius:3px;font-size:9px\">${c1.id}<\/span><strong style=\"font-size:12px;color:var(--color-text-primary)\">${c1.name}<\/strong><\/span>\r\n            ${c2?`<span style=\"font-size:12px;color:var(--color-text-tertiary)\">\u2192<\/span><span style=\"display:inline-flex;align-items:center;gap:4px\"><span class=\"badge\" style=\"background:${c2.badge};color:${c2.bt};width:18px;height:18px;border-radius:3px;font-size:9px\">${c2.id}<\/span><strong style=\"font-size:12px;color:var(--color-text-primary)\">${c2.name}<\/strong><\/span>`:\"\"}\r\n          <\/div>\r\n          <div class=\"leg-detail\"><strong>Combined fare: KSh ${fMin}\u2013${fMax}<\/strong>${c2?\" \u00b7 Change at Kencom or Archives stage\":\"\"}<\/div>\r\n        <\/div>`;\r\n      });\r\n    }\r\n  } else {\r\n    const shared=from.corridors.filter(id=>to.corridors.includes(id));\r\n    if(shared.length){\r\n      const cList=shared.map(id=>{const c=getCorridor(id);return c?`<span style=\"display:inline-flex;align-items:center;gap:4px;margin-right:6px\"><span class=\"badge\" style=\"background:${c.badge};color:${c.bt};width:18px;height:18px;border-radius:3px;font-size:9px\">${c.id}<\/span><strong style=\"font-size:12px;color:var(--color-text-primary)\">${c.name}<\/strong><\/span>`:\"\"}).join(\"\");\r\n      const fMin=Math.min(...shared.map(id=>{const c=getCorridor(id);return c?c.fareMin:999;}));\r\n      const fMax=Math.max(...shared.map(id=>{const c=getCorridor(id);return c?c.fareMax:0;}));\r\n      html=`<div class=\"route-card direct\">\r\n        <div class=\"rc-head\"><div class=\"rc-title\"><i class=\"ti ti-route\" style=\"font-size:14px;color:#0F6E56\"><\/i> Shared corridor<\/div><span class=\"tag tag-green\">Direct<\/span><\/div>\r\n        <div style=\"display:flex;align-items:center;gap:8px;margin-bottom:8px;font-size:12px\">\r\n          <span style=\"font-weight:500;color:var(--color-text-primary)\">${from.name}<\/span>\r\n          <div class=\"leg-bar\" style=\"background:#0F6E56\"><\/div>\r\n          <span style=\"font-weight:500;color:var(--color-text-primary)\">${to.name}<\/span>\r\n        <\/div>\r\n        <div style=\"margin-bottom:6px\">${cList}<\/div>\r\n        <div class=\"leg-detail\"><strong>Est. fare: KSh ${fMin}\u2013${fMax}<\/strong><\/div>\r\n      <\/div>`;\r\n    } else {\r\n      html=`<div class=\"no-route\"><i class=\"ti ti-route-off\" style=\"font-size:20px;color:var(--color-text-tertiary);display:block;margin:0 auto 6px\"><\/i><span style=\"display:block;margin-bottom:8px\">No stored route for this combination yet.<\/span><\/div>`;\r\n    }\r\n  }\r\n\r\n  res.innerHTML=html;\r\n}\r\n\r\nfunction swapAreas(){\r\n  const f=document.getElementById(\"fromSel\"),t=document.getElementById(\"toSel\");\r\n  const tmp=f.value;f.value=t.value;t.value=tmp;\r\n  planJourney();\r\n}\r\n\r\n\/\/ Boot\r\npopulateSelects();\r\nrenderBrowse();\r\nplanJourney();\r\n<\/script>\r\n<\/body>\r\n<\/html>\t\t\t\t<\/div>\n\t\t\n<\/div>\n\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Nairobi Matatu Route Finder Nairobi Matatu Guide Browse 20 corridors \u00b7 fare estimates \u00b7 operating hours \u00b7 journey planner Browse corridors Plan journey All corridors No corridors match \u2014 try a route number or area name. From To<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"footnotes":""},"class_list":["post-105","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/metros.co.ke\/NairobiMatatu\/wp-json\/wp\/v2\/pages\/105","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/metros.co.ke\/NairobiMatatu\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/metros.co.ke\/NairobiMatatu\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/metros.co.ke\/NairobiMatatu\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/metros.co.ke\/NairobiMatatu\/wp-json\/wp\/v2\/comments?post=105"}],"version-history":[{"count":112,"href":"https:\/\/metros.co.ke\/NairobiMatatu\/wp-json\/wp\/v2\/pages\/105\/revisions"}],"predecessor-version":[{"id":226,"href":"https:\/\/metros.co.ke\/NairobiMatatu\/wp-json\/wp\/v2\/pages\/105\/revisions\/226"}],"wp:attachment":[{"href":"https:\/\/metros.co.ke\/NairobiMatatu\/wp-json\/wp\/v2\/media?parent=105"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}