@a2f0/skyline 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +20 -0
- package/README.md +52 -2
- package/docs/package.md +222 -0
- package/docs/skyline-geography.md +503 -0
- package/lib/models/aon-center.d.ts +4 -0
- package/lib/models/aon-center.js +60 -0
- package/lib/models/aon-geographic.d.ts +9 -0
- package/lib/models/aon-geographic.js +35 -0
- package/lib/models/aon-tower.d.ts +23 -0
- package/lib/models/aon-tower.js +130 -0
- package/lib/models/blue-cross-geographic.d.ts +14 -0
- package/lib/models/blue-cross-geographic.js +248 -0
- package/lib/models/borg-warner-geographic.d.ts +20 -0
- package/lib/models/borg-warner-geographic.js +143 -0
- package/lib/models/buckingham-geographic.d.ts +10 -0
- package/lib/models/buckingham-geographic.js +121 -0
- package/lib/models/building-kit.d.ts +84 -0
- package/lib/models/building-kit.js +358 -0
- package/lib/models/celebrations.d.ts +39 -0
- package/lib/models/celebrations.js +44 -0
- package/lib/models/chicago-athletic-association-geographic.d.ts +32 -0
- package/lib/models/chicago-athletic-association-geographic.js +173 -0
- package/lib/models/crain-communications.d.ts +5 -0
- package/lib/models/crain-communications.js +75 -0
- package/lib/models/crain-geographic.d.ts +10 -0
- package/lib/models/crain-geographic.js +69 -0
- package/lib/models/crain-tower.d.ts +32 -0
- package/lib/models/crain-tower.js +378 -0
- package/lib/models/facade-grid.d.ts +18 -0
- package/lib/models/facade-grid.js +176 -0
- package/lib/models/gage-geographic.d.ts +19 -0
- package/lib/models/gage-geographic.js +154 -0
- package/lib/models/heritage-at-millennium-park.d.ts +3 -0
- package/lib/models/heritage-at-millennium-park.js +284 -0
- package/lib/models/heritage-geographic.d.ts +11 -0
- package/lib/models/heritage-geographic.js +208 -0
- package/lib/models/hyatt-west-tower-geographic.d.ts +26 -0
- package/lib/models/hyatt-west-tower-geographic.js +86 -0
- package/lib/models/keith-ascher-geographic.d.ts +29 -0
- package/lib/models/keith-ascher-geographic.js +110 -0
- package/lib/models/kemper-geographic.d.ts +8 -0
- package/lib/models/kemper-geographic.js +153 -0
- package/lib/models/kemper.d.ts +2 -0
- package/lib/models/kemper.js +78 -0
- package/lib/models/lake-view-geographic.d.ts +15 -0
- package/lib/models/lake-view-geographic.js +134 -0
- package/lib/models/maclean-center-geographic.d.ts +20 -0
- package/lib/models/maclean-center-geographic.js +162 -0
- package/lib/models/michigan-boulevard-geographic.d.ts +12 -0
- package/lib/models/michigan-boulevard-geographic.js +157 -0
- package/lib/models/michigan-plaza-south-geographic.d.ts +7 -0
- package/lib/models/michigan-plaza-south-geographic.js +84 -0
- package/lib/models/michigan-plaza-south.d.ts +2 -0
- package/lib/models/michigan-plaza-south.js +68 -0
- package/lib/models/millennium-park-plaza-geographic.d.ts +9 -0
- package/lib/models/millennium-park-plaza-geographic.js +103 -0
- package/lib/models/monroe-geographic.d.ts +19 -0
- package/lib/models/monroe-geographic.js +177 -0
- package/lib/models/north-michigan-180-geographic.d.ts +14 -0
- package/lib/models/north-michigan-180-geographic.js +117 -0
- package/lib/models/north-wabash-geographic.d.ts +14 -0
- package/lib/models/north-wabash-geographic.js +122 -0
- package/lib/models/on-the-park-geographic.d.ts +11 -0
- package/lib/models/on-the-park-geographic.js +245 -0
- package/lib/models/one-prudential-geographic.d.ts +12 -0
- package/lib/models/one-prudential-geographic.js +55 -0
- package/lib/models/one-prudential-plaza.d.ts +5 -0
- package/lib/models/one-prudential-plaza.js +72 -0
- package/lib/models/one-prudential-tower.d.ts +45 -0
- package/lib/models/one-prudential-tower.js +246 -0
- package/lib/models/peoples-gas-geographic.d.ts +23 -0
- package/lib/models/peoples-gas-geographic.js +250 -0
- package/lib/models/railway-exchange-geographic.d.ts +18 -0
- package/lib/models/railway-exchange-geographic.js +176 -0
- package/lib/models/river-plaza-geographic.d.ts +16 -0
- package/lib/models/river-plaza-geographic.js +104 -0
- package/lib/models/sheraton-grand-geographic.d.ts +24 -0
- package/lib/models/sheraton-grand-geographic.js +112 -0
- package/lib/models/six-north-michigan-geographic.d.ts +16 -0
- package/lib/models/six-north-michigan-geographic.js +180 -0
- package/lib/models/skyline-geography-data.d.ts +44 -0
- package/lib/models/skyline-geography-data.js +607 -0
- package/lib/models/skyline-geography.d.ts +23 -0
- package/lib/models/skyline-geography.js +322 -0
- package/lib/models/swissotel-geographic.d.ts +24 -0
- package/lib/models/swissotel-geographic.js +79 -0
- package/lib/models/three-illinois-center-geographic.d.ts +26 -0
- package/lib/models/three-illinois-center-geographic.js +86 -0
- package/lib/models/trump-geographic.d.ts +14 -0
- package/lib/models/trump-geographic.js +51 -0
- package/lib/models/trump-international-tower.d.ts +4 -0
- package/lib/models/trump-international-tower.js +84 -0
- package/lib/models/trump-tower.d.ts +43 -0
- package/lib/models/trump-tower.js +229 -0
- package/lib/models/two-illinois-center-geographic.d.ts +26 -0
- package/lib/models/two-illinois-center-geographic.js +85 -0
- package/lib/models/two-prudential-geographic.d.ts +25 -0
- package/lib/models/two-prudential-geographic.js +47 -0
- package/lib/models/two-prudential-plaza.d.ts +8 -0
- package/lib/models/two-prudential-plaza.js +55 -0
- package/lib/models/two-prudential-tower.d.ts +53 -0
- package/lib/models/two-prudential-tower.js +441 -0
- package/lib/models/university-club-geographic.d.ts +24 -0
- package/lib/models/university-club-geographic.js +217 -0
- package/lib/models/willoughby-tower-geographic.d.ts +17 -0
- package/lib/models/willoughby-tower-geographic.js +195 -0
- package/lib/models/window-illumination.d.ts +14 -0
- package/lib/models/window-illumination.js +64 -0
- package/lib/package-assets.d.ts +5 -0
- package/lib/package-assets.js +9 -0
- package/lib/skyline-package.d.ts +23 -0
- package/lib/skyline-package.js +25 -0
- package/lib/skyline-scene.d.ts +25 -0
- package/lib/skyline-scene.js +86 -0
- package/lib/study-types.d.ts +49 -0
- package/lib/study-types.js +1 -0
- package/lib/vendor/three-r186.d.ts +1 -0
- package/lib/vendor/three-r186.js +1 -0
- package/package.json +64 -4
- package/site/building-detail.html +54 -0
- package/site/building-detail.js +84 -0
- package/site/building-study.html +58 -0
- package/site/building-study.js +3 -0
- package/site/index.html +407 -0
- package/site/models/aon-center.js +60 -0
- package/site/models/aon-geographic.js +35 -0
- package/site/models/aon-tower.js +130 -0
- package/site/models/blue-cross-geographic.js +248 -0
- package/site/models/borg-warner-geographic.js +143 -0
- package/site/models/buckingham-geographic.js +121 -0
- package/site/models/building-kit.js +358 -0
- package/site/models/celebrations.js +44 -0
- package/site/models/chicago-athletic-association-geographic.js +173 -0
- package/site/models/crain-communications.js +75 -0
- package/site/models/crain-geographic.js +69 -0
- package/site/models/crain-reference.svg +10 -0
- package/site/models/crain-tower.js +378 -0
- package/site/models/facade-grid.js +176 -0
- package/site/models/gage-geographic.js +154 -0
- package/site/models/heritage-at-millennium-park.js +284 -0
- package/site/models/heritage-geographic.js +208 -0
- package/site/models/hyatt-west-tower-geographic.js +86 -0
- package/site/models/keith-ascher-geographic.js +110 -0
- package/site/models/kemper-geographic.js +153 -0
- package/site/models/kemper.js +78 -0
- package/site/models/lake-view-geographic.js +134 -0
- package/site/models/maclean-center-geographic.js +162 -0
- package/site/models/michigan-boulevard-geographic.js +157 -0
- package/site/models/michigan-plaza-south-geographic.js +84 -0
- package/site/models/michigan-plaza-south.js +68 -0
- package/site/models/millennium-park-plaza-geographic.js +103 -0
- package/site/models/monroe-geographic.js +177 -0
- package/site/models/north-michigan-180-geographic.js +117 -0
- package/site/models/north-wabash-geographic.js +122 -0
- package/site/models/on-the-park-geographic.js +245 -0
- package/site/models/one-prudential-geographic.js +55 -0
- package/site/models/one-prudential-plaza.js +72 -0
- package/site/models/one-prudential-tower.js +246 -0
- package/site/models/peoples-gas-geographic.js +250 -0
- package/site/models/railway-exchange-geographic.js +176 -0
- package/site/models/river-plaza-geographic.js +104 -0
- package/site/models/sheraton-grand-geographic.js +112 -0
- package/site/models/six-north-michigan-geographic.js +180 -0
- package/site/models/skyline-geography-data.js +607 -0
- package/site/models/skyline-geography.js +322 -0
- package/site/models/skyline-panorama.svg +3491 -0
- package/site/models/skyline-reference.svg +3090 -0
- package/site/models/swissotel-geographic.js +79 -0
- package/site/models/three-illinois-center-geographic.js +86 -0
- package/site/models/trump-geographic.js +51 -0
- package/site/models/trump-international-tower.js +84 -0
- package/site/models/trump-tower.js +229 -0
- package/site/models/two-illinois-center-geographic.js +85 -0
- package/site/models/two-prudential-geographic.js +47 -0
- package/site/models/two-prudential-plaza.js +55 -0
- package/site/models/two-prudential-tower.js +441 -0
- package/site/models/university-club-geographic.js +217 -0
- package/site/models/willoughby-tower-geographic.js +195 -0
- package/site/models/window-illumination.js +64 -0
- package/site/skyline-3d.html +92 -0
- package/site/skyline-3d.js +333 -0
- package/site/skyline-animated.svg +18795 -0
- package/site/skyline-comparison.js +97 -0
- package/site/skyline-original-fit.svg +18312 -0
- package/site/skyline-scene.js +86 -0
- package/site/skyline-study.html +83 -0
- package/site/skyline-study.js +109 -0
- package/site/skyline-webgl.html +667 -0
- package/site/stars.svg +176 -0
- package/site/study-loader.js +20 -0
- package/site/study-types.js +1 -0
- package/site/study-viewer.js +605 -0
- package/site/study.css +204 -0
- package/site/vendor/THREE-LICENSE.txt +21 -0
- package/site/vendor/three-r186.js +4228 -0
package/site/study.css
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
:root { color-scheme: dark; background: #080808; color: #ddd; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
|
|
2
|
+
* { box-sizing: border-box; -webkit-tap-highlight-color: #ffffff22; }
|
|
3
|
+
body { margin: 0; }
|
|
4
|
+
header, main { width: 100%; max-width: 1600px; margin: 0 auto; }
|
|
5
|
+
a { color: inherit; text-underline-offset: 4px; }
|
|
6
|
+
header { display: flex; justify-content: space-between; align-items: start; gap: 24px; padding: 32px 5vw 24px; }
|
|
7
|
+
.eyebrow, .caption { color: #858585; font-size: 10px; letter-spacing: 0.13em; text-transform: uppercase; }
|
|
8
|
+
.eyebrow { margin: 0 0 14px; }
|
|
9
|
+
h1 { margin: 0; color: #eee; font: 400 clamp(26px, 3.4vw, 46px)/1.08 Georgia, serif; }
|
|
10
|
+
.address { color: #999; font-size: 11px; margin: 12px 0 0; }
|
|
11
|
+
.back { font-size: 12px; white-space: nowrap; margin-top: 2px; }
|
|
12
|
+
.study-links { display: flex; flex-direction: column; align-items: end; gap: 14px; font-size: 12px; white-space: nowrap; }
|
|
13
|
+
main { padding: 0 5vw 24px; }
|
|
14
|
+
.comparison { display: grid; grid-template-columns: 0.85fr 1.4fr; border-top: 1px solid #292929; border-bottom: 1px solid #292929; }
|
|
15
|
+
figure { position: relative; margin: 0; min-width: 0; }
|
|
16
|
+
.reference { border-right: 1px solid #292929; display: flex; flex-direction: column; align-items: center; }
|
|
17
|
+
figcaption { position: absolute; top: 20px; left: 22px; z-index: 1; pointer-events: none; }
|
|
18
|
+
.reference img { position: absolute; left: 50%; transform: translateX(-50%); width: 65%; height: 100%; padding: 65px 0 45px; object-fit: contain; }
|
|
19
|
+
.viewport { height: clamp(440px, 67vh, 850px); min-height: 0; position: relative; background: radial-gradient(ellipse at 50% 55%, #191919, #0b0b0b 70%); }
|
|
20
|
+
canvas { display: block; width: 100%; height: calc(100% - 44px); touch-action: none; cursor: grab; }
|
|
21
|
+
canvas:active { cursor: grabbing; }
|
|
22
|
+
.view-label { position: absolute; right: 20px; top: 20px; color: #777; font-size: 10px; pointer-events: none; }
|
|
23
|
+
.hint { position: absolute; bottom: 7px; left: 12px; right: 12px; margin: 0; text-align: center; color: #777; font-size: 10px; line-height: 1.6; pointer-events: none; }
|
|
24
|
+
.narrow-hint { display: none; }
|
|
25
|
+
.loading { position: absolute; inset: 30% 24px auto; color: #bbb; font-size: 12px; line-height: 1.7; text-align: center; }
|
|
26
|
+
.toolbar { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 16px; padding: 20px 0 6px; }
|
|
27
|
+
.button-group { display: flex; flex-wrap: wrap; gap: 7px; }
|
|
28
|
+
button { border: 1px solid #393939; border-radius: 2px; padding: 10px 13px; background: #101010; color: #aaa; font: inherit; font-size: 11px; cursor: pointer; }
|
|
29
|
+
button:hover, button[aria-pressed="true"] { color: #fff; border-color: #999; background: #202020; }
|
|
30
|
+
button:disabled { cursor: default; opacity: 0.35; }
|
|
31
|
+
:focus-visible { outline: 1px solid #fff; outline-offset: 4px; }
|
|
32
|
+
.notes { display: flex; justify-content: space-between; gap: 30px; color: #777; font-size: 10px; line-height: 1.8; }
|
|
33
|
+
.notes p { max-width: 65ch; }
|
|
34
|
+
.tooltip { position: fixed; z-index: 3; border: 1px solid #3a3a3a; border-radius: 3px; padding: 4px 7px; background: #000; color: #fff; font: 600 12px/1.15 ui-monospace, monospace; pointer-events: none; }
|
|
35
|
+
[hidden] { display: none !important; }
|
|
36
|
+
/* The skyline study stacks the scene over the drawing, each the page's full width and the
|
|
37
|
+
viewport's height, so both contain the same frame at the same scale. */
|
|
38
|
+
.skyline-study .comparison { grid-template-columns: 1fr; }
|
|
39
|
+
.skyline-study .reference { height: clamp(440px, 67vh, 850px); border-right: 0; border-top: 1px solid #292929; }
|
|
40
|
+
.skyline-study .reference img { left: 0; transform: none; width: 100%; height: calc(100% - 44px); padding: 0; }
|
|
41
|
+
.layout-controls { display: flex; gap: 24px; align-items: center; padding: 0 0 18px; }
|
|
42
|
+
.layout-controls p { color: #b1b1b1; font-size: 11px; line-height: 1.7; max-width: 85ch; margin: 0; }
|
|
43
|
+
.layout-controls .button-group { flex-shrink: 0; }
|
|
44
|
+
.geographic-details { margin-top: 20px; border-top: 1px solid #292929; padding-top: 16px; color: #999; font-size: 11px; line-height: 1.8; }
|
|
45
|
+
.geographic-details summary { color: #ddd; cursor: pointer; }
|
|
46
|
+
.geographic-details p { max-width: 120ch; }
|
|
47
|
+
.dimension-scroll { overflow-x: auto; margin: 20px 0; }
|
|
48
|
+
.dimension-table { width: 100%; border-collapse: collapse; font-size: 10px; text-align: left; }
|
|
49
|
+
.dimension-table th, .dimension-table td { padding: 12px; vertical-align: top; border-bottom: 1px solid #292929; }
|
|
50
|
+
.dimension-table thead th { color: #ccc; font-weight: 400; }
|
|
51
|
+
.dimension-table tbody th { color: #cfcfcf; font-weight: 400; min-width: 135px; }
|
|
52
|
+
.dimension-table td:not(:last-child) { white-space: nowrap; }
|
|
53
|
+
.dimension-table td:last-child { min-width: 240px; max-width: 370px; }
|
|
54
|
+
.study-annotations { position: absolute; inset: 0 0 44px; pointer-events: none; overflow: hidden; }
|
|
55
|
+
.study-annotations span { position: absolute; transform: translate(-50%, -100%); margin-top: -10px; padding: 3px 5px; color: #e1e1e1; background: #101010d9; font-size: 9px; white-space: nowrap; }
|
|
56
|
+
.study-annotations [data-placement="below"] { transform: translate(-50%, 0); margin-top: 12px; }
|
|
57
|
+
.study-annotations [data-placement="right"] { transform: translate(0, -50%); margin-top: 0; margin-left: 14px; }
|
|
58
|
+
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
|
|
59
|
+
/* A building's detail fills its window: the model takes the height the header and toolbar
|
|
60
|
+
leave it, beside its notes, or above them in a narrow or short window, where the page
|
|
61
|
+
scrolls to them. Every height is set by the window, never by the canvas it holds.
|
|
62
|
+
Floated over the skyline viewer, the viewer's panel closes it, so the header leaves the
|
|
63
|
+
panel's close button its corner and drops the page's own links. */
|
|
64
|
+
.building-detail { display: flex; flex-direction: column; height: 100vh; height: 100dvh; }
|
|
65
|
+
.building-detail header { padding: 22px 5vw 16px; }
|
|
66
|
+
.building-detail h1 { font-size: clamp(24px, 3vw, 38px); }
|
|
67
|
+
.building-detail main { flex: 1 1 0; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr) minmax(200px, 270px); grid-template-rows: minmax(0, 1fr); gap: 0 28px; width: 100%; margin: 0 auto; }
|
|
68
|
+
.detail-model { display: flex; flex-direction: column; min-height: 0; }
|
|
69
|
+
.building-detail .viewport { flex: 1 1 0; height: auto; min-height: 280px; border-top: 1px solid #292929; border-bottom: 1px solid #292929; }
|
|
70
|
+
.building-detail .notes { display: block; min-height: 0; overflow-y: auto; border-top: 1px solid #292929; padding-top: 4px; }
|
|
71
|
+
.framed .building-detail header { padding-right: 60px; }
|
|
72
|
+
.framed .building-detail .study-links { display: none; }
|
|
73
|
+
@media (max-width: 799px), (max-height: 499px) {
|
|
74
|
+
.building-detail { height: auto; min-height: 100vh; min-height: 100dvh; }
|
|
75
|
+
.building-detail main, .detail-model { display: block; }
|
|
76
|
+
.building-detail .viewport { height: clamp(300px, 62vh, 560px); }
|
|
77
|
+
.building-detail .notes { overflow: visible; border-top: 0; padding-top: 0; }
|
|
78
|
+
}
|
|
79
|
+
/* A building's context menu: detail and any lighting choices, scrollable on short screens. */
|
|
80
|
+
.context-menu { position: fixed; z-index: 4; box-sizing: border-box; min-width: 160px; max-width: min(280px, calc(100vw - 8px)); max-height: calc(100dvh - 8px); overflow-y: auto; padding: 4px; border: 1px solid #393939; border-radius: 3px; background: #080808f2; box-shadow: 0 10px 30px #000000cc; font-size: 11px; }
|
|
81
|
+
.context-menu-title { margin: 0; padding: 5px 8px 6px; color: #858585; font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; }
|
|
82
|
+
.context-menu :is([role="menuitem"], [role="menuitemradio"]) { display: block; box-sizing: border-box; width: 100%; min-height: 32px; margin: 0; padding: 7px 8px; border: 0; border-radius: 2px; background: none; color: #ddd; font: inherit; text-align: left; text-decoration: none; white-space: normal; }
|
|
83
|
+
.context-menu :is([role="menuitem"], [role="menuitemradio"]):is(:hover, :focus) { background: #202020; color: #fff; }
|
|
84
|
+
#building-lighting-menu { margin-top: 4px; padding-top: 4px; border-top: 1px solid #393939; }
|
|
85
|
+
.context-menu [role="menuitemradio"]::before { content: "○"; display: inline-block; width: 16px; }
|
|
86
|
+
.context-menu [role="menuitemradio"][aria-checked="true"]::before { content: "●"; }
|
|
87
|
+
.context-menu :focus-visible { outline-offset: -1px; }
|
|
88
|
+
/* The detail its item floats over the skyline: centred in the scene above the control bar,
|
|
89
|
+
below anything that lies over the frame's top, as the skyline viewer's controls do, which
|
|
90
|
+
set --viewer-controls. The menu stays above it, so every building's menu can replace it. */
|
|
91
|
+
.detail-panel { position: absolute; z-index: 3; inset: calc(var(--viewer-controls, 0px) + 12px) 12px 12px; width: min(1040px, calc(100% - 24px)); height: min(760px, calc(100% - var(--viewer-controls, 0px) - 24px)); max-width: none; max-height: none; margin: auto; padding: 0; overflow: hidden; border: 1px solid #393939; border-radius: 3px; background: #080808; color: #ddd; box-shadow: 0 24px 80px #000000e6; }
|
|
92
|
+
.detail-panel[open] { animation: detail-in 0.18s cubic-bezier(0.2, 0.7, 0.2, 1); }
|
|
93
|
+
@keyframes detail-in { from { opacity: 0; scale: 0.98; } }
|
|
94
|
+
.detail-panel iframe { display: block; width: 100%; height: 100%; border: 0; }
|
|
95
|
+
.detail-panel .detail-close { position: absolute; top: 12px; right: 12px; display: grid; place-items: center; width: 32px; height: 32px; padding: 0; font-size: 18px; line-height: 1; }
|
|
96
|
+
.detail-panel .detail-close:focus-visible { outline-offset: 2px; }
|
|
97
|
+
/* The skyline viewer's full-screen 3D mode fills its frame above a control bar docked to
|
|
98
|
+
the bottom, and stays transparent, so the viewer's stars show above the towers. The
|
|
99
|
+
skyline stands on the bar, as the drawing stands on the viewer's bottom edge. */
|
|
100
|
+
:root:has(.skyline-3d) { background: transparent; }
|
|
101
|
+
.skyline-3d { display: flex; flex-direction: column; height: 100vh; height: 100dvh; overflow: hidden; }
|
|
102
|
+
.skyline-3d main.viewport { flex: 1 1 auto; min-height: 0; height: auto; max-width: none; margin: 0; padding: 0; background: none; }
|
|
103
|
+
.skyline-3d canvas { height: 100%; }
|
|
104
|
+
.skyline-3d .study-annotations { inset: 0; }
|
|
105
|
+
/* A level skyline elevation traces itself while the scene boots. It is inline so it
|
|
106
|
+
appears before the model graph loads; errors replace it with the normal loading text.
|
|
107
|
+
Its baseline stands on the toolbar. Scaled strokes and glow keep the outline legible. */
|
|
108
|
+
.skyline-3d .loading:has(.skyline-trace) { inset: 0; margin: 0; display: grid; place-items: end center; padding: 32px 24px 0; pointer-events: none; }
|
|
109
|
+
.skyline-trace { display: block; width: min(240px, calc(100% / 3)); max-height: 14vh; overflow: visible; fill: none; stroke: #ddd; stroke-width: 4.2; stroke-linejoin: round; stroke-linecap: round; }
|
|
110
|
+
.skyline-trace-rail { opacity: 0.08; }
|
|
111
|
+
.skyline-trace-line { stroke-dasharray: 1; stroke-dashoffset: 1; animation: skyline-trace 4s linear infinite; }
|
|
112
|
+
.skyline-trace-tip { stroke: #fff; stroke-width: 6.6; stroke-dasharray: 0.008 0.992; stroke-dashoffset: 0.008; filter: drop-shadow(0 0 9px #ffffff99); animation: skyline-trace-tip 4s linear infinite; }
|
|
113
|
+
/* Scene notes appear with the rendered scene, leaving the loading outline clear. */
|
|
114
|
+
.skyline-3d:has(#loading:not([hidden]) .skyline-trace) .scene-notes { visibility: hidden; }
|
|
115
|
+
@keyframes skyline-trace {
|
|
116
|
+
0% { stroke-dashoffset: 1; opacity: 0; }
|
|
117
|
+
5% { opacity: 1; }
|
|
118
|
+
78%, 88% { stroke-dashoffset: 0; opacity: 1; }
|
|
119
|
+
100% { stroke-dashoffset: 0; opacity: 0; }
|
|
120
|
+
}
|
|
121
|
+
@keyframes skyline-trace-tip {
|
|
122
|
+
0% { stroke-dashoffset: 0.008; opacity: 0; }
|
|
123
|
+
5% { opacity: 1; }
|
|
124
|
+
78% { stroke-dashoffset: -0.992; opacity: 1; }
|
|
125
|
+
88%, 100% { stroke-dashoffset: -0.992; opacity: 0; }
|
|
126
|
+
}
|
|
127
|
+
/* Small notes along the scene's bottom edge, over the canvas but not its drags: the camera
|
|
128
|
+
hint and map data's credit, both revealed with the controls. */
|
|
129
|
+
.scene-notes { position: absolute; left: 6px; right: 6px; bottom: 4px; z-index: 1; display: flex; flex-wrap: wrap; justify-content: space-between; align-items: end; gap: 4px 12px; pointer-events: none; }
|
|
130
|
+
.scene-notes p { position: static; margin: 0; padding: 1px 4px; background: #080808cc; color: #888; font-size: 9px; line-height: 1.4; text-align: left; }
|
|
131
|
+
.scene-notes .attribution { margin-left: auto; }
|
|
132
|
+
.scene-notes a { pointer-events: auto; }
|
|
133
|
+
.skyline-3d:has(#menu-toggle[aria-expanded="false"]) .scene-notes { display: none; }
|
|
134
|
+
/* The skyline study's toolbar, folded behind a muted grey six-pointed star, white under the
|
|
135
|
+
pointer, in the middle of the bar. Pressing the star opens it outward, camera views to the bar's left edge and model
|
|
136
|
+
display to its right edge, each group sliding out from the star as skyline-3d.ts clips it
|
|
137
|
+
open from its `--fold` inset; pressing it again folds them back. The star stays in the
|
|
138
|
+
middle, so narrower windows put the groups in a row under it, still at the edges, then
|
|
139
|
+
centred in a row each. */
|
|
140
|
+
.control-bar { position: sticky; bottom: 0; z-index: 2; display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); grid-template-areas: "views menu display"; align-items: center; gap: 5px 12px; padding: 5px max(12px, env(safe-area-inset-right)) max(5px, env(safe-area-inset-bottom)) max(12px, env(safe-area-inset-left)); border-top: 1px solid #292929; background: #080808; }
|
|
141
|
+
.control-bar .button-group { gap: 4px; }
|
|
142
|
+
.control-bar .camera-views { grid-area: views; justify-self: start; --fold: inset(0 0 0 100%); }
|
|
143
|
+
.control-bar .model-display { grid-area: display; justify-self: end; justify-content: end; --fold: inset(0 100% 0 0); }
|
|
144
|
+
.celebration-controls { display: flex; flex-wrap: wrap; align-items: center; justify-content: end; gap: 4px; flex-basis: 100%; }
|
|
145
|
+
.celebration-caption { margin-right: 4px; color: #888; font-size: 10px; }
|
|
146
|
+
.control-bar .celebration-controls button { display: grid; place-items: center; width: 36px; height: 36px; padding: 4px; }
|
|
147
|
+
.celebration-controls svg { width: 25px; height: 25px; fill: currentColor; }
|
|
148
|
+
.celebration-controls .logo-line { fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; }
|
|
149
|
+
.celebration-controls .logo-cut { fill: none; stroke: #080808; stroke-width: 2; }
|
|
150
|
+
.celebration-controls text { font: bold 15px Georgia, serif; }
|
|
151
|
+
.celebration-controls button[aria-pressed="true"] { color: #fff; border-color: #aaa; box-shadow: inset 0 -2px #eee; }
|
|
152
|
+
.celebration-controls button[aria-pressed="mixed"] { color: #eee; border-color: #aaa; border-style: dashed; }
|
|
153
|
+
.control-bar:not(.open) { row-gap: 0; }
|
|
154
|
+
.control-bar:not(.open) .button-group { display: none; }
|
|
155
|
+
.control-bar button { padding: 5px 8px; }
|
|
156
|
+
.control-bar :focus-visible { outline-offset: 1px; }
|
|
157
|
+
.control-bar .menu-toggle { grid-area: menu; display: grid; place-items: center; width: 28px; height: 28px; padding: 0; border: 0; border-radius: 50%; background: none; color: #8c8c8c; }
|
|
158
|
+
.control-bar .menu-toggle:hover { color: #fff; background: #ffffff14; }
|
|
159
|
+
.menu-toggle svg { width: 20px; height: 20px; fill: currentColor; transition: rotate 0.35s cubic-bezier(0.2, 0.7, 0.2, 1); }
|
|
160
|
+
.menu-toggle[aria-expanded="true"] svg { rotate: 30deg; }
|
|
161
|
+
/* At desktop widths the badges share the display row, so opening the controls
|
|
162
|
+
keeps the canvas height unchanged. Smaller screens retain 36px touch targets. */
|
|
163
|
+
@media (min-width: 1440px) {
|
|
164
|
+
.celebration-controls { flex-basis: auto; flex-wrap: nowrap; }
|
|
165
|
+
.celebration-caption { display: none; }
|
|
166
|
+
.control-bar .celebration-controls button { width: 28px; height: 28px; padding: 2px; }
|
|
167
|
+
.celebration-controls svg { width: 20px; height: 20px; }
|
|
168
|
+
}
|
|
169
|
+
@media (max-width: 1439px) {
|
|
170
|
+
.control-bar { grid-template-columns: auto auto; grid-template-areas: "menu menu" "views display"; justify-content: space-between; }
|
|
171
|
+
.control-bar .menu-toggle { justify-self: center; }
|
|
172
|
+
}
|
|
173
|
+
@media (max-width: 1023px) {
|
|
174
|
+
.control-bar { grid-template-columns: minmax(0, 1fr); grid-template-areas: "menu" "views" "display"; }
|
|
175
|
+
.control-bar .button-group { justify-self: center; justify-content: center; --fold: inset(0 50%); }
|
|
176
|
+
.celebration-controls { justify-content: center; }
|
|
177
|
+
}
|
|
178
|
+
@media (prefers-reduced-motion: reduce) {
|
|
179
|
+
.menu-toggle svg { transition: none; }
|
|
180
|
+
.detail-panel[open] { animation: none; }
|
|
181
|
+
.skyline-trace-line { animation: none; stroke-dasharray: none; stroke-dashoffset: 0; opacity: 0.65; }
|
|
182
|
+
.skyline-trace-tip { display: none; animation: none; }
|
|
183
|
+
}
|
|
184
|
+
@media (max-width: 600px) {
|
|
185
|
+
.skyline-trace { stroke-width: 8.4; }
|
|
186
|
+
.skyline-trace-tip { stroke-width: 12; }
|
|
187
|
+
.layout-controls { align-items: start; flex-direction: column; gap: 12px; }
|
|
188
|
+
header { padding: 24px 5vw; flex-wrap: wrap; gap: 18px; }
|
|
189
|
+
h1 { max-width: 300px; }
|
|
190
|
+
.comparison { grid-template-columns: 0.55fr 1fr; }
|
|
191
|
+
.viewport { height: 430px; }
|
|
192
|
+
figcaption { top: 14px; left: 10px; font-size: 9px; letter-spacing: 0.05em; }
|
|
193
|
+
.reference img { width: 88%; padding: 50px 0 48px; }
|
|
194
|
+
.view-label { top: 34px; left: 10px; right: auto; font-size: 9px; }
|
|
195
|
+
.hint { font-size: 9px; }
|
|
196
|
+
.wide-hint { display: none; }
|
|
197
|
+
.narrow-hint { display: inline; }
|
|
198
|
+
.notes { display: block; }
|
|
199
|
+
button { padding: 12px 11px; }
|
|
200
|
+
.study-links { align-items: start; flex-direction: row; flex-wrap: wrap; gap: 18px; }
|
|
201
|
+
.skyline-study .reference { height: 360px; }
|
|
202
|
+
.skyline-study .viewport { height: 480px; }
|
|
203
|
+
.control-bar button { font-size: 10px; }
|
|
204
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License
|
|
2
|
+
|
|
3
|
+
Copyright © 2010-2026 three.js authors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|