/* Wayfinding: one sign language for the route. The roadside signs, chapter plates, navigation, dash cluster and project plates share the same exit numbers (from src/journey/sign-routes.ts) and the chapter accent colours. Every label here is CSS generated content with empty alt text, so the semantic document is identical with and without JavaScript. Imported last. */ :root { --exit-ink: #160b22; --exit-chamfer: polygon(5px 0, calc(100% - 5px) 0, 100% 5px, 100% 100%, 0 100%, 0 5px); } /* Static vignette above the world, below the UI. Plain alpha, no blend mode, so the compositor never re-blends it against the animating canvas. */ body::after { content: ''; position: fixed; inset: 0; z-index: var(--z-atmosphere); pointer-events: none; background: radial-gradient(130% 95% at 50% 42%, transparent 58%, rgb(8 3 18 / 42%) 100%); } /* The hero scrim used to end in a hard edge that read as a dark band while scrolling away from the hero. Feather its bottom with a static mask. */ .hero-journey::before { mask-image: linear-gradient(to bottom, #000 72%, transparent); } /* ---------- Chapter exit plates ---------- */ .portfolio-section[data-exit] { position: relative; } /* The exit tab sits on the panel's top edge, like the tab on a motorway sign. */ .portfolio-section[data-exit]::before { content: 'EXIT ' attr(data-exit) / ''; position: absolute; z-index: 1; inset-block-start: 0; inset-inline-start: clamp(1.1rem, 4vw, 3.2rem); translate: 0 -50%; padding: 0.42rem 0.7rem 0.38rem; clip-path: var(--exit-chamfer); background: var(--chapter-accent, var(--accent)); color: var(--exit-ink); font: 720 0.7rem/1 var(--mono); letter-spacing: 0.16em; pointer-events: none; } /* "Then" line: the next exit, as on a real gantry. */ .portfolio-section[data-exit]::after { content: 'THEN \2192 ' attr(data-next) / ''; position: absolute; inset-block-start: 0; inset-inline-end: clamp(1.1rem, 4vw, 3.2rem); translate: 0 -50%; padding: 0.38rem 0.6rem; border: 1px solid color-mix(in srgb, var(--chapter-accent, var(--accent)) 42%, transparent); border-radius: 3px; background: var(--surface-strong); color: var(--text-muted); font: 560 0.64rem/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; white-space: pre; pointer-events: none; } .portfolio-section[data-exit='08']::after { content: 'END OF ROUTE' / ''; } /* The hero is the on-ramp. */ .hero-journey__content::before { content: 'EXIT 01 \00b7 ON-RAMP \00b7 BUCHAREST' / ''; display: block; inline-size: fit-content; justify-self: start; align-self: start; margin-block-end: clamp(0.8rem, 2vh, 1.4rem); padding: 0.42rem 0.7rem 0.38rem; clip-path: var(--exit-chamfer); background: var(--rose, var(--accent)); color: var(--exit-ink); font: 720 0.68rem/1 var(--mono); letter-spacing: 0.16em; white-space: pre; } /* ---------- Navigation: the overhead gantry carries the same numbers ---------- */ .site-navigation ul { counter-reset: exit; } .site-navigation li { counter-increment: exit; } @media (min-width: 1100px) { .site-navigation a::before { content: counter(exit, decimal-leading-zero) / ''; margin-inline-end: 0.55em; color: color-mix(in srgb, var(--nav-accent, var(--accent)) 70%, var(--text-muted)); font: 600 0.66em/1 var(--mono); letter-spacing: 0.06em; opacity: 0.8; } .site-navigation a[aria-current='page']::before { opacity: 1; } } /* ---------- Dash cluster: exit, chapter, route and local time in one unit ---------- */ .journey-hud[data-exit]::before { content: 'EXIT ' attr(data-exit) / ''; padding: 0.3rem 0.45rem 0.26rem; clip-path: var(--exit-chamfer); background: var(--rose, var(--accent)); color: var(--exit-ink); flex: none; white-space: pre; font: 720 0.62rem/1 var(--mono); letter-spacing: 0.14em; } .journey-hud[data-exit='03']::before, .journey-hud[data-exit='07']::before { background: var(--violet, var(--accent)); } .journey-hud[data-exit='04']::before { background: var(--accent); } .journey-hud[data-exit='05']::before, .journey-hud[data-exit='08']::before { background: var(--coral, var(--amber)); } .journey-hud[data-clock]::after { content: attr(data-clock) ' BUC' / ''; padding-inline-start: 0.72rem; border-inline-start: 1px solid rgb(126 220 232 / 22%); color: var(--text-muted); font-size: 0.66rem; letter-spacing: 0.1em; } @media (max-width: 767px) { .journey-hud[data-clock]::after { display: none; } } /* ---------- Project registration plates ---------- */ .project-case-study__header[data-plate]::before, .project-card[data-plate]::before { content: attr(data-plate) / ''; display: block; inline-size: max-content; max-inline-size: 100%; margin-block-end: 0.85rem; padding: 0.34rem 0.6rem 0.3rem; border: 1px solid color-mix(in srgb, var(--chapter-accent, var(--accent)) 55%, transparent); border-radius: 3px; color: color-mix(in srgb, var(--chapter-accent, var(--accent)) 72%, var(--text)); font: 650 0.64rem/1.2 var(--mono); letter-spacing: 0.14em; } /* Case-study evidence reads as a route log: lettered stops. */ .project-evidence { counter-reset: stop; } .project-evidence > div { counter-increment: stop; } .project-evidence dt::before { content: counter(stop, upper-alpha) / ''; display: inline-grid; place-items: center; inline-size: 1.45em; block-size: 1.45em; margin-inline-end: 0.6em; border: 1px solid currentColor; border-radius: 50%; font: 700 0.78em/1 var(--mono); vertical-align: 0.08em; } /* ---------- Arrival: the current chapter's plate strikes on, once ---------- */ .portfolio-section[data-current]::before { box-shadow: 0 0 0 1px color-mix(in srgb, var(--chapter-accent, var(--accent)) 60%, transparent); } @media (prefers-reduced-motion: no-preference) { .portfolio-section[data-current]::before { animation: exit-strike 1.1s ease-out both; } .portfolio-section[data-current] { animation: exit-panel-light 1.6s cubic-bezier(0.2, 0.75, 0.2, 1) both; } @supports (animation-timeline: view()) { .reading-stage:not([data-reading-stage='live']) .project-card { animation: wf-rise linear both; animation-timeline: view(); animation-range: entry 0% entry 40%; } } } /* A neon tube warming up: one soft swell, then steady. Below 3 Hz by design (photosensitivity): a single rise over the whole duration. */ @keyframes exit-strike { 0% { opacity: 0.25; } 45% { opacity: 0.85; } 60% { opacity: 0.7; } 100% { opacity: 1; } } @keyframes exit-panel-light { 0% { border-top-color: color-mix(in srgb, var(--chapter-accent, var(--accent)) 95%, transparent); } 100% { border-top-color: color-mix(in srgb, var(--chapter-accent, var(--accent)) 28%, transparent); } } @keyframes wf-rise { from { transform: translateY(28px); } to { transform: none; } } /* ---------- Narrow screens ---------- */ @media (max-width: 520px) { .portfolio-section[data-exit]::after, .journey-hud[data-exit]::before { display: none; } .hero-journey__content::before { content: 'EXIT 01 \00b7 ON-RAMP' / ''; } } /* ---------- Forced colours and print ---------- */ @media (forced-colors: active) { body::after { display: none !important; } .portfolio-section[data-exit]::before, .hero-journey__content::before, .journey-hud[data-exit]::before { forced-color-adjust: none; background: Canvas; color: CanvasText; border: 1px solid CanvasText; clip-path: none; } } @media print { body::after, .portfolio-section[data-exit]::before, .portfolio-section[data-exit]::after, .hero-journey__content::before, .project-case-study__header[data-plate]::before, .project-card[data-plate]::before { display: none !important; } }