Files
slaguru666andClaude Opus 4.8 9a8a331635 Implement RUNDOWN v1: rules, ladders, GM sheet, console
- rules/RUNDOWN.md: the complete system, self-contained
- reference/obstacle-ladders.md: eight six-rung ladders across foot,
  ground vehicle and spinner terrain
- reference/converting-from-raw.md: switching from the published chase
  rules mid-campaign or mid-chase, plus rulings the conversion needs
- reference/rundown-gm-sheet.html: one-page printable GM sheet
- gm-utility/rundown-console.html + modules/rundown.js: touch console
  matching the REP-DETECT panel style, no dependencies, runs from file://

Console logic verified by gm-utility/test/rundown.test.js — 42 assertions
driving the real module through a stub DOM, covering LEAD movement and
clamping, round capping, Overtime drift, undo, Collateral pips and every
outcome band.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 23:06:08 +01:00

230 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<title>RUNDOWN — Chase Console</title>
<style>
:root{
--bg:#07090b; --panel:#0e1216; --panel2:#131a20; --line:#1f2b33;
--teal:#5bd8c4; --teal-dim:#2a6e64; --amber:#e8a33d; --red:#d05353;
--ink:#cfd8dc; --dim:#748088;
--tap:54px;
}
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
html,body{height:100%}
body{
background:
radial-gradient(ellipse at 20% 0%, #14202a 0%, transparent 55%),
radial-gradient(ellipse at 85% 100%, #1a1410 0%, transparent 50%),
var(--bg);
background-attachment:fixed;
color:var(--ink);font-family:"Avenir Next","Segoe UI",Arial,sans-serif;
overscroll-behavior:none;user-select:none;
}
#app{display:flex;flex-direction:column;height:100dvh}
/* header */
header{display:flex;align-items:center;gap:12px;padding:10px 14px;border-bottom:1px solid var(--line);background:rgba(10,14,17,.75);backdrop-filter:blur(4px)}
header .logo{font-size:11px;letter-spacing:.34em;color:var(--teal);text-transform:uppercase;line-height:1.3}
header .logo b{display:block;color:var(--ink);font-size:15px;letter-spacing:.22em}
header .spacer{flex:1}
.roundbox{text-align:right;line-height:1.25}
.roundbox .lbl{font-size:9px;letter-spacing:.24em;color:var(--dim);text-transform:uppercase}
.roundbox .val{font-family:"Courier New",monospace;font-size:26px;color:var(--amber);font-weight:700}
.roundbox .val.over{color:var(--red)}
a.home{color:var(--dim);text-decoration:none;font-size:20px;padding:0 6px}
main{flex:1;overflow-y:auto;padding:14px;padding-bottom:20px}
.card{background:rgba(14,18,22,.92);border:1px solid var(--line);border-radius:8px;padding:14px;margin-bottom:14px}
.card h2{font-size:11px;letter-spacing:.3em;text-transform:uppercase;color:var(--teal);margin-bottom:12px;display:flex;justify-content:space-between;align-items:center;gap:8px}
.card h2 .sub{color:var(--dim);letter-spacing:.06em;text-transform:none;font-size:11px;font-weight:400}
button.big{
background:var(--panel2);border:1px solid var(--line);color:var(--ink);border-radius:8px;
min-height:var(--tap);padding:10px 16px;font-size:15px;cursor:pointer;font-family:inherit;letter-spacing:.04em;
}
button.big:active{background:#1a252e}
button.primary{background:#123a35;border-color:var(--teal-dim);color:var(--teal);font-weight:700}
button.danger{background:#3a1616;border-color:#6e2a2a;color:var(--red)}
button.amber{background:#3a2c12;border-color:#6e5a2a;color:var(--amber)}
button:disabled{opacity:.3;pointer-events:none}
.row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.grow{flex:1}
.muted{color:var(--dim);font-size:12px;line-height:1.5}
/* LEAD track */
.lead{display:flex;gap:5px;margin-bottom:10px}
.lead .n{
flex:1;text-align:center;padding:14px 2px 10px;border:1px solid var(--line);border-radius:8px;
background:#0a0f13;font-family:"Courier New",monospace;font-size:20px;font-weight:800;color:var(--dim);cursor:pointer;
}
.lead .n small{display:block;font-family:inherit;font-size:8px;letter-spacing:.12em;font-weight:600;margin-top:3px;color:var(--dim)}
.lead .n.cur{background:#123a35;border-color:var(--teal);color:var(--teal);box-shadow:0 0 16px rgba(91,216,196,.22)}
.lead .n.term{border-color:#33424c}
.lead .n.cur.zero{background:#123a35;border-color:var(--teal)}
.lead .n.cur.eight{background:#3a1616;border-color:var(--red);color:var(--red);box-shadow:0 0 16px rgba(208,83,83,.25)}
.leadends{display:flex;justify-content:space-between;font-size:9px;letter-spacing:.16em;text-transform:uppercase;color:var(--dim);margin-bottom:12px}
/* net entry */
.net{display:grid;grid-template-columns:1fr auto 1fr;gap:10px;align-items:end}
.stepper{background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:8px}
.stepper .lbl{font-size:9px;letter-spacing:.2em;color:var(--dim);text-transform:uppercase;text-align:center;margin-bottom:6px}
.stepper .ctrl{display:flex;align-items:center;gap:6px}
.stepper .ctrl button{flex:0 0 44px;min-height:44px;font-size:20px;padding:0}
.stepper .ctrl .v{flex:1;text-align:center;font-family:"Courier New",monospace;font-size:28px;font-weight:800;color:var(--ink)}
.netout{text-align:center;padding-bottom:14px}
.netout .lbl{font-size:9px;letter-spacing:.2em;color:var(--dim);text-transform:uppercase}
.netout .v{font-family:"Courier New",monospace;font-size:30px;font-weight:800}
.netout .v.pos{color:var(--teal)} .netout .v.neg{color:var(--red)} .netout .v.zero{color:var(--dim)}
/* obstacle */
.obstacle{background:#101820;border:1px solid var(--amber);border-radius:10px;padding:14px;margin-bottom:10px}
.obstacle .n{color:var(--amber);font-size:11px;letter-spacing:.24em;margin-bottom:7px;text-transform:uppercase}
.obstacle .t{font-size:18px;font-weight:700;line-height:1.35;margin-bottom:8px;user-select:text}
.obstacle .d{font-size:13px;line-height:1.6;color:var(--ink);user-select:text}
.obstacle .d b{color:var(--teal)}
.obstacle .d .tilt{color:var(--amber)}
.obstacle.term{border-color:var(--red)}
.obstacle.term .n{color:var(--red)}
.crowd{display:inline-block;font-size:9px;letter-spacing:.16em;border:1px solid var(--red);color:var(--red);padding:1px 6px;border-radius:3px;margin-left:8px;vertical-align:middle}
/* collateral */
.pips{display:flex;gap:8px;margin-bottom:10px}
.pips div{
flex:1;height:46px;border:2px solid var(--line);border-radius:8px;background:#0a0f13;cursor:pointer;
display:flex;align-items:center;justify-content:center;font-family:"Courier New",monospace;font-size:15px;color:var(--dim);font-weight:700;
}
.pips div.on{background:#3a2c12;border-color:var(--amber);color:var(--amber)}
.pips div.on.hot{background:#3a1616;border-color:var(--red);color:var(--red)}
.collnote{font-size:13px;line-height:1.55;color:var(--ink);border-left:2px solid var(--amber);padding-left:10px}
/* outcome */
.outcome{border-radius:10px;padding:14px;border:1px solid var(--line);background:#0a0f13}
.outcome .nm{font-size:22px;font-weight:800;letter-spacing:.1em;margin-bottom:6px}
.outcome .dsc{font-size:13px;line-height:1.55;color:var(--dim)}
.outcome.live{border-color:var(--teal)} .outcome.live .nm{color:var(--teal)}
.outcome.done{border-color:var(--amber)} .outcome.done .nm{color:var(--amber)}
.outcome.bad{border-color:var(--red)} .outcome.bad .nm{color:var(--red)}
/* roles table */
table.roles{width:100%;border-collapse:collapse;font-size:13px}
table.roles td{padding:7px 6px;border-top:1px solid var(--line);vertical-align:top;line-height:1.45}
table.roles tr:first-child td{border-top:none}
table.roles td:first-child{color:var(--teal);font-weight:700;white-space:nowrap;letter-spacing:.04em}
table.roles td:nth-child(2){color:var(--dim);white-space:nowrap;font-size:11px}
table.roles .cost{color:var(--amber)}
select{
background:#0a0f13;border:1px solid var(--line);color:var(--ink);border-radius:8px;
padding:0 10px;min-height:var(--tap);font-size:15px;font-family:inherit;flex:1;
}
details summary{cursor:pointer;list-style:none;color:var(--dim);font-size:11px;letter-spacing:.2em;text-transform:uppercase;padding:4px 0}
details summary::-webkit-details-marker{display:none}
details[open] summary{color:var(--teal)}
</style>
</head>
<body>
<div id="app">
<header>
<a class="home" href="index.html" title="Hub">&#8962;</a>
<div class="logo">Chase Console<b>RUNDOWN</b></div>
<div class="spacer"></div>
<div class="roundbox">
<div class="lbl">Round</div>
<div class="val" id="roundVal">1<span style="font-size:15px;color:var(--dim)">/6</span></div>
</div>
</header>
<main>
<div class="card">
<h2>Lead <span class="sub" id="leadSub">standard start</span></h2>
<div class="lead" id="leadTrack"></div>
<div class="leadends"><span>&#9664; pursuers gain</span><span>prey gains &#9654;</span></div>
<div class="net">
<div class="stepper">
<div class="lbl">Pursuers</div>
<div class="ctrl">
<button class="big" data-adj="pursuer,-1">&minus;</button>
<div class="v" id="pursuerVal">0</div>
<button class="big" data-adj="pursuer,1">+</button>
</div>
</div>
<div class="netout">
<div class="lbl">Net</div>
<div class="v zero" id="netVal">0</div>
</div>
<div class="stepper">
<div class="lbl">Prey</div>
<div class="ctrl">
<button class="big" data-adj="prey,-1">&minus;</button>
<div class="v" id="preyVal">0</div>
<button class="big" data-adj="prey,1">+</button>
</div>
</div>
</div>
<div class="row" style="margin-top:12px">
<button class="big primary grow" id="applyBtn">Apply &amp; next round</button>
<button class="big" id="undoBtn">Undo</button>
</div>
<div class="muted" style="margin-top:8px">
Side total = highest single Runner + all Pressure + banked Cutter spent.
</div>
</div>
<div class="card">
<h2>Obstacle <span class="sub" id="ladderName">&mdash;</span></h2>
<div id="obstacleBox"></div>
<div class="row">
<select id="ladderPick"></select>
<button class="big" id="peekBtn" title="Spotter: reveal next rung">Peek next</button>
</div>
<div class="muted" id="peekOut" style="margin-top:8px"></div>
</div>
<div class="card">
<h2>Collateral <span class="sub" id="collSub">the city pays</span></h2>
<div class="pips" id="pips"></div>
<div class="collnote" id="collNote"></div>
</div>
<div class="card">
<h2>Outcome <span class="sub">if it ended now</span></h2>
<div class="outcome" id="outcome"></div>
</div>
<div class="card">
<details>
<summary>&#9656; Roles reference</summary>
<table class="roles" style="margin-top:10px">
<tr><td>RUNNER</td><td>Mobility<br>Driving</td><td>Successes move LEAD. Free. The default.</td></tr>
<tr><td>PRESSURE</td><td>Firearms<br>Manipulation<br>Connections</td><td>Successes move LEAD. <span class="cost">1 Collateral each.</span></td></tr>
<tr><td>SPOTTER</td><td>Observation</td><td>Per success: negate a Toll &middot; remove 1 Collateral &middot; +1 advantage die &middot; reveal next rung.</td></tr>
<tr><td>CUTTER</td><td>Mobility<br>Driving</td><td>Banks successes, spend all at once later. No successes = out 1 round, bank lost.</td></tr>
<tr><td>GAMBIT</td><td>once each</td><td>Disadvantage. Win = double successes. Lose = out of the chase, <span class="cost">+1 Collateral.</span></td></tr>
</table>
</details>
</div>
<div class="card">
<h2>Chase</h2>
<div class="row">
<button class="big amber grow" id="overtimeBtn">Call Overtime</button>
<button class="big danger" id="resetBtn">Reset</button>
</div>
<div class="muted" id="otNote" style="margin-top:8px">
Overtime: max 3 rounds, Terminator stands, LEAD &minus;1 each round, Collateral doubled.
</div>
</div>
</main>
</div>
<script src="modules/rundown.js"></script>
</body>
</html>