Phase 21B.1 - Story Intelligence Experience Visual Refinement

This commit is contained in:
Nick Beckley 2026-07-11 20:23:27 +00:00
parent 0ebccf9ac8
commit e3d18b4a6b
3 changed files with 296 additions and 111 deletions

View File

@ -34,12 +34,22 @@
<aside class="story-exp-left" aria-label="Analysis progress"> <aside class="story-exp-left" aria-label="Analysis progress">
<div class="story-exp-progress"> <div class="story-exp-progress">
<p class="story-exp-eyebrow">Overall progress</p> <p class="story-exp-eyebrow">Overall progress</p>
<div class="story-exp-progress-row"> <div class="story-exp-progress-ring" aria-hidden="true">
<div class="story-exp-progress-orbit"></div>
<div class="story-exp-progress-core">
<strong data-progress-percent>0%</strong> <strong data-progress-percent>0%</strong>
<span data-estimated-remaining>Calculating</span> <span>complete</span>
</div>
</div>
<div class="story-exp-progress-times">
<div>
<span>Elapsed</span>
<strong data-elapsed-time>0m</strong>
</div>
<div>
<span>Remaining</span>
<strong data-estimated-remaining>Calculating</strong>
</div> </div>
<div class="story-exp-progress-track" aria-hidden="true">
<span data-progress-bar></span>
</div> </div>
</div> </div>

View File

