Liveweave: Generative AI Web Editor & HTML/CSS/JS Playground
Initializing
Liveweave
Web
expand_more
home
Home
Palette
Color Explorer
arrow_outward
Polyline
Graphics Editor
arrow_outward
frame_source
Python Playground
arrow_outward
build
Tools
expand_more
restart_alt
Load "Hello Weaver!"
post_add
Generate Lorem ipsum...
code
Format HTML
code_blocks
Format CSS
data_object
Format JavaScript
library_add
Library
expand_more
A
Algolia JS
Animate CSS
Apex Charts JS
B
Bulma CSS
Bootstrap
C
Chart JS
Chartist
Create JS
D
D3
Dojo
F
Foundation
Fullpage JS
G
Granim JS
Google Charts
H
Halfmoon
J
jQuery
M
Materialize
Moment JS
Masonry JS
Milligram CSS
P
Pure CSS
Primer CSS
Popper JS
Pattern CSS
Picnic CSS
R
React JS
Raphael JS
Raisin CSS
S
Semantic UI
Skeleton CSS
Spectre CSS
Tachyons CSS
T
Tailwind
Three JS
U
UI Kit
Vis JS
W
Water CSS
download
Download
expand_more
developer_mode
Download as HTML
folder_zip
Download as .ZIP
cloud_upload
Fork
account_circle
Login
settings
Settings
expand_more
Editor font
14
px
A
A
Night mode
Line number
Mini map
Word wrap
sync_alt
Reset Settings
smart_display
Run
left_panel_close
AI Assistant
dashboard
All
HTML
CSS
JS
visibility
Preview
bolt
Live Preview
terminal
JS Console
<!DOCTYPE html> <html> <head> <title>Flight Tracker</title> </head> <body> <!-- Start your code here --> <div class="app-shell"> <!-- SIDEBAR --> <aside class="sidebar"> <div class="brand"> <div class="brand-mark">✈</div> <div> <strong>SKYTRACK</strong> <span>FLIGHT OPERATIONS</span> </div> </div> <nav class="side-nav"> <button class="active"> <span>⌁</span> Overview </button> <button> <span>✈</span> Flights </button> <button> <span>◎</span> Airports </button> <button> <span>▦</span> Schedule </button> </nav> <div class="system-status"> <span class="status-dot"></span> <div> <strong>Systems operational</strong> <small>Updated just now</small> </div> </div> </aside> <!-- MAIN --> <main class="main"> <!-- HEADER --> <header class="topbar"> <div> <span class="eyebrow">FLIGHT TRACKER</span> <h1>Good morning.</h1> </div> <div class="header-right"> <div class="utc-clock"> <span>UTC TIME</span> <strong id="clock">13:42:08</strong> </div> <button class="profile"> AT </button> </div> </header> <!-- SEARCH --> <section class="search-panel"> <div class="search-icon">⌕</div> <input id="flightSearch" type="text" placeholder="Search flight number..." value="NW 482" > <button id="trackButton"> Track flight </button> </section> <!-- ACTIVE FLIGHT HEADER --> <section class="flight-heading"> <div class="airline-badge"> NW </div> <div class="flight-name"> <span>ACTIVE FLIGHT</span> <h2 id="flightNumber">NW 482</h2> <p>NewsWire Air · Boeing 787-9</p> </div> <div class="flight-status"> <span></span> ON TIME </div> </section> <!-- MAP --> <section class="map-card"> <div class="map-toolbar"> <div> <span>LIVE POSITION</span> <strong>North America</strong> </div> <div class="map-buttons"> <button id="zoomIn">+</button> <button id="zoomOut">−</button> </div> </div> <div class="map" id="map"> <!-- decorative geography --> <div class="continent continent-one"></div> <div class="continent continent-two"></div> <div class="continent continent-three"></div> <div class="grid-lines"></div> <!-- ROUTE --> <svg class="route-layer" viewBox="0 0 1000 400" preserveAspectRatio="none" > <path class="route-shadow" d="M125 285 C360 30 650 45 865 170" /> <path class="route-line" id="routePath" d="M125 285 C360 30 650 45 865 170" /> </svg> <!-- JFK --> <div class="airport-point origin"> <div class="airport-pulse"></div> <i></i> <div class="airport-label"> <strong>JFK</strong> <span>New York</span> </div> </div> <!-- LAX --> <div class="airport-point destination"> <div class="airport-pulse"></div> <i></i> <div class="airport-label"> <strong>LAX</strong> <span>Los Angeles</span> </div> </div> <!-- AIRCRAFT --> <div class="aircraft" id="aircraft"> ✈ <div class="aircraft-info"> <strong>NW482</strong> <span>36,000 ft</span> </div> </div> <!-- MAP LABELS --> <span class="city-label chicago"> CHICAGO </span> <span class="city-label denver"> DENVER </span> <span class="city-label dallas"> DALLAS </span> <!-- MAP SCALE --> <div class="map-scale"> 500 km </div> </div> </section> <!-- ROUTE SUMMARY --> <section class="route-card"> <!-- DEPARTURE --> <div class="airport"> <span class="airport-type"> DEPARTURE </span> <div class="airport-code"> JFK </div> <strong> New York </strong> <span class="airport-name"> John F. Kennedy International </span> <div class="time"> 08:35 </div> <small> Terminal 4 · Gate B28 </small> </div> <!-- PROGRESS --> <div class="journey"> <div class="journey-top"> <span>5h 48m</span> <span>2,475 mi</span> </div> <div class="progress-track"> <div class="progress-fill" id="progressFill" ></div> <div class="progress-plane" id="progressPlane" > ✈ </div> </div> <div class="journey-bottom"> <span>DEPARTED</span> <strong id="progressText">62%</strong> <span>ARRIVAL</span> </div> </div> <!-- ARRIVAL --> <div class="airport arrival"> <span class="airport-type"> ARRIVAL </span> <div class="airport-code"> LAX </div> <strong> Los Angeles </strong> <span class="airport-name"> Los Angeles International </span> <div class="time"> 11:23 </div> <small> Terminal B · Gate 154 </small> </div> </section> <!-- TELEMETRY --> <section class="stats-grid"> <article class="stat-card"> <div class="stat-icon">↥</div> <span>ALTITUDE</span> <strong id="altitude"> 36,000 </strong> <small>FEET</small> <div class="mini-chart"> <span style="height:30%"></span> <span style="height:45%"></span> <span style="height:68%"></span> <span style="height:80%"></span> <span style="height:80%"></span> <span style="height:81%"></span> <span style="height:80%"></span> </div> </article> <article class="stat-card"> <div class="stat-icon">→</div> <span>GROUND SPEED</span> <strong id="speed"> 548 </strong> <small>MPH</small> <div class="speed-line"></div> </article> <article class="stat-card"> <div class="stat-icon">⌁</div> <span>DISTANCE REMAINING</span> <strong id="distance"> 940 </strong> <small>MILES</small> <div class="distance-bar"> <div></div> </div> </article> <article class="stat-card"> <div class="stat-icon">◷</div> <span>TIME REMAINING</span> <strong id="remaining"> 2:12 </strong> <small>HOURS</small> <div class="eta"> ETA 11:23 PDT </div> </article> </section> <!-- LOWER GRID --> <section class="lower-grid"> <!-- FLIGHT INFO --> <article class="info-card"> <div class="card-title"> <div> <span>FLIGHT DETAILS</span> <h3>Aircraft</h3> </div> <div class="plane-symbol"> ✈ </div> </div> <div class="aircraft-name"> Boeing 787-9 Dreamliner </div> <div class="detail-grid"> <div> <span>REGISTRATION</span> <strong>N482NW</strong> </div> <div> <span>CALLSIGN</span> <strong>NW482</strong> </div> <div> <span>HEADING</span> <strong>267° W</strong> </div> <div> <span>VERTICAL SPEED</span> <strong>0 ft/min</strong> </div> </div> </article> <!-- WEATHER --> <article class="weather-card"> <div class="card-title"> <div> <span>DESTINATION</span> <h3>LAX Weather</h3> </div> <div class="weather-icon"> ☀ </div> </div> <div class="temperature"> 74° </div> <div class="condition"> Clear skies </div> <div class="weather-details"> <div> <span>WIND</span> <strong>8 mph W</strong> </div> <div> <span>VISIBILITY</span> <strong>10 mi</strong> </div> <div> <span>HUMIDITY</span> <strong>48%</strong> </div> </div> </article> </section> <!-- DEPARTURES --> <section class="departures"> <div class="departures-header"> <div> <span>AIRPORT ACTIVITY</span> <h2>Upcoming departures</h2> </div> <button> View all flights </button> </div> <div class="table-wrap"> <table> <thead> <tr> <th>FLIGHT</th> <th>DESTINATION</th> <th>DEPARTURE</th> <th>GATE</th> <th>STATUS</th> </tr> </thead> <tbody> <tr> <td> <strong>NW 224</strong> </td> <td> <b>SFO</b> San Francisco </td> <td>09:10</td> <td>A12</td> <td> <span class="table-status ontime"> ON TIME </span> </td> </tr> <tr> <td> <strong>NW 718</strong> </td> <td> <b>SEA</b> Seattle </td> <td>09:35</td> <td>B04</td> <td> <span class="table-status boarding"> BOARDING </span> </td> </tr> <tr> <td> <strong>NW 356</strong> </td> <td> <b>ORD</b> Chicago </td> <td>10:05</td> <td>C17</td> <td> <span class="table-status delayed"> DELAYED </span> </td> </tr> <tr> <td> <strong>NW 902</strong> </td> <td> <b>MIA</b> Miami </td> <td>10:28</td> <td>A09</td> <td> <span class="table-status ontime"> ON TIME </span> </td> </tr> </tbody> </table> </div> </section> </main> </div> <!-- End your code here --> </body> </html>
* { box-sizing: border-box; } :root { --bg: #07101c; --panel: #0c1725; --panel-light: #101d2d; --line: rgba(255,255,255,.07); --text: #f5f8fc; --muted: #77869a; --blue: #42a5ff; --cyan: #55d8ff; --green: #4ed49c; --orange: #ffb45e; } html, body { margin: 0; min-height: 100%; background: #07101c; color: var(--text); font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; } button, input { font: inherit; } button { cursor: pointer; } .app-shell { min-height: 100vh; display: grid; grid-template-columns: 210px 1fr; } /* ========================= SIDEBAR ========================= */ .sidebar { position: fixed; left: 0; top: 0; bottom: 0; width: 210px; display: flex; flex-direction: column; padding: 25px 18px; border-right: 1px solid var(--line); background: #08121f; } .brand { display: flex; align-items: center; gap: 10px; padding: 0 8px 28px; } .brand-mark { width: 35px; height: 35px; display: grid; place-items: center; border-radius: 10px; background: linear-gradient( 135deg, #2588ff, #55d8ff ); color: white; font-size: 17px; box-shadow: 0 8px 25px rgba(39,143,255,.22); } .brand strong { display: block; font-size: 13px; letter-spacing: .4px; } .brand span { display: block; margin-top: 2px; color: #53647a; font-size: 6px; letter-spacing: 1.2px; } .side-nav { display: flex; flex-direction: column; gap: 4px; } .side-nav button { width: 100%; display: flex; align-items: center; gap: 11px; padding: 11px 12px; border: 0; border-radius: 9px; background: transparent; color: #68798f; font-size: 9px; text-align: left; } .side-nav button span { width: 20px; color: #708198; font-size: 15px; } .side-nav button:hover { background: rgba(255,255,255,.03); color: white; } .side-nav button.active { background: rgba(56,155,255,.1); color: #65b8ff; } .side-nav button.active span { color: #58afff; } .system-status { display: flex; align-items: center; gap: 9px; margin-top: auto; padding: 14px 10px; border-top: 1px solid var(--line); } .status-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--green); box-shadow: 0 0 10px rgba(78,212,156,.5); } .system-status strong { display: block; font-size: 8px; } .system-status small { display: block; margin-top: 2px; color: #526278; font-size: 6px; } /* ========================= MAIN ========================= */ .main { grid-column: 2; width: 100%; max-width: 1450px; margin: auto; padding: 28px 32px 60px; } /* ========================= TOP BAR ========================= */ .topbar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 24px; } .eyebrow { color: #52647b; font-size: 7px; font-weight: 700; letter-spacing: 1.6px; } .topbar h1 { margin: 5px 0 0; font-size: 25px; font-weight: 600; letter-spacing: -1px; } .header-right { display: flex; align-items: center; gap: 17px; } .utc-clock { text-align: right; } .utc-clock span { display: block; color: #52647b; font-size: 6px; letter-spacing: 1px; } .utc-clock strong { display: block; margin-top: 3px; font-size: 11px; font-variant-numeric: tabular-nums; } .profile { width: 36px; height: 36px; border: 0; border-radius: 50%; background: #17283b; color: #83bff5; font-size: 9px; font-weight: 700; } /* ========================= SEARCH ========================= */ .search-panel { height: 53px; display: grid; grid-template-columns: 30px 1fr auto; align-items: center; gap: 7px; margin-bottom: 26px; padding: 6px 7px 6px 14px; border: 1px solid var(--line); border-radius: 12px; background: #0b1725; } .search-icon { color: #566a81; font-size: 20px; } .search-panel input { width: 100%; border: 0; outline: 0; background: transparent; color: white; font-size: 10px; } .search-panel input::placeholder { color: #506176; } .search-panel button { height: 39px; padding: 0 18px; border: 0; border-radius: 8px; background: #1687ed; color: white; font-size: 8px; font-weight: 700; transition: .2s ease; } .search-panel button:hover { background: #2999ff; transform: translateY(-1px); } /* ========================= FLIGHT HEADER ========================= */ .flight-heading { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 12px; margin-bottom: 15px; } .airline-badge { width: 43px; height: 43px; display: grid; place-items: center; border: 1px solid rgba(74,170,255,.25); border-radius: 11px; background: rgba(52,152,255,.08); color: #6bb9ff; font-size: 11px; font-weight: 800; } .flight-name > span { color: #51647a; font-size: 6px; font-weight: 700; letter-spacing: 1.3px; } .flight-name h2 { display: inline-block; margin: 3px 6px 0 0; font-size: 18px; } .flight-name p { display: inline; color: #62748a; font-size: 8px; } .flight-status { display: flex; align-items: center; gap: 6px; padding: 7px 10px; border: 1px solid rgba(70,211,153,.15); border-radius: 20px; background: rgba(70,211,153,.06); color: #62daa7; font-size: 7px; font-weight: 700; letter-spacing: .5px; } .flight-status span { width: 6px; height: 6px; border-radius: 50%; background: #52d99e; box-shadow: 0 0 8px rgba(82,217,158,.5); } /* ========================= MAP CARD ========================= */ .map-card { overflow: hidden; border: 1px solid var(--line); border-radius: 15px; background: #0b1725; } .map-toolbar { height: 58px; display: flex; align-items: center; justify-content: space-between; padding: 0 17px; border-bottom: 1px solid var(--line); } .map-toolbar span { display: block; color: #516278; font-size: 6px; letter-spacing: 1.2px; } .map-toolbar strong { display: block; margin-top: 3px; font-size: 10px; } .map-buttons { display: flex; gap: 5px; } .map-buttons button { width: 29px; height: 29px; border: 1px solid var(--line); border-radius: 7px; background: #101e2e; color: #8999aa; } .map { position: relative; height: 340px; overflow: hidden; background: radial-gradient( circle at 45% 45%, #10243a, #091624 65% ); transition: background-size .3s; } /* MAP GRID */ .grid-lines { position: absolute; inset: 0; opacity: .18; background-image: linear-gradient( rgba(90,150,200,.12) 1px, transparent 1px ), linear-gradient( 90deg, rgba(90,150,200,.12) 1px, transparent 1px ); background-size: 55px 55px; } /* FAKE LAND */ .continent { position: absolute; background: #132b3c; opacity: .72; filter: drop-shadow( 0 0 15px rgba(40,100,130,.12) ); } .continent-one { width: 390px; height: 230px; left: 20px; top: 65px; border-radius: 40% 55% 35% 60%; transform: rotate(-10deg); clip-path: polygon( 5% 30%, 20% 8%, 42% 4%, 62% 17%, 90% 13%, 100% 36%, 86% 52%, 75% 81%, 52% 94%, 34% 77%, 20% 82%, 10% 61% ); } .continent-two { width: 270px; height: 150px; right: 40px; top: 90px; border-radius: 50%; transform: rotate(7deg); clip-path: polygon( 0 33%, 25% 12%, 55% 20%, 79% 5%, 100% 28%, 91% 67%, 62% 76%, 48% 95%, 17% 80% ); } .continent-three { width: 140px; height: 90px; left: 43%; bottom: -25px; border-radius: 50%; transform: rotate(20deg); } /* ROUTE */ .route-layer { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; } .route-shadow, .route-line { fill: none; } .route-shadow { stroke: rgba(54,166,255,.12); stroke-width: 10; } .route-line { stroke: #44b8ff; stroke-width: 2; stroke-dasharray: 6 8; filter: drop-shadow( 0 0 5px rgba(68,184,255,.6) ); animation: routeFlow 3s linear infinite; } @keyframes routeFlow { to { stroke-dashoffset: -28; } } /* AIRPORTS */ .airport-point { position: absolute; z-index: 5; } .airport-point.origin { left: 12%; top: 70%; } .airport-point.destination { right: 12%; top: 40%; } .airport-point i { position: relative; z-index: 2; width: 9px; height: 9px; display: block; border: 2px solid #6fcaff; border-radius: 50%; background: #0c1825; box-shadow: 0 0 12px rgba(75,190,255,.7); } .airport-pulse { position: absolute; left: -7px; top: -7px; width: 23px; height: 23px; border: 1px solid rgba(79,189,255,.3); border-radius: 50%; animation: airportPulse 2s infinite; } @keyframes airportPulse { 70% { transform: scale(1.5); opacity: 0; } 100% { opacity: 0; } } .airport-label { position: absolute; top: 15px; min-width: 80px; } .destination .airport-label { right: 0; text-align: right; } .airport-label strong { display: block; color: #d7ecff; font-size: 9px; } .airport-label span { color: #577087; font-size: 6px; } /* AIRCRAFT */ .aircraft { position: absolute; z-index: 10; left: 57%; top: 29%; color: white; font-size: 23px; transform: rotate(-13deg); filter: drop-shadow( 0 0 8px rgba(100,200,255,.8) ); transition: left 1s linear, top 1s linear; } .aircraft-info { position: absolute; left: 28px; top: -3px; width: 70px; padding: 5px 7px; border: 1px solid rgba(255,255,255,.08); border-radius: 6px; background: rgba(5,14,23,.85); transform: rotate(13deg); } .aircraft-info strong { display: block; font-size: 7px; } .aircraft-info span { display: block; margin-top: 2px; color: #688198; font-size: 6px; } .city-label { position: absolute; color: #405970; font-size: 6px; letter-spacing: 1px; } .chicago { left: 65%; top: 27%; } .denver { left: 43%; top: 51%; } .dallas { left: 56%; top: 70%; } .map-scale { position: absolute; right: 16px; bottom: 14px; padding-top: 5px; border-top: 2px solid #526b80; color: #526b80; font-size: 6px; } /* ========================= ROUTE SUMMARY ========================= */ .route-card { display: grid; grid-template-columns: 1fr 1.3fr 1fr; gap: 30px; margin-top: 14px; padding: 20px; border: 1px solid var(--line); border-radius: 14px; background: var(--panel); } .airport-type { color: #53667c; font-size: 6px; letter-spacing: 1.2px; } .airport-code { margin-top: 6px; font-size: 25px; font-weight: 700; letter-spacing: -1px; } .airport > strong { display: block; font-size: 9px; } .airport-name { display: block; margin-top: 2px; color: #576a7f; font-size: 6px; } .time { margin-top: 11px; font-size: 15px; font-weight: 600; } .airport small { color: #5e7186; font-size: 6px; } .airport.arrival { text-align: right; } /* JOURNEY */ .journey { align-self: center; } .journey-top, .journey-bottom { display: flex; justify-content: space-between; color: #5b6e83; font-size: 6px; } .journey-bottom { margin-top: 9px; letter-spacing: .6px; } .journey-bottom strong { color: #70bfff; } .progress-track { position: relative; height: 2px; margin-top: 13px; background: #233447; } .progress-fill { width: 62%; height: 100%; background: linear-gradient( 90deg, #278ff1, #63caff ); box-shadow: 0 0 7px rgba(66,174,255,.4); } .progress-plane { position: absolute; left: 62%; top: 50%; color: #72c8ff; font-size: 13px; transform: translate(-50%,-50%) rotate(0deg); transition: left 1s; } /* ========================= STATS ========================= */ .stats-grid { display: grid; grid-template-columns: repeat(4,1fr); gap: 12px; margin-top: 14px; } .stat-card { position: relative; min-height: 140px; overflow: hidden; padding: 17px; border: 1px solid var(--line); border-radius: 13px; background: var(--panel); } .stat-icon { width: 26px; height: 26px; display: grid; place-items: center; margin-bottom: 13px; border-radius: 7px; background: rgba(55,158,255,.08); color: #55b3ff; font-size: 12px; } .stat-card > span { display: block; color: #53677d; font-size: 6px; letter-spacing: 1px; } .stat-card > strong { display: inline-block; margin-top: 5px; font-size: 24px; letter-spacing: -1px; } .stat-card > small { margin-left: 4px; color: #516479; font-size: 6px; } .mini-chart { position: absolute; right: 13px; bottom: 15px; width: 70px; height: 30px; display: flex; align-items: flex-end; gap: 3px; } .mini-chart span { flex: 1; border-radius: 2px 2px 0 0; background: rgba(70,174,255,.25); } .speed-line { position: absolute; right: 15px; bottom: 20px; width: 70px; height: 25px; border-top: 2px solid #46aaff; border-radius: 50%; transform: rotate(-6deg); } .distance-bar { height: 3px; margin-top: 18px; background: #223347; } .distance-bar div { width: 38%; height: 100%; background: #47adff; } .eta { margin-top: 14px; color: #59b6ff; font-size: 6px; } /* ========================= LOWER CARDS ========================= */ .lower-grid { display: grid; grid-template-columns: 1.4fr 1fr; gap: 12px; margin-top: 14px; } .info-card, .weather-card { padding: 19px; border: 1px solid var(--line); border-radius: 13px; background: var(--panel); } .card-title { display: flex; justify-content: space-between; align-items: flex-start; } .card-title span { color: #52657a; font-size: 6px; letter-spacing: 1.1px; } .card-title h3 { margin: 4px 0 0; font-size: 13px; } .plane-symbol, .weather-icon { color: #53b6ff; font-size: 22px; } .aircraft-name { margin-top: 21px; font-size: 12px; font-weight: 600; } .detail-grid { display: grid; grid-template-columns: repeat(4,1fr); gap: 10px; margin-top: 20px; padding-top: 15px; border-top: 1px solid var(--line); } .detail-grid span, .weather-details span { display: block; color: #506379; font-size: 5px; letter-spacing: .8px; } .detail-grid strong, .weather-details strong { display: block; margin-top: 4px; font-size: 8px; } .temperature { margin-top: 13px; font-size: 34px; font-weight: 500; letter-spacing: -2px; } .condition { color: #77899b; font-size: 8px; } .weather-details { display: grid; grid-template-columns: repeat(3,1fr); margin-top: 18px; padding-top: 15px; border-top: 1px solid var(--line); } /* ========================= DEPARTURES ========================= */ .departures { margin-top: 14px; overflow: hidden; border: 1px solid var(--line); border-radius: 14px; background: var(--panel); } .departures-header { display: flex; align-items: center; justify-content: space-between; padding: 18px; border-bottom: 1px solid var(--line); } .departures-header span { color: #53667c; font-size: 6px; letter-spacing: 1px; } .departures-header h2 { margin: 4px 0 0; font-size: 14px; } .departures-header button { padding: 7px 10px; border: 1px solid var(--line); border-radius: 6px; background: #101e2e; color: #73869b; font-size: 7px; } .table-wrap { overflow-x: auto; } table { width: 100%; border-collapse: collapse; min-width: 600px; } th { padding: 11px 18px; background: #0a1522; color: #506277; font-size: 6px; font-weight: 600; letter-spacing: .8px; text-align: left; } td { padding: 14px 18px; border-top: 1px solid rgba(255,255,255,.04); color: #7c8c9d; font-size: 8px; } td strong { color: #e3eaf1; font-size: 9px; } td b { display: block; margin-bottom: 2px; color: #e0e8ef; font-size: 8px; } .table-status { display: inline-block; padding: 5px 7px; border-radius: 12px; font-size: 6px; font-weight: 700; } .ontime { background: rgba(65,208,148,.08); color: #55d69e; } .boarding { background: rgba(66,163,255,.1); color: #58afff; } .delayed { background: rgba(255,175,78,.1); color: #ffb65c; } /* ========================= RESPONSIVE ========================= */ @media (max-width: 1000px) { .app-shell { grid-template-columns: 70px 1fr; } .sidebar { width: 70px; padding: 20px 10px; } .brand { justify-content: center; padding: 0 0 25px; } .brand > div:last-child, .side-nav button:not(.active)::after, .side-nav button { font-size: 0; } .side-nav button { justify-content: center; padding: 12px; } .side-nav button span { width: auto; font-size: 17px; } .system-status div { display: none; } .system-status { justify-content: center; } .main { grid-column: 2; } } @media (max-width: 760px) { .app-shell { display: block; } .sidebar { display: none; } .main { width: 100%; padding: 22px 15px 40px; } .stats-grid { grid-template-columns: repeat(2,1fr); } .lower-grid { grid-template-columns: 1fr; } .route-card { grid-template-columns: 1fr; } .journey { order: 3; margin: 10px 0; } .airport.arrival { text-align: left; } .map { height: 290px; } } @media (max-width: 500px) { .topbar h1 { font-size: 21px; } .utc-clock { display: none; } .search-panel { grid-template-columns: 25px 1fr; } .search-panel button { grid-column: 1 / -1; width: 100%; margin-top: 5px; } .search-panel { height: auto; padding: 8px; } .flight-heading { grid-template-columns: auto 1fr; } .flight-status { grid-column: 1 / -1; justify-self: start; } .stats-grid { grid-template-columns: 1fr; } .detail-grid { grid-template-columns: repeat(2,1fr); } }
/* ====================================== UTC CLOCK ====================================== */ const clock = document.getElementById( "clock" ); function updateClock() { const now = new Date(); const hours = String( now.getUTCHours() ).padStart(2, "0"); const minutes = String( now.getUTCMinutes() ).padStart(2, "0"); const seconds = String( now.getUTCSeconds() ).padStart(2, "0"); clock.textContent = hours + ":" + minutes + ":" + seconds; } updateClock(); setInterval( updateClock, 1000 ); /* ====================================== SIMULATED FLIGHT ====================================== */ let progress = 62; let altitude = 36000; let speed = 548; const totalDistance = 2475; const aircraft = document.getElementById( "aircraft" ); const progressFill = document.getElementById( "progressFill" ); const progressPlane = document.getElementById( "progressPlane" ); const progressText = document.getElementById( "progressText" ); const altitudeLabel = document.getElementById( "altitude" ); const speedLabel = document.getElementById( "speed" ); const distanceLabel = document.getElementById( "distance" ); const remainingLabel = document.getElementById( "remaining" ); function updateFlight() { /* Slowly move the simulated aircraft. */ progress += .035; if (progress >= 97) { progress = 12; } /* Small altitude and speed changes make the dashboard feel live. */ altitude += Math.round( Math.random() * 40 - 20 ); speed += Math.round( Math.random() * 4 - 2 ); altitude = Math.max( 35750, Math.min( 36250, altitude ) ); speed = Math.max( 535, Math.min( 560, speed ) ); /* Distance calculation */ const distance = Math.round( totalDistance * (1 - progress / 100) ); /* Approximate remaining time */ const remainingHours = distance / speed; const hours = Math.floor( remainingHours ); const minutes = Math.round( ( remainingHours - hours ) * 60 ); /* Update dashboard */ progressFill.style.width = progress + "%"; progressPlane.style.left = progress + "%"; progressText.textContent = Math.round(progress) + "%"; altitudeLabel.textContent = altitude.toLocaleString(); speedLabel.textContent = speed; distanceLabel.textContent = distance.toLocaleString(); remainingLabel.textContent = hours + ":" + String(minutes) .padStart(2, "0"); /* Move aircraft across map. This follows an approximate curved flight path. */ const normalized = (progress - 12) / 85; const x = 12 + normalized * 76; /* Parabolic arc */ const arc = Math.sin( normalized * Math.PI ); const y = 70 - arc * 44 - normalized * 30; aircraft.style.left = x + "%"; aircraft.style.top = y + "%"; /* Update aircraft label */ const aircraftAltitude = aircraft.querySelector( ".aircraft-info span" ); aircraftAltitude.textContent = altitude.toLocaleString() + " ft"; } setInterval( updateFlight, 1000 ); /* ====================================== SEARCH ====================================== */ const searchInput = document.getElementById( "flightSearch" ); const trackButton = document.getElementById( "trackButton" ); const flightNumber = document.getElementById( "flightNumber" ); function trackFlight() { let value = searchInput.value .trim() .toUpperCase(); if (!value) { return; } flightNumber.textContent = value; const aircraftCallsign = aircraft.querySelector( ".aircraft-info strong" ); aircraftCallsign.textContent = value.replace( /\s/g, "" ); /* Restart simulated progress for newly searched flight. */ progress = 35 + Math.random() * 35; trackButton.textContent = "Tracking"; setTimeout( function() { trackButton.textContent = "Track flight"; }, 900 ); } trackButton.addEventListener( "click", trackFlight ); searchInput.addEventListener( "keydown", function(event) { if ( event.key === "Enter" ) { trackFlight(); } } ); /* ====================================== MAP ZOOM EFFECT ====================================== */ const map = document.getElementById( "map" ); const zoomIn = document.getElementById( "zoomIn" ); const zoomOut = document.getElementById( "zoomOut" ); let zoom = 100; function applyZoom() { map.style.backgroundSize = zoom + "%"; } zoomIn.addEventListener( "click", function() { zoom = Math.min( 150, zoom + 10 ); applyZoom(); } ); zoomOut.addEventListener( "click", function() { zoom = Math.max( 80, zoom - 10 ); applyZoom(); } ); /* ====================================== SIDEBAR ====================================== */ const navButtons = document.querySelectorAll( ".side-nav button" ); navButtons.forEach( function(button) { button.addEventListener( "click", function() { navButtons.forEach( function(item) { item.classList.remove( "active" ); } ); button.classList.add( "active" ); } ); } );
terminal
JavaScript Console
Preview
Clear
close
›
Run