feat(rectification): show the credible range as a persistent timeline
The range is the only quantity that expresses convergence, and it existed only as a sentence in the transcript. The bar makes it permanent. It is the chat grid's first row, outside the scroll container, so scrollHeight is untouched and use-conversation-scroll-anchor needs no change. Its height is fixed because nothing observes it: a growing bar would alter clientHeight and let an anchored reader lose the tail. The axis is the current search window, not the opening one, since widening overruns the opening window. Marks are binary — in range or excluded — because relative support between candidate minutes carries no demonstrated minute-level discrimination (BUG-560, blocked). Band and marks move by transform alone; globals.css bans width transitions, and transform keeps the motion off the layout path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016P5RoqzmUQEbeC2qjAkeGr
This commit is contained in:
co-authored by
Claude Fable 5
parent
109b1d7f0c
commit
ce91a0d23c
@@ -2673,7 +2673,127 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
display: grid;
|
||||
grid-template-rows: minmax(0, 1fr) auto;
|
||||
/* Timeline row, scroll row, composer row. The timeline is deliberately its
|
||||
own row rather than a sticky child of .conversation: outside the scroll
|
||||
container it leaves scrollHeight untouched, so the stick-to-bottom distance
|
||||
in use-conversation-scroll-anchor stays exact and its ResizeObserver (which
|
||||
watches only the container's children) never sees it. */
|
||||
grid-template-rows: var(--rectification-timeline-height) minmax(0, 1fr) auto;
|
||||
}
|
||||
/* Fixed height is correctness, not taste: the bar sits outside the scroll
|
||||
container, so a height change alters clientHeight with nothing observing it,
|
||||
and an anchored reader would have content slide out of view unrecovered.
|
||||
The pending state keeps the same box for the same reason. */
|
||||
.rectification-workspace__chat {
|
||||
--rectification-timeline-height: 64px;
|
||||
}
|
||||
.rectification-timeline {
|
||||
height: var(--rectification-timeline-height);
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: var(--space-1);
|
||||
padding: 0 var(--space-5);
|
||||
background: var(--color-canvas);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
overflow: hidden;
|
||||
}
|
||||
.rectification-timeline__readout {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: var(--space-2);
|
||||
font-size: 13px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.rectification-timeline__range {
|
||||
font-variant-numeric: tabular-nums;
|
||||
font-weight: 500;
|
||||
color: var(--color-ink);
|
||||
}
|
||||
.rectification-timeline__width {
|
||||
color: var(--color-ink-secondary);
|
||||
}
|
||||
.rectification-timeline__axis {
|
||||
position: relative;
|
||||
height: 26px;
|
||||
flex: none;
|
||||
}
|
||||
.rectification-timeline__rule {
|
||||
position: absolute;
|
||||
inset-inline: 0;
|
||||
top: 7px;
|
||||
height: 1px;
|
||||
background: var(--color-border-strong);
|
||||
}
|
||||
/* Positioned and resized by transform alone: transitioning left/width would run
|
||||
layout on every frame, and this stylesheet bans width transitions outright
|
||||
(the sidebar shell animates none of its geometry either). The band is full
|
||||
width and scaled down from its left edge, so one transform carries both the
|
||||
start and the span. No side borders — scaleX would distort them, and the
|
||||
fill edge already reads as the boundary. */
|
||||
.rectification-timeline__band {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 11px;
|
||||
border-radius: 2px;
|
||||
background: var(--color-action-soft);
|
||||
transform-origin: left center;
|
||||
will-change: transform;
|
||||
transition: transform 420ms cubic-bezier(.32, .72, .24, 1);
|
||||
}
|
||||
.rectification-timeline__mark-at {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
transition: transform 420ms cubic-bezier(.32, .72, .24, 1);
|
||||
}
|
||||
/* Every mark is the same size. Relative support between candidate minutes is
|
||||
7–9 out of 100 with no demonstrated minute-level discrimination (BUG-560,
|
||||
blocked), so grading them by size or weight would show a difference the
|
||||
engine cannot back. In-range versus excluded is the only honest encoding. */
|
||||
.rectification-timeline__mark {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: -4.5px;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid var(--color-action);
|
||||
background: var(--color-action);
|
||||
transition: background 260ms ease, border-color 260ms ease, opacity 260ms ease;
|
||||
}
|
||||
.rectification-timeline__mark[data-state="out"] {
|
||||
background: var(--color-canvas);
|
||||
border-color: var(--color-border-strong);
|
||||
opacity: .55;
|
||||
}
|
||||
.rectification-timeline__tick {
|
||||
position: absolute;
|
||||
top: 13px;
|
||||
transform: translateX(-50%);
|
||||
font-size: 10px;
|
||||
line-height: 1.3;
|
||||
color: var(--color-ink-tertiary);
|
||||
font-variant-numeric: tabular-nums;
|
||||
white-space: nowrap;
|
||||
}
|
||||
/* 56px is the existing --rectification-jump-clearance (44px touch target plus
|
||||
space-3), reused rather than inventing a second constant. Past ~64px the bar
|
||||
costs a whole message bubble on a 667px viewport. */
|
||||
@media (max-width: 767px) {
|
||||
.rectification-workspace__chat {
|
||||
--rectification-timeline-height: 56px;
|
||||
}
|
||||
.rectification-timeline {
|
||||
padding-inline: var(--space-4);
|
||||
}
|
||||
}
|
||||
.rectification-workspace__chat .conversation {
|
||||
--rectification-jump-clearance: calc(44px + var(--space-3));
|
||||
|
||||
Reference in New Issue
Block a user