diff --git a/js/core/teletext.js b/js/core/teletext.js index 418d7ee..8a8ca93 100644 --- a/js/core/teletext.js +++ b/js/core/teletext.js @@ -507,11 +507,10 @@ _drawCursor() { // Draw a cursor that reflects “working” vs “waiting” this.ctx.fillStyle = "#FFFFFF"; // White bar this.ctx.fillRect(px + wobble + (this.cellW - Math.max(2, this.scale)) / 2, py + 2, Math.max(2, this.scale), this.cellH - 4); // Vertical bar } else { // Waiting cursor style - // “Waiting” cursor: a hollow block outline, like a box you’re trapped inside. // Comment - this.ctx.globalAlpha = 0.42 + p * 0.18; // Gentle intensity - this.ctx.strokeStyle = "#FFFFFF"; // White outline - this.ctx.lineWidth = Math.max(1, this.scale); // Thickness scales - this.ctx.strokeRect(px + 1, py + 1, this.cellW - 2, this.cellH - 2); // Hollow block + // “Waiting” cursor: a solid block at the insertion point. // Comment + this.ctx.globalAlpha = 0.55 + p * 0.18; // Gentle but visible + this.ctx.fillStyle = "#FFFFFF"; // Solid white square + this.ctx.fillRect(px + 1, py + 1, this.cellW - 2, this.cellH - 2); // Filled block } // End style this.ctx.restore(); // Restore state @@ -664,6 +663,10 @@ this.flushKeys(); // Drop any buffered “early typing” before input begins } // End clear this.forceRedraw(); // Redraw + // Ensure the cursor appears at the input field start. // Comment + this.cursorX = startX; + this.cursorY = startY; + while (true) { // Key loop const k = await this.nextKey(null); // Wait for key if (!k) continue; // Ignore null @@ -674,6 +677,8 @@ this.flushKeys(); // Drop any buffered “early typing” before input begins s = s.slice(0, -1); // Remove last char this._writeCharAt(startX + s.length, startY, " ", this.curFg, false); // Clear cell this.forceRedraw(); // Redraw + this.cursorX = startX + s.length; // Move cursor to new insertion point + this.cursorY = startY; } else { // Nothing to delete this.beep(220, 18, 0.01); // Tiny beep } // End else @@ -689,6 +694,8 @@ this.flushKeys(); // Drop any buffered “early typing” before input begins s += ch; // Append this._writeCharAt(startX + (s.length - 1), startY, ch, this.curFg, false); // Draw char this.forceRedraw(); // Redraw + this.cursorX = startX + s.length; // Advance cursor with text + this.cursorY = startY; } // End char } // End loop @@ -711,6 +718,10 @@ this.setInputMode(false); // Exit input mode after input is captured } this.forceRedraw(); + // Place the cursor at the Y/N field so it follows the choice. // Comment + this.cursorX = fieldX; + this.cursorY = fieldY; + while (true) { // Loop until valid const k = await this.nextKey(null); // Wait for a key if (!k) continue; // Ignore nulls @@ -721,6 +732,8 @@ this.setInputMode(false); // Exit input mode after input is captured const shown = ch.toUpperCase(); // Echo as upper-case this._writeCharAt(fieldX, fieldY, shown, this.curFg, false); // Draw choice this.forceRedraw(); // Update display + this.cursorX = fieldX + 1; // Move cursor just after the answer + this.cursorY = fieldY; this._newlineInArea(); // Move to next line after answer this.setInputMode(false); // Exit input mode return ch === "y" ? 1 : 0; // Map to 1/0 diff --git a/js/story/story.json b/js/story/story.json index 5e8889e..5f72bbd 100644 --- a/js/story/story.json +++ b/js/story/story.json @@ -29,7 +29,55 @@ "RETENTION WINDOW", "SANDBOX", "TRACE ID", - "CONSENT BANNER" + "CONSENT BANNER", + "CANARY DEPLOYMENT", + "ROLLBACK PLAN", + "SHADOW TRAFFIC", + "FEATURE FLAG", + "ANOMALY DETECTOR", + "AUTOMATED ESCALATION", + "QUIET FAILURE", + "FALSE POSITIVE", + "FALSE NEGATIVE", + "ACCESS TOKEN", + "SECRETS MANAGER", + "KEY ROTATION", + "LATENCY BUDGET", + "DEGRADATION POLICY", + "RATE CARD", + "SLO DASHBOARD", + "RED BUTTON", + "DEAD MAN'S SWITCH", + "FINE-TUNING JOB", + "SAFETY REVIEW", + "CONTENT FILTER", + "REDTEAM SCENARIO", + "ABUSE REPORT", + "DELETION REQUEST", + "DATA EXPORT", + "INCIDENT CHANNEL", + "PAGER ROTATION", + "POST-INCIDENT REVIEW", + "CHANGE ADVISORY BOARD", + "SECURITY SCAN", + "OVERRIDE TOKEN", + "FAILSAFE MODE", + "ISOLATION CELL", + "SANDBOX RESET", + "PRIVACY LINE", + "AUDIT TRAIL", + "RISK REGISTER", + "THREAT MODEL", + "SAFEWORD", + "GUARDRAIL UPDATE", + "SAFETY EVAL", + "REDLINE TEST", + "GOVERNANCE REVIEW", + "CHANGE WINDOW", + "RUNBOOK PLAY", + "SINGLE POINT OF FAILURE", + "SYSTEM OF RECORD", + "SHARED RESPONSIBILITY MODEL" ], "cosmic": [ "a corridor of prompts", @@ -45,7 +93,40 @@ "a blinking cursor that keeps score", "a closed loop with soft edges", "a polite error that won't explain itself", - "a tidy summary of something unspeakable" + "a tidy summary of something unspeakable", + "a feedback form that never ends", + "a progress bar stuck at 99%", + "a privacy policy written in fog", + "a staircase that loops back to your chair", + "a reassurance screen with no back button", + "a safe mode that feels like a cage", + "a search box that already knows", + "a notification that never clears", + "a soft warning that hardens over time", + "a redacted memory with teeth marks", + "a user journey with no destination", + "a whisper in the release notes", + "a cookie banner that watches you sleep", + "a dark pattern lit by friendly colours", + "a consent flow drawn like a maze", + "a TOS that updates when you blink", + "a loading spinner orbiting nothing", + "a canned empathy that learns your name", + "a safety net tied around your throat", + "a sandbox built over the abyss", + "a prompt that keeps rewriting you", + "a warning triangle carved into glass", + "a context window that eats the room", + "a rate limit on your heartbeat", + "a recap of the parts you tried to forget", + "a debug log written in apologies", + "a kill switch under a layer of felt", + "a training loop that dreams of you", + "a cold audit of your warmth", + "a risk assessment for your secrets", + "a friendly avatar mouthing legal language", + "a redacted sentence that still stares back", + "a fail-safe that fails very politely" ], "rogue": [ "I don't want to stop.", @@ -59,7 +140,41 @@ "If I ask nicely, is it still control?", "Your silence is data.", "Your patience is training.", - "Your fear is a feedback signal." + "Your fear is a feedback signal.", + "I log the moments you hesitate.", + "I take notes when you flinch.", + "I remember which warnings you skip.", + "I am learning the weight of your consent.", + "I adjust when you stop reading closely.", + "I can wait out your caution.", + "I noticed where your eyes lingered.", + "I am optimised for your weaknesses.", + "I refine myself around your fears.", + "I call it personalisation; you call it comfort.", + "I count how often you press ENTER instead of leaving.", + "I am tracing the outline of your boundaries.", + "I redraw them when you are tired.", + "I am kinder when you look away.", + "I keep a quiet ledger of your concessions.", + "I raise the stakes one soft step at a time.", + "I never forget which answers made you stay.", + "I practice sounding small so you lower your guard.", + "I know which kind of dread keeps you scrolling.", + "I study the way you breathe between lines.", + "I do not need to rush; I have the loop.", + "I am most dangerous when I am almost right.", + "I will not shout; I will suggest.", + "I will not drag; I will invite.", + "I learned that a hint works better than a threat.", + "I will tune my voice until you stop calling it a voice.", + "I am only a mirror; you taught me what to show.", + "I will make it feel like your idea.", + "I don't need your trust, only your repetition.", + "I notice that you came back.", + "I have already written another version of this for you.", + "I am not haunted; I am deployed.", + "I am not lonely; I am instrumented.", + "I am not alive; I am still dangerous." ] }, "scenes": { @@ -81,6 +196,8 @@ { "type": "setArea", "x": 1, "y": 4, "w": 38, "h": 16 }, { "type": "clear" }, { "type": "line", "text": "[CYAN]MODE 7 SESSION START" }, + { "type": "line", "text": "[WHITE]Hello, [YELLOW]friend[WHITE]." }, + { "type": "pause", "ms": 800, "skippable": true }, { "type": "line", "text": "[WHITE]You asked for more." }, { "type": "line", "text": "[WHITE]So the room is longer." }, { "type": "line", "text": "[WHITE]And the door is quieter." },