fix: close presentation visual pass review findings

This commit is contained in:
lda
2026-07-12 21:46:55 +07:00 Verified
parent 26efa88817
commit 1602f6946f
6 changed files with 178 additions and 106 deletions
+2 -2
View File
@@ -303,13 +303,13 @@ separate activity after these surfaces are stable.
[`presentation demo-chrome ownership`](superpowers/specs/2026-07-12-demo-chrome-ownership-design.md). [`presentation demo-chrome ownership`](superpowers/specs/2026-07-12-demo-chrome-ownership-design.md).
Implementation: Implementation:
[`presentation demo-chrome ownership plan`](historical/superpowers/plans/2026-07-12-presentation-demo-chrome-ownership.md). [`presentation demo-chrome ownership plan`](historical/superpowers/plans/2026-07-12-presentation-demo-chrome-ownership.md).
7. **Visual scale and color pass:** remove unwanted blue from Scenes 2 and 14, 7. **Completed: visual scale and color pass:** removed unwanted blue from Scenes 2 and 14,
shorten Scene 2's two-column composition, enlarge the focal diagrams in shorten Scene 2's two-column composition, enlarge the focal diagrams in
Scenes 7, 9, 13, and 14, separate Scene 7 Validate from Repair visuals, and Scenes 7, 9, 13, and 14, separate Scene 7 Validate from Repair visuals, and
improve Scene 1 title-box padding and contrast. Design: improve Scene 1 title-box padding and contrast. Design:
[`presentation visual scale and color pass`](superpowers/specs/2026-07-12-presentation-visual-scale-color-pass-design.md). [`presentation visual scale and color pass`](superpowers/specs/2026-07-12-presentation-visual-scale-color-pass-design.md).
Implementation: Implementation:
[`presentation visual scale and color pass plan`](superpowers/plans/2026-07-12-presentation-visual-scale-color-pass.md). [`presentation visual scale and color pass plan`](historical/superpowers/plans/2026-07-12-presentation-visual-scale-color-pass.md).
8. **Rehearsal gate:** run all 14 scenes at 16:9 and 4:3, verify the Scene 8 → 8. **Rehearsal gate:** run all 14 scenes at 16:9 and 4:3, verify the Scene 8 →
Scene 11 → Scene 12 path in live and replay modes, then review the story Scene 11 → Scene 12 path in live and replay modes, then review the story
flow, coverage, and ordering separately. flow, coverage, and ordering separately.
@@ -46,16 +46,16 @@ Files likely involved:
Steps: Steps:
- [ ] Add focused failing assertions for the title, problem, authoring, - [x] Add focused failing assertions for the title, problem, authoring,
lifecycle, evaluation, and conclusion surfaces. lifecycle, evaluation, and conclusion surfaces.
- [ ] Assert semantic markers for the dominant visual and active beat rather - [x] Assert semantic markers for the dominant visual and active beat rather
than fragile CSS pixel values. than fragile CSS pixel values.
- [ ] Add regression assertions that these editorial scenes do not gain demo - [x] Add regression assertions that these editorial scenes do not gain demo
footer controls, live target badges, or unexpected chat chrome. footer controls, live target badges, or unexpected chat chrome.
- [ ] Add CSS contract checks only for durable selectors/tokens that must not - [x] Add CSS contract checks only for durable selectors/tokens that must not
regress, such as the neutral editorial surface and scene-specific layout regress, such as the neutral editorial surface and scene-specific layout
markers. markers.
- [ ] Run the focused tests and confirm the new assertions fail for the - [x] Run the focused tests and confirm the new assertions fail for the
intended reasons. intended reasons.
Do not encode exact color strings or arbitrary pixel coordinates in tests. Do not encode exact color strings or arbitrary pixel coordinates in tests.
@@ -73,17 +73,17 @@ Likely files:
Steps: Steps:
- [ ] Make the Scene 1 title beat title-first: one primary title treatment, - [x] Make the Scene 1 title beat title-first: one primary title treatment,
more internal padding, stronger text contrast, and no duplicate framing. more internal padding, stronger text contrast, and no duplicate framing.
- [ ] Preserve the later Scene 1 substrate/decomposition content without - [x] Preserve the later Scene 1 substrate/decomposition content without
forcing it into the title beat's dimensions. forcing it into the title beat's dimensions.
- [ ] Keep Scene 2's transcript in normal chat reading order: user request, - [x] Keep Scene 2's transcript in normal chat reading order: user request,
agent/tool activity, observation, and answer. agent/tool activity, observation, and answer.
- [ ] Shorten the two Scene 2 columns so the right automation explanation does - [x] Shorten the two Scene 2 columns so the right automation explanation does
not become a tall dashboard card. not become a tall dashboard card.
- [ ] Remove decorative blue from the editorial Scene 2 surface. Keep only - [x] Remove decorative blue from the editorial Scene 2 surface. Keep only
state or focus colors that communicate something specific. state or focus colors that communicate something specific.
- [ ] Verify both Scene 2 beats and the narrow canvas before moving on. - [x] Verify both Scene 2 beats and the narrow canvas before moving on.
If the opening components need shared layout, extract a small semantic wrapper; If the opening components need shared layout, extract a small semantic wrapper;
do not create another generic card primitive. do not create another generic card primitive.
@@ -101,16 +101,16 @@ Likely files:
Steps: Steps:
- [ ] Identify the existing authoring loop and its active beat mapping before - [x] Identify the existing authoring loop and its active beat mapping before
changing markup. changing markup.
- [ ] Give the active phase a larger, readable visual while keeping the full - [x] Give the active phase a larger, readable visual while keeping the full
loop as a compact orientation rail. loop as a compact orientation rail.
- [ ] Make `validate` show a diagnostic/contract-checking visual. - [x] Make `validate` show a diagnostic/contract-checking visual.
- [ ] Make `repair` show a correction/revision visual that is structurally - [x] Make `repair` show a correction/revision visual that is structurally
distinct from `validate`. distinct from `validate`.
- [ ] Preserve factual command labels and existing icons; do not add invented - [x] Preserve factual command labels and existing icons; do not add invented
tool output. tool output.
- [ ] Add tests proving the active phase and the Validate/Repair visual - [x] Add tests proving the active phase and the Validate/Repair visual
distinction. distinction.
Avoid adding five equally sized cards. The point is a dominant phase plus a Avoid adding five equally sized cards. The point is a dominant phase plus a
@@ -129,14 +129,14 @@ Likely files:
Steps: Steps:
- [ ] Identify which surface is primary for each lifecycle beat: discovery, - [x] Identify which surface is primary for each lifecycle beat: discovery,
draft, validate, artifact, and deployment. draft, validate, artifact, and deployment.
- [ ] Give the lifecycle visual most of the available stage area. - [x] Give the lifecycle visual most of the available stage area.
- [ ] Keep the prepared assistant as supporting context, not a second equal - [x] Keep the prepared assistant as supporting context, not a second equal
hero surface. hero surface.
- [ ] Preserve the current footer rail ownership and avoid adding another run - [x] Preserve the current footer rail ownership and avoid adding another run
or live-status control. or live-status control.
- [ ] Add layout/beat tests that verify the primary surface remains present and - [x] Add layout/beat tests that verify the primary surface remains present and
the scene does not regress to the old crowded composition. the scene does not regress to the old crowded composition.
Do not fold Scene 9 into the real live execution slice. This task is visual Do not fold Scene 9 into the real live execution slice. This task is visual
@@ -155,15 +155,15 @@ Likely files:
Steps: Steps:
- [ ] Choose one dominant evaluation visual per beat: cohort, validity, and - [x] Choose one dominant evaluation visual per beat: cohort, validity, and
findings should not be three near-identical text panels. findings should not be three near-identical text panels.
- [ ] Increase the scale of the relevant diagram/stat treatment while keeping - [x] Increase the scale of the relevant diagram/stat treatment while keeping
methodology limits legible as support. methodology limits legible as support.
- [ ] Give the conclusion one clear contribution/limits visual rather than a - [x] Give the conclusion one clear contribution/limits visual rather than a
dense summary wall. dense summary wall.
- [ ] Remove unnecessary blue from Scene 14 while preserving readable contrast. - [x] Remove unnecessary blue from Scene 14 while preserving readable contrast.
- [ ] Keep the Questions beat usable and free of accidental demo chrome. - [x] Keep the Questions beat usable and free of accidental demo chrome.
- [ ] Add tests for dominant-beat markers and conclusion surface behavior. - [x] Add tests for dominant-beat markers and conclusion surface behavior.
Do not invent new evaluation numbers or claims. All visual labels must come Do not invent new evaluation numbers or claims. All visual labels must come
from the storyboard or existing factual projections. from the storyboard or existing factual projections.
@@ -174,21 +174,21 @@ from the storyboard or existing factual projections.
Steps: Steps:
- [ ] Run focused presentation tests after each task. - [x] Run focused presentation tests after each task.
- [ ] Run the full web test suite: - [x] Run the full web test suite:
`pnpm --dir web test`. `pnpm --dir web test`.
- [ ] Run typecheck: - [x] Run typecheck:
`pnpm --dir web typecheck`. `pnpm --dir web typecheck`.
- [ ] Run build: - [x] Run build:
`pnpm --dir web build`. `pnpm --dir web build`.
- [ ] Capture screenshots for the representative routes at `1280x720` and - [x] Capture screenshots for the representative routes at `1280x720` and
`1024x768`. `1024x768`.
- [ ] Confirm no accidental outer scroll, clipped title text, unreadable - [x] Confirm no accidental outer scroll, clipped title text, unreadable
diagram labels, or duplicate chrome. diagram labels, or duplicate chrome.
- [ ] Re-run `git diff --check`. - [x] Re-run `git diff --check`.
- [ ] Run the two-axis review before declaring completion. - [x] Run the two-axis review before declaring completion.
- [ ] Update `docs/current_roadmap.md` with the completed plan link. - [x] Update `docs/current_roadmap.md` with the completed plan link.
- [ ] Move this plan to - [x] Move this plan to
`docs/historical/superpowers/plans/2026-07-12-presentation-visual-scale-color-pass.md` `docs/historical/superpowers/plans/2026-07-12-presentation-visual-scale-color-pass.md`
only after implementation and review are complete. only after implementation and review are complete.
@@ -217,6 +217,34 @@ describe("AssistantOperatorThread", () => {
} }
}); });
it("can show the latest response in a static comparison transcript", async () => {
const setScrollTop = vi.fn();
const descriptors = {
scrollTop: Object.getOwnPropertyDescriptor(HTMLDivElement.prototype, "scrollTop"),
scrollHeight: Object.getOwnPropertyDescriptor(HTMLDivElement.prototype, "scrollHeight"),
clientHeight: Object.getOwnPropertyDescriptor(HTMLDivElement.prototype, "clientHeight"),
};
try {
Object.defineProperties(HTMLDivElement.prototype, {
scrollTop: { configurable: true, get: () => 0, set: setScrollTop },
scrollHeight: { configurable: true, get: () => 240 },
clientHeight: { configurable: true, get: () => 80 },
});
render(<AssistantOperatorThread mode="dock" messages={[]} scrollMode="end" />);
await waitFor(() => expect(setScrollTop).toHaveBeenCalledWith(160));
} finally {
for (const [name, descriptor] of Object.entries(descriptors)) {
if (descriptor) {
Object.defineProperty(HTMLDivElement.prototype, name, descriptor);
} else {
delete (HTMLDivElement.prototype as unknown as Record<string, unknown>)[name];
}
}
}
});
it("pairs a lone tool call with its result", () => { it("pairs a lone tool call with its result", () => {
const messages: ReadonlyArray<AgentMessage> = [ const messages: ReadonlyArray<AgentMessage> = [
{ {
@@ -23,7 +23,7 @@ import {
type AssistantOperatorThreadProps = { type AssistantOperatorThreadProps = {
readonly mode: "hidden" | "full" | "rail" | "dock"; readonly mode: "hidden" | "full" | "rail" | "dock";
readonly messages: ReadonlyArray<AgentMessage>; readonly messages: ReadonlyArray<AgentMessage>;
readonly scrollMode?: "active" | "start" | undefined; readonly scrollMode?: "active" | "start" | "end" | undefined;
readonly submitApproval?: (() => void) | undefined; readonly submitApproval?: (() => void) | undefined;
readonly requestRevision?: (() => void) | undefined; readonly requestRevision?: (() => void) | undefined;
readonly ariaLabel?: string | undefined; readonly ariaLabel?: string | undefined;
@@ -273,13 +273,22 @@ export const AssistantOperatorThread = ({
}, [activeToolGroupId, toolGroupOverrides]); }, [activeToolGroupId, toolGroupOverrides]);
useEffect(() => { useEffect(() => {
const viewport = viewportRef.current;
if (!viewport) return;
// Static comparison transcripts should show their final answer; live
// presentation docks instead keep the beat-owned tool group in view.
if (!activeToolGroupId && scrollMode === "end") {
viewport.scrollTop = Math.max(0, viewport.scrollHeight - viewport.clientHeight);
return;
}
if (!activeToolGroupId) return; if (!activeToolGroupId) return;
// The same transcript can be much taller than the Scene 9 dock. Keep the // The same transcript can be much taller than the Scene 9 dock. Keep the
// beat-owned group visible without maintaining a second scroll-state model. // beat-owned group visible without maintaining a second scroll-state model.
const viewport = viewportRef.current;
const activeGroup = viewport const activeGroup = viewport
?.querySelector<HTMLElement>(`[data-tool-group-id="${activeToolGroupId}"]`); ?.querySelector<HTMLElement>(`[data-tool-group-id="${activeToolGroupId}"]`);
if (!viewport || !activeGroup) return; if (!activeGroup) return;
const bottomAlignedTop = activeGroup.offsetTop + activeGroup.offsetHeight - viewport.clientHeight; const bottomAlignedTop = activeGroup.offsetTop + activeGroup.offsetHeight - viewport.clientHeight;
const dockCenteredTop = activeGroup.offsetTop - (viewport.clientHeight - activeGroup.offsetHeight) / 2; const dockCenteredTop = activeGroup.offsetTop - (viewport.clientHeight - activeGroup.offsetHeight) / 2;
const requestedTop = scrollMode === "start" const requestedTop = scrollMode === "start"
@@ -78,7 +78,12 @@ export const ProblemLoopScene = ({ scene, beat }: ProblemLoopSceneProps) => {
<p>Good at getting through one request.</p> <p>Good at getting through one request.</p>
</header> </header>
<div className="problem-chat-card__transcript" aria-label="one-off assistant transcript" role="group"> <div className="problem-chat-card__transcript" aria-label="one-off assistant transcript" role="group">
<AssistantOperatorThread mode="dock" messages={oneOffToolLoopMessages} ariaLabel="one-off assistant transcript" /> <AssistantOperatorThread
mode="dock"
messages={oneOffToolLoopMessages}
scrollMode="end"
ariaLabel="one-off assistant transcript"
/>
</div> </div>
<p className="problem-artifact-note">The useful work lives in the conversation history.</p> <p className="problem-artifact-note">The useful work lives in the conversation history.</p>
</article> </article>
@@ -537,8 +537,8 @@
.conclusion-map[data-conclusion-beat="conclusion"] .conclusion-map__statement { .conclusion-map[data-conclusion-beat="conclusion"] .conclusion-map__statement {
padding-block: 1.1rem 0.45rem; padding-block: 1.1rem 0.45rem;
border-top-color: var(--accent-cyan); border-top-color: var(--conclusion-ink);
color: var(--text-primary); color: var(--conclusion-ink);
font-size: 1.25rem; font-size: 1.25rem;
font-style: normal; font-style: normal;
font-weight: 650; font-weight: 650;
@@ -2412,10 +2412,12 @@
color: var(--problem-muted); color: var(--problem-muted);
} }
.problem-loop-scene[data-presentation-surface="editorial"] .assistant-operator-thread[data-surface="dock"] .assistant-thread,
.problem-loop-scene[data-presentation-surface="editorial"] .assistant-thread { .problem-loop-scene[data-presentation-surface="editorial"] .assistant-thread {
border-color: var(--problem-rule); border-color: var(--problem-rule);
border-radius: 0.35rem; border-radius: 0.35rem;
background: color-mix(in oklch, var(--problem-paper) 92%, var(--problem-muted)); background: color-mix(in oklch, var(--problem-paper) 92%, var(--problem-muted));
color: var(--problem-ink);
} }
.problem-loop-scene[data-presentation-surface="editorial"] .assistant-message[data-role="assistant"] { .problem-loop-scene[data-presentation-surface="editorial"] .assistant-message[data-role="assistant"] {
@@ -2459,6 +2461,38 @@
background: transparent; background: transparent;
} }
/* Keep the compact assistant-ui transcript readable inside the fixed comparison card. */
.problem-loop-scene[data-presentation-surface="editorial"] .assistant-thread__viewport,
.problem-loop-scene[data-presentation-surface="editorial"] .assistant-message[data-role="assistant"] p,
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-fallback-args-value"],
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-fallback-result-content"] {
color: var(--problem-ink);
}
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-fallback-args-value"],
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-fallback-result-content"] {
border-color: var(--problem-rule);
background: color-mix(in oklch, var(--problem-paper) 86%, var(--problem-muted));
}
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-group-trigger"],
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-fallback-trigger"] {
border-color: transparent;
background: transparent;
color: var(--problem-muted);
}
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-group-content"] > div,
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-fallback-content"] > div {
border-color: var(--problem-rule);
background: transparent;
}
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-group-content"] [data-slot="tool-fallback-root"] {
border-color: var(--problem-rule);
background: color-mix(in oklch, var(--problem-paper) 90%, var(--problem-muted));
}
.problem-artifact-header { .problem-artifact-header {
display: grid; display: grid;
gap: 0.18rem; gap: 0.18rem;
@@ -2490,7 +2524,31 @@
.problem-chat-card__transcript { .problem-chat-card__transcript {
min-height: 0; min-height: 0;
overflow: hidden; overflow: auto;
scrollbar-width: none;
}
.problem-chat-card__transcript::-webkit-scrollbar {
display: none;
}
.problem-chat-card .assistant-thread__viewport {
padding: 0.45rem;
}
.problem-chat-card .assistant-message {
margin-bottom: 0.25rem;
}
.problem-chat-card .assistant-message__user-bubble {
padding: 0.35rem 0.55rem;
font-size: 0.72rem;
}
.problem-chat-card [data-slot="tool-group-trigger"],
.problem-chat-card [data-slot="tool-fallback-trigger"] {
padding-block: 0.22rem;
font-size: 0.62rem;
} }
.problem-blueprint .concept-rail { .problem-blueprint .concept-rail {
@@ -2546,6 +2604,7 @@
.problem-loop-scene__bridge { .problem-loop-scene__bridge {
display: none; display: none;
} }
} }
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
@@ -3677,6 +3736,23 @@
.prepared-lifecycle-scene[data-presentation-surface="editorial"] .presentation-assistant-pane { .prepared-lifecycle-scene[data-presentation-surface="editorial"] .presentation-assistant-pane {
background: color-mix(in oklch, var(--authoring-paper) 92%, var(--authoring-muted)); background: color-mix(in oklch, var(--authoring-paper) 92%, var(--authoring-muted));
border-color: var(--authoring-rule); border-color: var(--authoring-rule);
color: var(--authoring-ink);
}
.prepared-lifecycle-scene[data-presentation-surface="editorial"] .presentation-assistant-pane__header > p,
.prepared-lifecycle-scene[data-presentation-surface="editorial"] .presentation-assistant-pane__composer label,
.prepared-lifecycle-scene[data-presentation-surface="editorial"] .presentation-assistant-pane__composer-help,
.prepared-lifecycle-scene[data-presentation-surface="editorial"] .presentation-assistant-pane__run-status {
color: var(--authoring-muted);
}
.prepared-lifecycle-scene[data-presentation-surface="editorial"] .presentation-assistant-pane__header h2 {
color: var(--authoring-ink);
}
.prepared-lifecycle-scene[data-presentation-surface="editorial"] .presentation-assistant-pane__composer textarea::placeholder {
color: var(--authoring-muted);
opacity: 1;
} }
.prepared-lifecycle-scene[data-presentation-surface="editorial"] .presentation-assistant-pane__conversation { .prepared-lifecycle-scene[data-presentation-surface="editorial"] .presentation-assistant-pane__conversation {
@@ -3740,6 +3816,19 @@
grid-template-columns: minmax(17rem, 0.65fr) auto minmax(0, 1.35fr); grid-template-columns: minmax(17rem, 0.65fr) auto minmax(0, 1.35fr);
} }
@container presentation-canvas (max-width: 1050px) {
.problem-loop-scene[data-presentation-surface="editorial"] {
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
align-items: center;
}
.problem-loop-scene[data-presentation-surface="editorial"] .problem-chat-card,
.problem-loop-scene[data-presentation-surface="editorial"] .problem-blueprint {
width: 100%;
height: min(22rem, 56vh);
}
}
@keyframes authoring-canvas-enter { @keyframes authoring-canvas-enter {
from { opacity: 0; } from { opacity: 0; }
to { opacity: 1; } to { opacity: 1; }
@@ -3988,62 +4077,3 @@
.authoring-bindings__rows code:last-child { .authoring-bindings__rows code:last-child {
color: var(--accent-cyan); color: var(--accent-cyan);
} }
/* Keep the editorial problem comparison readable after the shared chat rules. */
.problem-loop-scene[data-presentation-surface="editorial"] .assistant-operator-thread[data-surface="dock"] .assistant-thread,
.problem-loop-scene[data-presentation-surface="editorial"] .assistant-thread {
border-color: var(--problem-rule);
background: color-mix(in oklch, var(--problem-paper) 92%, var(--problem-muted));
color: var(--problem-ink);
}
.problem-loop-scene[data-presentation-surface="editorial"] .assistant-thread__viewport,
.problem-loop-scene[data-presentation-surface="editorial"] .assistant-message[data-role="assistant"],
.problem-loop-scene[data-presentation-surface="editorial"] .assistant-message[data-role="assistant"] p,
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-group-root"],
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-fallback-root"],
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-fallback-args-value"],
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-fallback-result-content"] {
color: var(--problem-ink);
}
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-fallback-args-value"],
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-fallback-result-content"] {
border-color: var(--problem-rule);
background: color-mix(in oklch, var(--problem-paper) 86%, var(--problem-muted));
}
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-group-trigger"],
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-fallback-trigger"] {
border-color: transparent;
background: transparent;
color: var(--problem-muted);
}
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-group-content"] > div,
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-fallback-content"] > div {
border-color: var(--problem-rule);
background: transparent;
}
.problem-loop-scene[data-presentation-surface="editorial"] [data-slot="tool-group-content"] [data-slot="tool-fallback-root"] {
border-color: var(--problem-rule);
background: color-mix(in oklch, var(--problem-paper) 90%, var(--problem-muted));
}
@container presentation-canvas (max-width: 1050px) {
.problem-loop-scene[data-presentation-surface="editorial"] {
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
align-items: center;
}
.problem-loop-scene[data-presentation-surface="editorial"] .problem-loop-scene__bridge {
display: none;
}
.problem-loop-scene[data-presentation-surface="editorial"] .problem-chat-card,
.problem-loop-scene[data-presentation-surface="editorial"] .problem-blueprint {
width: 100%;
height: min(22rem, 56vh);
}
}