<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Airport Wayfinding - Tall B Design</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap');
:root {
--airport-yellow: #FFD500;
--airport-black: #0F0F0F;
--airport-gray: #7A7A7A;
--airport-white: #FFFFFF;
}
* {
margin: 0; padding: 0; box-sizing: border-box;
font-family: 'Geist', sans-serif;
-webkit-font-smoothing: antialiased;
}
body, html {
width: 100%; height: 100%;
background-color: #000;
overflow: hidden;
display: flex; align-items: center; justify-content: center;
}
#viewport { perspective: 2500px; width: 100vw; height: 100vh; overflow: hidden; }
#sign-container {
position: relative; width: 100vw; height: 100vh;
display: flex; gap: 1.5vw; padding: 1.5vh;
transform-style: preserve-3d; background: #000;
}
#webgl-canvas {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
z-index: 20; pointer-events: none; mix-blend-mode: overlay; opacity: 0.35;
}
.rotating-arrow {
display: inline-block;
transition: transform 0.8s cubic-bezier(0.65, 0, 0.35, 1);
}
/* --- PANELS --- */
.panel-left {
flex: 0 0 40vw; background-color: var(--airport-white);
position: relative; padding: 6vh 4vw; margin-left: -15vw; overflow: hidden;
}
.dest-list { font-size: 8.5vh; font-weight: 800; line-height: 0.92; color: var(--airport-black); }
.dest-yellow { color: var(--airport-yellow); }
.panel-right {
flex: 1; background-color: var(--airport-white);
padding: 1vh; display: flex; flex-direction: column; gap: 1vh; overflow: hidden;
}
/* --- UPDATED TOP ROW WITH TALL B & AIRPLANE --- */
.row-top {
background-color: var(--airport-yellow);
display: flex;
padding: 0 4vh;
gap: 4vw;
flex: 0 0 25vh;
align-items: center;
overflow: hidden;
position: relative; /* Context for plane */
}
/* Giant Plane Styling */
.giant-plane {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 1000px;
color: var(--airport-black);
opacity: 0.4;
z-index: 0;
pointer-events: none;
animation: plane-fly-up 3s linear infinite;
}
@keyframes plane-fly-up {
from { bottom: -1100px; }
to { bottom: 1100px; }
}
.gate-b-container {
height: 100%;
display: flex;
align-items: center;
gap: 2vh;
padding: 1.5vh 0;
position: relative;
z-index: 1;
}
.gate-b {
font-size: 22vh;
font-weight: 900;
line-height: 0.8;
color: var(--airport-black);
display: flex;
align-items: center;
}
.gate-arrow {
font-size: 10vh;
margin-top: 2vh;
}
.services-list {
display: grid;
grid-template-columns: 1fr 1.2fr;
gap: 0.8vh 2vw;
font-size: 2.1vh;
font-weight: 700;
align-content: center;
height: 100%;
position: relative;
z-index: 1;
}
.service-item { display: flex; align-items: center; gap: 10px; }
.icon-box { width: 3vh; height: 3vh; background: #000; color: var(--airport-yellow); display: flex; justify-content: center; align-items: center; font-size: 1.8vh; border-radius: 4px; }
/* --- OTHER ROWS --- */
.row-pills { display: flex; gap: 1vw; flex: 0 0 10vh; }
.pill { background: var(--airport-black); color: white; border-radius: 8px; display: flex; align-items: center; gap: 15px; font-size: 3.5vh; font-weight: 800; flex: 1; padding: 0 2vw; }
.row-arrows-marquee {
background: var(--airport-yellow); position: relative; flex: 0 0 22vh;
overflow: hidden; display: flex; align-items: center;
}
.marquee-track { display: flex; width: max-content; animation: scroll 20s linear infinite; }
.marquee-group { display: flex; gap: 10vw; padding-right: 10vw; align-items: center; }
@keyframes scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.arrow-circle { width: 15vh; height: 15vh; background: var(--airport-black); border-radius: 50%; display: flex; justify-content: center; align-items: center; color: var(--airport-yellow); font-size: 8.5vh; }
.row-cities {
background: var(--airport-black); color: white;
flex: 0 0 10vh; padding: 0 3vw;
display: flex; align-items: center; justify-content: space-between;
font-size: 3.5vh; font-weight: 800; overflow: hidden;
}
.city-box { width: 25vw; display: flex; justify-content: center; overflow: hidden; }
.mask-text { display: block; height: 4.5vh; overflow: hidden; position: relative; }
.slide-up { display: block; transform: translateY(100%); transition: transform 0.6s cubic-bezier(0.23, 1, 0.32, 1); }
.slide-up.active { transform: translateY(0%); }
.arrow-divider-marquee {
border: 3px solid white; border-radius: 50%; width: 6vh; height: 6vh;
display: flex; align-items: center; overflow: hidden; position: relative;
}
.mini-marquee-track { display: flex; gap: 2vh; animation: mini-scroll 2s linear infinite; }
@keyframes mini-scroll { from { transform: translateX(-40%); } to { transform: translateX(0%); } }
.clock-box { width: 12vw; display: flex; justify-content: flex-end; }
.clock-display { color: var(--airport-yellow); font-variant-numeric: tabular-nums; }
.row-bottom { display: flex; gap: 1vw; flex: 0 0 16vh; }
.box-am { background: var(--airport-yellow); flex: 1.4; display: flex; font-size: 14vh; font-weight: 900; }
.box-am div { display: flex; align-items: center; padding: 0 2vw; }
.black-part { background: var(--airport-black); color: var(--airport-yellow); }
.yellow-part { color: var(--airport-black); }
.box-22 { background: var(--airport-black); color: white; flex: 1; display: flex; justify-content: center; align-items: center; font-size: 10vh; font-weight: 800; gap: 15px; }
.row-dist { background: var(--airport-yellow); flex: 0 0 15vh; display: flex; justify-content: space-between; align-items: center; padding: 0 6vw; font-size: 12vh; font-weight: 900; }
</style>
<script src="https://unpkg.com/@phosphor-icons/web"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
</head>
<body>
<div id="viewport">
<div id="sign-container">
<canvas id="webgl-canvas"></canvas>
<div class="panel-left">
<div class="dest-list">Zürich<br>London<br>Hong Kong<br>Tokyo<br><span class="dest-yellow">New York</span></div>
</div>
<div class="panel-right">
<div class="row-top">
<i class="ph-fill ph-airplane giant-plane"></i>
<div class="gate-b-container">
<div class="gate-b">B</div>
<i class="ph-bold ph-arrow-up rotating-arrow gate-arrow"></i>
</div>
<div class="services-list">
<div class="service-item"><div class="icon-box"><i class="ph-fill ph-identification-card"></i></div> Passport</div>
<div class="service-item"><div class="icon-box"><i class="ph-fill ph-airplane-tilt"></i></div> Gates B5-10</div>
<div class="service-item"><div class="icon-box"><i class="ph-fill ph-fork-knife"></i></div> Food</div>
<div class="service-item"><div class="icon-box"><i class="ph-fill ph-airplane-takeoff"></i></div> Gates C D</div>
<div class="service-item"><div class="icon-box"><i class="ph-fill ph-briefcase"></i></div> Baggage</div>
<div class="service-item"><div class="icon-box"><i class="ph-fill ph-taxi"></i></div> Taxi</div>
<div class="service-item"><div class="icon-box"><i class="ph-bold ph-p"></i></div> Park</div>
</div>
</div>
<div class="row-pills">
<div class="pill"><i class="ph-bold ph-crosshair"></i> RB74</div>
<div class="pill"><i class="ph-fill ph-airplane"></i> B40</div>
<div class="pill"><i class="ph-bold ph-clock"></i> 08H</div>
</div>
<div class="row-arrows-marquee">
<div class="marquee-track">
<div class="marquee-group">
<div class="arrow-circle"><i class="ph-bold ph-arrow-up rotating-arrow"></i></div>
<div class="arrow-circle"><i class="ph-bold ph-arrow-up rotating-arrow"></i></div>
<div class="arrow-circle"><i class="ph-bold ph-arrow-up rotating-arrow"></i></div>
<div class="arrow-circle"><i class="ph-bold ph-arrow-up rotating-arrow"></i></div>
<div class="arrow-circle"><i class="ph-bold ph-arrow-up rotating-arrow"></i></div>
</div>
<div class="marquee-group">
<div class="arrow-circle"><i class="ph-bold ph-arrow-up rotating-arrow"></i></div>
<div class="arrow-circle"><i class="ph-bold ph-arrow-up rotating-arrow"></i></div>
<div class="arrow-circle"><i class="ph-bold ph-arrow-up rotating-arrow"></i></div>
<div class="arrow-circle"><i class="ph-bold ph-arrow-up rotating-arrow"></i></div>
<div class="arrow-circle"><i class="ph-bold ph-arrow-up rotating-arrow"></i></div>
</div>
</div>
</div>
<div class="row-cities">
<div class="city-box"><div class="mask-text"><span class="slide-up active" id="city1">ZURICH</span></div></div>
<div class="arrow-divider-marquee">
<div class="mini-marquee-track"><i class="ph-bold ph-arrow-right"></i><i class="ph-bold ph-arrow-right"></i><i class="ph-bold ph-arrow-right"></i><i class="ph-bold ph-arrow-right"></i></div>
</div>
<div class="city-box"><div class="mask-text"><span class="slide-up active" id="city2">NEW YORK</span></div></div>
<div class="clock-box"><div class="mask-text"><span class="slide-up active clock-display" id="clock">12:00</span></div></div>
</div>
<div class="row-bottom">
<div class="box-am"><div class="black-part">A</div><div class="yellow-part">M</div></div>
<div class="box-22">22 <i class="ph-bold ph-arrow-up rotating-arrow"></i></div>
</div>
<div class="row-dist"><span>250m</span><i class="ph-bold ph-arrow-up rotating-arrow"></i></div>
</div>
</div>
</div>
<script>
// WebGL & Arrow Logic
const canvas = document.getElementById('webgl-canvas');
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
const renderer = new THREE.WebGLRenderer({ canvas, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
const material = new THREE.ShaderMaterial({
transparent: true, uniforms: { time: { value: 0.0 } },
vertexShader: `void main() { gl_Position = vec4(position, 1.0); }`,
fragmentShader: `uniform float time; float random(vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123); } void main() { vec2 uv = gl_FragCoord.xy / vec2(600.0); float n = random(uv + mod(time, 2.0)); gl_FragColor = vec4(vec3(n), 0.12); }`
});
scene.add(new THREE.Mesh(new THREE.PlaneGeometry(2, 2), material));
function animate(t) { material.uniforms.time.value = t * 0.001; renderer.render(scene, camera); requestAnimationFrame(animate); }
animate(0);
const arrows = document.querySelectorAll('.rotating-arrow');
function rotateRandomly(arrow) {
const rot = Math.floor(Math.random() * 4) * 90;
arrow.style.transform = `rotate(${rot}deg)`;
setTimeout(() => rotateRandomly(arrow), Math.random() * 3000 + 2000);
}
arrows.forEach(a => setTimeout(() => rotateRandomly(a), Math.random() * 1000));
// Sync Cities Logic
const cities = ["LONDON", "TOKYO", "BERLIN", "PARIS", "SINGAPORE", "SYDNEY", "DUBAI"];
const c1 = document.getElementById('city1'), c2 = document.getElementById('city2'), clk = document.getElementById('clock');
function updateContent() {
[c1, c2, clk].forEach(el => el.classList.remove('active'));
setTimeout(() => {
const r1 = cities[Math.floor(Math.random() * cities.length)];
let r2 = cities[Math.floor(Math.random() * cities.length)];
while(r2 === r1) r2 = cities[Math.floor(Math.random() * cities.length)];
const now = new Date();
c1.textContent = r1; c2.textContent = r2;
clk.textContent = now.getHours().toString().padStart(2, '0') + ":" + now.getMinutes().toString().padStart(2, '0');
c1.classList.add('active');
setTimeout(() => c2.classList.add('active'), 100);
setTimeout(() => clk.classList.add('active'), 200);
}, 600);
}
setInterval(updateContent, 5000);
updateContent();
// Mouse Tilt
const container = document.getElementById('sign-container');
document.addEventListener('mousemove', (e) => {
const x = (e.clientX / window.innerWidth - 0.5) * 3;
const y = (e.clientY / window.innerHeight - 0.5) * -3;
container.style.transform = `rotateY(${x}deg) rotateX(${y}deg)`;
});
</script>
</body>
</html>“Create a "Airport Wayfinding - Tall B Design" component. Use Phosphor Icons, Three.js for 3D WebGL rendering. Implement custom GLSL shaders for visual effects. Apply keyframe animations, 3D CSS perspective, blend modes. Color palette: #ffd500, #0f0f0f, #7a7a7a, #ffffff. Layout: CSS Grid, Flexbox, full-viewport sizing. Interactivity: mouse tracking, scroll-based effects, continuous animation loop.”