34f3c2888f
Nine screens against orchestra-ui-spec.md and the accepted mockups, on the ethos design system: signal violet #8F7AE5, the routing fork motif, the 64px rail and 56px top bar, mono for every machine value and sans for every human one. Each screen was built by its own agent against a fixed foundation, so the shell, tokens and primitives have one author and the screens cannot drift into nine dialects. Real data only. Where no endpoint exists the screen says which one it needs instead of inventing a value. That is most of what was learned here: Steer / Correct is disabled because nothing records a human decision from the web, take-control is disabled because nothing forwards keystrokes to a pane, context occupancy is missing from three screens, and projects can show no repo, remote, quality gate or verification policy because those live only in config.jsonc. Three bugs the render caught that no computed value would have: The previous stylesheet fought every shared class name and leaked properties the new rules never mention, which is how position:fixed survived on .topbar. It is now scoped under .legacy and applies only to the login route, which also stops its green accent and its backdrop-filter from reaching the console. Go marshals a zero time.Time as "0001-01-01T00:00:00Z" and omitempty does not omit a struct, so absent timestamps arrived populated-looking and rendered as "739855d ago". Stripped once at the API boundary every screen reads through, with a test. Long machine ids overflowed their cards and painted under the next one. Verified by rendering: chromium screenshots of the dashboard, tasks, task detail, terminal, workers and review at 1440px, and the dashboard at 390px. Geist is still not on disk, so both stacks fall back to the system faces. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CVbaKucEYBjMqVeUgJUsc1
203 lines
3.5 KiB
CSS
203 lines
3.5 KiB
CSS
/* Tasks list. Only what the shared shell does not already carry: the row
|
|
column geometry, the group disclosure, and the filter bar. */
|
|
|
|
.tasks-controls {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 16px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.tasks-tabs {
|
|
display: flex;
|
|
gap: 2px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.tasks-tab {
|
|
background: none;
|
|
border: 0;
|
|
border-bottom: 2px solid transparent;
|
|
padding: 7px 11px;
|
|
color: var(--text-mid);
|
|
cursor: pointer;
|
|
transition: color var(--fast) var(--ease), border-color var(--fast) var(--ease);
|
|
}
|
|
|
|
.tasks-tab span {
|
|
font-size: 12px;
|
|
margin-left: 5px;
|
|
}
|
|
|
|
.tasks-tab:hover {
|
|
color: var(--text-hi);
|
|
}
|
|
|
|
.tasks-tab[aria-selected='true'] {
|
|
color: var(--text-hi);
|
|
border-bottom-color: var(--accent);
|
|
}
|
|
|
|
.tasks-filters {
|
|
display: flex;
|
|
gap: 10px;
|
|
margin-left: auto;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.tasks-filter {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 7px;
|
|
}
|
|
|
|
.tasks-filter select {
|
|
font-family: var(--mono);
|
|
font-size: 12px;
|
|
color: var(--text-machine);
|
|
background: var(--bg-2);
|
|
border: 1px solid var(--line);
|
|
border-radius: var(--r-sm);
|
|
padding: 5px 8px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.tasks-filter select:hover {
|
|
border-color: var(--line-hi);
|
|
}
|
|
|
|
.page-head .count {
|
|
font-size: 12px;
|
|
padding: 2px 8px;
|
|
border-radius: 999px;
|
|
background: var(--bg-2);
|
|
border: 1px solid var(--line);
|
|
}
|
|
|
|
/* ── group disclosure ────────────────────────────────────────────────── */
|
|
|
|
.tasks-group > summary {
|
|
cursor: pointer;
|
|
list-style: none;
|
|
}
|
|
|
|
.tasks-group > summary::-webkit-details-marker {
|
|
display: none;
|
|
}
|
|
|
|
.tasks-group:not([open]) > summary {
|
|
border-bottom: 0;
|
|
}
|
|
|
|
.tasks-group > summary > svg:first-child {
|
|
color: var(--text-lo);
|
|
}
|
|
|
|
.tasks-group > summary > svg:last-child {
|
|
margin-left: auto;
|
|
color: var(--text-lo);
|
|
transform: rotate(90deg);
|
|
transition: transform var(--fast) var(--ease);
|
|
}
|
|
|
|
.tasks-group[open] > summary > svg:last-child {
|
|
transform: rotate(-90deg);
|
|
}
|
|
|
|
/* ── row geometry ────────────────────────────────────────────────────── */
|
|
|
|
.task-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 18px;
|
|
color: inherit;
|
|
}
|
|
|
|
.task-row > svg:last-child {
|
|
color: var(--text-lo);
|
|
flex: none;
|
|
}
|
|
|
|
.task-row-main {
|
|
flex: 1 1 220px;
|
|
min-width: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.task-row-main .row-title,
|
|
.task-row-main .row-sub {
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.task-row-phase {
|
|
flex: none;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 4px;
|
|
}
|
|
|
|
.task-row-phase-name {
|
|
font-size: 10px;
|
|
letter-spacing: 0.04em;
|
|
}
|
|
|
|
/* The compact path carries no labels, so the connector no longer needs to
|
|
sit above a name. */
|
|
.tasks-phases .phase-step {
|
|
min-width: 0;
|
|
}
|
|
|
|
.tasks-phases .phase-link {
|
|
width: 14px;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.task-row-worker {
|
|
flex: none;
|
|
width: 150px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.task-row-when {
|
|
flex: none;
|
|
width: 118px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.task-row-status {
|
|
flex: none;
|
|
display: flex;
|
|
gap: 6px;
|
|
justify-content: flex-end;
|
|
min-width: 130px;
|
|
}
|
|
|
|
@media (max-width: 900px) {
|
|
.task-row-phase,
|
|
.task-row-when {
|
|
display: none;
|
|
}
|
|
|
|
.task-row-worker {
|
|
width: 110px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 640px) {
|
|
.task-row-worker {
|
|
display: none;
|
|
}
|
|
|
|
.tasks-filters {
|
|
margin-left: 0;
|
|
}
|
|
}
|