feat: strengthen evaluation and conclusion visuals
This commit is contained in:
@@ -76,9 +76,18 @@ describe("ConclusionScene", () => {
|
||||
|
||||
it("states the closing boundary and recedes future branches", () => {
|
||||
render(<ConclusionScene scene={scene} beat={beat("conclusion")} />);
|
||||
const map = screen.getByRole("region", { name: "thesis contribution boundary" });
|
||||
const substrate = map.querySelector('[data-node-id="substrate"]');
|
||||
const nonClaims = screen.getByRole("list", { name: "explicit non-claims" });
|
||||
const future = screen.getByRole("list", { name: "future work layers" });
|
||||
|
||||
expect(map).toHaveAttribute("data-conclusion-focus", "conclusion");
|
||||
expect(substrate).toHaveAttribute("data-contribution-focus", "primary");
|
||||
expect(screen.getByText("Planner proposes; runtime executes.")).toBeInTheDocument();
|
||||
expect(screen.getByRole("list", { name: "future work layers" })).toHaveAttribute("data-state", "receded");
|
||||
expect(screen.getByText("Planner proposes; runtime executes.")).toHaveAttribute("data-conclusion-support", "primary");
|
||||
expect(screen.getByText("Planner proposes; runtime executes.")).toHaveAttribute("data-contribution-focus", "primary");
|
||||
expect(nonClaims).toHaveAttribute("data-conclusion-support", "receded");
|
||||
expect(future).toHaveAttribute("data-state", "receded");
|
||||
expect(future).toHaveAttribute("data-conclusion-support", "receded");
|
||||
});
|
||||
|
||||
it("attaches evidence vertically beneath the typed substrate rather than extending the contribution line", () => {
|
||||
|
||||
@@ -37,6 +37,7 @@ export const ConclusionScene: FC<ConclusionSceneProps> = ({ scene, beat }) => {
|
||||
className="conclusion-map"
|
||||
aria-label="thesis contribution boundary"
|
||||
data-conclusion-beat={beatId}
|
||||
data-conclusion-focus={beatId}
|
||||
data-visual-role="contribution-boundary"
|
||||
data-presentation-surface="editorial"
|
||||
>
|
||||
@@ -56,6 +57,7 @@ export const ConclusionScene: FC<ConclusionSceneProps> = ({ scene, beat }) => {
|
||||
className="conclusion-map__node conclusion-map__node--substrate"
|
||||
data-node-id={contributionNodes[1].id}
|
||||
data-emphasis="substrate"
|
||||
data-contribution-focus={beatId === "conclusion" ? "primary" : "support"}
|
||||
>
|
||||
<span className="conclusion-map__node-index">02</span>
|
||||
<strong>{contributionNodes[1].label}</strong>
|
||||
@@ -87,6 +89,7 @@ export const ConclusionScene: FC<ConclusionSceneProps> = ({ scene, beat }) => {
|
||||
aria-label="explicit non-claims"
|
||||
data-emphasis={beatId === "limits" ? "limits" : "neutral"}
|
||||
data-conclusion-support={beatId === "limits" ? "primary" : "receded"}
|
||||
data-state={beatId === "limits" ? "primary" : "receded"}
|
||||
>
|
||||
{nonClaims.map((claim) => <li key={claim}>{claim}</li>)}
|
||||
</ul>
|
||||
@@ -111,7 +114,13 @@ export const ConclusionScene: FC<ConclusionSceneProps> = ({ scene, beat }) => {
|
||||
})}
|
||||
</ul>
|
||||
|
||||
<p className="conclusion-map__statement" data-conclusion-support={beatId === "conclusion" ? "primary" : "receded"}>Planner proposes; runtime executes.</p>
|
||||
<p
|
||||
className="conclusion-map__statement"
|
||||
data-conclusion-support={beatId === "conclusion" ? "primary" : "receded"}
|
||||
data-contribution-focus={beatId === "conclusion" ? "primary" : "support"}
|
||||
>
|
||||
Planner proposes; runtime executes.
|
||||
</p>
|
||||
</section>
|
||||
<p className="scene-body__evidence">{scene.evidencePointer}</p>
|
||||
</>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { cleanup, render, screen } from "@testing-library/react";
|
||||
import { cleanup, render, screen, within } from "@testing-library/react";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { EvaluationEvidenceScene } from "./EvaluationEvidenceScene.js";
|
||||
|
||||
@@ -58,6 +58,19 @@ describe("EvaluationEvidenceScene", () => {
|
||||
it("renders six labelled finding icons without ranking language", () => {
|
||||
render(<EvaluationEvidenceScene scene={scene} beat={beat("findings")} />);
|
||||
const findings = screen.getByRole("list", { name: /ux gaps exposed by trials/i });
|
||||
const board = screen.getByRole("group", { name: /evaluation evidence board/i });
|
||||
const campaignStrip = screen.getByRole("group", { name: /campaign and outcome evidence strip/i });
|
||||
|
||||
expect(board).toHaveAttribute("data-evaluation-layout", "3x2-with-evidence-strip");
|
||||
expect(findings).toHaveAttribute("data-grid-layout", "3x2");
|
||||
expect(within(findings).getAllByRole("listitem")).toHaveLength(6);
|
||||
expect(campaignStrip).toHaveAttribute("data-visual-role", "campaign-evidence");
|
||||
expect(within(campaignStrip).getByText("36")).toBeInTheDocument();
|
||||
expect(campaignStrip).toHaveTextContent(/3\s+waves/);
|
||||
expect(
|
||||
screen.getByText("Bounded longitudinal engineering evidence, not a controlled model comparison."),
|
||||
).toBeInTheDocument();
|
||||
|
||||
expect(findings.querySelectorAll("svg")).toHaveLength(6);
|
||||
for (const label of [
|
||||
"Schema discovery",
|
||||
|
||||
@@ -33,30 +33,33 @@ export const EvaluationEvidenceScene: FC<EvaluationEvidenceSceneProps> = ({ scen
|
||||
aria-label="evaluation evidence board"
|
||||
data-evaluation-beat={beatId}
|
||||
data-evaluation-focus={beatId}
|
||||
data-evaluation-layout={beatId === "findings" ? "3x2-with-evidence-strip" : "campaign-audit-board"}
|
||||
data-visual-role="evaluation-summary"
|
||||
data-presentation-surface="editorial"
|
||||
>
|
||||
<div className="evaluation-board__cohort" aria-label="campaign cohort equation">
|
||||
<span className="evaluation-board__cohort-total">{evaluationEvidence.totalTrials}</span>
|
||||
<span className="evaluation-board__cohort-label">audited trials</span>
|
||||
<span className="evaluation-board__cohort-equation" aria-label="cohort factors">
|
||||
{evaluationEvidence.cohortFactors.map((factor, index) => (
|
||||
<span className="evaluation-board__factor" key={factor.label}>
|
||||
{index > 0 ? " × " : ""}
|
||||
<strong>{factor.value}</strong> {factor.label}
|
||||
</span>
|
||||
))}
|
||||
</span>
|
||||
</div>
|
||||
<div className="evaluation-board__campaign-strip" role="group" aria-label="campaign and outcome evidence strip" data-visual-role="campaign-evidence">
|
||||
<div className="evaluation-board__cohort" aria-label="campaign cohort equation">
|
||||
<span className="evaluation-board__cohort-total">{evaluationEvidence.totalTrials}</span>
|
||||
<span className="evaluation-board__cohort-label">audited trials</span>
|
||||
<span className="evaluation-board__cohort-equation" aria-label="cohort factors">
|
||||
{evaluationEvidence.cohortFactors.map((factor, index) => (
|
||||
<span className="evaluation-board__factor" key={factor.label}>
|
||||
{index > 0 ? " × " : ""}
|
||||
<strong>{factor.value}</strong> {factor.label}
|
||||
</span>
|
||||
))}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<ol className="evaluation-board__outcomes" aria-label="audited outcomes">
|
||||
{evaluationEvidence.outcomes.map((outcome) => (
|
||||
<li className={`evaluation-board__outcome evaluation-board__outcome--${outcome.kind}`} key={outcome.label}>
|
||||
<strong>{outcome.value}</strong>
|
||||
<span>{outcome.label}</span>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
<ol className="evaluation-board__outcomes" aria-label="audited outcomes">
|
||||
{evaluationEvidence.outcomes.map((outcome) => (
|
||||
<li className={`evaluation-board__outcome evaluation-board__outcome--${outcome.kind}`} key={outcome.label}>
|
||||
<strong>{outcome.value}</strong>
|
||||
<span>{outcome.label}</span>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div className="evaluation-board__audit" aria-label="automatic and manual audit reconciliation">
|
||||
<p className="evaluation-board__section-label">Automatic grading → manual audit</p>
|
||||
@@ -69,7 +72,7 @@ export const EvaluationEvidenceScene: FC<EvaluationEvidenceSceneProps> = ({ scen
|
||||
))}
|
||||
</div>
|
||||
|
||||
<ol className="evaluation-board__findings" aria-label="UX gaps exposed by trials">
|
||||
<ol className="evaluation-board__findings" aria-label="UX gaps exposed by trials" data-grid-layout="3x2">
|
||||
{evaluationEvidence.findings.map((finding) => {
|
||||
const Icon = findingIcons[finding.icon];
|
||||
return (
|
||||
|
||||
@@ -152,20 +152,27 @@
|
||||
|
||||
.evaluation-board[data-evaluation-focus="cohort"] {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-areas: "cohort" "outcomes" "boundary";
|
||||
grid-template-areas: "campaign" "boundary";
|
||||
}
|
||||
|
||||
.evaluation-board[data-evaluation-focus="validity"] {
|
||||
grid-template-areas: "cohort outcomes" "audit audit" "boundary boundary";
|
||||
grid-template-areas: "campaign campaign" "audit audit" "boundary boundary";
|
||||
}
|
||||
|
||||
.evaluation-board[data-evaluation-focus="findings"] {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-areas: "findings" "boundary";
|
||||
grid-template-areas: "campaign" "findings" "boundary";
|
||||
min-height: 0;
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
.evaluation-board__campaign-strip {
|
||||
display: grid;
|
||||
grid-area: campaign;
|
||||
grid-template-columns: minmax(14rem, 0.8fr) minmax(20rem, 1.2fr);
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.evaluation-board__cohort { grid-area: cohort; }
|
||||
.evaluation-board__outcomes { grid-area: outcomes; }
|
||||
.evaluation-board__audit { grid-area: audit; }
|
||||
.evaluation-board__findings { grid-area: findings; }
|
||||
.evaluation-board__boundary { grid-area: boundary; }
|
||||
@@ -173,12 +180,19 @@
|
||||
.evaluation-board[data-evaluation-focus="cohort"] .evaluation-board__audit,
|
||||
.evaluation-board[data-evaluation-focus="cohort"] .evaluation-board__findings,
|
||||
.evaluation-board[data-evaluation-focus="validity"] .evaluation-board__findings,
|
||||
.evaluation-board[data-evaluation-focus="findings"] .evaluation-board__cohort,
|
||||
.evaluation-board[data-evaluation-focus="findings"] .evaluation-board__outcomes,
|
||||
.evaluation-board[data-evaluation-focus="findings"] .evaluation-board__audit {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.evaluation-board[data-evaluation-focus="cohort"] .evaluation-board__campaign-strip {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.evaluation-board[data-evaluation-focus="findings"] .evaluation-board__campaign-strip {
|
||||
/* grid-template-columns: minmax(12rem, 0.7fr) minmax(20rem, 1.3fr); */
|
||||
/* difference between two beats -> shifting */
|
||||
}
|
||||
|
||||
.evaluation-board[data-evaluation-focus="cohort"] .evaluation-board__cohort {
|
||||
border-right: 0;
|
||||
padding-block: 1.35rem 0.8rem;
|
||||
@@ -186,8 +200,9 @@
|
||||
|
||||
.evaluation-board[data-evaluation-focus="findings"] .evaluation-board__findings {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
grid-template-rows: repeat(2, minmax(2.4rem, auto));
|
||||
border-top: 0;
|
||||
padding-block: 1.35rem;
|
||||
padding-block: 0.95rem;
|
||||
}
|
||||
|
||||
.evaluation-board[data-evaluation-beat="cohort"] .evaluation-board__cohort,
|
||||
@@ -279,6 +294,7 @@
|
||||
.evaluation-board__findings {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
grid-template-rows: repeat(2, minmax(2.4rem, auto));
|
||||
gap: 0.45rem 0.8rem;
|
||||
}
|
||||
|
||||
@@ -302,12 +318,21 @@
|
||||
|
||||
@media (max-width: 1080px) {
|
||||
.evaluation-board { grid-template-columns: minmax(12rem, 0.7fr) minmax(20rem, 1.3fr); }
|
||||
.evaluation-board__campaign-strip { grid-template-columns: minmax(12rem, 0.7fr) minmax(20rem, 1.3fr); }
|
||||
.evaluation-board__cohort { border-right: 1px solid var(--evaluation-rule); }
|
||||
.evaluation-board__audit-row { grid-template-columns: 1fr; }
|
||||
.evaluation-board[data-evaluation-focus="cohort"],
|
||||
.evaluation-board[data-evaluation-focus="findings"] {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.evaluation-board[data-evaluation-focus="cohort"] .evaluation-board__campaign-strip,
|
||||
.evaluation-board[data-evaluation-focus="findings"] .evaluation-board__campaign-strip {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.evaluation-board[data-evaluation-focus="cohort"] .evaluation-board__cohort,
|
||||
.evaluation-board[data-evaluation-focus="findings"] .evaluation-board__cohort {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.stage-caption__eyebrow {
|
||||
@@ -520,9 +545,7 @@
|
||||
}
|
||||
|
||||
.conclusion-map[data-conclusion-beat="limits"] .conclusion-map__future,
|
||||
.conclusion-map[data-conclusion-beat="conclusion"] .conclusion-map__future,
|
||||
.conclusion-map[data-conclusion-beat="future"] .conclusion-map__non-claims,
|
||||
.conclusion-map[data-conclusion-beat="conclusion"] .conclusion-map__non-claims {
|
||||
.conclusion-map[data-conclusion-beat="future"] .conclusion-map__non-claims {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -535,11 +558,59 @@
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
.conclusion-map[data-conclusion-beat="conclusion"] .conclusion-map__node--substrate {
|
||||
min-height: 7.5rem;
|
||||
padding: 1rem 1.25rem;
|
||||
border-width: 2px;
|
||||
box-shadow: 0 0 0 0.25rem color-mix(in oklch, var(--conclusion-ink) 10%, transparent);
|
||||
}
|
||||
|
||||
.conclusion-map[data-conclusion-beat="conclusion"] {
|
||||
min-height: min(26rem, 62vh);
|
||||
}
|
||||
|
||||
.conclusion-map[data-conclusion-beat="conclusion"] .conclusion-map__flow-unit--substrate-stack {
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
.conclusion-map[data-conclusion-beat="conclusion"] .conclusion-map__node--evidence {
|
||||
min-height: 3.6rem;
|
||||
padding: 0.55rem 0.75rem;
|
||||
}
|
||||
|
||||
.conclusion-map[data-conclusion-beat="conclusion"] .conclusion-map__node--evidence small {
|
||||
font-size: 0.76rem;
|
||||
}
|
||||
|
||||
.conclusion-map[data-conclusion-beat="conclusion"] .conclusion-map__non-claims li {
|
||||
padding: 0.35rem 0.5rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.conclusion-map[data-conclusion-beat="conclusion"] .conclusion-map__future li {
|
||||
gap: 0.35rem;
|
||||
padding: 0.3rem 0.45rem;
|
||||
}
|
||||
|
||||
.conclusion-map[data-conclusion-beat="conclusion"] .conclusion-map__future small {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.conclusion-map[data-conclusion-beat="conclusion"] .conclusion-map__node--substrate strong {
|
||||
font-size: clamp(1.35rem, 2.3vw, 1.75rem);
|
||||
}
|
||||
|
||||
.conclusion-map[data-conclusion-beat="conclusion"] .conclusion-map__non-claims,
|
||||
.conclusion-map[data-conclusion-beat="conclusion"] .conclusion-map__future {
|
||||
opacity: 0.38;
|
||||
transform: translateY(0.15rem);
|
||||
}
|
||||
|
||||
.conclusion-map[data-conclusion-beat="conclusion"] .conclusion-map__statement {
|
||||
padding-block: 1.1rem 0.45rem;
|
||||
padding-block: 0.45rem 0.2rem;
|
||||
border-top-color: var(--conclusion-ink);
|
||||
color: var(--conclusion-ink);
|
||||
font-size: 1.25rem;
|
||||
font-size: clamp(1.45rem, 2.7vw, 2rem);
|
||||
font-style: normal;
|
||||
font-weight: 650;
|
||||
text-align: center;
|
||||
@@ -2169,7 +2240,7 @@
|
||||
display: grid;
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
grid-template-rows: 8rem minmax(0, 1fr);
|
||||
grid-template-rows: auto minmax(0, 1fr);
|
||||
gap: 0.9rem;
|
||||
}
|
||||
|
||||
@@ -2215,6 +2286,7 @@
|
||||
|
||||
.opening-thesis__statement h2 {
|
||||
margin: 0;
|
||||
border-bottom: 0;
|
||||
color: var(--opening-ink);
|
||||
font: 800 clamp(2.85rem, 5.5vw, 4.2rem) / 0.94 var(--font-editorial);
|
||||
letter-spacing: -0.03em;
|
||||
|
||||
Reference in New Issue
Block a user