:root { color-scheme: dark; font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-synthesis: none; text-rendering: optimizeLegibility; --ink: #f2f5f7; --muted: rgba(227, 235, 240, 0.58); --line: rgba(232, 240, 245, 0.16); --glass: rgba(12, 18, 26, 0.54); --accent: #a9d4ff; } * { box-sizing: border-box; } html, body, #app, #scene { width: 100%; height: 100%; margin: 0; overflow: hidden; } body { background: #0b1018; color: var(--ink); overscroll-behavior: none; } button, a { color: inherit; font: inherit; } button { border: 0; } button:focus-visible, a:focus-visible { outline: 2px solid #c4e5ff; outline-offset: 4px; } #scene, #scene canvas { display: block; touch-action: none; } #scene canvas { width: 100%; height: 100%; cursor: grab; } #scene canvas:active { cursor: grabbing; } .interface { position: fixed; inset: 0; z-index: 3; pointer-events: none; opacity: 0; transition: opacity 1.1s ease; } .interface.is-ready { opacity: 1; } .topbar { position: absolute; top: max(24px, env(safe-area-inset-top)); left: max(30px, env(safe-area-inset-left)); right: max(30px, env(safe-area-inset-right)); display: flex; align-items: center; justify-content: space-between; } .brand { display: flex; gap: 13px; align-items: center; color: var(--ink); text-decoration: none; pointer-events: auto; } .brand__glyph { display: grid; width: 38px; height: 38px; place-items: center; border: 1px solid rgba(255, 255, 255, 0.38); border-radius: 50%; font-size: 9px; font-weight: 700; letter-spacing: 0.12em; } .brand b, .brand small { display: block; } .brand b { font-size: 12px; font-weight: 650; letter-spacing: 0.11em; text-transform: uppercase; } .brand small { margin-top: 3px; color: var(--muted); font-size: 9px; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; } .conditions { display: flex; align-items: center; gap: 10px; padding: 10px 13px; border: 1px solid var(--line); border-radius: 999px; background: rgba(9, 14, 21, 0.3); box-shadow: inset 0 1px rgba(255, 255, 255, 0.05); backdrop-filter: blur(16px); color: rgba(239, 244, 247, 0.78); font-size: 9px; font-weight: 600; letter-spacing: 0.12em; } .conditions i { width: 1px; height: 10px; background: var(--line); } .conditions__pulse { width: 5px; height: 5px; border-radius: 50%; background: #a5dcff; box-shadow: 0 0 12px #88ceff; } .intro { position: absolute; bottom: max(115px, calc(env(safe-area-inset-bottom) + 105px)); left: max(42px, env(safe-area-inset-left)); width: min(390px, calc(100vw - 84px)); isolation: isolate; transition: opacity 0.6s ease, transform 0.8s cubic-bezier(0.2, 0.75, 0.2, 1); } .intro::before { position: absolute; inset: -38px -70px -34px -46px; z-index: -1; background: radial-gradient(ellipse at 28% 55%, rgba(5, 10, 16, 0.64) 0%, rgba(5, 10, 16, 0.33) 45%, transparent 74%); content: ""; filter: blur(10px); pointer-events: none; } .intro.is-hidden { opacity: 0; transform: translateY(12px); } .eyebrow { display: block; color: rgba(221, 233, 240, 0.56); font-size: 9px; font-weight: 650; letter-spacing: 0.2em; text-transform: uppercase; } .intro h2 { margin: 13px 0 14px; font-size: clamp(42px, 5.5vw, 78px); font-weight: 420; letter-spacing: -0.065em; line-height: 0.88; text-shadow: 0 2px 26px rgba(0, 0, 0, 0.22); } .intro h2 em { color: #b9dfff; font-family: Georgia, "Times New Roman", serif; font-weight: 400; letter-spacing: -0.035em; } .intro p { width: min(360px, 100%); margin: 0 0 22px; color: rgba(235, 240, 244, 0.68); font-size: 12px; line-height: 1.65; } .text-button { display: inline-flex; align-items: center; gap: 16px; padding: 0 0 8px; border-bottom: 1px solid rgba(255, 255, 255, 0.4); background: transparent; cursor: pointer; pointer-events: auto; font-size: 10px; font-weight: 650; letter-spacing: 0.13em; text-transform: uppercase; } .text-button i { font-size: 13px; font-style: normal; transition: transform 0.25s ease; } .text-button:hover i { transform: translate(3px, -3px); } .metrics { position: absolute; right: max(32px, env(safe-area-inset-right)); bottom: max(114px, calc(env(safe-area-inset-bottom) + 104px)); display: flex; gap: 30px; padding-left: 22px; border-left: 1px solid var(--line); } .metrics div { display: flex; flex-direction: column; gap: 4px; } .metrics b { font-size: 15px; font-weight: 450; letter-spacing: -0.02em; } .metrics span { color: var(--muted); font-size: 8px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; } .dock { position: absolute; bottom: max(24px, env(safe-area-inset-bottom)); left: 50%; display: flex; height: 64px; align-items: center; gap: 18px; padding: 0 12px 0 19px; transform: translateX(-50%); border: 1px solid rgba(235, 243, 248, 0.17); border-radius: 17px; background: rgba(10, 16, 23, 0.62); box-shadow: 0 14px 44px rgba(0, 0, 0, 0.28), inset 0 1px rgba(255, 255, 255, 0.06); backdrop-filter: blur(20px) saturate(120%); pointer-events: auto; } .dock__group { display: flex; align-items: center; } .dock__group > span { margin-right: 12px; color: rgba(229, 237, 242, 0.38); font-size: 8px; font-weight: 650; letter-spacing: 0.15em; text-transform: uppercase; } .dock__views { gap: 3px; } .dock__views button { padding: 8px 10px; border-radius: 8px; background: transparent; color: rgba(235, 241, 244, 0.52); cursor: pointer; font-size: 9px; font-weight: 600; letter-spacing: 0.035em; transition: color 0.2s, background 0.2s; } .dock__views button:hover, .dock__views button.is-active { background: rgba(255, 255, 255, 0.08); color: #fff; } .dock__divider { width: 1px; height: 25px; background: var(--line); } .dock__time { min-width: 153px; } .dock__time > b { width: 34px; margin-left: 9px; color: rgba(238, 244, 247, 0.72); font-size: 9px; font-weight: 550; } .time-dots { position: relative; display: flex; align-items: center; gap: 0; } .time-dots::before { position: absolute; top: 50%; right: 15px; left: 15px; z-index: -1; height: 1px; background: rgba(255, 255, 255, 0.14); content: ""; } .time-dots button { position: relative; width: 30px; height: 44px; padding: 0; background: transparent; cursor: pointer; } .time-dots button::after { position: absolute; top: 50%; left: 50%; width: 8px; height: 8px; transform: translate(-50%, -50%); border: 2px solid rgba(7, 12, 18, 0.8); border-radius: 50%; background: #778797; box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.22); content: ""; transition: transform 0.2s, box-shadow 0.2s; } .time-dots button:nth-child(1)::after { background: #f6b184; } .time-dots button:nth-child(2)::after { background: #cfe8f2; } .time-dots button:nth-child(3)::after { background: #829fc2; } .time-dots button:nth-child(4)::after { background: #33425f; } .time-dots button:hover::after, .time-dots button.is-active::after { transform: translate(-50%, -50%) scale(1.45); box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.55), 0 0 10px rgba(178, 216, 255, 0.6); } .icon-button { display: grid; width: 38px; height: 38px; flex: 0 0 38px; place-items: center; border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 10px; background: rgba(255, 255, 255, 0.045); cursor: pointer; transition: background 0.2s, border-color 0.2s; } .icon-button:hover, .icon-button.is-active { border-color: rgba(255, 255, 255, 0.25); background: rgba(255, 255, 255, 0.11); } .icon-button svg { width: 16px; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.4; } .icon-button span { font-family: Georgia, serif; font-size: 15px; } .hint { position: absolute; bottom: max(38px, calc(env(safe-area-inset-bottom) + 14px)); left: max(30px, env(safe-area-inset-left)); display: flex; align-items: center; gap: 10px; color: rgba(230, 237, 241, 0.48); font-size: 8px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; transition: opacity 0.5s ease; } .hint.is-hidden { opacity: 0; } .mouse { position: relative; width: 13px; height: 19px; border: 1px solid rgba(255, 255, 255, 0.38); border-radius: 7px; } .mouse i { position: absolute; top: 4px; left: 5px; width: 1px; height: 4px; background: rgba(255, 255, 255, 0.58); animation: scroll-hint 1.8s ease-in-out infinite; } .quality { position: absolute; right: max(30px, env(safe-area-inset-right)); bottom: max(39px, calc(env(safe-area-inset-bottom) + 15px)); display: flex; align-items: center; gap: 7px; color: rgba(231, 238, 242, 0.42); font-size: 8px; font-weight: 600; letter-spacing: 0.11em; text-transform: uppercase; } .quality span { width: 5px; height: 5px; border-radius: 50%; background: #83cfad; box-shadow: 0 0 8px rgba(107, 227, 166, 0.55); } .quality b { font-weight: inherit; } .building-card { position: absolute; top: 50%; right: max(32px, env(safe-area-inset-right)); width: 260px; padding: 22px; transform: translate(18px, -50%); border: 1px solid rgba(255, 255, 255, 0.16); border-radius: 14px; background: rgba(10, 16, 24, 0.65); box-shadow: 0 24px 60px rgba(0, 0, 0, 0.24), inset 0 1px rgba(255, 255, 255, 0.06); backdrop-filter: blur(20px); opacity: 0; pointer-events: none; transition: opacity 0.3s ease, transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1); } .building-card.is-visible { transform: translate(0, -50%); opacity: 1; pointer-events: auto; } .building-card > button, .help-panel__head button { position: absolute; top: 12px; right: 12px; width: 26px; height: 26px; border-radius: 50%; background: transparent; color: rgba(255, 255, 255, 0.55); cursor: pointer; font-size: 17px; } .building-card h3 { margin: 9px 0 19px; font-family: Georgia, "Times New Roman", serif; font-size: 25px; font-weight: 400; letter-spacing: -0.025em; } .building-card__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; padding-top: 15px; border-top: 1px solid var(--line); } .building-card__grid b, .building-card__grid span { display: block; } .building-card__grid b { font-size: 11px; font-weight: 550; } .building-card__grid span { margin-top: 3px; color: var(--muted); font-size: 7px; letter-spacing: 0.1em; text-transform: uppercase; } .help-panel { position: absolute; top: max(80px, calc(env(safe-area-inset-top) + 64px)); right: max(30px, env(safe-area-inset-right)); width: 290px; padding: 24px; transform: translateY(-10px); border: 1px solid rgba(255, 255, 255, 0.16); border-radius: 15px; background: rgba(10, 16, 24, 0.72); box-shadow: 0 24px 60px rgba(0, 0, 0, 0.3), inset 0 1px rgba(255, 255, 255, 0.06); backdrop-filter: blur(22px); opacity: 0; pointer-events: none; transition: opacity 0.25s, transform 0.35s ease; } .help-panel.is-visible { transform: translateY(0); opacity: 1; pointer-events: auto; } .help-panel__head { position: relative; } .help-panel__head button { top: -12px; right: -12px; } .help-panel h3 { margin: 9px 0 17px; font-family: Georgia, serif; font-size: 23px; font-weight: 400; } .help-panel dl { margin: 0; border-top: 1px solid var(--line); } .help-panel dl div { display: flex; justify-content: space-between; padding: 9px 0; border-bottom: 1px solid var(--line); font-size: 10px; } .help-panel dt { color: rgba(255, 255, 255, 0.84); font-weight: 600; } .help-panel dd { margin: 0; color: var(--muted); } .help-panel > p { margin: 16px 0 0; color: var(--muted); font-size: 10px; line-height: 1.6; } .loading { position: fixed; inset: 0; z-index: 10; display: flex; align-items: center; justify-content: center; gap: 34px; background: radial-gradient(circle at 65% 35%, rgba(47, 72, 97, 0.28), transparent 40%), #0b1119; transition: opacity 0.9s ease, visibility 0.9s; } .loading.is-complete { visibility: hidden; opacity: 0; } .loading__mark { display: grid; width: 50px; height: 50px; grid-template-columns: 1fr 1fr; gap: 3px; transform: rotate(45deg); } .loading__mark span { border: 1px solid rgba(190, 222, 245, 0.55); animation: city-mark 1.6s ease-in-out infinite alternate; } .loading__mark span:nth-child(2) { animation-delay: -0.35s; } .loading__mark span:nth-child(3) { animation-delay: -0.7s; } .loading__mark span:nth-child(4) { animation-delay: -1.05s; } .loading__copy { width: min(280px, 52vw); } .loading__copy h1 { margin: 8px 0 14px; font-family: Georgia, serif; font-size: 30px; font-weight: 400; letter-spacing: -0.03em; } .loading__track { width: 100%; height: 1px; background: rgba(255, 255, 255, 0.12); } .loading__track i { display: block; width: 6%; height: 100%; background: #c7e8ff; box-shadow: 0 0 10px rgba(164, 217, 255, 0.65); transition: width 0.45s ease; } .loading__copy p { margin: 10px 0 0; color: var(--muted); font-size: 8px; font-weight: 600; letter-spacing: 0.13em; text-transform: uppercase; } .grain, .vignette { position: fixed; inset: 0; z-index: 2; pointer-events: none; } .grain { opacity: 0.15; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 160 160' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.26'/%3E%3C/svg%3E"); mix-blend-mode: soft-light; } .vignette { background: radial-gradient(circle at 50% 46%, transparent 42%, rgba(2, 5, 9, 0.33) 120%); } .webgl-error { position: fixed; inset: 0; z-index: 20; display: grid; align-content: center; justify-items: center; padding: 30px; background: #0c121b; text-align: center; } .webgl-error[hidden] { display: none; } .webgl-error h1 { margin: 12px 0; font-family: Georgia, serif; font-size: clamp(36px, 7vw, 72px); font-weight: 400; } .webgl-error p { color: var(--muted); } @keyframes scroll-hint { 0%, 100% { transform: translateY(0); opacity: 0.4; } 50% { transform: translateY(4px); opacity: 1; } } @keyframes city-mark { from { background: rgba(177, 220, 252, 0.04); transform: scale(0.88); } to { background: rgba(177, 220, 252, 0.42); transform: scale(1); } } @media (max-width: 900px) { .metrics, .hint, .quality { display: none; } .intro { bottom: max(112px, calc(env(safe-area-inset-bottom) + 100px)); } .dock { max-width: calc(100vw - 24px); gap: 9px; padding-right: 9px; padding-left: 12px; } .dock__group > span, .dock__divider:first-of-type, #help-toggle { display: none; } .dock__views button { min-height: 44px; padding-right: 8px; padding-left: 8px; } .dock__time { min-width: 106px; } .building-card { top: auto; right: 12px; bottom: max(101px, calc(env(safe-area-inset-bottom) + 89px)); left: 12px; width: auto; transform: translateY(12px); } .building-card.is-visible { transform: translateY(0); } } @media (max-width: 560px) { .topbar { top: max(16px, env(safe-area-inset-top)); right: max(16px, env(safe-area-inset-right)); left: max(16px, env(safe-area-inset-left)); } .brand small, .conditions i, #condition-weather { display: none; } .intro { left: max(22px, env(safe-area-inset-left)); width: calc(100vw - 44px); } .intro h2 { font-size: clamp(45px, 15vw, 64px); } .intro p { max-width: 310px; font-size: 11px; } .dock { width: calc(100vw - 20px); height: 60px; justify-content: center; border-radius: 15px; } .dock__views button { font-size: 8px; } .dock__time > b, .dock__divider:last-of-type { display: none; } .dock__time { min-width: auto; } .icon-button { width: 44px; height: 44px; flex-basis: 44px; } .help-panel { right: 12px; left: 12px; width: auto; } .loading { flex-direction: column; gap: 26px; } .loading__copy { width: min(280px, calc(100vw - 54px)); text-align: center; } } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } }