// ===== BICYCLES & E-BIKES ===== // ---------- Shared: hand signals data ---------- const bike_signals = [ { id: 1, label: 'Turn left', desc: 'Left arm straight out', icon: '⬅️' }, { id: 2, label: 'Turn right', desc: 'Right arm out, or left arm bent up', icon: '➡️' }, { id: 3, label: 'Slowing / stop', desc: 'Left arm bent down, palm back', icon: '✋' }, { id: 4, label: 'Hazard ahead', desc: 'Point down at the road hazard', icon: '👇' }, ]; const bike_gear = [ { id: 'helmet', icon: '🪖', label: 'Certified helmet', desc: 'Properly fastened, correct fit' }, { id: 'lights', icon: '💡', label: 'Front & rear lights', desc: 'White front, red rear — esp. at night' }, { id: 'reflect', icon: '🦺', label: 'Reflective vest / strips', desc: 'Be visible from all sides' }, { id: 'bell', icon: '🔔', label: 'Working bell or horn', desc: 'Alert pedestrians & vehicles' }, { id: 'brakes', icon: '🛑', label: 'Brakes checked', desc: 'Both brakes firm and responsive' }, { id: 'tires', icon: '🛞', label: 'Tire pressure & tread', desc: 'Inflated, no cracks or bulges' }, ]; const bike_rules = [ { id: 1, cat: 'Use the bike lane', icon: '🛣️', rules: [ 'Ride in designated bike lanes where provided (per local bike-lane ordinances)', 'Where no lane exists, keep to the rightmost part of the road', 'Ride in single file on busy roads; max two abreast on quiet ones', ]}, { id: 2, cat: 'Obey traffic rules', icon: '🚦', rules: [ 'Cyclists follow the same signals and signs as motor vehicles', 'Stop at red lights and pedestrian crossings', 'Never ride against the flow of traffic (no counterflow)', ]}, { id: 3, cat: 'Be visible & predictable', icon: '👁️', rules: [ 'Use hand signals before turning or stopping', 'Make eye contact with drivers at intersections', 'Avoid riding in vehicle blind spots, especially trucks & buses', ]}, { id: 4, cat: 'Your protections', icon: '🛡️', rules: [ 'Many LGUs protect bike lanes — blocking them is finable', 'Motorists must keep a safe overtaking distance from cyclists', 'You have equal right to the road as a vulnerable road user', ]}, ]; const bike_routes = [ { name: 'EDSA Protected Bike Lane', len: '23 km', type: 'Protected', color: '#00c48c' }, { name: 'Marikina Bikeways', len: '52 km', type: 'Protected', color: '#00c48c' }, { name: 'Pasig Greenways', len: '14 km', type: 'Painted', color: '#ffa502' }, { name: 'BGC Cycle Network', len: '11 km', type: 'Protected', color: '#00c48c' }, ]; function BicycleScreen({ t, go }) { const [checked, setChecked] = useState({}); const [open, setOpen] = useState(1); const [toast, setToast] = useState(''); const note = (m) => { setToast(m); setTimeout(() => setToast(''), 2000); }; const done = Object.values(checked).filter(Boolean).length; return (
{toast &&
{toast}
}
🚲
Cyclist Hub
Ride safe, know your rights, and find protected bike lanes across Metro Manila.
{/* Pre-ride gear checklist */}
{done}/{bike_gear.length}}>Pre-Ride Safety Check {bike_gear.map((g, i) => { const on = !!checked[g.id]; return ( ); })}
{/* Bike lanes */}
note('Opening bike-lane map…')} className="no-select" style={{ background: 'none', border: 'none', color: t.mid, fontSize: 12.5, fontWeight: 700 }}>View map}>Protected Bike Lanes
{bike_routes.map(r => (
{r.name}
{r.len} · {r.type} lane
{r.type}
))}
{/* Hand signals */}
Hand Signals
{bike_signals.map(s => (
{s.icon}
{s.label}
{s.desc}
))}
{/* Rights & rules */}
Cyclist Rights & Rules
{bike_rules.map(l => { const isOpen = open === l.id; return (
{l.rules.map((r, i) => (
{r}
))}
); })}
{/* Report */}
Blocked or unsafe bike lane?
Report obstructions, parked vehicles, or hazards in bike lanes to your LGU.
); } // ---------- E-BIKES ---------- const ebike_classes = [ { id: 1, cls: 'Type A1 · Pedal-assist', speed: '≤ 25 km/h', reg: false, lic: false, where: 'Bike lanes & local roads', color: '#00c48c', icon: '🚲', note: 'Light e-bikes & pedal-assist. No LTO registration or license required.' }, { id: 2, cls: 'Type A2/B · Throttle e-bike', speed: '26–50 km/h', reg: true, lic: false, where: 'Local roads (not bike lanes)', color: '#ffa502', icon: '🛵', note: 'Must be LTO-registered with a plate. Driver\u2019s license generally not required but helmet is mandatory.' }, { id: 3, cls: 'Type L · E-motorcycle', speed: '> 50 km/h', reg: true, lic: true, where: 'Roads only (no bike lanes/sidewalks)', color: '#ff4757', icon: '🏍️', note: 'Treated as a motorcycle: LTO registration, plate, and driver\u2019s license all required.' }, ]; const ebike_battery = [ { icon: '🔌', text: 'Use only the manufacturer\u2019s charger and cable' }, { icon: '🌡️', text: 'Charge in a cool, dry, ventilated area — never on exits or stairs' }, { icon: '⏰', text: 'Don\u2019t charge overnight or unattended; unplug when full' }, { icon: '🚫', text: 'Stop using a battery that is swollen, hot, or damaged' }, { icon: '💧', text: 'Keep batteries away from water and direct heat/sun' }, { icon: '🧯', text: 'Keep a working smoke alarm where you charge' }, ]; const ebike_stations = [ { name: 'SM Megamall — EV Bay', dist: '1.2 km', slots: '4 free', color: '#00c48c' }, { name: 'Ayala Triangle Charge Point', dist: '3.4 km', slots: '1 free', color: '#ffa502' }, { name: 'Robinsons Galleria Hub', dist: '2.1 km', slots: 'Full', color: '#ff4757' }, ]; function EbikeScreen({ t, go }) { const [sel, setSel] = useState(1); const [toast, setToast] = useState(''); const note = (m) => { setToast(m); setTimeout(() => setToast(''), 2000); }; const cur = ebike_classes.find(c => c.id === sel); return (
{toast &&
{toast}
}
🛵
E-Bike Center
Know your e-bike class, registration rules, where you can ride, and how to charge safely.
{/* Classification selector */}
What class is your e-bike?
{ebike_classes.map(c => ( setSel(c.id)} color={c.color}>{c.icon} {c.speed} ))}
{cur.cls}
Top speed {cur.speed}

{cur.note}

{[['LTO registration', cur.reg], ["Driver's license", cur.lic]].map(([label, need]) => (
{need ? 'Required' : 'Not needed'}
{label}
))}
Required
Helmet
Allowed: {cur.where}
Guidance based on LTO rules for light electric vehicles. Always confirm the latest LTO/LGU requirements.
{cur.reg && ( note('Opening LTO e-vehicle registration…')}>Register with LTO )} {/* Battery safety */}
🔋 Battery & Charging Safety
{ebike_battery.map((b, i) => (
{b.icon} {b.text}
))}
{/* Charging stations */}
note('Opening charging map…')} className="no-select" style={{ background: 'none', border: 'none', color: t.mid, fontSize: 12.5, fontWeight: 700 }}>View map}>Nearby Charging Stations
{ebike_stations.map(s => (
{s.name}
{s.dist} away
{s.slots}
))}
); } Object.assign(window, { BicycleScreen, EbikeScreen });