@ -4,8 +4,8 @@
--story-bg-deep: #030813; --story-bg-deep: #030813;
--story-panel: rgba(10, 22, 39, 0.74); --story-panel: rgba(10, 22, 39, 0.74);
--story-panel-strong: rgba(14, 30, 52, 0.9); --story-panel-strong: rgba(14, 30, 52, 0.9);
--story-line: rgba(151, 185, 218, 0.18); --story-line: rgba(151, 185, 218, 0.13);
--story-line-strong: rgba(169, 205, 240, 0.34); --story-line-strong: rgba(169, 205, 240, 0.28);
--story-text: #f3f8ff; --story-text: #f3f8ff;
--story-muted: #9eb1c7; --story-muted: #9eb1c7;
--story-soft: #c4d6eb; --story-soft: #c4d6eb;
@ -15,7 +15,8 @@
--story-green: #79d2a6; --story-green: #79d2a6;
--story-rose: #e38ca8; --story-rose: #e38ca8;
--story-radius: 18px; --story-radius: 18px;
--story-shadow: 0 28px 80px rgba(0, 0, 0, 0.36); --story-shadow: 0 28px 84px rgba(0, 0, 0, 0.32);
--progress-value: 0deg;
} }
* { * {
@ -31,8 +32,9 @@ body {
body { body {
overflow: hidden; overflow: hidden;
background: background:
radial-gradient(circle at 50% 18%, rgba(47, 106, 168, 0.25), transparent 28rem), radial-gradient(circle at 50% 18%, rgba(47, 106, 168, 0.28), transparent 30rem),
radial-gradient(circle at 90% 80%, rgba(215, 168, 93, 0.12), transparent 22rem), radial-gradient(circle at 78% 72%, rgba(215, 168, 93, 0.13), transparent 24rem),
radial-gradient(circle at 16% 72%, rgba(121, 210, 166, 0.08), transparent 22rem),
linear-gradient(145deg, var(--story-bg-deep), var(--story-bg) 48%, #101725); linear-gradient(145deg, var(--story-bg-deep), var(--story-bg) 48%, #101725);
color: var(--story-text); color: var(--story-text);
font-family: "Segoe UI", system-ui, -apple-system, BlinkMacSystemFont, sans-serif; font-family: "Segoe UI", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
@ -64,12 +66,25 @@ input:focus-visible {
inset: 0; inset: 0;
z-index: -2; z-index: -2;
background: background:
radial-gradient(circle, rgba(255, 255, 255, 0.18) 0 1px, transparent 1.4px),
linear-gradient(rgba(255, 255, 255, 0.026) 1px, transparent 1px), linear-gradient(rgba(255, 255, 255, 0.026) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.018) 1px, transparent 1px); linear-gradient(90deg, rgba(255, 255, 255, 0.018) 1px, transparent 1px);
background-size: 64px 64px; background-size: 130px 130px, 64px 64px, 64px 64px;
mask-image: radial-gradient(circle at 50% 50%, black, transparent 75%); mask-image: radial-gradient(circle at 50% 50%, black, transparent 75%);
} }
.story-exp::after {
content: "";
position: fixed;
inset: 70px 0 0;
z-index: -1;
background:
linear-gradient(122deg, transparent 0 23%, rgba(109, 181, 255, 0.055) 23.1% 23.25%, transparent 23.35%),
linear-gradient(37deg, transparent 0 68%, rgba(215, 168, 93, 0.045) 68.1% 68.25%, transparent 68.35%);
opacity: 0.8;
pointer-events: none;
}
.story-exp-header { .story-exp-header {
display: grid; display: grid;
grid-template-columns: minmax(210px, 0.65fr) minmax(460px, 1.35fr) auto; grid-template-columns: minmax(210px, 0.65fr) minmax(460px, 1.35fr) auto;
@ -136,10 +151,10 @@ input:focus-visible {
.story-exp-shell { .story-exp-shell {
display: grid; display: grid;
grid-template-columns: minmax(250px, 0.72fr) minmax(620px, 1.92fr) minmax(280px, 0.86fr); grid-template-columns: minmax(206px, 0.54fr) minmax(760px, 2.44fr) minmax(214px, 0.56fr);
gap: 18px; gap: 16px;
min-height: 0; min-height: 0;
padding: 18px 24px 84px; padding: 18px 22px 84px;
} }
.story-exp-left, .story-exp-left,
@ -159,10 +174,12 @@ input:focus-visible {
.story-exp-progress, .story-exp-progress,
.story-exp-panel, .story-exp-panel,
.story-exp-stats { .story-exp-stats {
border: 1px solid var(--story-line); border: 1px solid rgba(151, 185, 218, 0.11);
border-radius: var(--story-radius); border-radius: var(--story-radius);
background: linear-gradient(180deg, rgba(18, 34, 58, 0.84), rgba(7, 17, 31, 0.68)); background:
linear-gradient(180deg, rgba(18, 34, 58, 0.62), rgba(7, 17, 31, 0.42));
box-shadow: var(--story-shadow); box-shadow: var(--story-shadow);
backdrop-filter: blur(18px);
} }
.story-exp-progress, .story-exp-progress,
@ -170,42 +187,87 @@ input:focus-visible {
padding: 16px; padding: 16px;
} }
.story-exp-progress-row { .story-exp-progress-ring {
display: flex; position: relative;
align-items: end; display: grid;
justify-content: space-between; place-items: center;
gap: 12px; width: min(100%, 190px);
margin: 4px 0 12px; aspect-ratio: 1;
margin: 8px auto 16px;
border-radius: 50%;
background:
conic-gradient(from -90deg, var(--story-gold) var(--progress-value), rgba(255, 255, 255, 0.08) 0),
radial-gradient(circle, rgba(109, 181, 255, 0.18), transparent 58%);
box-shadow: 0 0 44px rgba(109, 181, 255, 0.18), inset 0 0 34px rgba(215, 168, 93, 0.06);
transition: background 900ms cubic-bezier(.2, .8, .2, 1);
} }
.story-exp-progress-row strong { .story-exp-progress-ring::before {
font-size: clamp(2.1rem, 4vw, 3.2rem); content: "";
position: absolute;
inset: 10px;
border-radius: inherit;
background: linear-gradient(180deg, rgba(8, 19, 34, 0.98), rgba(3, 8, 19, 0.96));
box-shadow: inset 0 0 24px rgba(255, 255, 255, 0.035);
}
.story-exp-progress-orbit {
position: absolute;
inset: -5px;
border: 1px solid rgba(215, 168, 93, 0.28);
border-radius: 50%;
opacity: 0.72;
}
.story-exp-progress-core {
position: relative;
z-index: 1;
display: grid;
justify-items: center;
gap: 3px;
}
.story-exp-progress-core strong {
font-size: clamp(2.4rem, 4.8vw, 3.25rem);
line-height: 0.95; line-height: 0.95;
} }
.story-exp-progress-row span { .story-exp-progress-core span {
color: var(--story-muted);
font-size: 0.68rem;
font-weight: 800;
letter-spacing: 0.12em;
text-transform: uppercase;
}
.story-exp-progress-times {
display: grid;
grid-template-columns: 1fr;
gap: 8px;
}
.story-exp-progress-times div {
display: flex;
justify-content: space-between;
gap: 10px;
padding-top: 8px;
border-top: 1px solid rgba(255, 255, 255, 0.075);
}
.story-exp-progress-times span {
color: var(--story-muted);
font-size: 0.72rem;
font-weight: 800;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.story-exp-progress-times strong {
color: var(--story-soft); color: var(--story-soft);
font-weight: 700; font-size: 0.85rem;
text-align: right; text-align: right;
} }
.story-exp-progress-track {
overflow: hidden;
height: 10px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.09);
}
.story-exp-progress-track span {
display: block;
width: 0;
height: 100%;
border-radius: inherit;
background: linear-gradient(90deg, var(--story-blue), var(--story-gold));
box-shadow: 0 0 22px rgba(109, 181, 255, 0.42);
transition: width 900ms ease;
}
.story-exp-stats { .story-exp-stats {
display: grid; display: grid;
gap: 1px; gap: 1px;
@ -251,20 +313,57 @@ input:focus-visible {
.story-exp-list li, .story-exp-list li,
.story-exp-feed li, .story-exp-feed li,
.story-exp-insight { .story-exp-insight {
border: 1px solid rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.065);
border-radius: 12px; border-radius: 14px;
padding: 10px 11px; padding: 10px 11px;
background: rgba(255, 255, 255, 0.045); background: rgba(255, 255, 255, 0.035);
color: var(--story-soft); color: var(--story-soft);
} }
.story-exp-list li {
display: grid;
grid-template-columns: 18px 1fr;
align-items: start;
gap: 8px;
}
.story-exp-list li span {
width: 10px;
height: 10px;
margin-top: 5px;
border-radius: 50%;
background: var(--story-blue);
box-shadow: 0 0 14px rgba(109, 181, 255, 0.5);
}
.story-exp-list li[data-discovery-type="asset"] span {
border-radius: 3px;
background: var(--story-gold);
}
.story-exp-list li[data-discovery-type="location"] span {
background: var(--story-green);
}
.story-exp-list li[data-discovery-type="relationship"] span {
background: var(--story-rose);
}
.story-exp-list li[data-discovery-type="knowledge"] span {
background: #b6a2ff;
}
.story-exp-list p {
margin: 0;
}
.story-exp-feed li { .story-exp-feed li {
color: var(--story-muted); color: var(--story-muted);
} }
.story-exp-stage { .story-exp-stage {
display: grid; display: grid;
grid-template-rows: auto minmax(0, 1fr) 160px; grid-template-rows: auto minmax(0, 1fr) 166px;
gap: 14px; gap: 14px;
min-height: 0; min-height: 0;
} }
@ -296,21 +395,34 @@ input:focus-visible {
.story-exp-visual { .story-exp-visual {
position: relative; position: relative;
display: grid; display: grid;
grid-template-columns: minmax(360px, 1.1fr) minmax(260px, 0.92fr) minmax(230px, 0.68fr); grid-template-columns: minmax(470px, 1.22fr) minmax(320px, 0.9fr) minmax(238px, 0.58fr);
grid-template-rows: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr);
gap: 16px; gap: 10px;
min-height: 0; min-height: 0;
overflow: hidden; overflow: hidden;
border: 1px solid var(--story-line); border: 1px solid rgba(151, 185, 218, 0.11);
border-radius: 26px; border-radius: 30px;
padding: 18px; padding: 22px;
background: background:
radial-gradient(circle at 28% 34%, rgba(109, 181, 255, 0.13), transparent 20rem), radial-gradient(circle at 22% 40%, rgba(109, 181, 255, 0.18), transparent 24rem),
radial-gradient(circle at 69% 45%, rgba(215, 168, 93, 0.12), transparent 18rem), radial-gradient(circle at 58% 49%, rgba(215, 168, 93, 0.15), transparent 20rem),
linear-gradient(180deg, rgba(11, 24, 43, 0.82), rgba(4, 10, 20, 0.72)); radial-gradient(circle at 86% 30%, rgba(227, 140, 168, 0.08), transparent 18rem),
linear-gradient(180deg, rgba(11, 24, 43, 0.66), rgba(4, 10, 20, 0.54));
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), var(--story-shadow); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), var(--story-shadow);
} }
.story-exp-visual::before {
content: "";
position: absolute;
inset: 28px 34px;
border-radius: 28px;
background:
linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.05), transparent),
linear-gradient(180deg, transparent, rgba(109, 181, 255, 0.04), transparent);
opacity: 0.52;
pointer-events: none;
}
.story-exp-connections { .story-exp-connections {
position: absolute; position: absolute;
inset: 0; inset: 0;
@ -338,7 +450,8 @@ input:focus-visible {
} }
.story-exp-zone-label { .story-exp-zone-label {
margin: 0 0 10px; margin: 0 0 8px;
opacity: 0.72;
} }
.story-exp-characters { .story-exp-characters {
@ -353,7 +466,7 @@ input:focus-visible {
width: var(--node-size, 150px); width: var(--node-size, 150px);
transform: translate(var(--x, 0), var(--y, 0)) scale(var(--scale, 1)); transform: translate(var(--x, 0), var(--y, 0)) scale(var(--scale, 1));
opacity: var(--opacity, 1); opacity: var(--opacity, 1);
transition: transform 900ms cubic-bezier(.2, .8, .2, 1), opacity 700ms ease; transition: transform 1050ms cubic-bezier(.16, .84, .28, 1), opacity 780ms ease;
} }
.story-character.is-pov { .story-character.is-pov {
@ -365,9 +478,9 @@ input:focus-visible {
.story-asset__image { .story-asset__image {
display: block; display: block;
overflow: hidden; overflow: hidden;
border: 1px solid var(--story-line-strong); border: 1px solid rgba(169, 205, 240, 0.2);
background: rgba(255, 255, 255, 0.06); background: rgba(255, 255, 255, 0.045);
box-shadow: 0 22px 48px rgba(0, 0, 0, 0.3); box-shadow: 0 24px 54px rgba(0, 0, 0, 0.28);
} }
.story-character__image { .story-character__image {
@ -386,7 +499,7 @@ input:focus-visible {
.story-character.is-pov .story-character__image { .story-character.is-pov .story-character__image {
border-color: rgba(215, 168, 93, 0.82); border-color: rgba(215, 168, 93, 0.82);
box-shadow: 0 0 0 6px rgba(215, 168, 93, 0.12), 0 28px 70px rgba(215, 168, 93, 0.2); box-shadow: 0 0 0 7px rgba(215, 168, 93, 0.1), 0 34px 78px rgba(215, 168, 93, 0.2);
} }
.story-character__text { .story-character__text {
@ -410,9 +523,10 @@ input:focus-visible {
.story-location { .story-location {
display: grid; display: grid;
align-content: center; align-content: center;
gap: 12px; gap: 14px;
height: calc(100% - 28px); height: calc(100% - 28px);
transition: opacity 500ms ease, transform 700ms ease; padding: 8px 0;
transition: opacity 560ms ease, transform 800ms cubic-bezier(.16, .84, .28, 1);
} }
.story-location.is-changing { .story-location.is-changing {
@ -421,8 +535,11 @@ input:focus-visible {
} }
.story-location__image { .story-location__image {
width: 100%;
max-height: 360px;
aspect-ratio: 4 / 5; aspect-ratio: 4 / 5;
border-radius: 28px; border-radius: 32px;
box-shadow: 0 28px 78px rgba(0, 0, 0, 0.34), 0 0 54px rgba(109, 181, 255, 0.1);
} }
.story-location h2, .story-location h2,
@ -441,24 +558,25 @@ input:focus-visible {
.story-exp-assets { .story-exp-assets {
display: grid; display: grid;
align-content: center; align-content: center;
gap: 12px; gap: 14px;
height: calc(100% - 28px); height: calc(100% - 28px);
padding-top: 24px;
} }
.story-asset { .story-asset {
display: grid; display: grid;
grid-template-columns: 72px 1fr; grid-template-columns: 66px 1fr;
align-items: center; align-items: center;
gap: 12px; gap: 11px;
opacity: var(--opacity, 1); opacity: var(--opacity, 1);
transform: translateY(var(--y, 0)) scale(var(--scale, 1)); transform: translateY(var(--y, 0)) scale(var(--scale, 1));
transition: transform 760ms ease, opacity 560ms ease; transition: transform 860ms cubic-bezier(.16, .84, .28, 1), opacity 620ms ease;
} }
.story-asset__image { .story-asset__image {
width: 72px; width: 66px;
height: 72px; height: 66px;
border-radius: 18px; border-radius: 17px;
} }
.story-asset strong, .story-asset strong,
@ -475,10 +593,12 @@ input:focus-visible {
display: grid; display: grid;
gap: 12px; gap: 12px;
min-width: 0; min-width: 0;
border: 1px solid var(--story-line); border: 1px solid rgba(151, 185, 218, 0.1);
border-radius: 22px; border-radius: 24px;
padding: 14px; padding: 15px;
background: rgba(6, 16, 30, 0.72); background: rgba(6, 16, 30, 0.54);
box-shadow: 0 20px 58px rgba(0, 0, 0, 0.22);
backdrop-filter: blur(14px);
} }
.story-exp-ribbon { .story-exp-ribbon {
@ -486,33 +606,34 @@ input:focus-visible {
display: flex; display: flex;
align-items: stretch; align-items: stretch;
justify-content: center; justify-content: center;
gap: 10px; gap: 12px;
min-height: 86px; min-height: 94px;
overflow: hidden; overflow: hidden;
} }
.story-scene-card { .story-scene-card {
flex: 0 0 130px; flex: 0 0 136px;
display: grid; display: grid;
align-content: space-between; align-content: space-between;
gap: 7px; gap: 7px;
border: 1px solid rgba(255, 255, 255, 0.09); border: 1px solid rgba(255, 255, 255, 0.07);
border-radius: 16px; border-radius: 15px;
padding: 10px; padding: 10px 11px;
background: rgba(255, 255, 255, 0.045); background: rgba(255, 255, 255, 0.032);
color: var(--story-muted); color: var(--story-muted);
opacity: 0.62; opacity: 0.68;
transform: scale(0.92); transform: scale(0.91) translateY(4px);
transition: transform 760ms ease, opacity 760ms ease, background 760ms ease, border-color 760ms ease; transition: transform 840ms cubic-bezier(.16, .84, .28, 1), opacity 760ms ease, background 760ms ease, border-color 760ms ease, box-shadow 760ms ease;
} }
.story-scene-card.is-current { .story-scene-card.is-current {
flex-basis: 170px; flex-basis: 194px;
border-color: rgba(215, 168, 93, 0.58); border-color: rgba(215, 168, 93, 0.64);
background: rgba(215, 168, 93, 0.14); background: linear-gradient(180deg, rgba(215, 168, 93, 0.18), rgba(109, 181, 255, 0.075));
color: var(--story-text); color: var(--story-text);
opacity: 1; opacity: 1;
transform: scale(1); transform: scale(1.04) translateY(0);
box-shadow: 0 18px 42px rgba(215, 168, 93, 0.16);
} }
.story-scene-card strong { .story-scene-card strong {
@ -533,7 +654,7 @@ input:focus-visible {
display: grid; display: grid;
grid-template-columns: repeat(var(--timeline-count, 1), minmax(0, 1fr)); grid-template-columns: repeat(var(--timeline-count, 1), minmax(0, 1fr));
gap: 0; gap: 0;
min-height: 42px; min-height: 46px;
} }
.story-exp-timeline::before { .story-exp-timeline::before {
@ -541,9 +662,10 @@ input:focus-visible {
position: absolute; position: absolute;
left: 0; left: 0;
right: 0; right: 0;
top: 16px; top: 17px;
height: 2px; height: 2px;
background: linear-gradient(90deg, rgba(109, 181, 255, 0.28), rgba(215, 168, 93, 0.68)); background: linear-gradient(90deg, rgba(109, 181, 255, 0.24), rgba(215, 168, 93, 0.78));
box-shadow: 0 0 18px rgba(109, 181, 255, 0.16);
} }
.story-timeline-marker { .story-timeline-marker {
@ -552,38 +674,43 @@ input:focus-visible {
justify-items: center; justify-items: center;
gap: 8px; gap: 8px;
color: var(--story-muted); color: var(--story-muted);
font-size: 0.72rem; font-size: 0.73rem;
font-weight: 700;
text-align: center; text-align: center;
} }
.story-timeline-marker::before { .story-timeline-marker::before {
content: ""; content: "";
z-index: 1; z-index: 1;
width: 12px; width: 14px;
height: 12px; height: 14px;
margin-top: 11px; margin-top: 10px;
border: 2px solid rgba(215, 168, 93, 0.8); border: 2px solid rgba(215, 168, 93, 0.8);
border-radius: 50%; border-radius: 50%;
background: var(--story-bg); background: var(--story-bg);
} }
.story-timeline-marker.is-current::before { .story-timeline-marker.is-current::before {
width: 18px; width: 22px;
height: 18px; height: 22px;
margin-top: 8px; margin-top: 6px;
background: var(--story-gold); background: var(--story-gold);
box-shadow: 0 0 20px rgba(215, 168, 93, 0.5); box-shadow: 0 0 0 7px rgba(215, 168, 93, 0.12), 0 0 24px rgba(215, 168, 93, 0.55);
} }
.story-exp-insight-list { .story-exp-insight-list {
display: grid; display: grid;
gap: 10px; gap: 9px;
} }
.story-exp-insight { .story-exp-insight {
display: grid; display: grid;
gap: 4px; gap: 4px;
transition: opacity 500ms ease, transform 600ms ease; border-color: rgba(255, 255, 255, 0.055);
background:
linear-gradient(180deg, rgba(255, 255, 255, 0.038), rgba(255, 255, 255, 0.018));
box-shadow: 0 16px 38px rgba(0, 0, 0, 0.16);
transition: opacity 560ms ease, transform 700ms cubic-bezier(.16, .84, .28, 1);
} }
.story-exp-insight strong { .story-exp-insight strong {

View File

@ -19,8 +19,9 @@
stageLabel: root.querySelector("[data-stage-label]"), stageLabel: root.querySelector("[data-stage-label]"),
currentScene: root.querySelector("[data-current-scene]"), currentScene: root.querySelector("[data-current-scene]"),
progressPercent: root.querySelector("[data-progress-percent]"), progressPercent: root.querySelector("[data-progress-percent]"),
elapsedTime: root.querySelector("[data-elapsed-time]"),
estimatedRemaining: root.querySelector("[data-estimated-remaining]"), estimatedRemaining: root.querySelector("[data-estimated-remaining]"),
progressBar: root.querySelector("[data-progress-bar]"), progressRing: root.querySelector(".story-exp-progress-ring"),
chapterCount: root.querySelector("[data-chapter-count]"), chapterCount: root.querySelector("[data-chapter-count]"),
sceneCount: root.querySelector("[data-scene-count]"), sceneCount: root.querySelector("[data-scene-count]"),
currentStage: root.querySelector("[data-current-stage]"), currentStage: root.querySelector("[data-current-stage]"),
@ -68,11 +69,12 @@
text(dom.stageLabel, scene.stage); text(dom.stageLabel, scene.stage);
text(dom.currentScene, scene.sceneNumber); text(dom.currentScene, scene.sceneNumber);
text(dom.progressPercent, `${scene.progressPercent}%`); text(dom.progressPercent, `${scene.progressPercent}%`);
text(dom.elapsedTime, `${Math.max(1, Math.round(scene.progressPercent / 9))}m`);
text(dom.estimatedRemaining, scene.estimatedRemaining); text(dom.estimatedRemaining, scene.estimatedRemaining);
text(dom.chapterCount, `${scene.chaptersAnalysed} of ${scene.chapterTotal}`); text(dom.chapterCount, `${scene.chaptersAnalysed} of ${scene.chapterTotal}`);
text(dom.sceneCount, `${scene.scenesAnalysed} of ${scene.sceneTotal}`); text(dom.sceneCount, `${scene.scenesAnalysed} of ${scene.sceneTotal}`);
text(dom.currentStage, scene.stage); text(dom.currentStage, scene.stage);
if (dom.progressBar) dom.progressBar.style.width = `${scene.progressPercent}%`; if (dom.progressRing) dom.progressRing.style.setProperty("--progress-value", `${scene.progressPercent * 3.6}deg`);
} }
function updateSceneCopy(scene) { function updateSceneCopy(scene) {
@ -242,11 +244,26 @@
container.innerHTML = ""; container.innerHTML = "";
items.forEach((item) => { items.forEach((item) => {
const node = document.createElement(container.tagName === "OL" ? "li" : "li"); const node = document.createElement(container.tagName === "OL" ? "li" : "li");
if (container === dom.discoveries) {
node.dataset.discoveryType = discoveryType(item);
node.innerHTML = "<span aria-hidden=\"true\"></span><p></p>";
text(node.querySelector("p"), item);
} else {
node.textContent = item; node.textContent = item;
}
container.append(node); container.append(node);
}); });
} }
function discoveryType(item) {
const value = String(item || "").toLowerCase();
if (value.includes("relationship") || value.includes("trust") || value.includes("conflict")) return "relationship";
if (value.includes("knowledge") || value.includes("thread") || value.includes("secret")) return "knowledge";
if (value.includes("location") || value.includes("doweries") || value.includes("flat") || value.includes("stairwell")) return "location";
if (value.includes("letter") || value.includes("notebook") || value.includes("rucksack") || value.includes("tr6") || value.includes("keys") || value.includes("phone")) return "asset";
return "character";
}
function scheduleConnectionDraw() { function scheduleConnectionDraw() {
window.requestAnimationFrame(() => drawConnections(loadSceneState(state.index))); window.requestAnimationFrame(() => drawConnections(loadSceneState(state.index)));
} }
@ -313,17 +330,44 @@
} }
function characterPosition(character, index, povId) { function characterPosition(character, index, povId) {
const bounds = dom.characters?.getBoundingClientRect();
const width = Math.max(520, bounds?.width || 620);
const height = Math.max(520, bounds?.height || 620);
const povSize = Math.min(238, Math.max(206, width * 0.34));
if (character.id === povId) { if (character.id === povId) {
return { x: 145, y: 130, size: 210, scale: 1, opacity: 1 }; return {
x: Math.round(width * 0.36 - povSize / 2),
y: Math.round(height * 0.46 - povSize / 2),
size: Math.round(povSize),
scale: 1,
opacity: 1
};
} }
const important = character.weight >= 70; const important = character.weight >= 70;
const positions = important const positions = important
? [{ x: 18, y: 54 }, { x: 344, y: 44 }, { x: 322, y: 286 }] ? [
: [{ x: 34, y: 300 }, { x: 396, y: 240 }, { x: 20, y: 198 }]; { x: width * 0.08, y: height * 0.18 },
{ x: width * 0.62, y: height * 0.15 },
{ x: width * 0.58, y: height * 0.58 }
]
: [
{ x: width * 0.12, y: height * 0.62 },
{ x: width * 0.73, y: height * 0.48 },
{ x: width * 0.06, y: height * 0.42 }
];
const slot = positions[index % positions.length]; const slot = positions[index % positions.length];
const size = important ? 138 + (character.weight - 70) * 0.9 : 92 + Math.max(0, character.weight - 24) * 0.45; const size = important
return { x: slot.x, y: slot.y, size: Math.round(size), scale: 1, opacity: important ? 0.94 : 0.72 }; ? Math.min(176, 136 + (character.weight - 70) * 0.9)
: Math.min(116, 88 + Math.max(0, character.weight - 24) * 0.45);
return {
x: Math.round(slot.x),
y: Math.round(slot.y),
size: Math.round(size),
scale: 1,
opacity: important ? 0.94 : 0.72
};
} }
function centrePoint(node, parentRect) { function centrePoint(node, parentRect) {
@ -394,7 +438,11 @@
startTimer(); startTimer();
}); });
window.addEventListener("resize", () => scheduleConnectionDraw()); window.addEventListener("resize", () => {
const current = loadSceneState(state.index);
reconcileCharacters(current);
scheduleConnectionDraw();
});
transitionToNextState(0); transitionToNextState(0);
startTimer(); startTimer();