diff --git a/script.html b/script.html
index b99f413..6426ec9 100644
--- a/script.html
+++ b/script.html
@@ -49,6 +49,12 @@
.tlhead{position:absolute;top:0;bottom:0;width:2px;background:var(--accent2);pointer-events:none}
.tlruler{position:absolute;left:0;right:0;bottom:0;height:14px;font:9px/14px var(--mono);color:var(--muted)}
.tlruler span{position:absolute;transform:translateX(-50%)}
+ .steps{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:24px}
+ .steps button{background:#0f1117;border:1px solid var(--line);color:var(--muted);
+ border-radius:999px;padding:8px 15px;font:12px/1 var(--mono);cursor:pointer}
+ .steps button.done{color:var(--ink)}
+ .steps button.on{background:var(--accent);border-color:var(--accent);color:#fff;cursor:default}
+ .steps button[disabled]{opacity:.35;cursor:not-allowed}
.stage{position:relative;width:100%;max-width:300px}
.stage>video{width:100%;aspect-ratio:9/16;border-radius:10px;background:#000;display:block}
.ovl{position:absolute;inset:0;border-radius:10px;overflow:hidden;background:#000;display:none}
@@ -161,6 +167,38 @@ function shotHtml(s, locked) {
+ '';
}
+// Four jobs, one at a time. Which one you are on follows from the project's
+// status; VIEW lets you step back to look at an earlier one without pretending
+// the work has been undone.
+var STAGES = ["The words", "The layout", "Filming", "The cut"];
+var VIEW = null;
+
+function stageOf(st) {
+ if (st === "ready" || st === "film_failed") return 4;
+ if (st === "queued_to_film" || st === "filming") return 3;
+ if (st === "approved") return 2;
+ return 1;
+}
+
+function stepper(stage, view) {
+ return '
' + STAGES.map(function (n, k) {
+ var i = k + 1;
+ var cls = i === view ? "on" : (i <= stage ? "done" : "");
+ return '';
+ }).join("") + '
';
+}
+
+// Stage one shows the writing and nothing else: no frames, no camera, no
+// settings. Just what the pet actually says.
+function linesHtml(s) {
+ return '
'
+ + 'Shot ' + (s.index || "") + ''
+ + '
' + esc(s.line || "") + '
'
+ + '
' + (s.word_count || 0) + ' words · about '
+ + (s.est_seconds || 0) + 's
';
+}
+
function render(r) {
DATA = r;
var p = r.project, s = r.script, out = document.getElementById("out");
@@ -190,7 +228,12 @@ function render(r) {
document.getElementById("title").textContent = s.title || "The script";
document.getElementById("sub").textContent = s.premise || "";
- var locked = p.status === "approved";
+ var stage = stageOf(p.status);
+ if (VIEW === null || VIEW > stage) VIEW = stage;
+ // Shot controls belong to the layout stage. Elsewhere the shots are shown
+ // but not touchable, which is what "locked" means to shotHtml.
+ var locked = VIEW !== 2;
+ var canEditScript = (stage === 1);
var warn = (s._warnings && s._warnings.length)
? '
Worth a look: ' + s._warnings.map(esc).join(" ยท ") + '
';
- out.innerHTML = cams + head + warn + full
- + '
The shots
'
- + s.segments.map(function (x) { return shotHtml(x, locked); }).join("")
- + own
- + film
- + post
- + actions;
+ var body;
+ if (VIEW === 1) {
+ body = head + warn + full
+ + '
The words, shot by shot
'
+ + s.segments.map(linesHtml).join("")
+ + actions;
+ } else if (VIEW === 2) {
+ body = head
+ + '
How it will be laid out. '
+ + 'Each shot has a setting, a camera move and an opening frame that carries your '
+ + 'pet’s likeness. Cutaways sit across the joins so the cut is never on screen. '
+ + 'All of it has been chosen for you — change anything you disagree with, or '
+ + 'go straight to filming.
'
+ + '
The shots
'
+ + s.segments.map(function (x) { return shotHtml(x, false); }).join("")
+ + own
+ + film;
+ } else if (VIEW === 3) {
+ body = head + film;
+ } else {
+ body = head + post + film;
+ }
+
+ out.innerHTML = cams + stepper(stage, VIEW) + body;
wire(locked);
}
@@ -447,6 +508,16 @@ function bindPics() {
}
function wire(locked) {
+ [].forEach.call(document.querySelectorAll("[data-stage]"), function (b) {
+ b.onclick = function () {
+ var want = parseInt(b.getAttribute("data-stage"), 10);
+ if (want === VIEW) return;
+ VIEW = want;
+ hideMsg("msg");
+ render(DATA);
+ window.scrollTo({ top: 0, behavior: "smooth" });
+ };
+ });
bindPics();
bindFilm((DATA && DATA.project) || {});
bindPost();