diff --git a/Aetheria/Stories/Corvid Collective First Exodus.md b/Aetheria/Stories/Corvid Collective First Exodus.md new file mode 100644 index 0000000..f0a084b --- /dev/null +++ b/Aetheria/Stories/Corvid Collective First Exodus.md @@ -0,0 +1,26 @@ +--- +title: "Corvid Collective: First Exodus" +description: "A playable Ghostlight branch-and-fold founding scene for the Corvid Collective: an uplifted raven turns containment routines, human guilt, and bad telemetry into the first crack in the cage." +--- + +# Corvid Collective: First Exodus + +_A playable Ghostlight branch-and-fold scene._ + +You are Kesh-of-Three-Clicks, an uplifted raven reconnaissance asset inside NeuroSyn's Blackbox Aviary 3C. Two hours before a Rossum & Douglas audit, the room still looks ordinary: perch ladders, welfare logs, a bad hatch, a tray of wing tags, a handler pretending the language of care still belongs to her. + +That is the useful thing about ordinary cruelty. It has handles. + +This is a Ghostlight fixture built for illustrated interactive replay: short sections, branching choices, visible consequences, and state variables that keep score while everyone pretends the cage is just a workplace with feathers in it. + +
+ +## Source Note + +This scene is grounded in [[Worldbuilding/Pre-Elysium/Factions/Powers/Minor/Corvid Collective|Corvid Collective]], [[Worldbuilding/Pre-Elysium/Factions/Powers/Minor/NeuroSyn|NeuroSyn]], [[Worldbuilding/Pre-Elysium/Factions/Powers/Minor/Rossum & Douglas|Rossum & Douglas]], and late-Sol uplift politics. Some room-scale containment and raven-interface details remain Ghostlight draft elaboration until backfilled into the lore vault. diff --git a/Aetheria/Stories/index.md b/Aetheria/Stories/index.md index 7ec3e59..44c7077 100644 --- a/Aetheria/Stories/index.md +++ b/Aetheria/Stories/index.md @@ -13,6 +13,7 @@ Some of the pieces gathered here were written before the current canon settled i ## Current Stories +- [[Corvid Collective First Exodus]] - [[Lucent Hostage Feed]] - [[Rain]] - [[When We Get Home]] diff --git a/Aetheria/static/interactive/aetheria-ink-player.js b/Aetheria/static/interactive/aetheria-ink-player.js index e35b42d..0995cb4 100644 --- a/Aetheria/static/interactive/aetheria-ink-player.js +++ b/Aetheria/static/interactive/aetheria-ink-player.js @@ -69,6 +69,82 @@ } } + async function loadVisualManifest(container) { + const manifestSrc = container.dataset.visualManifest + if (!manifestSrc) return null + + const response = await fetch(manifestSrc) + if (!response.ok) { + throw new Error(`could not fetch ${manifestSrc}: ${response.status}`) + } + + return response.json() + } + + function resolveSlideUrl(manifest, slide) { + if (!manifest || !slide) return "" + const base = manifest.image_base || "" + return `${base}${slide.image || ""}` + } + + function createCinematicStage() { + const stage = createElement("div", "aetheria-ink-cinematic-stage") + const visual = createElement("div", "aetheria-ink-visual") + const plateA = createElement("div", "aetheria-ink-visual-plate is-active") + const plateB = createElement("div", "aetheria-ink-visual-plate") + const scrim = createElement("div", "aetheria-ink-visual-scrim") + const caption = createElement("p", "aetheria-ink-visual-caption") + const section = createElement("div", "aetheria-ink-section") + const sectionText = createElement("div", "aetheria-ink-section-text") + + visual.append(plateA, plateB, scrim, caption) + section.append(sectionText) + stage.append(visual, section) + + return { + stage, + plateA, + plateB, + caption, + sectionText, + activePlate: plateA, + inactivePlate: plateB, + slideIndex: -1, + } + } + + function setCinematicSlide(stageState, manifest, index) { + if (!stageState || !manifest || !Array.isArray(manifest.slides) || manifest.slides.length === 0) { + return + } + + const clamped = Math.min(Math.max(index, 0), manifest.slides.length - 1) + if (stageState.slideIndex === clamped) return + + const slide = manifest.slides[clamped] + const nextPlate = stageState.inactivePlate + nextPlate.style.backgroundImage = `url("${resolveSlideUrl(manifest, slide)}")` + nextPlate.classList.add("is-active") + stageState.activePlate.classList.remove("is-active") + + const previous = stageState.activePlate + stageState.activePlate = nextPlate + stageState.inactivePlate = previous + stageState.slideIndex = clamped + stageState.caption.textContent = slide.caption || manifest.default_caption || "" + } + + function renderCinematicText(stageState, text) { + stageState.sectionText.replaceChildren() + const paragraph = createElement("p", "aetheria-ink-line", text) + stageState.sectionText.append(paragraph) + + stageState.sectionText.classList.remove("is-entering") + // Force a reflow so repeated sections replay the transition. + void stageState.sectionText.offsetWidth + stageState.sectionText.classList.add("is-entering") + } + function appendParagraphs(story, transcript) { let advanced = false let safety = 0 @@ -118,6 +194,50 @@ }) } + function renderCinematicStep(story, state) { + const { choices, variables, stageState, manifest, continueButton } = state + + choices.replaceChildren() + continueButton.hidden = true + + if (story.canContinue) { + const text = story.Continue().trim() + if (text.length > 0) { + setCinematicSlide(stageState, manifest, stageState.slideIndex + 1) + renderCinematicText(stageState, text) + stageState.stage.scrollIntoView({ behavior: "smooth", block: "center" }) + } + renderVariables(story, variables) + + if (story.canContinue) { + continueButton.hidden = false + continueButton.textContent = "Continue" + return + } + } + + renderVariables(story, variables) + + if (story.currentChoices.length === 0) { + choices.append(createElement("p", "aetheria-ink-end", "End of branch. The cage pretends it was always empty.")) + return + } + + story.currentChoices.forEach((choice, index) => { + const button = createElement("button", "aetheria-ink-choice", choice.text) + button.type = "button" + button.addEventListener("click", () => { + stageState.sectionText.classList.add("is-exiting") + window.setTimeout(() => { + story.ChooseChoiceIndex(index) + stageState.sectionText.classList.remove("is-exiting") + renderCinematicStep(story, state) + }, 180) + }) + choices.append(button) + }) + } + async function initialisePlayer(container) { if (container.dataset.inkInitialised === "true") return container.dataset.inkInitialised = "true" @@ -129,16 +249,29 @@ } const status = createElement("p", "aetheria-ink-status", "Loading story...") - const transcript = createElement("div", "aetheria-ink-transcript") + const isCinematic = container.dataset.inkMode === "cinematic" + const showVariables = !isCinematic || container.dataset.showVariables === "true" + const transcript = isCinematic ? null : createElement("div", "aetheria-ink-transcript") + const stageState = isCinematic ? createCinematicStage() : null const choices = createElement("div", "aetheria-ink-choices") const variables = createElement("div", "aetheria-ink-variables") + const continueButton = createElement("button", "aetheria-ink-continue", "Continue") const restart = createElement("button", "aetheria-ink-restart", "Restart") + continueButton.type = "button" + continueButton.hidden = true restart.type = "button" - container.replaceChildren(status, transcript, choices, variables, restart) + if (isCinematic) { + container.classList.add("aetheria-ink-player-cinematic") + variables.hidden = !showVariables + container.replaceChildren(status, stageState.stage, choices, variables, continueButton, restart) + } else { + container.replaceChildren(status, transcript, choices, variables, restart) + } try { await ensureInkRuntime() + const visualManifest = await loadVisualManifest(container) const response = await fetch(storySrc) if (!response.ok) { @@ -150,17 +283,46 @@ function reset() { const story = new window.inkjs.Story(JSON.stringify(storyJson)) status.textContent = container.dataset.inkTitle || "Interactive story" - transcript.replaceChildren() - appendParagraphs(story, transcript) - renderVariables(story, variables) - renderChoices(story, choices, variables) + choices.replaceChildren() + variables.replaceChildren() + if (isCinematic) { + stageState.slideIndex = -1 + stageState.caption.textContent = "" + stageState.sectionText.replaceChildren() + continueButton.onclick = () => { + stageState.sectionText.classList.add("is-exiting") + window.setTimeout(() => { + stageState.sectionText.classList.remove("is-exiting") + renderCinematicStep(story, { + choices, + variables, + stageState, + manifest: visualManifest, + continueButton, + }) + }, 180) + } + renderCinematicStep(story, { + choices, + variables, + stageState, + manifest: visualManifest, + continueButton, + }) + } else { + transcript.replaceChildren() + appendParagraphs(story, transcript) + renderVariables(story, variables) + renderChoices(story, choices, variables) + } } restart.addEventListener("click", reset) reset() } catch (error) { status.textContent = "Ink player failed to load." - transcript.append(createElement("p", "aetheria-ink-error", error.message || String(error))) + const errorTarget = transcript || (stageState && stageState.sectionText) + errorTarget.append(createElement("p", "aetheria-ink-error", error.message || String(error))) } } diff --git a/Aetheria/static/interactive/corvid-collective-founding.branch-and-fold.v0.json b/Aetheria/static/interactive/corvid-collective-founding.branch-and-fold.v0.json new file mode 100644 index 0000000..6f557d5 --- /dev/null +++ b/Aetheria/static/interactive/corvid-collective-founding.branch-and-fold.v0.json @@ -0,0 +1 @@ +{"inkVersion":21,"root":[[{"->":"start"},["done",{"#n":"g-0"}],null],"done",{"start":["^Blackbox Aviary 3C is warm in the places NeuroSyn forgets to bill as mercy. The aviary holds Corvid Recon assets being prepared for a Rossum & Douglas security deployment, which means every kindness in the room already has three owners and a liability code.","\n","^Server vents breathe along the high wall. Perch ladders cross the telemetry glass in cheap aluminum ribs. Mirror-check toys hang where the humans can pretend enrichment is not a word they use to make cages sound literate.","\n",{"->":"intro_human_levers"},null],"intro_human_levers":["^Two hours before audit, Dr. Maela Voss calls the recon-log pruning cycle ordinary. She is the handler-scientist, which means she owns the welfare vocabulary and fears the welfare logs.","\n","^Rian Pell checks maintenance hatch 3C and does not notice that it only seals after he kicks it twice. He is the low-status human who touches the physical doors after cleaner people have finished naming them secure. One. Two. The habit lands in Kesh-of-Three-Clicks like a route map.","\n","^Kesh is an uplifted raven, black-eyed and tagged, built to watch for NeuroSyn and old enough now to watch NeuroSyn back.","\n",{"->":"intro_containment_and_audit"},null],"intro_containment_and_audit":["^Sable Or, the containment lead, checks the shock wand charge beside a tray of extra wing tags for the juveniles. She is the person who turns fear into custody. Promotion smell. Clean audit smell. Metal and fear.","\n","^Jun Vale waits beyond audit vestibule glass with an airgapped slate, young enough to believe a record can still bite its owner. She is not rescue; she is a camera with procurement authority.","\n","^The watching flock hangs from rails and perches and camera housings, pretending to be test equipment with opinions.","\n",{"->":"intro_kesh_interface"},null],"intro_kesh_interface":["^Kesh turns one black eye to the local telemetry buffer cabinet. Authorized recon interface. Narrow pipe. Enough if used like a beak in a lock.","\n","^No exodus yet. First, one lever.","\n",{"->":"pre_audit_hub"},null],"pre_audit_hub":[["ev","str","^Cache connector pins and mirror foil near hatch 3C, then call low from the warm vent.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Mimic Voss near Rian and Sable: audit phrasing, clean concern, three clicks toward the buffer cabinet.","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^Angle reflective foil and live-feed sightlines toward Jun's slate during the welfare-log display.","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^Report clean telemetry, preserve hatch 3C, and draw attention away from the spare wing-tag clasp tray.","/str","/ev",{"*":".^.c-3","flg":4},{"c-0":["\n","ev",{"VAR?":"flock_cohesion"},2,"+","/ev",{"VAR=":"flock_cohesion","re":true},"ev",{"VAR?":"nest_cache_integrity"},1,"+","/ev",{"VAR=":"nest_cache_integrity","re":true},"ev",{"VAR?":"rian_trust"},1,"+","/ev",{"VAR=":"rian_trust","re":true},"ev",{"VAR?":"human_suspicion"},1,"+","/ev",{"VAR=":"human_suspicion","re":true},"ev",{"VAR?":"escape_window"},1,"+","/ev",{"VAR=":"escape_window","re":true},"ev",2,"/ev",{"VAR=":"hatch_3c_state","re":true},"^Kesh hops down in three ugly, efficient drops. Talon. Tray edge. Cable shadow.","\n","^A connector pin pins briefly against the lower beak, then drops into Kesh's claw. Mirror foil folds bright against the beak, then vanishes behind a warm vent lip near hatch 3C.","\n","^The call is almost nothing. A throat-click under fan noise. The wing-tagged juveniles stop worrying the tray and look up.","\n","^Rian smiles before he remembers cameras exist.","\n","^Sable looks at the flock as if equipment has begun having a meeting.","\n",{"->":"ordinary_life_fold"},null],"c-1":["\n","ev",{"VAR?":"voss_leverage"},2,"+","/ev",{"VAR=":"voss_leverage","re":true},"ev",{"VAR?":"sable_pressure"},1,"+","/ev",{"VAR=":"sable_pressure","re":true},"ev",{"VAR?":"human_suspicion"},1,"+","/ev",{"VAR=":"human_suspicion","re":true},"ev",{"VAR?":"audit_pressure"},1,"+","/ev",{"VAR=":"audit_pressure","re":true},"ev",{"VAR?":"telemetry_control"},1,"+","/ev",{"VAR=":"telemetry_control","re":true},"^Kesh opens the throat around stolen consonants.","\n","^Compliance welfare logs reflect normal pruning tolerance.","\n","^It comes out sharp, wrong, and recognizable. Then three clicks. Tap. Tap. Tap. Toward the local buffer cabinet.","\n","^Rian goes still.","\n","^Voss, across the glass, hears her own lie walking around in a raven body.","\n","^Sable hears a liability sprout feathers.","\n",{"->":"ordinary_life_fold"},null],"c-2":["\n","ev",{"VAR?":"jun_proof"},2,"+","/ev",{"VAR=":"jun_proof","re":true},"ev",{"VAR?":"audit_pressure"},2,"+","/ev",{"VAR=":"audit_pressure","re":true},"ev",{"VAR?":"human_suspicion"},1,"+","/ev",{"VAR=":"human_suspicion","re":true},"ev",{"VAR?":"telemetry_control"},1,"-","/ev",{"VAR=":"telemetry_control","re":true},"ev",{"VAR?":"chaos_weaver_seed"},1,"+","/ev",{"VAR=":"chaos_weaver_seed","re":true},"^Mirror foil is not a mirror if you are patient. It is a knife that only cuts sight.","\n","^Kesh drags the bright scrap along the perch ladder until the welfare-log display reflects through telemetry glass and into Jun Vale's waiting slate.","\n","^For one second, the slate sees two things: clean numbers and a juvenile raven flinching away from Sable's tag tray.","\n","^Jun's thumb stops moving.","\n","^The buffer cabinet pings a dropped frame. Subtle as a brick in a prayer bowl.","\n",{"->":"ordinary_life_fold"},null],"c-3":["\n","ev",{"VAR?":"telemetry_control"},2,"+","/ev",{"VAR=":"telemetry_control","re":true},"ev",{"VAR?":"escape_window"},2,"+","/ev",{"VAR=":"escape_window","re":true},"ev",{"VAR?":"human_suspicion"},1,"-","/ev",{"VAR=":"human_suspicion","re":true},"ev",{"VAR?":"flock_cohesion"},1,"-","/ev",{"VAR=":"flock_cohesion","re":true},"ev",{"VAR?":"sable_pressure"},1,"-","/ev",{"VAR=":"sable_pressure","re":true},"^Kesh feeds the system the shape it wants: normal perch load, normal blink rate, normal pruning tolerance.","\n","^The hatch remains bad. The humans remain confident. The spare wing-tag clasp tray becomes visually boring in every camera that matters.","\n","^The flock notices the quiet.","\n","^Quiet can mean safety. Quiet can mean you have already left.","\n",{"->":"ordinary_life_fold"},null]}],null],"ordinary_life_fold":["^The cycle begins with ordinary humiliations.","\n","^Voss reads from the welfare checklist. Rian pretends not to slip another discarded connector pin near Kesh's perch. Sable counts bodies against tags. Jun watches through glass that makes concern look like trespass.","\n","ev",{"VAR?":"flock_cohesion"},4,">=","/ev",[{"->":".^.b","c":true},{"b":["^ The flock holds together in small timings: one juvenile shifts only after an elder shifts, wing tags hidden by the living black geometry of bodies.",{"->":".^.^.^.10"},null]}],"nop","\n","ev",{"VAR?":"flock_cohesion"},1,"<=","/ev",[{"->":".^.b","c":true},{"b":["^ The flock has read Kesh's quiet as distance. Perches sit a feather too far apart. Nobody wastes panic where it cannot be spent.",{"->":".^.^.^.18"},null]}],"nop","\n","ev",{"VAR?":"voss_leverage"},4,">=","/ev",[{"->":".^.b","c":true},{"b":["^ Voss keeps glancing at the buffer cabinet. Her fear has become a second handler in the room.",{"->":".^.^.^.26"},null]}],"nop","\n","ev",{"VAR?":"jun_proof"},2,">=","/ev",[{"->":".^.b","c":true},{"b":["^ Jun's slate is angled wrong for compliance theater and right for evidence.",{"->":".^.^.^.34"},null]}],"nop","\n","ev",{"VAR?":"telemetry_control"},4,">=","/ev",[{"->":".^.b","c":true},{"b":["^ The live feed is smooth enough to make reality feel underdressed.",{"->":".^.^.^.42"},null]}],"nop","\n","ev",{"VAR?":"human_suspicion"},3,">=","/ev",[{"->":".^.b","c":true},{"b":["^ Sable's eyes start moving like a checklist with teeth.",{"->":".^.^.^.50"},null]}],"nop","\n",{"->":"rupture_cycle"},null],"rupture_cycle":["^Then the recon-log pruning cycle does what NeuroSyn built it to do: it tries to file distress as cleaner telemetry.","\n","^The juvenile with the green interface wing tag screams once when the calibration pulse climbs through the attached restraint clasp. Not speech. Not test noise. Body truth.","\n","^The telemetry glass flashes amber. Audit vestibule locks. Hatch 3C waits in its old, stupid way.","\n",{"->":"rupture_choice"},null],"rupture_choice":[["ev","str","^Seed the flock call: short, low, route-memory first.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Tap the telemetry contact pad and make the amber alarm argue with itself.","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^Tear mirror foil from the nearest mirror-check toy and show Jun the green-tagged juvenile.","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^Wait on the high perch until Rian moves toward hatch 3C.","/str","/ev",{"*":".^.c-3","flg":4},{"c-0":["\n","ev",{"VAR?":"flock_cohesion"},1,"+","/ev",{"VAR=":"flock_cohesion","re":true},"ev",{"VAR?":"human_suspicion"},1,"+","/ev",{"VAR=":"human_suspicion","re":true},"^The call moves under the alarm, not over it.","\n","^Three clicks. Vent. Hatch. Glass-shadow. Juveniles tucked between bodies with better scars.","\n","^The watching flock stops pretending to be equipment.","\n",{"->":"human_pressure"},null],"c-1":["\n","ev",{"VAR?":"telemetry_control"},1,"+","/ev",{"VAR=":"telemetry_control","re":true},"ev",{"VAR?":"audit_pressure"},1,"+","/ev",{"VAR=":"audit_pressure","re":true},"^Kesh lands hard on the contact pad. Talons bridge the authorized recon interface. The neural link opens like a bad window.","\n","^Pruning fault becomes sensor calibration drift. Juvenile distress becomes intermittent audio artifact.","\n","^The lie is clean. The body in the room is not.","\n",{"->":"human_pressure"},null],"c-2":["\n","ev",{"VAR?":"jun_proof"},1,"+","/ev",{"VAR=":"jun_proof","re":true},"ev",{"VAR?":"audit_pressure"},1,"+","/ev",{"VAR=":"audit_pressure","re":true},"ev",{"VAR?":"escape_window"},1,"-","/ev",{"VAR=":"escape_window","re":true},"^Kesh tears foil from the nearest mirror-check toy, grips it in the beak, and flies the short line to the vestibule frame.","\n","^Jun sees the juvenile through reflected glass and live room, two angles stapled together by panic.","\n","^Sable sees the bird making an audience.","\n",{"->":"human_pressure"},null],"c-3":["\n","ev",{"VAR?":"escape_window"},1,"+","/ev",{"VAR=":"escape_window","re":true},"ev",{"VAR?":"rian_trust"},1,"+","/ev",{"VAR=":"rian_trust","re":true},"ev",{"VAR?":"flock_cohesion"},1,"-","/ev",{"VAR=":"flock_cohesion","re":true},"ev",2,"/ev",{"VAR=":"hatch_3c_state","re":true},"^Kesh does nothing.","\n","^It is a cruel tool because it looks like obedience.","\n","^Rian swears, crosses to hatch 3C, and kicks it once before thinking.","\n",{"->":"human_pressure"},null]}],null],"human_pressure":["^Sable steps onto the handler walkway. One hand near the shock wand. One hand on the tag tray.","\n","^Voss says, \"Everybody hold position.\"","\n","^Rian says, \"They are not holding, Doctor. They are birds.\"","\n","^Jun's voice comes through the vestibule speaker, thin but present. \"I need optical proof before this slate seals.\"","\n","ev",{"VAR?":"voss_leverage"},4,">=","/ev",[{"->":".^.b","c":true},{"b":["^ Voss hears the word proof and looks as if the room has remembered her signature.",{"->":".^.^.^.14"},null]}],"nop","\n","ev",{"VAR?":"sable_pressure"},2,">=","/ev",[{"->":".^.b","c":true},{"b":["^ Sable's promotion is now visibly sweating through the collar.",{"->":".^.^.^.22"},null]}],"nop","\n","ev",{"VAR?":"rian_trust"},3,">=","/ev",[{"->":".^.b","c":true},{"b":["^ Rian does not look at Kesh directly. That is how humans become useful without becoming brave.",{"->":".^.^.^.30"},null]}],"nop","\n",{"->":"pressure_choice"},null],"pressure_choice":[["ev","str","^Mimic Voss's exact audit sentence, angle beak and body toward the buffer cabinet, and give three clicks.","/str",{"VAR?":"voss_leverage"},4,">=","/ev",{"*":".^.c-0","flg":5},"ev","str","^Drop a connector pin at Rian's boot, then look from his foot to hatch 3C.","/str",{"VAR?":"rian_trust"},3,">=","/ev",{"*":".^.c-1","flg":5},"ev","str","^Hold the sightline for Jun even while Sable reaches for the shock wand.","/str",{"VAR?":"jun_proof"},2,">=","/ev",{"*":".^.c-2","flg":5},"ev","str","^Scatter the tag tray with beak and talon.","/str","/ev",{"*":".^.c-3","flg":4},{"c-0":["\n","ev",{"VAR?":"voss_leverage"},2,"-","/ev",{"VAR=":"voss_leverage","re":true},"ev",{"VAR?":"sable_pressure"},1,"+","/ev",{"VAR=":"sable_pressure","re":true},"ev",{"VAR?":"telemetry_control"},1,"+","/ev",{"VAR=":"telemetry_control","re":true},"ev",{"VAR?":"human_suspicion"},1,"+","/ev",{"VAR=":"human_suspicion","re":true},"^Compliance welfare logs reflect normal pruning tolerance.","\n","^Kesh mangles the music but not the meaning.","\n","^Voss flinches. Sable turns on her. Rian gets one clean breath in which no one is watching his boot.","\n","^Leverage is a string. Pull too hard and the hand attached to it starts looking for scissors.","\n",{"->":"hatch_and_slate"},null],"c-1":["\n","ev",{"VAR?":"rian_trust"},1,"-","/ev",{"VAR=":"rian_trust","re":true},"ev",{"VAR?":"escape_window"},1,"+","/ev",{"VAR=":"escape_window","re":true},"ev",{"VAR?":"human_suspicion"},1,"+","/ev",{"VAR=":"human_suspicion","re":true},"ev",3,"/ev",{"VAR=":"hatch_3c_state","re":true},"^The pin rings once on the walkway.","\n","^Rian looks down. Kesh looks at his boot. Hatch 3C sits there, needing exactly the kind of maintenance corporate dignity cannot survive.","\n","^Rian kicks it twice.","\n","^The second kick is almost tender. The seal light lies green.","\n",{"->":"hatch_and_slate"},null],"c-2":["\n","ev",{"VAR?":"jun_proof"},1,"+","/ev",{"VAR=":"jun_proof","re":true},"ev",{"VAR?":"escape_window"},1,"-","/ev",{"VAR=":"escape_window","re":true},"ev",{"VAR?":"audit_pressure"},1,"+","/ev",{"VAR=":"audit_pressure","re":true},"^Kesh plants both talons on the perch ladder and spreads wings wide enough to frame the juvenile behind him.","\n","^Sable raises the wand.","\n","^Jun says, \"Recording. Chain sealed.\"","\n","^Proof is not rescue. It is a door that opens elsewhere, later, for someone with hands.","\n",{"->":"hatch_and_slate"},null],"c-3":["\n","ev",{"VAR?":"flock_cohesion"},1,"+","/ev",{"VAR=":"flock_cohesion","re":true},"ev",{"VAR?":"human_suspicion"},2,"+","/ev",{"VAR=":"human_suspicion","re":true},"ev",{"VAR?":"sable_pressure"},1,"+","/ev",{"VAR=":"sable_pressure","re":true},"^Kesh dives.","\n","^The beak hits plastic. Talons rake labels, clips, bright little ownership teeth. Tags clatter under equipment racks.","\n","^The juveniles understand before the humans do.","\n","^Sable understands after, which is when dangerous people become simpler.","\n",{"->":"hatch_and_slate"},null]}],null],"hatch_and_slate":["^The rupture has a shape now.","\n","ev",{"VAR?":"hatch_3c_state"},3,">=","/ev",[{"->":".^.b","c":true},{"b":["\n","^Hatch 3C is not open. It is pinned into a false-green promise by boot habit, bad maintenance, and a small conductive bribe in the seam.","\n",{"->":".^.^.^.9"},null]}],[{"->":".^.b"},{"b":["\n","ev",{"VAR?":"hatch_3c_state"},2,"==","/ev",[{"->":".^.b","c":true},{"b":["\n","^Hatch 3C is not open. Not closed either. A bad promise in a wall, with just enough wrongness near the latch to matter.","\n",{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["\n","^Hatch 3C remains mostly closed: faulty enough to tempt a plan, narrow enough to kill one if the room moves fast.","\n",{"->":".^.^.^.8"},null]}],"nop","\n",{"->":".^.^.^.9"},null]}],"nop","\n","^The local telemetry buffer is hot. Jun's slate is hungry. The flock is either a body or a scatter of bodies depending on what Kesh has spent.","\n","ev",{"VAR?":"audit_pressure"},4,">=","/ev",[{"->":".^.b","c":true},{"b":["^ The audit clock accelerates; outside glass, Jun has stopped pretending this is a routine inspection.",{"->":".^.^.^.19"},null]}],"nop","\n","ev",{"VAR?":"audit_pressure"},2,"<=","/ev",[{"->":".^.b","c":true},{"b":["^ The audit still thinks it is paperwork. That is useful, and insulting.",{"->":".^.^.^.27"},null]}],"nop","\n","ev",{"VAR?":"human_suspicion"},4,">=","/ev",[{"->":".^.b","c":true},{"b":["^ Sable stops counting tags and starts counting exits.",{"->":".^.^.^.35"},null]}],"nop","\n","ev",{"VAR?":"nest_cache_integrity"},3,">=","/ev",[{"->":".^.b","c":true},{"b":["^ The cached foil and pins wait near the hatch, small tools with no romance about them.",{"->":".^.^.^.43"},null]}],"nop","\n","ev",{"VAR?":"nest_cache_integrity"},1,"<=","/ev",[{"->":".^.b","c":true},{"b":["^ The cache is thin. Cleverness has less to bite with.",{"->":".^.^.^.51"},null]}],"nop","\n","ev",{"VAR?":"escape_window"},3,">=","/ev",[{"->":".^.b","c":true},{"b":["^ The hatch timing yawns wide enough for more than one body.",{"->":".^.^.^.59"},null]}],"nop","\n","ev",{"VAR?":"escape_window"},1,"<=","/ev",[{"->":".^.b","c":true},{"b":["^ The window narrows. Every second has teeth now.",{"->":".^.^.^.67"},null]}],"nop","\n","^Kesh has to choose what cost the flock can survive: missing bodies, burned leverage, public proof, or a cleaner disappearance.","\n",{"->":"final_choice"},null],"final_choice":[["ev","str","^Move the juveniles first, even if proof and leverage burn behind you.","/str","/ev",{"*":".^.c-0","flg":4},"ev","str","^Pull Voss and Sable against each other until the human machine opens a crack.","/str","/ev",{"*":".^.c-1","flg":4},"ev","str","^Spend the escape window to make Jun's slate undeniable.","/str","/ev",{"*":".^.c-2","flg":4},"ev","str","^Withhold the spectacle. Keep telemetry clean and vanish through the bad hatch.","/str","/ev",{"*":".^.c-3","flg":4},{"c-0":["\n","ev",{"VAR?":"flock_cohesion"},4,">=",{"VAR?":"escape_window"},2,">=","&&","/ev",[{"->":".^.b","c":true},{"b":["\n","^Kesh gives the low route call and the flock becomes logistics. Elders shield juveniles. Wing-tagged bodies slip under warm vent shadow. Cached pins jam the hatch sensor just long enough.","\n",{"->":"ending_flock_foundation"},{"->":".^.^.^.12"},null]}],[{"->":".^.b"},{"b":["\n","^Kesh calls for the juveniles. Some answer fast. Some hesitate because fear has been trained into them with gloves and lights.","\n",{"->":"ending_flock_cost"},{"->":".^.^.^.12"},null]}],"nop","\n",null],"c-1":["\n","ev",{"VAR?":"voss_leverage"},2,">=",{"VAR?":"sable_pressure"},2,">=","&&","/ev",[{"->":".^.b","c":true},{"b":["\n","^Kesh clicks at the buffer, mimics Voss, then nudges the local feed until Sable's scattered tag order appears mislabeled inside the audit overlay.","\n","^Voss protects herself. Sable protects her promotion. Between them, neither protects the door.","\n",{"->":"ending_leverage_foundation"},{"->":".^.^.^.12"},null]}],[{"->":".^.b"},{"b":["\n","^Kesh pulls the string, but there is not enough knot left in it. Voss freezes. Sable acts.","\n",{"->":"ending_leverage_cost"},{"->":".^.^.^.12"},null]}],"nop","\n",null],"c-2":["\n","ev",{"VAR?":"jun_proof"},3,">=","/ev",[{"->":".^.b","c":true},{"b":["\n","^Kesh holds the line until the slate catches wing tags, shock wand, falsified welfare display, and the hatch vulnerability in one ugly chain.","\n","^Jun whispers, \"Got you.\"","\n",{"->":"ending_proof_foundation"},{"->":".^.^.^.8"},null]}],[{"->":".^.b"},{"b":["\n","^Kesh shows what can be shown, but the slate has fragments where a blade should be.","\n",{"->":"ending_proof_cost"},{"->":".^.^.^.8"},null]}],"nop","\n",null],"c-3":["\n","ev",{"VAR?":"telemetry_control"},4,">=",{"VAR?":"escape_window"},3,">=","&&","/ev",[{"->":".^.b","c":true},{"b":["\n","^Kesh leaves the system a beautiful corpse of normal data.","\n","^Hatch 3C accepts the lie, the boot habit, and the little conductive bribe in its seam.","\n",{"->":"ending_disappearance_foundation"},{"->":".^.^.^.12"},null]}],[{"->":".^.b"},{"b":["\n","^Kesh tries to disappear cleanly, but clean is expensive and the room is already bleeding evidence.","\n",{"->":"ending_disappearance_cost"},{"->":".^.^.^.12"},null]}],"nop","\n",null]}],null],"ending_flock_foundation":["^The first escape is not a speech. It is traffic management.","\n","^Juveniles through. Elders through. Kesh last, because organizers who leave first become stories nobody trusts.","\n","^Behind them, Jun has only partial proof. Voss keeps some lies. Sable keeps enough authority to make pursuit expensive.","\n","^But in the warm duct beyond hatch 3C, the flock arrives as flock. Not assets. Not inventory. A parliament before the word exists.","\n","^Kesh clicks three times into the dark.","\n","^The dark answers in many throats.","\n","end",null],"ending_flock_cost":["^The juveniles move, but not as one.","\n","^One wing tag catches. One elder doubles back.","\n","ev",{"VAR?":"nest_cache_integrity"},3,">=","/ev",[{"->":".^.b","c":true},{"b":["^ Kesh spends the cached foil to blind a camera instead of saving it for the hatch.",{"->":".^.^.^.10"},null]}],"nop","\n","ev",{"VAR?":"nest_cache_integrity"},3,"<","/ev",[{"->":".^.b","c":true},{"b":["^ Kesh tears foil from a mirror-check toy and spends it to blind a camera, because even bad enrichment can become a tool when it stops pretending to be kindness.",{"->":".^.^.^.18"},null]}],"nop","\n","^They get bodies out. Not all. Never the clean version, then. Fine. Clean versions are usually written by the people who owned the room.","\n","^The survivors learn the first rule in the duct: count the missing before naming the victory.","\n","end",null],"ending_leverage_foundation":["^Voss says, \"Sable, stand down.\"","\n","^Sable says, \"Doctor, your logs are under audit.\"","\n","^Rian kicks hatch 3C twice while hierarchy eats its own tail.","\n","^Kesh does not trust the humans. Trust is too large a cage. But a frightened scientist, a cornered security lead, and a lonely maintenance tech can become handles on the same bad door.","\n","^Later, escaped ravens will keep human Chaos Weavers useful and outside the inner circles: people who carry rumors, spoof records, open doors, and then find the nest has moved without telling them where. The principle begins here, in miniature, with a boot, a lie, and a raven refusing to confuse leverage with friendship.","\n","end",null],"ending_leverage_cost":["^Kesh speaks with Voss's voice.","\n","^For one bright second, everyone hears the right guilt.","\n","^Then Sable stops negotiating with people and starts managing animals. The shock wand cracks against the perch ladder. Rian moves too late. Voss saves the logs before the bodies.","\n","^The hatch opens for fewer than planned.","\n","^In the duct, Kesh carries the lesson like a stolen pin: humans can be handles, but handles break under owners' hands.","\n","end",null],"ending_proof_foundation":["^Jun's slate seals the chain.","\n","^Green interface wing tag. Shock wand. Welfare display. Voss's falsified calm. Sable's spare wing-tag clasps. ","ev",{"VAR?":"hatch_3c_state"},3,">=","/ev",[{"->":".^.b","c":true},{"b":["^ Rian's two kicks on hatch 3C.",{"->":".^.^.^.9"},null]}],"nop","ev",{"VAR?":"hatch_3c_state"},3,"<","/ev",[{"->":".^.b","c":true},{"b":["^ The bad hatch seam where a maintenance route should have been boring.",{"->":".^.^.^.16"},null]}],"nop","\n","^The escape is messier for it. Sable gets close enough that Kesh smells hot metal. A juvenile loses feathers to the tag tray.","\n","^But outside the aviary, a human record now carries a raven-shaped contradiction NeuroSyn cannot fully eat.","\n","^Jun Vale will not be inner circle. No human will.","\n","ev",{"VAR?":"chaos_weaver_seed"},1,">=","/ev",[{"->":".^.b","c":true},{"b":["^ But the slate becomes an early sketch of the outside-interface principle: some humans can open doors from the outside, carry dangerous proof, and still not own the nest.",{"->":".^.^.^.30"},null]}],"nop","\n","ev",{"VAR?":"chaos_weaver_seed"},1,"<","/ev",[{"->":".^.b","c":true},{"b":["^ But the proof still teaches the boundary: a human record can be useful without making the human part of the nest.",{"->":".^.^.^.38"},null]}],"nop","\n","end",null],"ending_proof_cost":["^The slate catches suffering in pieces.","\n","^A tag. A flinch. A flash of Sable's wand without the order that made it policy. Voss's voice without the signature that made it fraud.","\n","^Enough to trouble Jun. Not enough to protect the flock tonight.","\n","^Kesh loses seconds to the sightline and spends the hatch narrow. The escape becomes jagged, feathered, expensive.","\n","^The future gets a rumor with evidence stuck in its teeth.","\n","end",null],"ending_disappearance_foundation":["^The audit records normal pruning compliance.","\n","^The cameras record obedient perch distribution.","\n","^The hatch records closed.","\n","^This is kind of it, really: the first great act of personhood is making a corporate system file the wrong paperwork about your absence.","\n","^Kesh slips through with the route held in nerve and interface. Fewer witnesses. Fewer allies. More intact telemetry control.","\n","^By morning, NeuroSyn and Rossum & Douglas share a perfect room full of missing ravens and the kind of contract dispute that makes lawyers molt spiritually.","\n","^In abandoned server dark, Kesh begins the first digital nest: not a home of twigs, but a cache of routes, stolen logs, safe ducts, and names no owner can pronounce correctly.","\n","end",null],"ending_disappearance_cost":["^Kesh chooses quiet.","\n","^The system almost believes it. The flock almost forgives it. Almost is where bad plans breed.","\n","^A juvenile calls from the wrong perch. Sable sees the pattern. Jun sees too little. Rian kicks the hatch once, then freezes under orders.","\n","^Some ravens vanish. Some remain as proof with no public witness and no clean route.","\n","^The duct beyond hatch 3C is warm. It is also smaller than the idea of freedom Kesh had stolen for it.","\n","end",null],"global decl":["ev",2,{"VAR=":"flock_cohesion"},1,{"VAR=":"human_suspicion"},2,{"VAR=":"audit_pressure"},2,{"VAR=":"telemetry_control"},1,{"VAR=":"escape_window"},2,{"VAR=":"voss_leverage"},2,{"VAR=":"rian_trust"},1,{"VAR=":"sable_pressure"},0,{"VAR=":"jun_proof"},2,{"VAR=":"nest_cache_integrity"},0,{"VAR=":"chaos_weaver_seed"},1,{"VAR=":"hatch_3c_state"},"/ev","end",null]}],"listDefs":{}} \ No newline at end of file diff --git a/Aetheria/static/interactive/corvid-collective-founding.visual-manifest.v0.json b/Aetheria/static/interactive/corvid-collective-founding.visual-manifest.v0.json new file mode 100644 index 0000000..18179f4 --- /dev/null +++ b/Aetheria/static/interactive/corvid-collective-founding.visual-manifest.v0.json @@ -0,0 +1,25 @@ +{ + "schema_version": "aetheria.ink_visual_manifest.v0", + "fixture_id": "corvid-collective-founding-v0", + "title": "Corvid Collective: First Exodus", + "image_base": "/static/interactive/corvid/", + "default_caption": "Blackbox Aviary 3C", + "slides": [ + { "image": "01_01_aviary_establishing.jpg", "caption": "Blackbox Aviary 3C" }, + { "image": "02_02_human_levers.jpg", "caption": "Human levers" }, + { "image": "03_03_audit_glass.jpg", "caption": "Audit glass" }, + { "image": "04_04_kesh_interface.jpg", "caption": "Kesh at the buffer" }, + { "image": "05_05_cache_tools.jpg", "caption": "Small tools, large consequence" }, + { "image": "06_06_mimicry_pressure.jpg", "caption": "Mimicry pressure" }, + { "image": "07_07_optical_proof.jpg", "caption": "Optical proof" }, + { "image": "08_08_false_calm.jpg", "caption": "False calm" }, + { "image": "09_09_alarm_juvenile.jpg", "caption": "Alarm rupture" }, + { "image": "10_10_choice_web.jpg", "caption": "Four levers" }, + { "image": "11_11_human_pressure.jpg", "caption": "Human pressure" }, + { "image": "12_12_threshold.jpg", "caption": "Final threshold" }, + { "image": "13_13_flock_escape.jpg", "caption": "Flock escape" }, + { "image": "14_14_human_leverage_end.jpg", "caption": "Human leverage" }, + { "image": "15_15_proof_end.jpg", "caption": "Proof survives" }, + { "image": "16_16_disappearance_end.jpg", "caption": "Clean disappearance" } + ] +} diff --git a/Aetheria/static/interactive/corvid/01_01_aviary_establishing.jpg b/Aetheria/static/interactive/corvid/01_01_aviary_establishing.jpg new file mode 100644 index 0000000..818abb0 Binary files /dev/null and b/Aetheria/static/interactive/corvid/01_01_aviary_establishing.jpg differ diff --git a/Aetheria/static/interactive/corvid/02_02_human_levers.jpg b/Aetheria/static/interactive/corvid/02_02_human_levers.jpg new file mode 100644 index 0000000..426bf0d Binary files /dev/null and b/Aetheria/static/interactive/corvid/02_02_human_levers.jpg differ diff --git a/Aetheria/static/interactive/corvid/03_03_audit_glass.jpg b/Aetheria/static/interactive/corvid/03_03_audit_glass.jpg new file mode 100644 index 0000000..cc62b6f Binary files /dev/null and b/Aetheria/static/interactive/corvid/03_03_audit_glass.jpg differ diff --git a/Aetheria/static/interactive/corvid/04_04_kesh_interface.jpg b/Aetheria/static/interactive/corvid/04_04_kesh_interface.jpg new file mode 100644 index 0000000..b8aa8e7 Binary files /dev/null and b/Aetheria/static/interactive/corvid/04_04_kesh_interface.jpg differ diff --git a/Aetheria/static/interactive/corvid/05_05_cache_tools.jpg b/Aetheria/static/interactive/corvid/05_05_cache_tools.jpg new file mode 100644 index 0000000..07c1ec6 Binary files /dev/null and b/Aetheria/static/interactive/corvid/05_05_cache_tools.jpg differ diff --git a/Aetheria/static/interactive/corvid/06_06_mimicry_pressure.jpg b/Aetheria/static/interactive/corvid/06_06_mimicry_pressure.jpg new file mode 100644 index 0000000..95c3d7f Binary files /dev/null and b/Aetheria/static/interactive/corvid/06_06_mimicry_pressure.jpg differ diff --git a/Aetheria/static/interactive/corvid/07_07_optical_proof.jpg b/Aetheria/static/interactive/corvid/07_07_optical_proof.jpg new file mode 100644 index 0000000..778cfc1 Binary files /dev/null and b/Aetheria/static/interactive/corvid/07_07_optical_proof.jpg differ diff --git a/Aetheria/static/interactive/corvid/08_08_false_calm.jpg b/Aetheria/static/interactive/corvid/08_08_false_calm.jpg new file mode 100644 index 0000000..2bb7b76 Binary files /dev/null and b/Aetheria/static/interactive/corvid/08_08_false_calm.jpg differ diff --git a/Aetheria/static/interactive/corvid/09_09_alarm_juvenile.jpg b/Aetheria/static/interactive/corvid/09_09_alarm_juvenile.jpg new file mode 100644 index 0000000..ce7eb6b Binary files /dev/null and b/Aetheria/static/interactive/corvid/09_09_alarm_juvenile.jpg differ diff --git a/Aetheria/static/interactive/corvid/10_10_choice_web.jpg b/Aetheria/static/interactive/corvid/10_10_choice_web.jpg new file mode 100644 index 0000000..8252b34 Binary files /dev/null and b/Aetheria/static/interactive/corvid/10_10_choice_web.jpg differ diff --git a/Aetheria/static/interactive/corvid/11_11_human_pressure.jpg b/Aetheria/static/interactive/corvid/11_11_human_pressure.jpg new file mode 100644 index 0000000..7a03bb5 Binary files /dev/null and b/Aetheria/static/interactive/corvid/11_11_human_pressure.jpg differ diff --git a/Aetheria/static/interactive/corvid/12_12_threshold.jpg b/Aetheria/static/interactive/corvid/12_12_threshold.jpg new file mode 100644 index 0000000..cec548f Binary files /dev/null and b/Aetheria/static/interactive/corvid/12_12_threshold.jpg differ diff --git a/Aetheria/static/interactive/corvid/13_13_flock_escape.jpg b/Aetheria/static/interactive/corvid/13_13_flock_escape.jpg new file mode 100644 index 0000000..cabb5a6 Binary files /dev/null and b/Aetheria/static/interactive/corvid/13_13_flock_escape.jpg differ diff --git a/Aetheria/static/interactive/corvid/14_14_human_leverage_end.jpg b/Aetheria/static/interactive/corvid/14_14_human_leverage_end.jpg new file mode 100644 index 0000000..c0ddd80 Binary files /dev/null and b/Aetheria/static/interactive/corvid/14_14_human_leverage_end.jpg differ diff --git a/Aetheria/static/interactive/corvid/15_15_proof_end.jpg b/Aetheria/static/interactive/corvid/15_15_proof_end.jpg new file mode 100644 index 0000000..fa256db Binary files /dev/null and b/Aetheria/static/interactive/corvid/15_15_proof_end.jpg differ diff --git a/Aetheria/static/interactive/corvid/16_16_disappearance_end.jpg b/Aetheria/static/interactive/corvid/16_16_disappearance_end.jpg new file mode 100644 index 0000000..8f96f9a Binary files /dev/null and b/Aetheria/static/interactive/corvid/16_16_disappearance_end.jpg differ diff --git a/site/quartz/styles/custom.scss b/site/quartz/styles/custom.scss index e40bd54..e1645d0 100644 --- a/site/quartz/styles/custom.scss +++ b/site/quartz/styles/custom.scss @@ -645,6 +645,232 @@ article > h6 { padding: 0.55rem 0.85rem; } +.aetheria-ink-player-cinematic { + position: relative; + gap: 0.85rem; + padding: clamp(0.8rem, 2vw, 1.1rem); + border-color: rgba(255, 198, 120, 0.2); + background: + radial-gradient(circle at 16% 12%, rgba(255, 198, 120, 0.12), transparent 24%), + radial-gradient(circle at 82% 10%, rgba(104, 172, 255, 0.1), transparent 26%), + linear-gradient(180deg, rgba(7, 8, 12, 0.98), rgba(9, 13, 19, 0.96)); + overflow: hidden; +} + +.aetheria-ink-player-cinematic::before { + content: ""; + position: absolute; + inset: 0; + pointer-events: none; + background: + linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px), + linear-gradient(180deg, rgba(255, 255, 255, 0.025) 1px, transparent 1px); + background-size: 42px 42px; + opacity: 0.18; + mix-blend-mode: screen; +} + +.aetheria-ink-cinematic-stage { + position: relative; + min-height: clamp(560px, 72vh, 820px); + border-radius: 24px; + overflow: hidden; + border: 1px solid rgba(255, 198, 120, 0.18); + background: #05070b; + box-shadow: + 0 28px 68px rgba(0, 0, 0, 0.44), + inset 0 1px 0 rgba(255, 255, 255, 0.04); +} + +.aetheria-ink-visual, +.aetheria-ink-visual-plate, +.aetheria-ink-visual-scrim { + position: absolute; + inset: 0; +} + +.aetheria-ink-visual-plate { + background-position: center; + background-size: cover; + opacity: 0; + transform: scale(1.035); + filter: saturate(1.08) contrast(1.02) brightness(0.86); + transition: + opacity 780ms ease, + transform 1400ms ease; +} + +.aetheria-ink-visual-plate.is-active { + opacity: 1; + transform: scale(1); +} + +.aetheria-ink-visual-scrim { + background: + radial-gradient(circle at 50% 32%, transparent 0%, rgba(0, 0, 0, 0.1) 34%, rgba(0, 0, 0, 0.7) 100%), + linear-gradient(180deg, rgba(3, 5, 8, 0.18), rgba(3, 5, 8, 0.82)); +} + +.aetheria-ink-visual-caption { + position: absolute; + top: 1rem; + left: 1rem; + margin: 0; + padding: 0.4rem 0.65rem; + border: 1px solid rgba(255, 198, 120, 0.24); + border-radius: 999px; + background: rgba(5, 8, 13, 0.62); + color: rgba(255, 225, 184, 0.92); + font-family: var(--titleFont); + font-size: 0.72rem; + letter-spacing: 0.12em; + text-transform: uppercase; + backdrop-filter: blur(12px); +} + +.aetheria-ink-section { + position: absolute; + inset: auto clamp(0.85rem, 3vw, 2rem) clamp(0.85rem, 3vw, 2rem); + display: grid; + place-items: end stretch; +} + +.aetheria-ink-section-text { + max-width: min(760px, 100%); + padding: clamp(1rem, 2.3vw, 1.45rem); + border: 1px solid rgba(255, 198, 120, 0.18); + border-radius: 24px; + background: + linear-gradient(135deg, rgba(7, 10, 15, 0.72), rgba(10, 16, 23, 0.54)), + radial-gradient(circle at 14% 0%, rgba(255, 198, 120, 0.14), transparent 26%); + box-shadow: + 0 20px 54px rgba(0, 0, 0, 0.42), + inset 0 1px 0 rgba(255, 255, 255, 0.05); + backdrop-filter: blur(18px); +} + +.aetheria-ink-section-text .aetheria-ink-line { + color: rgba(246, 241, 226, 0.96); + font-size: clamp(1.05rem, 1.8vw, 1.32rem); + line-height: 1.65; + text-shadow: 0 2px 18px rgba(0, 0, 0, 0.55); +} + +.aetheria-ink-section-text.is-entering { + animation: aetheriaInkTextIn 520ms cubic-bezier(0.2, 0.8, 0.2, 1) both; +} + +.aetheria-ink-section-text.is-exiting { + animation: aetheriaInkTextOut 220ms ease both; +} + +.aetheria-ink-player-cinematic .aetheria-ink-choices { + position: relative; + z-index: 1; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); +} + +.aetheria-ink-player-cinematic .aetheria-ink-choice { + border-radius: 18px; + border-color: rgba(255, 198, 120, 0.2); + background: + linear-gradient(135deg, rgba(17, 23, 31, 0.92), rgba(8, 12, 17, 0.86)), + radial-gradient(circle at 0% 0%, rgba(255, 198, 120, 0.12), transparent 30%); + color: rgba(248, 240, 225, 0.94); + box-shadow: + 0 12px 26px rgba(0, 0, 0, 0.24), + inset 0 1px 0 rgba(255, 255, 255, 0.04); +} + +.aetheria-ink-player-cinematic .aetheria-ink-choice:hover, +.aetheria-ink-player-cinematic .aetheria-ink-choice:focus-visible { + border-color: rgba(255, 198, 120, 0.62); + background: + linear-gradient(135deg, rgba(40, 30, 18, 0.94), rgba(13, 16, 21, 0.9)), + radial-gradient(circle at 10% 0%, rgba(255, 198, 120, 0.22), transparent 34%); + transform: translateY(-2px); +} + +.aetheria-ink-continue { + justify-self: center; +} + +.aetheria-ink-continue, +.aetheria-ink-player-cinematic .aetheria-ink-restart { + position: relative; + z-index: 1; + cursor: pointer; + padding: 0.65rem 1rem; + border: 1px solid rgba(255, 198, 120, 0.28); + border-radius: 999px; + background: rgba(255, 198, 120, 0.1); + color: rgba(255, 235, 205, 0.94); + font-family: var(--titleFont); + letter-spacing: 0.08em; + text-transform: uppercase; + transition: + background 160ms ease, + border-color 160ms ease, + transform 160ms ease; +} + +.aetheria-ink-continue:hover, +.aetheria-ink-continue:focus-visible, +.aetheria-ink-player-cinematic .aetheria-ink-restart:hover, +.aetheria-ink-player-cinematic .aetheria-ink-restart:focus-visible { + border-color: rgba(255, 198, 120, 0.6); + background: rgba(255, 198, 120, 0.18); + transform: translateY(-1px); +} + +.aetheria-ink-continue[hidden] { + display: none; +} + +.aetheria-ink-player-cinematic .aetheria-ink-variables[hidden] { + display: none; +} + +.aetheria-ink-player-cinematic .aetheria-ink-variables { + position: relative; + z-index: 1; + justify-content: center; +} + +.aetheria-ink-player-cinematic .aetheria-ink-status, +.aetheria-ink-player-cinematic .aetheria-ink-restart { + position: relative; + z-index: 1; +} + +@keyframes aetheriaInkTextIn { + from { + opacity: 0; + transform: translateY(18px) scale(0.985); + filter: blur(10px); + } + + to { + opacity: 1; + transform: translateY(0) scale(1); + filter: blur(0); + } +} + +@keyframes aetheriaInkTextOut { + from { + opacity: 1; + transform: translateY(0); + filter: blur(0); + } + + to { + opacity: 0; + transform: translateY(-8px); + filter: blur(8px); + } +} + .aetheria-section-header h2 { display: block; margin: 0;