feat: cinematic outro that mirrors the intro crane

On arrival the camera cranes back toward the sun on a long lens, letterbox
bars close in on every tier and a closing credit of real identity facts
fades into the upper bar. Leaving the destination reverses it.
This commit is contained in:
2026-10-10 22:25:25 +03:00
parent 0ae27168cd
commit 06b6e996a0
6 changed files with 90 additions and 1 deletions

View File

@@ -504,6 +504,76 @@
}
}
/* Round 5 outro: letterbox bars close in on arrival, on every tier (they are
CSS, so the static poster gets them too). They sit in the world layer,
under the reading column, so they frame the sky and never cover content.
The upper bar hangs below the gantry and carries a closing credit built
from real identity facts; the lower bar is left clear for the trip
summary that ends the contact chapter. */
.journey-world::before,
.journey-world::after {
position: absolute;
z-index: 1;
inset-inline: 0;
block-size: max(54px, 10vh);
background: #020108;
content: '';
transform: scaleY(0);
transition: transform 1.6s cubic-bezier(0.65, 0, 0.35, 1);
}
.journey-world::before {
inset-block-start: 0;
display: grid;
align-items: end;
justify-items: center;
block-size: calc(var(--gantry-h, 72px) + max(30px, 4.5vh));
padding: 0 16px max(8px, 1.2vh);
color: rgb(255 226 196 / 0%);
font: 600 0.6rem/1.3 var(--mono, ui-monospace, monospace);
letter-spacing: 0.32em;
text-align: center;
text-transform: uppercase;
white-space: nowrap;
content: attr(data-credit) / '';
transform-origin: top;
transition:
transform 1.6s cubic-bezier(0.65, 0, 0.35, 1),
color 1.2s ease;
}
.journey-world::after {
inset-block-end: 0;
transform-origin: bottom;
}
.journey-world[data-arrived='true']::before,
.journey-world[data-arrived='true']::after {
transform: scaleY(1);
transition-delay: 0.5s;
}
.journey-world[data-arrived='true']::before {
color: rgb(255 226 196 / 74%);
transition-delay: 0.5s, 1.9s;
}
@media (max-width: 767px) {
.journey-world::after { block-size: max(40px, 7vh); }
.journey-world::before {
font-size: 0.5rem;
letter-spacing: 0.14em;
white-space: normal;
}
}
@media (prefers-reduced-motion: reduce) {
.journey-world::before,
.journey-world::after,
.journey-world[data-arrived='true']::before,
.journey-world[data-arrived='true']::after {
transition: none;
}
}
@media (forced-colors: active) {
.journey-world::before,
.journey-world::after { display: none; }
}
@media (prefers-reduced-motion: reduce) {
.journey-poster {
filter: saturate(0.86) brightness(0.92);