Spaces:
Running on Zero
Running on Zero
| /* ============================================================================= | |
| Lightloom — stage.css · "La Sala" projection-room look & layout | |
| Built entirely on css/tokens.css. Warm darkness, amber projector glow. | |
| NEVER blue tech dark-mode. No frameworks, no build step. | |
| Sections: | |
| 0. Reset & base 4. Lobby (S0) + projector beam | |
| 1. Screens & geometry 5. The Set (S1): HUD, subtitles, stage-bar | |
| 2. Global post-FX 6. The Slate (hero clapperboard) + mobile sheet | |
| 3. Shared atoms 7. Theater / Showcase / About | |
| (pills, links) 8. Reduced motion + responsive/mobile | |
| ========================================================================== */ | |
| /* ---------- 0. Reset & base ------------------------------------------------ */ | |
| *, | |
| *::before, | |
| *::after { | |
| box-sizing: border-box; | |
| } | |
| html, | |
| body { | |
| margin: 0; | |
| height: 100%; | |
| } | |
| body { | |
| background: var(--bg); | |
| color: var(--ink); | |
| font-family: var(--font-ui); | |
| font-size: 16px; | |
| line-height: 1.5; | |
| -webkit-font-smoothing: antialiased; | |
| text-rendering: optimizeLegibility; | |
| overflow: hidden; /* screens manage their own scroll */ | |
| } | |
| button { | |
| font: inherit; | |
| color: inherit; | |
| cursor: pointer; | |
| } | |
| a { | |
| color: var(--amber); | |
| text-decoration: none; | |
| } | |
| a:hover { | |
| text-decoration: underline; | |
| } | |
| :focus-visible { | |
| outline: 2px solid var(--amber); | |
| outline-offset: 2px; | |
| border-radius: 4px; | |
| } | |
| /* ---------- 1. Screens & geometry ----------------------------------------- */ | |
| #app { | |
| position: fixed; | |
| inset: 0; | |
| overflow: hidden; | |
| /* A faint warm floor-glow so the room is never flat black. */ | |
| background: | |
| radial-gradient(120% 80% at 50% 118%, rgba(232, 163, 61, 0.06), transparent 60%), | |
| var(--bg); | |
| } | |
| /* Each screen is a full-bleed layer; only .is-active is shown. We crossfade | |
| rather than hard-cut between screens (cinema, not tab-switch). */ | |
| .screen { | |
| position: absolute; | |
| inset: 0; | |
| display: flex; | |
| flex-direction: column; | |
| opacity: 0; | |
| visibility: hidden; | |
| pointer-events: none; | |
| transition: | |
| opacity var(--transition-ms) var(--ease), | |
| visibility 0s linear var(--transition-ms); | |
| } | |
| .screen.is-active { | |
| opacity: 1; | |
| visibility: visible; | |
| pointer-events: auto; | |
| transition: | |
| opacity var(--transition-ms) var(--ease), | |
| visibility 0s; | |
| } | |
| .screen__heading { | |
| font-family: var(--font-display); | |
| font-weight: 500; | |
| letter-spacing: 0.01em; | |
| margin: 0; | |
| } | |
| /* ---------- 2. Global post-FX (grain + vignette) -------------------------- */ | |
| /* These sit above all screens; pointer-events:none so they never block input. | |
| The animated film grain is a tiled SVG noise nudged every frame; the WebGL | |
| stage paints its own grain too, but this guarantees the whole ROOM grains. */ | |
| .fx { | |
| position: fixed; | |
| inset: 0; | |
| pointer-events: none; | |
| z-index: 50; | |
| } | |
| .fx--grain { | |
| opacity: var(--grain-opacity); | |
| mix-blend-mode: overlay; | |
| background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>"); | |
| background-size: 160px 160px; | |
| animation: grain-shift 0.6s steps(4) infinite; | |
| will-change: transform; | |
| } | |
| @keyframes grain-shift { | |
| 0% { transform: translate(0, 0); } | |
| 25% { transform: translate(-3%, 2%); } | |
| 50% { transform: translate(2%, -4%); } | |
| 75% { transform: translate(-2%, 3%); } | |
| 100% { transform: translate(3%, -2%); } | |
| } | |
| /* Radial vignette ~12% (token --vignette) darkens the room edges. */ | |
| .fx--vignette { | |
| background: radial-gradient( | |
| 120% 100% at 50% 45%, | |
| transparent 55%, | |
| rgba(0, 0, 0, calc(var(--vignette) * 4)) 100% | |
| ); | |
| } | |
| /* ---------- 3. Shared atoms (pills, links, toast) ------------------------- */ | |
| .pill { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.5em; | |
| padding: 0.62em 1.05em; | |
| border: 1px solid var(--line); | |
| border-radius: var(--r-pill); | |
| background: rgba(245, 239, 230, 0.04); | |
| color: var(--ink-dim); | |
| font-size: 0.84rem; | |
| letter-spacing: 0.02em; | |
| line-height: 1; | |
| transition: color 0.25s var(--ease), border-color 0.25s var(--ease), | |
| background 0.25s var(--ease), box-shadow 0.25s var(--ease); | |
| } | |
| .pill:hover { | |
| color: var(--ink); | |
| border-color: var(--amber-soft); | |
| background: var(--amber-soft); | |
| } | |
| .pill[aria-pressed="true"] { | |
| color: var(--amber); | |
| border-color: rgba(232, 163, 61, 0.4); | |
| box-shadow: var(--halo-soft); | |
| } | |
| .pill__icon, | |
| .pill__flag { | |
| font-size: 0.95em; | |
| line-height: 1; | |
| } | |
| /* REC-accented call to action (Roll / Cut). */ | |
| .pill--rec { | |
| color: var(--ink); | |
| border-color: rgba(224, 68, 46, 0.5); | |
| background: rgba(224, 68, 46, 0.12); | |
| } | |
| .pill--rec:hover { | |
| border-color: var(--rec); | |
| background: rgba(224, 68, 46, 0.22); | |
| box-shadow: 0 0 20px rgba(224, 68, 46, 0.25); | |
| } | |
| .pill--lang { | |
| font-variant: tabular-nums; | |
| letter-spacing: 0.06em; | |
| } | |
| .pill--icon { | |
| padding: 0.5em 0.7em; | |
| } | |
| .ghostlink { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.5em; | |
| background: none; | |
| border: none; | |
| color: var(--ink-faint); | |
| font-size: 0.86rem; | |
| letter-spacing: 0.02em; | |
| padding: 0.4em 0; | |
| transition: color 0.25s var(--ease); | |
| } | |
| .ghostlink:hover { | |
| color: var(--amber); | |
| } | |
| .linklike { | |
| background: none; | |
| border: none; | |
| padding: 0; | |
| color: var(--amber); | |
| font-size: inherit; | |
| } | |
| .linklike:hover { | |
| text-decoration: underline; | |
| } | |
| /* Soft-error toast: amber, slides up from bottom-center. */ | |
| .toast { | |
| position: fixed; | |
| left: 50%; | |
| bottom: 6vh; | |
| transform: translate(-50%, 1.2rem); | |
| z-index: 80; | |
| max-width: min(90vw, 30rem); | |
| padding: 0.85em 1.3em; | |
| border: 1px solid rgba(232, 163, 61, 0.45); | |
| border-radius: var(--r-pill); | |
| background: rgba(27, 18, 6, 0.92); | |
| color: var(--ink); | |
| box-shadow: var(--halo); | |
| font-size: 0.9rem; | |
| text-align: center; | |
| opacity: 0; | |
| pointer-events: none; | |
| transition: opacity 0.4s var(--ease), transform 0.4s var(--ease); | |
| } | |
| .toast.is-visible { | |
| opacity: 1; | |
| transform: translate(-50%, 0); | |
| } | |
| /* ---------- 4. Lobby (S0) + volumetric projector beam --------------------- */ | |
| #lobby { | |
| padding: clamp(1.2rem, 3vw, 2.4rem); | |
| text-align: center; | |
| z-index: 10; | |
| } | |
| .lobby__top { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| z-index: 2; | |
| } | |
| .brandmark { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.55em; | |
| font-family: var(--font-display); | |
| font-weight: 600; | |
| font-size: 0.82rem; | |
| letter-spacing: var(--tracking-title); | |
| color: var(--ink-dim); | |
| } | |
| .brandmark__dot { | |
| width: 0.55em; | |
| height: 0.55em; | |
| border-radius: 50%; | |
| background: var(--rec); | |
| box-shadow: 0 0 10px rgba(224, 68, 46, 0.7); | |
| } | |
| /* Volumetric amber beam: a clipped cone from a top-right "lamp" sweeping down | |
| across the dim room. Layered cone + drifting dust + a glowing lamp source. */ | |
| .beam { | |
| position: absolute; | |
| inset: 0; | |
| overflow: hidden; | |
| pointer-events: none; | |
| z-index: 0; | |
| } | |
| .beam__cone { | |
| position: absolute; | |
| top: -16%; | |
| right: -6%; | |
| width: 86%; | |
| height: 150%; | |
| /* The cone narrows toward the lamp (top-right) and widens to the screen. */ | |
| background: conic-gradient( | |
| from 210deg at 96% 4%, | |
| transparent 0deg, | |
| rgba(232, 163, 61, 0.16) 14deg, | |
| rgba(232, 163, 61, 0.05) 30deg, | |
| transparent 44deg | |
| ); | |
| filter: blur(6px); | |
| mix-blend-mode: screen; | |
| transform-origin: top right; | |
| animation: beam-breathe 7s var(--ease) infinite; | |
| } | |
| .beam__dust { | |
| position: absolute; | |
| inset: 0; | |
| background-image: | |
| radial-gradient(1.5px 1.5px at 70% 30%, rgba(245, 239, 230, 0.5), transparent 60%), | |
| radial-gradient(1px 1px at 60% 55%, rgba(245, 239, 230, 0.4), transparent 60%), | |
| radial-gradient(1.5px 1.5px at 80% 65%, rgba(232, 163, 61, 0.5), transparent 60%), | |
| radial-gradient(1px 1px at 52% 40%, rgba(245, 239, 230, 0.35), transparent 60%); | |
| mix-blend-mode: screen; | |
| opacity: 0.7; | |
| animation: dust-drift 16s linear infinite; | |
| } | |
| .beam__lamp { | |
| position: absolute; | |
| top: 2%; | |
| right: 3%; | |
| width: 4.2rem; | |
| height: 4.2rem; | |
| border-radius: 50%; | |
| background: radial-gradient(circle, rgba(232, 163, 61, 0.85), rgba(232, 163, 61, 0.12) 60%, transparent 72%); | |
| filter: blur(2px); | |
| mix-blend-mode: screen; | |
| animation: lamp-flicker 4.5s steps(8) infinite; | |
| } | |
| @keyframes beam-breathe { | |
| 0%, 100% { opacity: 0.85; transform: rotate(0deg) scaleX(1); } | |
| 50% { opacity: 1; transform: rotate(0.6deg) scaleX(1.03); } | |
| } | |
| @keyframes dust-drift { | |
| from { transform: translateY(0); } | |
| to { transform: translateY(-3%); } | |
| } | |
| @keyframes lamp-flicker { | |
| 0%, 100% { opacity: 0.9; } | |
| 40% { opacity: 1; } | |
| 55% { opacity: 0.82; } | |
| 70% { opacity: 0.97; } | |
| } | |
| .lobby__center { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| gap: clamp(1rem, 2.4vh, 1.8rem); | |
| z-index: 2; | |
| max-width: 56rem; | |
| margin: 0 auto; | |
| width: 100%; | |
| } | |
| .title { | |
| font-family: var(--font-display); | |
| font-weight: 600; | |
| font-size: clamp(3.2rem, 11vw, 8.2rem); | |
| line-height: 0.95; | |
| letter-spacing: 0.01em; | |
| margin: 0; | |
| text-shadow: var(--halo); | |
| } | |
| .title__word--amber { | |
| color: var(--amber); | |
| } | |
| .tagline { | |
| font-family: var(--font-display); | |
| font-style: italic; | |
| font-size: clamp(1.05rem, 2.5vw, 1.55rem); | |
| color: var(--ink-dim); | |
| margin: 0; | |
| max-width: 34ch; | |
| } | |
| /* The two doors. */ | |
| .doors { | |
| display: grid; | |
| grid-template-columns: repeat(2, minmax(0, 1fr)); | |
| gap: clamp(0.8rem, 2vw, 1.4rem); | |
| width: 100%; | |
| max-width: 42rem; | |
| margin-top: 0.4rem; | |
| } | |
| .door { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: flex-start; | |
| gap: 0.45rem; | |
| text-align: left; | |
| padding: 1.3rem 1.4rem; | |
| border: 1px solid var(--line); | |
| border-radius: var(--r-panel); | |
| background: linear-gradient(160deg, rgba(245, 239, 230, 0.05), rgba(245, 239, 230, 0.015)); | |
| box-shadow: var(--panel-shadow); | |
| transition: transform 0.3s var(--ease), border-color 0.3s var(--ease), | |
| box-shadow 0.3s var(--ease); | |
| } | |
| .door:hover { | |
| transform: translateY(-3px); | |
| border-color: rgba(232, 163, 61, 0.45); | |
| box-shadow: var(--halo); | |
| } | |
| .door__icon { | |
| font-size: 1.7rem; | |
| } | |
| .door__title { | |
| font-family: var(--font-display); | |
| font-size: 1.2rem; | |
| font-weight: 600; | |
| color: var(--ink); | |
| } | |
| .door__sub { | |
| font-size: 0.86rem; | |
| color: var(--ink-faint); | |
| } | |
| /* Recital composer. */ | |
| .recital { | |
| width: 100%; | |
| max-width: 42rem; | |
| text-align: left; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 0.6rem; | |
| padding: 1.1rem 1.2rem; | |
| border: 1px solid var(--line); | |
| border-radius: var(--r-panel); | |
| background: rgba(10, 10, 12, 0.6); | |
| box-shadow: var(--panel-shadow); | |
| } | |
| .recital__label { | |
| font-size: 0.74rem; | |
| letter-spacing: 0.12em; | |
| text-transform: uppercase; | |
| color: var(--ink-faint); | |
| } | |
| .recital__text { | |
| width: 100%; | |
| min-height: 8.5rem; | |
| resize: vertical; | |
| padding: 0.9rem 1rem; | |
| border: 1px solid var(--line); | |
| border-radius: 10px; | |
| background: rgba(10, 10, 12, 0.7); | |
| color: var(--ink); | |
| font-family: var(--font-display); | |
| font-size: 1.02rem; | |
| line-height: 1.6; | |
| } | |
| .recital__text:focus-visible { | |
| border-color: var(--amber); | |
| outline: none; | |
| box-shadow: var(--halo-soft); | |
| } | |
| .recital__cite { | |
| margin: 0; | |
| font-size: 0.76rem; | |
| color: var(--ink-faint); | |
| } | |
| .recital__actions { | |
| display: flex; | |
| justify-content: flex-end; | |
| } | |
| .lobby__foot { | |
| display: flex; | |
| flex-wrap: wrap; | |
| align-items: center; | |
| justify-content: space-between; | |
| gap: 0.5rem 1rem; | |
| z-index: 2; | |
| font-size: 0.78rem; | |
| color: var(--ink-faint); | |
| } | |
| .foot__ledger strong { | |
| color: var(--ink-dim); | |
| font-variant: tabular-nums; | |
| } | |
| .foot__links { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| } | |
| .foot__sep { | |
| color: var(--line); | |
| } | |
| /* ---------- 5. The Set (S1): stage, HUD, subtitles, stage-bar ------------- */ | |
| #set { | |
| display: grid; | |
| /* The stage spans full width; the slate floats over its right edge on | |
| desktop; controls sit on a bottom rail. */ | |
| grid-template-rows: 1fr auto; | |
| padding: clamp(0.6rem, 1.6vw, 1.2rem); | |
| gap: clamp(0.6rem, 1.4vh, 1rem); | |
| } | |
| /* The 2.39:1 letterbox wrapper, centered. The black bars are the body bg, and | |
| the HUD lives in them. We size by available space and clamp to the aspect. */ | |
| .stage { | |
| position: relative; | |
| align-self: center; | |
| justify-self: center; | |
| width: min(100%, calc((100dvh - 9.5rem) * var(--aspect-film))); | |
| aspect-ratio: var(--aspect-film); | |
| max-height: calc(100dvh - 8.5rem); | |
| border-radius: 8px; | |
| overflow: hidden; | |
| background: #000; | |
| box-shadow: var(--halo), inset 0 0 120px rgba(0, 0, 0, 0.8); | |
| } | |
| .stage__canvas { | |
| position: absolute; | |
| inset: 0; | |
| width: 100%; | |
| height: 100%; | |
| display: block; | |
| } | |
| /* HUD lives in the (effectively black) top/bottom regions of the stage. */ | |
| .hud { | |
| position: absolute; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.6em; | |
| font-size: 0.72rem; | |
| letter-spacing: 0.16em; | |
| color: var(--ink-dim); | |
| z-index: 4; | |
| pointer-events: none; | |
| text-shadow: 0 1px 6px rgba(0, 0, 0, 0.9); | |
| } | |
| .hud--top { | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| justify-content: space-between; | |
| padding: 0.7rem 1rem 0; | |
| } | |
| .hud__title { | |
| font-family: var(--font-display); | |
| font-weight: 600; | |
| letter-spacing: var(--tracking-title); | |
| color: var(--ink); | |
| } | |
| .hud__counter { | |
| font-variant: tabular-nums; | |
| } | |
| .hud--budget { | |
| bottom: 0; | |
| left: 0; | |
| padding: 0 1rem 0.7rem; | |
| } | |
| .hud__rec { | |
| width: 0.5rem; | |
| height: 0.5rem; | |
| border-radius: 50%; | |
| background: var(--rec); | |
| box-shadow: 0 0 8px rgba(224, 68, 46, 0.8); | |
| animation: rec-pulse 1.6s var(--ease) infinite; | |
| } | |
| @keyframes rec-pulse { | |
| 0%, 100% { opacity: 1; transform: scale(1); } | |
| 50% { opacity: 0.35; transform: scale(0.78); } | |
| } | |
| .hud__budget-val { | |
| font-variant: tabular-nums; | |
| } | |
| /* JS adds .is-warning at 70% budget; the ledger turns amber. */ | |
| .hud--budget.is-warning { | |
| color: var(--amber); | |
| } | |
| .hud--budget.is-warning .hud__rec { | |
| background: var(--amber); | |
| } | |
| /* Subtitles: narrated words in Fraunces italic, AA-contrast scrim. */ | |
| .subtitles { | |
| position: absolute; | |
| left: 50%; | |
| bottom: 12%; | |
| transform: translateX(-50%); | |
| z-index: 5; | |
| width: min(82%, 46rem); | |
| text-align: center; | |
| font-family: var(--font-display); | |
| font-style: italic; | |
| font-size: clamp(1rem, 2.4vw, 1.6rem); | |
| line-height: 1.4; | |
| color: var(--ink); | |
| /* Layered text-shadow = readable over any frame without a hard box. */ | |
| text-shadow: | |
| 0 2px 10px rgba(0, 0, 0, 0.95), | |
| 0 0 24px rgba(0, 0, 0, 0.8); | |
| opacity: 0; | |
| transition: opacity 0.5s var(--ease); | |
| pointer-events: none; | |
| } | |
| .subtitles.is-visible { | |
| opacity: 1; | |
| } | |
| /* Micro-stage bar: thin amber rail with chips that light up in sequence. */ | |
| .stage-bar { | |
| position: absolute; | |
| left: 50%; | |
| bottom: 3%; | |
| transform: translateX(-50%); | |
| z-index: 5; | |
| display: flex; | |
| gap: 0.4rem; | |
| padding: 0.35rem 0.5rem; | |
| border-radius: var(--r-pill); | |
| background: rgba(0, 0, 0, 0.45); | |
| backdrop-filter: blur(4px); | |
| opacity: 0; | |
| transition: opacity 0.4s var(--ease); | |
| } | |
| .stage-bar.is-active { | |
| opacity: 1; | |
| } | |
| .stage-bar__chip { | |
| font-size: 0.6rem; | |
| letter-spacing: 0.14em; | |
| padding: 0.32em 0.7em; | |
| border-radius: var(--r-pill); | |
| color: var(--ink-faint); | |
| background: transparent; | |
| transition: color 0.3s var(--ease), background 0.3s var(--ease), | |
| box-shadow 0.3s var(--ease); | |
| } | |
| .stage-bar__chip.is-on { | |
| color: var(--bg); | |
| background: var(--amber); | |
| box-shadow: var(--halo-soft); | |
| } | |
| .stage-bar__chip.is-done { | |
| color: var(--amber); | |
| } | |
| /* Bottom control rail. */ | |
| .controls { | |
| display: flex; | |
| flex-wrap: wrap; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 0.55rem; | |
| padding-bottom: env(safe-area-inset-bottom); | |
| } | |
| /* ---------- 6. The Slate (hero clapperboard) ------------------------------ */ | |
| /* On desktop the slate floats over the stage's right edge — a real prop in the | |
| room. Chalk-on-slate body with an amber accent and clapper sticks on top. */ | |
| .slate { | |
| position: absolute; | |
| top: clamp(0.8rem, 4vh, 3rem); | |
| right: clamp(0.8rem, 2vw, 2rem); | |
| z-index: 20; | |
| width: clamp(15rem, 22vw, 18.5rem); | |
| padding: 0.9rem 1.1rem 1.1rem; | |
| border: 1px solid var(--line); | |
| border-radius: var(--r-panel); | |
| /* Slate-stone gradient, warm not blue. */ | |
| background: | |
| linear-gradient(165deg, rgba(34, 32, 30, 0.96), rgba(18, 17, 16, 0.97)); | |
| box-shadow: var(--panel-shadow), inset 0 1px 0 rgba(245, 239, 230, 0.05); | |
| font-size: 0.82rem; | |
| /* Subtle chalk grain. */ | |
| background-blend-mode: normal; | |
| } | |
| .slate__hinge { | |
| position: absolute; | |
| top: -6px; | |
| left: 1.1rem; | |
| right: 1.1rem; | |
| height: 6px; | |
| border-radius: 3px 3px 0 0; | |
| background: linear-gradient(180deg, #3a3631, #211f1c); | |
| } | |
| /* Diagonal clapper sticks — the unmistakable clapperboard silhouette. */ | |
| .slate__sticks { | |
| position: absolute; | |
| top: -6px; | |
| left: 1.1rem; | |
| right: 1.1rem; | |
| height: 1.05rem; | |
| display: flex; | |
| gap: 0; | |
| overflow: hidden; | |
| border-radius: 3px 3px 0 0; | |
| transform-origin: left center; | |
| transition: transform 0.35s var(--ease); | |
| background: repeating-linear-gradient( | |
| -55deg, | |
| var(--ink) 0 0.85rem, | |
| #1b1a18 0.85rem 1.7rem | |
| ); | |
| } | |
| .slate__sticks span { | |
| display: none; | |
| } | |
| /* When the decision flips, JS toggles .is-clapping for a quick snap. */ | |
| .slate.is-clapping .slate__sticks { | |
| animation: clap 0.32s var(--ease); | |
| } | |
| @keyframes clap { | |
| 0% { transform: rotate(-9deg); } | |
| 55% { transform: rotate(2deg); } | |
| 100% { transform: rotate(0deg); } | |
| } | |
| .slate__head { | |
| display: flex; | |
| align-items: baseline; | |
| justify-content: space-between; | |
| margin-top: 0.35rem; | |
| padding-bottom: 0.5rem; | |
| border-bottom: 1px dashed rgba(245, 239, 230, 0.16); | |
| } | |
| .slate__label { | |
| font-size: 0.62rem; | |
| letter-spacing: 0.2em; | |
| color: var(--ink-faint); | |
| } | |
| .slate__shot { | |
| font-family: var(--font-display); | |
| font-weight: 600; | |
| font-size: 0.92rem; | |
| color: var(--amber); | |
| font-variant: tabular-nums; | |
| } | |
| /* The hero decision chip: a flip card. CONTINUITY (amber) <-> CUT (red). */ | |
| .slate__decision { | |
| display: flex; | |
| justify-content: center; | |
| margin: 0.8rem 0; | |
| perspective: 600px; | |
| } | |
| .decision-chip { | |
| position: relative; | |
| display: inline-block; | |
| min-width: 9.5rem; | |
| height: 2.5rem; | |
| transform-style: preserve-3d; | |
| transition: transform 0.45s var(--ease); | |
| } | |
| .decision-chip__face { | |
| position: absolute; | |
| inset: 0; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| border-radius: var(--r-pill); | |
| font-family: var(--font-display); | |
| font-weight: 700; | |
| font-size: 1rem; | |
| letter-spacing: 0.08em; | |
| backface-visibility: hidden; | |
| } | |
| /* Front face = CONTINUITY (amber). */ | |
| .decision-chip__face--front { | |
| color: var(--bg); | |
| background: var(--amber); | |
| box-shadow: 0 0 22px rgba(232, 163, 61, 0.4); | |
| } | |
| /* Back face = CUT (red), pre-rotated so the flip reveals it. */ | |
| .decision-chip__face--back { | |
| color: var(--ink); | |
| background: var(--rec); | |
| box-shadow: 0 0 22px rgba(224, 68, 46, 0.45); | |
| transform: rotateX(180deg); | |
| } | |
| /* JS sets data-decision="cut" to flip to the red CUT face. */ | |
| .decision-chip[data-decision="cut"] { | |
| transform: rotateX(180deg); | |
| } | |
| .slate__grid { | |
| margin: 0; | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 0.5rem 0.7rem; | |
| } | |
| .slate__row { | |
| min-width: 0; | |
| } | |
| .slate__row--wide { | |
| grid-column: 1 / -1; | |
| } | |
| .slate__row dt { | |
| font-size: 0.56rem; | |
| letter-spacing: 0.16em; | |
| color: var(--ink-faint); | |
| margin-bottom: 0.12rem; | |
| } | |
| .slate__row dd { | |
| margin: 0; | |
| font-size: 0.88rem; | |
| color: var(--ink); | |
| /* Camera/scale read as crisp chalk. */ | |
| font-family: var(--font-ui); | |
| font-weight: 500; | |
| overflow-wrap: anywhere; | |
| } | |
| .slate__palette { | |
| display: flex; | |
| gap: 0.4rem; | |
| margin-top: 0.85rem; | |
| } | |
| .swatch { | |
| flex: 1; | |
| height: 1.4rem; | |
| border-radius: 5px; | |
| border: 1px solid rgba(245, 239, 230, 0.12); | |
| background: var(--line); | |
| transition: background 0.5s var(--ease); | |
| } | |
| .slate__translation { | |
| margin: 0.7rem 0 0; | |
| font-size: 0.74rem; | |
| font-style: italic; | |
| color: var(--ink-faint); | |
| } | |
| /* ---------- 7. Theater / Showcase / About --------------------------------- */ | |
| /* Theater: a red curtain that parts (1.2s) to reveal the film. */ | |
| #theater { | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .curtain { | |
| position: absolute; | |
| inset: 0; | |
| z-index: 30; | |
| pointer-events: none; | |
| } | |
| .curtain__half { | |
| position: absolute; | |
| top: 0; | |
| bottom: 0; | |
| width: 52%; | |
| background: | |
| repeating-linear-gradient(90deg, rgba(0,0,0,0.28) 0 14px, transparent 14px 38px), | |
| linear-gradient(180deg, #7d1d16, #4a0f0b); | |
| box-shadow: inset 0 0 60px rgba(0, 0, 0, 0.6); | |
| transition: transform 1.2s var(--ease); | |
| } | |
| .curtain__half--left { | |
| left: 0; | |
| transform-origin: left; | |
| } | |
| .curtain__half--right { | |
| right: 0; | |
| transform-origin: right; | |
| } | |
| /* JS adds .is-open on #theater to part the curtain. */ | |
| #theater.is-open .curtain__half--left { | |
| transform: translateX(-101%); | |
| } | |
| #theater.is-open .curtain__half--right { | |
| transform: translateX(101%); | |
| } | |
| .theater__inner { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 1rem; | |
| width: min(94%, 60rem); | |
| z-index: 5; | |
| } | |
| .theater__screen { | |
| width: 100%; | |
| aspect-ratio: var(--aspect-film); | |
| border-radius: 8px; | |
| background: #000; | |
| box-shadow: var(--halo); | |
| display: grid; | |
| place-items: center; | |
| overflow: hidden; | |
| } | |
| .theater__placeholder { | |
| color: var(--ink-faint); | |
| font-family: var(--font-display); | |
| font-style: italic; | |
| } | |
| .theater__transport { | |
| display: flex; | |
| flex-wrap: wrap; | |
| justify-content: center; | |
| gap: 0.55rem; | |
| } | |
| .theater__note { | |
| margin: 0; | |
| font-size: 0.76rem; | |
| color: var(--ink-faint); | |
| } | |
| /* Showcase: grid of pre-rendered film cards, each visibly stamped. */ | |
| #showcase { | |
| padding: clamp(1.2rem, 3vw, 2.4rem); | |
| overflow-y: auto; | |
| } | |
| .showcase__banner { | |
| margin-bottom: 1.2rem; | |
| padding: 0.9rem 1.2rem; | |
| border: 1px solid rgba(232, 163, 61, 0.4); | |
| border-radius: var(--r-panel); | |
| background: var(--amber-soft); | |
| color: var(--ink); | |
| font-size: 0.92rem; | |
| } | |
| .showcase__head { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| gap: 1rem; | |
| margin-bottom: 1.4rem; | |
| } | |
| .showcase__head .screen__heading { | |
| font-size: clamp(1.6rem, 4vw, 2.4rem); | |
| } | |
| .showcase__grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); | |
| gap: 1.2rem; | |
| } | |
| .film-card { | |
| position: relative; | |
| border: 1px solid var(--line); | |
| border-radius: var(--r-panel); | |
| overflow: hidden; | |
| background: rgba(245, 239, 230, 0.03); | |
| box-shadow: var(--panel-shadow); | |
| transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease); | |
| } | |
| .film-card:hover { | |
| transform: translateY(-3px); | |
| box-shadow: var(--halo); | |
| } | |
| .film-card__thumb { | |
| aspect-ratio: var(--aspect-film); | |
| background: | |
| radial-gradient(80% 120% at 70% 20%, var(--amber-soft), transparent 60%), | |
| linear-gradient(160deg, #161821, #0c0d10); | |
| } | |
| .film-card__stamp { | |
| position: absolute; | |
| top: 0.7rem; | |
| left: 0.7rem; | |
| padding: 0.28em 0.7em; | |
| border: 1px solid rgba(232, 163, 61, 0.6); | |
| border-radius: var(--r-pill); | |
| background: rgba(10, 10, 12, 0.7); | |
| color: var(--amber); | |
| font-size: 0.6rem; | |
| letter-spacing: 0.16em; | |
| transform: rotate(-3deg); | |
| } | |
| .film-card__title { | |
| margin: 0.8rem 1rem 0.2rem; | |
| font-family: var(--font-display); | |
| font-size: 1.2rem; | |
| } | |
| .film-card__src { | |
| margin: 0 1rem 1rem; | |
| font-size: 0.78rem; | |
| color: var(--ink-faint); | |
| } | |
| /* About: a centered overlay panel above a dimmed room. */ | |
| .screen--overlay { | |
| background: rgba(6, 6, 8, 0.78); | |
| backdrop-filter: blur(8px); | |
| z-index: 60; | |
| align-items: center; | |
| justify-content: center; | |
| padding: clamp(1rem, 4vw, 2.5rem); | |
| } | |
| .about__panel { | |
| width: min(94%, 44rem); | |
| max-height: 86dvh; | |
| overflow-y: auto; | |
| padding: clamp(1.2rem, 3vw, 2rem); | |
| border: 1px solid var(--line); | |
| border-radius: var(--r-panel); | |
| background: linear-gradient(165deg, rgba(20, 19, 22, 0.98), rgba(12, 12, 14, 0.98)); | |
| box-shadow: var(--halo); | |
| } | |
| .about__head { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| margin-bottom: 1rem; | |
| } | |
| .about__head .screen__heading { | |
| font-size: clamp(1.6rem, 4vw, 2.2rem); | |
| } | |
| .about__intro { | |
| font-size: 0.92rem; | |
| color: var(--ink-dim); | |
| margin: 0 0 1.2rem; | |
| } | |
| .about__table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| font-size: 0.86rem; | |
| } | |
| .about__table th, | |
| .about__table td { | |
| text-align: left; | |
| padding: 0.5rem 0.6rem; | |
| border-bottom: 1px solid var(--line); | |
| } | |
| .about__table th { | |
| font-size: 0.66rem; | |
| letter-spacing: 0.12em; | |
| text-transform: uppercase; | |
| color: var(--ink-faint); | |
| } | |
| .about__table tfoot td { | |
| border-bottom: none; | |
| color: var(--amber); | |
| font-variant: tabular-nums; | |
| } | |
| .about__engine { | |
| margin: 1.2rem 0 0; | |
| font-size: 0.88rem; | |
| color: var(--ink-dim); | |
| } | |
| /* ---------- 8. Reduced motion --------------------------------------------- */ | |
| /* Triggered by body.reduced-motion (manual toggle) OR prefers-reduced-motion. | |
| Kills the grain shimmer, beam breathing, dust drift, REC pulse, chip flip | |
| animation timing — crossfade-only, static grain. (Parallax k=0 is handled | |
| in the WebGL stage module via the same body class.) */ | |
| body.reduced-motion .fx--grain { | |
| animation: none; | |
| } | |
| body.reduced-motion .beam__cone, | |
| body.reduced-motion .beam__dust, | |
| body.reduced-motion .beam__lamp, | |
| body.reduced-motion .hud__rec { | |
| animation: none; | |
| } | |
| body.reduced-motion .decision-chip, | |
| body.reduced-motion .slate__sticks { | |
| transition-duration: 0.18s; | |
| } | |
| body.reduced-motion .slate.is-clapping .slate__sticks { | |
| animation: none; | |
| } | |
| @media (prefers-reduced-motion: reduce) { | |
| .fx--grain, | |
| .beam__cone, | |
| .beam__dust, | |
| .beam__lamp, | |
| .hud__rec { | |
| animation: none; | |
| } | |
| } | |
| /* ---------- 8b. Responsive / mobile --------------------------------------- */ | |
| @media (max-width: 860px) { | |
| .doors { | |
| grid-template-columns: 1fr; | |
| } | |
| /* Mobile letterbox switches to 16:9. */ | |
| .stage, | |
| .theater__screen, | |
| .film-card__thumb { | |
| --aspect-film: var(--aspect-film-mobile); | |
| } | |
| .stage { | |
| width: 100%; | |
| max-height: calc(100dvh - 12rem); | |
| } | |
| /* The slate becomes a bottom sheet docked under the stage. */ | |
| #set { | |
| grid-template-rows: 1fr auto auto; | |
| } | |
| .slate { | |
| position: static; | |
| width: 100%; | |
| order: 2; | |
| border-radius: var(--r-panel) var(--r-panel) 0 0; | |
| /* Sheet handle look. */ | |
| border-bottom: none; | |
| } | |
| .slate__decision { | |
| margin: 0.6rem 0; | |
| } | |
| .controls { | |
| order: 3; | |
| } | |
| .subtitles { | |
| bottom: 16%; | |
| font-size: 1.05rem; | |
| } | |
| .hud { | |
| font-size: 0.62rem; | |
| letter-spacing: 0.1em; | |
| } | |
| .lobby__foot { | |
| justify-content: center; | |
| text-align: center; | |
| } | |
| } | |
| /* Very narrow phones: tighten the control rail so it never wraps awkwardly. */ | |
| @media (max-width: 480px) { | |
| .controls .pill span:not(.pill__icon):not(.pill__flag):not(.pill__lang) { | |
| display: none; /* icon-only controls; lang pill keeps its label */ | |
| } | |
| .pill--rec span:not(.pill__icon) { | |
| display: inline; /* keep the primary CTA labeled */ | |
| } | |
| } | |