Stabilize Planner Chat task detail spacing across expanded and mobile layouts. - Move Planner Chat body padding to the base selector so expand/collapse only changes height and flex behavior. - Apply the mobile Planner Chat padding override to the same base body selector. - Add CSS regression coverage and a patch changeset for the published CLI bundle. Files changed: .changeset/planner-chat-stable-spacing.md | 7 ++++ .../dashboard/app/components/TaskDetailModal.css | 11 +++++- ...etailModal.responsive-and-dependencies.test.tsx | 44 ++++++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-7333 Fusion-Task-Lineage: 84130908-fabb-433f-a48d-5d9c6649c234 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2847 lines
65 KiB
CSS
2847 lines
65 KiB
CSS
/* === Detail Modal === */
|
|
.task-detail-content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100%;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
}
|
|
|
|
.modal.task-detail-modal {
|
|
width: min(95vw, 800px);
|
|
max-width: 95vw;
|
|
min-width: 480px;
|
|
height: 85vh;
|
|
min-height: 480px;
|
|
max-height: calc(100dvh - var(--overlay-padding-top, 10vh) - 16px);
|
|
overflow: hidden;
|
|
resize: both;
|
|
}
|
|
|
|
/*
|
|
FNXC:TaskDetail 2026-06-22-20:00:
|
|
The gray top header band (task id + column badge) was over-padded. Trim its vertical padding for a more compact band, scoped to the task-detail header so the shared global .modal-header (used by other modals) is unaffected. Keep horizontal padding from --modal-padding; only the block padding shrinks.
|
|
*/
|
|
.task-detail-content > .modal-header {
|
|
padding-block: var(--space-sm);
|
|
}
|
|
|
|
.detail-title-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.detail-id {
|
|
font-family: var(--font-mono);
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.detail-column-badge {
|
|
font-size: 0.6875rem;
|
|
padding: calc(var(--space-xs) / 2) var(--space-sm);
|
|
border-radius: var(--radius-pill);
|
|
font-weight: 600;
|
|
letter-spacing: 0.03125rem;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
/*
|
|
FNXC:WorkflowBadges 2026-06-30-00:00:
|
|
Task detail workflow badges share the board badge's slight token-based icon-to-label gap so the canonical metadata badge stays readable while preserving inline truncation and timestamp ownership.
|
|
*/
|
|
.detail-workflow-badge {
|
|
column-gap: calc(var(--space-xs) / 2);
|
|
font-size: 0.6875rem;
|
|
padding: calc(var(--space-xs) / 2) var(--space-sm);
|
|
border-radius: var(--radius-pill);
|
|
font-weight: 600;
|
|
letter-spacing: 0.03125rem;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
flex: 0 1 auto;
|
|
min-width: 0;
|
|
max-width: 100%;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
color: var(--text-muted);
|
|
background: var(--surface-raised);
|
|
border: 1px solid var(--border);
|
|
}
|
|
.badge-triage {
|
|
background: var(--status-triage-bg);
|
|
color: var(--triage);
|
|
}
|
|
.badge-todo {
|
|
background: var(--status-todo-bg);
|
|
color: var(--todo);
|
|
}
|
|
.badge-in-progress {
|
|
background: var(--status-in-progress-bg);
|
|
color: var(--in-progress);
|
|
}
|
|
.badge-in-review {
|
|
background: var(--status-in-review-bg);
|
|
color: var(--in-review);
|
|
}
|
|
.badge-done {
|
|
background: var(--status-done-bg);
|
|
color: var(--done);
|
|
}
|
|
|
|
.detail-body {
|
|
padding: calc(var(--space-lg) + var(--space-xs));
|
|
min-width: 0;
|
|
overflow-x: hidden;
|
|
overflow-y: auto;
|
|
scrollbar-color: var(--border) transparent;
|
|
scrollbar-width: thin;
|
|
flex: 1;
|
|
}
|
|
|
|
.detail-body::-webkit-scrollbar {
|
|
width: 6px;
|
|
}
|
|
|
|
.detail-body::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
|
|
.detail-body::-webkit-scrollbar-thumb {
|
|
background: var(--border);
|
|
border-radius: var(--radius-sm);
|
|
}
|
|
|
|
.detail-body::-webkit-scrollbar-thumb:hover {
|
|
background: var(--text-muted);
|
|
}
|
|
|
|
/* When Activity → Raw Logs is active, switch to flex layout so the log section
|
|
can stretch to fill the remaining space above the action bar.
|
|
The detail-body itself should NOT scroll; the agent-log-viewer scrolls instead. */
|
|
.detail-body--agent-log {
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow-y: hidden;
|
|
}
|
|
|
|
/* Activity → Live and expanded Activity mirror the Raw Logs fill-height layout: the modal body does not scroll;
|
|
each segment owns internal scrolling while composers and controls stay visible. */
|
|
.detail-body--chat,
|
|
.detail-body--planner-chat {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
overflow-y: hidden;
|
|
/* FNXC:TaskDetailChat 2026-06-13-19:55: Chat box should sit in the chat view without excess vertical spacing around the composer (FN-6418), so only the chat body tightens vertical padding while shared detail tab padding remains unchanged. */
|
|
padding-block: var(--space-md);
|
|
}
|
|
|
|
/*
|
|
FNXC:TaskDetailPlannerChat 2026-06-30-23:58:
|
|
Planner Chat expand/collapse may reallocate height or hide mobile chrome, but it must not change the chat surface spacing. Keep body padding on the collapsed base selector and let expanded selectors own only flex/height behavior.
|
|
*/
|
|
.detail-body--planner-chat {
|
|
padding: var(--space-md);
|
|
}
|
|
|
|
.detail-title {
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
margin-bottom: var(--space-md);
|
|
overflow-wrap: anywhere;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.detail-title--collapsed {
|
|
display: -webkit-box;
|
|
-webkit-box-orient: vertical;
|
|
-webkit-line-clamp: 2;
|
|
line-clamp: 2;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/*
|
|
FNXC:TaskDetail 2026-06-22-20:00:
|
|
Summarize-as-title is an in-field affordance, not a separate full-width row: it sits inline with the title, pinned to the far right and bottom of the title area. Use a nowrap flex row where the title flexes to fill and the button is pushed right (margin-left:auto) and bottom-aligned (align-self:flex-end). The button shrinks to its content so it never steals title space.
|
|
*/
|
|
.detail-heading-row {
|
|
display: flex;
|
|
align-items: flex-end;
|
|
flex-wrap: nowrap;
|
|
gap: var(--space-sm);
|
|
margin-bottom: var(--space-md);
|
|
}
|
|
|
|
.detail-heading-row .detail-title {
|
|
margin-bottom: 0;
|
|
flex: 1 1 auto;
|
|
min-width: 0;
|
|
}
|
|
|
|
.detail-summarize-title-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-xs);
|
|
background: none;
|
|
border: none;
|
|
color: var(--text-dim);
|
|
font-size: 0.8125rem;
|
|
padding: 0;
|
|
cursor: pointer;
|
|
text-align: right;
|
|
margin-left: auto;
|
|
align-self: flex-end;
|
|
flex: 0 0 auto;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.detail-summarize-title-btn:hover:not(:disabled) {
|
|
color: var(--text);
|
|
}
|
|
|
|
.detail-summarize-title-btn:focus-visible {
|
|
outline: none;
|
|
box-shadow: var(--focus-ring-strong);
|
|
}
|
|
|
|
.detail-summarize-title-btn:disabled {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.detail-description-toggle {
|
|
display: block;
|
|
background: none;
|
|
border: none;
|
|
color: var(--text-dim);
|
|
font-size: 13px;
|
|
padding: 2px 0;
|
|
margin-bottom: var(--space-md);
|
|
cursor: pointer;
|
|
text-align: left;
|
|
}
|
|
|
|
.detail-description-toggle:hover {
|
|
color: var(--text);
|
|
}
|
|
|
|
/*
|
|
FNXC:TaskDetailMeta 2026-06-13-17:32:
|
|
The task-detail modal metadata must keep priority, execution mode, provenance, PR context, and timestamps in one horizontal row that wraps as needed instead of stacking each child as a separate line.
|
|
*/
|
|
.detail-meta {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: var(--space-sm) var(--space-md);
|
|
font-size: 12px;
|
|
color: var(--text-muted);
|
|
margin-bottom: var(--space-lg);
|
|
}
|
|
|
|
.detail-provenance {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-xs);
|
|
margin-top: 0;
|
|
margin-bottom: 0;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.detail-provenance svg {
|
|
width: 1em;
|
|
height: 1em;
|
|
}
|
|
|
|
.detail-provenance-link {
|
|
padding: 0;
|
|
border: 0;
|
|
background: transparent;
|
|
color: var(--todo);
|
|
cursor: pointer;
|
|
text-decoration: none;
|
|
font: inherit;
|
|
}
|
|
|
|
.detail-provenance-link:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.detail-provenance-link:focus-visible {
|
|
outline: none;
|
|
box-shadow: var(--focus-ring-strong);
|
|
border-radius: var(--radius-sm);
|
|
}
|
|
|
|
.detail-provenance-context {
|
|
display: inline-block;
|
|
max-width: 32ch;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
vertical-align: bottom;
|
|
}
|
|
|
|
.detail-timestamps {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
flex-wrap: nowrap;
|
|
gap: var(--space-xs);
|
|
color: var(--text-dim);
|
|
margin-top: 0;
|
|
}
|
|
|
|
.detail-timestamp-item {
|
|
display: inline-flex;
|
|
align-items: baseline;
|
|
gap: var(--space-xs);
|
|
}
|
|
|
|
.detail-timestamp-label {
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.detail-timestamp-separator {
|
|
color: var(--text-dim);
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
/*
|
|
FNXC:TaskDetail 2026-06-22-20:00:
|
|
Keep summarize-as-title pinned bottom-right inline with the title on mobile too (no wrap to a separate row), matching the desktop in-field affordance.
|
|
*/
|
|
.detail-heading-row {
|
|
align-items: flex-end;
|
|
}
|
|
|
|
.detail-summarize-title-btn {
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.detail-meta {
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.detail-provenance {
|
|
align-items: center;
|
|
}
|
|
|
|
/*
|
|
FNXC:TaskDetailWorkflow 2026-06-30-07:37:
|
|
Task details show workflow identity in the Updated timestamp section across desktop and mobile. Keep the canonical badge inline with Created/Updated metadata so header rows, embedded detail hosts, and mobile back-header details do not render duplicate workflow badges or empty mobile-only shells.
|
|
*/
|
|
.detail-timestamps {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: nowrap;
|
|
}
|
|
|
|
.detail-provenance-context {
|
|
max-width: 20ch;
|
|
}
|
|
|
|
.detail-timestamp-item {
|
|
align-items: baseline;
|
|
flex-wrap: nowrap;
|
|
}
|
|
}
|
|
|
|
.detail-meta-inline-controls {
|
|
/*
|
|
FNXC:TaskDetail 2026-06-22-20:00:
|
|
Priority chip and speed (execution-mode) toggle share one min-height token so they render at identical, equal height. Reduced from the old calc(space-2xl + space-xs) (~too tall) to a compact 30px that stays legible and tappable. Both controls also get trimmed vertical padding to match.
|
|
*/
|
|
--detail-priority-control-min-height: 30px;
|
|
|
|
display: flex;
|
|
align-items: stretch;
|
|
flex-wrap: nowrap;
|
|
gap: var(--space-xs);
|
|
}
|
|
|
|
.detail-priority-chip {
|
|
gap: var(--space-xs);
|
|
min-height: var(--detail-priority-control-min-height);
|
|
padding-block: var(--space-xs);
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.detail-priority-chip--saving {
|
|
opacity: 0.75;
|
|
}
|
|
|
|
.detail-priority-select {
|
|
border: 0;
|
|
background: transparent;
|
|
color: inherit;
|
|
font: inherit;
|
|
text-transform: uppercase;
|
|
letter-spacing: inherit;
|
|
cursor: pointer;
|
|
padding: 0;
|
|
min-height: inherit;
|
|
}
|
|
|
|
.detail-priority-select:focus-visible {
|
|
outline: none;
|
|
box-shadow: var(--focus-ring-strong);
|
|
border-radius: var(--radius-sm);
|
|
}
|
|
|
|
.detail-priority-select:disabled {
|
|
cursor: wait;
|
|
}
|
|
|
|
.detail-priority-select option {
|
|
color: var(--text);
|
|
background: var(--surface);
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.detail-execution-mode-toggle {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-xs);
|
|
min-height: var(--detail-priority-control-min-height);
|
|
padding-block: var(--space-xs);
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.detail-execution-mode-toggle svg {
|
|
width: 1em;
|
|
height: 1em;
|
|
}
|
|
|
|
.detail-execution-mode-toggle--fast {
|
|
color: var(--color-warning);
|
|
}
|
|
|
|
.detail-execution-mode-toggle--fast svg {
|
|
color: var(--color-warning);
|
|
background: color-mix(in srgb, var(--color-warning) 20%, transparent);
|
|
border-radius: var(--radius-pill);
|
|
padding: var(--space-xs);
|
|
box-shadow: var(--glow-warning);
|
|
}
|
|
|
|
.detail-execution-mode-toggle--saving {
|
|
opacity: 0.75;
|
|
}
|
|
|
|
.detail-execution-mode-toggle:disabled {
|
|
cursor: wait;
|
|
}
|
|
|
|
|
|
/* Error alert in task detail modal */
|
|
.detail-error-alert {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: var(--space-md);
|
|
margin: var(--space-md) 0 var(--space-lg);
|
|
padding: var(--space-md) calc(var(--space-md) + var(--space-xs) / 2);
|
|
background: color-mix(in srgb, var(--color-error-dark) 10%, transparent);
|
|
border: 1px solid color-mix(in srgb, var(--color-error-dark) 30%, transparent);
|
|
border-radius: var(--radius-md);
|
|
}
|
|
|
|
.detail-error-icon {
|
|
flex-shrink: 0;
|
|
font-size: 18px;
|
|
line-height: 1;
|
|
}
|
|
|
|
.detail-error-content {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.detail-error-title {
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
color: var(--color-error-dark);
|
|
margin-bottom: var(--space-xs);
|
|
}
|
|
|
|
.detail-error-message {
|
|
font-size: 12px;
|
|
color: var(--text-muted);
|
|
line-height: 1.5;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.task-pause-reason {
|
|
margin: var(--space-md) 0 var(--space-lg);
|
|
padding: var(--space-md);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-md);
|
|
background: color-mix(in srgb, var(--color-warning) 12%, transparent);
|
|
}
|
|
|
|
.task-pause-reason-label {
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
color: var(--text);
|
|
}
|
|
|
|
.task-pause-stderr {
|
|
margin: var(--space-sm) 0 0;
|
|
padding: var(--space-sm);
|
|
border-radius: var(--radius-sm);
|
|
border: 1px solid var(--border);
|
|
background: var(--bg);
|
|
color: var(--text-muted);
|
|
font-family: var(--font-mono);
|
|
font-size: 11px;
|
|
max-height: 220px;
|
|
overflow: auto;
|
|
white-space: pre-wrap;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.detail-section {
|
|
margin-top: var(--space-lg);
|
|
}
|
|
|
|
.detail-pr-tab {
|
|
display: grid;
|
|
gap: var(--space-lg);
|
|
}
|
|
|
|
.detail-pr-tab .detail-section,
|
|
.detail-pr-section {
|
|
margin-top: 0;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.detail-pr-tab {
|
|
gap: var(--space-md);
|
|
}
|
|
}
|
|
|
|
.detail-provider-icons {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-xs);
|
|
}
|
|
|
|
.detail-meta-label-icon {
|
|
vertical-align: middle;
|
|
margin-right: var(--space-xs);
|
|
}
|
|
|
|
.detail-source-section {
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-md);
|
|
background: var(--card);
|
|
padding: var(--space-sm) var(--space-md);
|
|
}
|
|
|
|
.detail-source-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: var(--space-md);
|
|
margin: 0;
|
|
}
|
|
|
|
.detail-source-grid dt {
|
|
font-size: 11px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.4px;
|
|
color: var(--text-muted);
|
|
margin-bottom: var(--space-xs);
|
|
}
|
|
|
|
.detail-source-grid dd {
|
|
margin: 0;
|
|
color: var(--text);
|
|
font-family: var(--font-mono);
|
|
word-break: break-word;
|
|
}
|
|
|
|
.detail-source-link {
|
|
color: var(--todo);
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.detail-source-link--summary {
|
|
text-decoration: none;
|
|
}
|
|
|
|
.detail-source-link:hover {
|
|
color: var(--text);
|
|
}
|
|
|
|
.detail-source-empty {
|
|
color: var(--text-dim);
|
|
}
|
|
|
|
.detail-source-edit-group {
|
|
margin-top: var(--space-sm);
|
|
}
|
|
|
|
.detail-source-edit-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.detail-source-edit-group small {
|
|
display: block;
|
|
margin-top: var(--space-xs);
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.detail-source-header {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: var(--space-xs);
|
|
}
|
|
|
|
.detail-source-section .detail-source-header {
|
|
flex-wrap: nowrap;
|
|
align-items: center;
|
|
min-width: 0;
|
|
}
|
|
|
|
.detail-source-summary {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: var(--space-xs);
|
|
}
|
|
|
|
.detail-source-section .detail-source-summary {
|
|
flex: 1 1 auto;
|
|
min-width: 0;
|
|
}
|
|
|
|
.detail-source-label {
|
|
color: var(--text-muted);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.detail-source-provider-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-xs);
|
|
padding: 0 var(--space-xs);
|
|
border-radius: var(--radius-pill);
|
|
background: color-mix(in srgb, var(--text-muted) 18%, transparent);
|
|
color: var(--text-muted);
|
|
font-size: calc(var(--space-sm) + var(--space-xs) * 0.75);
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.detail-source-provider-badge svg {
|
|
width: 1em;
|
|
height: 1em;
|
|
}
|
|
|
|
.detail-source-number {
|
|
color: var(--text);
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
.detail-github-tracking-enable {
|
|
margin-left: auto;
|
|
align-self: center;
|
|
flex: 0 0 auto;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
padding-block: calc(var(--space-xs) / 2);
|
|
padding-inline: var(--space-sm);
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.detail-source-toggle {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
min-width: calc(var(--space-lg) + var(--space-xl) - var(--space-xs));
|
|
min-height: calc(var(--space-lg) + var(--space-xl) - var(--space-xs));
|
|
padding: var(--space-xs);
|
|
border: 0;
|
|
border-radius: var(--radius-sm);
|
|
background: transparent;
|
|
color: var(--text-muted);
|
|
cursor: pointer;
|
|
transition: background var(--transition-fast), color var(--transition-fast);
|
|
}
|
|
|
|
.detail-source-section .detail-source-toggle {
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.detail-source-header .detail-source-toggle {
|
|
margin-left: var(--space-sm);
|
|
}
|
|
|
|
.detail-source-toggle:hover {
|
|
color: var(--text);
|
|
background: var(--card-hover);
|
|
}
|
|
|
|
.detail-source-toggle:focus-visible {
|
|
outline: none;
|
|
box-shadow: var(--focus-ring-strong);
|
|
}
|
|
|
|
.detail-source-chevron--expanded {
|
|
transform: rotate(90deg);
|
|
}
|
|
|
|
.detail-source-section .detail-source-grid {
|
|
margin-top: var(--space-sm);
|
|
padding-top: var(--space-sm);
|
|
border-top: 1px solid var(--border);
|
|
}
|
|
|
|
.detail-github-tracking-section {
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-md);
|
|
background: var(--card);
|
|
padding: var(--space-xs) var(--space-md);
|
|
}
|
|
|
|
.detail-github-tracking-section .detail-source-header {
|
|
flex-wrap: nowrap;
|
|
align-items: center;
|
|
min-width: 0;
|
|
}
|
|
|
|
.detail-github-tracking-section .detail-source-summary {
|
|
flex: 1 1 auto;
|
|
flex-wrap: nowrap;
|
|
min-width: 0;
|
|
}
|
|
|
|
.detail-github-tracking-section .detail-source-empty {
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.detail-github-tracking-section .detail-source-toggle {
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.detail-github-tracking-section .detail-github-tracking-enable {
|
|
align-self: center;
|
|
}
|
|
|
|
.detail-github-tracking-spinner {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-left: auto;
|
|
align-self: center;
|
|
flex: 0 0 auto;
|
|
min-width: var(--space-lg);
|
|
min-height: var(--space-lg);
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.detail-github-tracking-content {
|
|
margin-top: var(--space-xs);
|
|
padding-top: var(--space-xs);
|
|
border-top: 1px solid var(--border);
|
|
}
|
|
|
|
.detail-github-tracking-grid {
|
|
margin-top: 0;
|
|
padding-top: 0;
|
|
}
|
|
|
|
.detail-github-issue-state {
|
|
font-weight: 600;
|
|
text-transform: lowercase;
|
|
}
|
|
|
|
.detail-github-issue-state--open {
|
|
color: var(--color-success);
|
|
}
|
|
|
|
.detail-github-issue-state--closed {
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.detail-github-tracking-controls {
|
|
margin-top: var(--space-sm);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.detail-github-tracking-helper {
|
|
display: block;
|
|
color: var(--text-muted);
|
|
line-height: 1.4;
|
|
white-space: normal;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.detail-github-tracking-repo-row {
|
|
display: flex;
|
|
gap: var(--space-sm);
|
|
align-items: center;
|
|
}
|
|
|
|
.detail-github-tracking-repo-row .input {
|
|
flex: 1;
|
|
}
|
|
|
|
.detail-github-tracking-error {
|
|
color: var(--color-error);
|
|
}
|
|
|
|
/* Activity → Raw Logs: stretch to fill the remaining modal body height
|
|
so the log viewer uses all available space above the action bar. */
|
|
.detail-section--agent-log {
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 1;
|
|
min-height: 0;
|
|
margin-top: var(--space-lg);
|
|
}
|
|
|
|
.detail-section--chat {
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 1;
|
|
min-height: 0;
|
|
/* FNXC:TaskDetailChat 2026-06-13-19:55: Chat box should sit in the chat view without excess vertical spacing around the composer (FN-6418), so the chat section opts out of the shared top margin used by other detail tabs. */
|
|
margin-top: 0;
|
|
}
|
|
|
|
/*
|
|
FNXC:TaskDetailChat 2026-06-16-22:13:
|
|
Expanded chat should take over the modal except for the task title row, so users keep task ID and column context while tabs and modal actions stay hidden.
|
|
|
|
FNXC:TaskDetailChat 2026-06-22-13:27:
|
|
Expanded chat must also cover the task metadata row — priority, execution mode, provenance/Created by, and Created/Updated timestamps — so the chat grows all the way up to the title row instead of stopping below secondary metadata controls.
|
|
|
|
FNXC:TaskDetailActivity 2026-06-30-23:55:
|
|
The same expanded-mode chrome collapse now applies to all Activity segments: Live, Feed, and Raw Logs. Keep the legacy `--chat-expanded` class for test and styling compatibility while treating it as Activity-expanded behavior.
|
|
*/
|
|
.task-detail-content--chat-expanded .detail-meta {
|
|
display: none;
|
|
}
|
|
|
|
.task-detail-content--chat-expanded .detail-tabs {
|
|
display: none;
|
|
}
|
|
|
|
.task-detail-content--chat-expanded .modal-actions {
|
|
display: none;
|
|
}
|
|
|
|
.task-detail-content--chat-expanded .modal-header {
|
|
flex: 0 0 auto;
|
|
justify-content: space-between;
|
|
padding-block: var(--space-sm);
|
|
}
|
|
|
|
.task-detail-content--chat-expanded .detail-body--chat {
|
|
flex: 1;
|
|
min-height: 0;
|
|
padding: var(--space-md);
|
|
}
|
|
|
|
.task-detail-content--chat-expanded .detail-section--chat {
|
|
flex: 1;
|
|
min-height: 0;
|
|
margin-top: 0;
|
|
}
|
|
|
|
.task-detail-content--chat-expanded .detail-activity {
|
|
display: flex;
|
|
flex: 1;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
}
|
|
|
|
.task-detail-content--chat-expanded .detail-activity-list {
|
|
flex: 1;
|
|
min-height: 0;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
/*
|
|
FNXC:TaskDetailPlannerChat 2026-06-30-23:58:
|
|
Planner Chat defaults to a focused state, but operator steering says large screens should keep the full task-detail context visible. Desktop therefore uses the same internal-scroll chat body without hiding rows; narrow/mobile layouts collapse nonessential title/provenance/actions so the composer remains reachable while header identity and close/back controls stay available.
|
|
|
|
FNXC:TaskDetailPlannerChat 2026-06-30-20:06:
|
|
Expanded Planner Chat must still expose task Priority, Execution Mode, and the tab bar on mobile. Hide only lower-priority metadata in the metadata row so inline handlers and tab navigation remain reachable without overlapping the transcript/composer.
|
|
*/
|
|
.detail-section--planner-chat {
|
|
display: flex;
|
|
flex: 1;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
margin-top: 0;
|
|
}
|
|
|
|
.task-detail-content--planner-chat-expanded .detail-body--planner-chat {
|
|
flex: 1;
|
|
min-height: 0;
|
|
}
|
|
|
|
.task-detail-content--planner-chat-expanded .detail-section--planner-chat {
|
|
flex: 1;
|
|
min-height: 0;
|
|
}
|
|
|
|
|
|
.detail-spec-edit-trigger {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
margin-bottom: var(--space-md);
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.detail-spec-edit-trigger {
|
|
align-items: stretch;
|
|
}
|
|
|
|
.detail-spec-edit-trigger .btn {
|
|
flex: 1 1 auto;
|
|
}
|
|
}
|
|
|
|
.detail-attachments-grid {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: var(--space-md);
|
|
margin-bottom: var(--space-sm);
|
|
}
|
|
|
|
.detail-attachment-card {
|
|
position: relative;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-sm);
|
|
padding: var(--space-xs);
|
|
background: var(--card);
|
|
}
|
|
|
|
.detail-attachment-link {
|
|
display: block;
|
|
}
|
|
|
|
.detail-attachment-image {
|
|
display: block;
|
|
max-width: 150px;
|
|
max-height: 100px;
|
|
border-radius: var(--radius-sm);
|
|
}
|
|
|
|
.detail-attachment-meta {
|
|
margin-top: var(--space-xs);
|
|
font-size: 11px;
|
|
opacity: 0.7;
|
|
}
|
|
|
|
.detail-attachment-delete {
|
|
position: absolute;
|
|
top: 2px;
|
|
right: 2px;
|
|
width: 20px;
|
|
height: 20px;
|
|
padding: 0;
|
|
border: none;
|
|
border-radius: 50%;
|
|
background: color-mix(in srgb, var(--bg) 65%, var(--text));
|
|
color: var(--text);
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
line-height: 20px;
|
|
text-align: center;
|
|
}
|
|
|
|
.detail-empty-inline {
|
|
margin-bottom: var(--space-sm);
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.detail-hidden-file-input {
|
|
display: none;
|
|
}
|
|
|
|
.dep-remove-btn {
|
|
margin-left: 6px;
|
|
background: none;
|
|
border: none;
|
|
color: var(--text-muted);
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
padding: 0 4px;
|
|
}
|
|
|
|
.dep-trigger-wrap {
|
|
position: relative;
|
|
}
|
|
|
|
.detail-blocking-item--stale {
|
|
color: var(--color-warning);
|
|
font-size: 0.75rem;
|
|
}
|
|
|
|
.modal-actions-spacer {
|
|
flex: 1;
|
|
}
|
|
|
|
/* Detail modal split-menu dropdowns */
|
|
.detail-actions-dropdown,
|
|
.detail-move-dropdown {
|
|
position: relative;
|
|
}
|
|
|
|
.detail-move-actions-in-review {
|
|
display: flex;
|
|
gap: var(--space-md);
|
|
align-items: center;
|
|
}
|
|
|
|
.detail-move-btn {
|
|
position: relative;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-xs);
|
|
}
|
|
|
|
.detail-move-btn__label {
|
|
flex: 1;
|
|
}
|
|
|
|
.detail-move-btn__arrow {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: var(--space-xs);
|
|
margin-right: calc(-1 * var(--space-xs));
|
|
margin-block: calc(-1 * var(--space-xs));
|
|
border-radius: 0 var(--radius-md) var(--radius-md) 0;
|
|
cursor: pointer;
|
|
}
|
|
|
|
@media (hover: hover) {
|
|
.detail-move-btn:hover .detail-move-btn__arrow {
|
|
background: color-mix(in srgb, var(--text) 12%, transparent);
|
|
}
|
|
}
|
|
|
|
.detail-actions-menu,
|
|
.detail-move-menu {
|
|
position: absolute;
|
|
bottom: calc(100% + var(--space-xs));
|
|
z-index: 50;
|
|
min-width: calc(var(--space-2xl) + var(--space-2xl) + var(--space-md));
|
|
background: var(--surface);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-md);
|
|
box-shadow: var(--shadow-md);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.detail-actions-menu {
|
|
left: 0;
|
|
}
|
|
|
|
.detail-move-menu {
|
|
right: 0;
|
|
}
|
|
|
|
.detail-actions-menu-item,
|
|
.detail-move-menu-item {
|
|
display: block;
|
|
width: 100%;
|
|
padding: var(--space-sm) var(--space-md);
|
|
font-size: 13px;
|
|
font-weight: 400;
|
|
color: var(--text);
|
|
background: transparent;
|
|
border: none;
|
|
cursor: pointer;
|
|
text-align: left;
|
|
transition: background var(--transition-fast);
|
|
}
|
|
|
|
.detail-actions-menu-item:hover,
|
|
.detail-move-menu-item:hover {
|
|
background: var(--surface-hover, color-mix(in srgb, var(--text) 6%, transparent));
|
|
}
|
|
|
|
.detail-actions-menu-item:focus,
|
|
.detail-move-menu-item:focus {
|
|
outline: none;
|
|
background: var(--surface-hover, color-mix(in srgb, var(--text) 6%, transparent));
|
|
}
|
|
|
|
.detail-actions-menu-note {
|
|
color: var(--text-muted);
|
|
font-size: calc(var(--space-sm) + var(--space-xs) * 0.75);
|
|
}
|
|
|
|
/*
|
|
FNXC:TaskDetailModalResponsive 2026-06-16-19:13:
|
|
FN-6500 fixes a tablet regression from FN-5599: the task-detail overlay offset and modal max-height subtraction must use the same `--overlay-padding-top` value so the `.modal-actions` footer remains on-screen, while the modal uses more of the tablet viewport to avoid a cramped layout.
|
|
*/
|
|
@media (min-width: 769px) and (max-width: 1024px) {
|
|
.modal-overlay:has(.task-detail-modal) {
|
|
--overlay-padding-top: 6vh;
|
|
}
|
|
|
|
.modal.task-detail-modal {
|
|
width: 98vw;
|
|
max-width: 98vw;
|
|
height: 92vh;
|
|
max-height: calc(100dvh - var(--overlay-padding-top, 6vh) - var(--space-md));
|
|
}
|
|
|
|
.detail-tabs {
|
|
width: 100%;
|
|
max-inline-size: 100%;
|
|
min-width: 0;
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
overscroll-behavior-inline: contain;
|
|
touch-action: pan-x pan-y;
|
|
-webkit-overflow-scrolling: touch;
|
|
}
|
|
|
|
.detail-tab {
|
|
touch-action: pan-x pan-y;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.detail-move-btn__arrow {
|
|
padding: var(--space-xs);
|
|
}
|
|
|
|
/* Full-screen sheet on mobile. Desktop `min-width: 480px` would otherwise
|
|
push the modal off narrow viewports; overlay padding-top leaves awkward
|
|
gaps. Resize is disabled (touchscreens can't drag the grip). */
|
|
.modal-overlay:has(.task-detail-modal) {
|
|
padding-top: 0;
|
|
align-items: stretch;
|
|
justify-content: stretch;
|
|
}
|
|
|
|
.modal.task-detail-modal {
|
|
width: 100vw;
|
|
min-width: 0;
|
|
max-width: 100vw;
|
|
height: 100dvh;
|
|
min-height: 0;
|
|
max-height: 100dvh;
|
|
margin: 0;
|
|
border: none;
|
|
border-radius: 0;
|
|
resize: none;
|
|
}
|
|
|
|
.detail-body--chat {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
overflow-y: hidden;
|
|
padding-block: var(--space-sm);
|
|
}
|
|
|
|
.detail-section--chat {
|
|
flex: 1;
|
|
min-height: 0;
|
|
margin-top: 0;
|
|
}
|
|
|
|
.task-detail-content--chat-expanded .detail-body--chat {
|
|
padding: var(--space-sm);
|
|
}
|
|
|
|
.task-detail-content--chat-expanded .detail-tabs {
|
|
display: none;
|
|
}
|
|
|
|
.task-detail-content--chat-expanded .modal-actions {
|
|
display: none;
|
|
}
|
|
|
|
.task-detail-content--planner-chat-expanded .detail-heading-row,
|
|
.task-detail-content--planner-chat-expanded .detail-description-toggle,
|
|
.task-detail-content--planner-chat-expanded .detail-near-duplicate-banner,
|
|
.task-detail-content--planner-chat-expanded .branch-group-card,
|
|
.task-detail-content--planner-chat-expanded .workspace-worktrees-summary,
|
|
.task-detail-content--planner-chat-expanded .modal-actions,
|
|
.task-detail-content--planner-chat-expanded .detail-provenance,
|
|
.task-detail-content--planner-chat-expanded .detail-timestamps {
|
|
display: none;
|
|
}
|
|
|
|
.task-detail-content--planner-chat-expanded .modal-header {
|
|
flex: 0 0 auto;
|
|
justify-content: space-between;
|
|
padding-block: var(--space-sm);
|
|
}
|
|
|
|
.task-detail-content--planner-chat-expanded .detail-meta {
|
|
flex: 0 0 auto;
|
|
margin-bottom: var(--space-sm);
|
|
}
|
|
|
|
.task-detail-content--planner-chat-expanded .detail-tabs {
|
|
flex: 0 0 auto;
|
|
margin-bottom: var(--space-sm);
|
|
}
|
|
|
|
.detail-body--planner-chat {
|
|
padding: var(--space-sm);
|
|
}
|
|
}
|
|
|
|
.detail-actions-menu-item-danger {
|
|
color: var(--color-error);
|
|
}
|
|
|
|
.detail-actions-menu-item-danger:hover {
|
|
background: color-mix(in srgb, var(--color-error) 8%, transparent);
|
|
}
|
|
|
|
.detail-refine-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: color-mix(in srgb, var(--bg) 70%, transparent);
|
|
z-index: 100;
|
|
}
|
|
|
|
.detail-refine-modal {
|
|
max-width: min(90vw, calc(var(--space-2xl) * 16));
|
|
width: 90%;
|
|
margin: 0;
|
|
}
|
|
|
|
/*
|
|
FNXC:TaskDetail 2026-06-22-18:40:
|
|
Embedded in the full-width board-card panel the detail content must be width-bounded so it cannot overflow and get clipped on the right. Constrain the embedded root and its header/body to the host width (width:100%; min-width:0; max-width:100%); min-width:0 lets inner flex rows (header title row, tabs, action bars) shrink and wrap instead of forcing horizontal overflow. Vertical scroll stays on .detail-body.
|
|
*/
|
|
.task-detail-content--embedded {
|
|
height: 100%;
|
|
width: 100%;
|
|
min-width: 0;
|
|
max-width: 100%;
|
|
}
|
|
|
|
.task-detail-content--embedded .modal-header,
|
|
.task-detail-content--embedded .detail-body,
|
|
.task-detail-content--embedded .detail-tabs,
|
|
.task-detail-content--embedded .modal-actions {
|
|
width: 100%;
|
|
min-width: 0;
|
|
max-width: 100%;
|
|
}
|
|
|
|
.task-detail-content--embedded .detail-tabs {
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
overscroll-behavior-inline: contain;
|
|
touch-action: pan-x pan-y;
|
|
-webkit-overflow-scrolling: touch;
|
|
}
|
|
|
|
.task-detail-content--embedded .detail-tab {
|
|
touch-action: pan-x pan-y;
|
|
}
|
|
|
|
/* The gray header row must wrap (task id left, Back-to-board right) instead of overflowing on narrow panels. */
|
|
.task-detail-content--embedded .modal-header {
|
|
flex-wrap: wrap;
|
|
row-gap: var(--space-xs);
|
|
}
|
|
|
|
.task-detail-content--embedded .detail-title-row {
|
|
min-width: 0;
|
|
}
|
|
|
|
.task-detail-content--embedded .modal-header-actions {
|
|
min-width: 0;
|
|
}
|
|
|
|
/*
|
|
FNXC:TaskDetail 2026-06-22-18:40:
|
|
"Back to board" affordance inside the gray header. margin-left:auto pushes it to the far right (across from the task id on the left); it shares the header-actions row but stays pinned right and wraps when space is tight. Theme tokens only.
|
|
*/
|
|
.task-detail-header-back-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-xs);
|
|
margin-left: auto;
|
|
padding: var(--space-xs) var(--space-sm);
|
|
font-size: 13px;
|
|
color: var(--text-muted);
|
|
background: var(--card);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-sm);
|
|
cursor: pointer;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.task-detail-header-back-btn:hover {
|
|
color: var(--text);
|
|
background: var(--card-hover);
|
|
}
|
|
|
|
/*
|
|
FNXC:TaskDetail 2026-06-22-20:15:
|
|
The footer Actions/Move dropdown buttons sit at the BOTTOM of the embedded panel, so the menus must open UPWARD (above the button). The earlier embedded rule opened them downward (top:100%), which dropped the menu off the panel bottom where the body's overflow clipped it — the popups appeared to vanish. Anchor to bottom:100% so they always open above the trigger and stay on-screen.
|
|
*/
|
|
.task-detail-content--embedded .detail-actions-menu,
|
|
.task-detail-content--embedded .detail-move-menu {
|
|
bottom: calc(100% + var(--space-xs));
|
|
top: auto;
|
|
}
|
|
|
|
.detail-refine-title {
|
|
margin: 0;
|
|
}
|
|
|
|
.detail-refine-help {
|
|
margin-bottom: var(--space-md);
|
|
opacity: 0.8;
|
|
}
|
|
|
|
.detail-refine-textarea {
|
|
width: 100%;
|
|
min-height: 120px;
|
|
padding: var(--space-md);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-sm);
|
|
background: var(--surface);
|
|
color: var(--text);
|
|
font-size: 14px;
|
|
resize: vertical;
|
|
}
|
|
|
|
.detail-refine-input-group {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-top: var(--space-sm);
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.detail-refine-char-count {
|
|
font-size: 12px;
|
|
opacity: 0.6;
|
|
}
|
|
|
|
.task-changes-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: var(--space-sm);
|
|
padding: var(--space-xl);
|
|
min-height: 180px;
|
|
border: 1px dashed var(--border);
|
|
border-radius: var(--radius-md);
|
|
background: var(--card);
|
|
text-align: center;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.task-changes-state--loading,
|
|
.task-changes-state--error {
|
|
flex-direction: row;
|
|
min-height: auto;
|
|
padding: var(--space-md);
|
|
justify-content: flex-start;
|
|
border-style: solid;
|
|
}
|
|
|
|
.task-changes-state--error {
|
|
color: var(--color-error);
|
|
background: color-mix(in srgb, var(--color-error) 8%, transparent);
|
|
border-color: color-mix(in srgb, var(--color-error) 25%, transparent);
|
|
}
|
|
|
|
.task-changes-state-hint {
|
|
font-size: 12px;
|
|
color: var(--text-dim);
|
|
max-width: 440px;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.task-changes-tab {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-md);
|
|
}
|
|
|
|
.changes-header {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: var(--space-md);
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.changes-header h4 {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
margin: 0;
|
|
}
|
|
|
|
.changes-header-actions {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.changes-header-actions-wrapper {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-end;
|
|
gap: var(--space-xs);
|
|
}
|
|
|
|
.changes-header-actions-secondary {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
/* Keep the compact Refresh and expand buttons visually aligned in the Changes
|
|
header even though one is text and the other is icon-only. */
|
|
.task-changes-tab .changes-header-actions-secondary > .btn {
|
|
height: calc(var(--space-lg) + var(--space-sm) + (var(--space-xs) / 2));
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.task-changes-tab .changes-header-actions-secondary > .btn-icon {
|
|
width: calc(var(--space-lg) + var(--space-sm) + (var(--space-xs) / 2));
|
|
min-width: calc(var(--space-lg) + var(--space-sm) + (var(--space-xs) / 2));
|
|
min-height: calc(var(--space-lg) + var(--space-sm) + (var(--space-xs) / 2));
|
|
padding: 0;
|
|
gap: 0;
|
|
justify-content: center;
|
|
}
|
|
|
|
.changes-nav {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-xs);
|
|
}
|
|
|
|
.changes-nav-indicator {
|
|
font-size: 12px;
|
|
color: var(--text-muted);
|
|
font-family: var(--font-mono);
|
|
min-width: 32px;
|
|
text-align: center;
|
|
}
|
|
|
|
.changes-file-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.changes-file-item {
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-md);
|
|
background: var(--card);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.changes-file-item.expanded {
|
|
border-color: var(--text-dim);
|
|
background: var(--surface);
|
|
}
|
|
|
|
.changes-file-header {
|
|
width: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
padding: var(--space-sm) var(--space-md);
|
|
background: transparent;
|
|
border: none;
|
|
color: var(--text);
|
|
text-align: left;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.changes-file-header:hover {
|
|
background: var(--card-hover);
|
|
}
|
|
|
|
.changes-file-header:focus-visible {
|
|
outline: none;
|
|
box-shadow: var(--focus-ring-strong);
|
|
}
|
|
|
|
.changes-file-header:active {
|
|
background: var(--border);
|
|
}
|
|
|
|
.changes-file-toggle {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: var(--text-muted);
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.changes-file-status {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-width: 20px;
|
|
font-family: var(--font-mono);
|
|
font-size: 12px;
|
|
font-weight: 700;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* Semantic status colors for changed-file entries — theme-aware via CSS variables */
|
|
.changes-file-status--added {
|
|
color: var(--color-success);
|
|
}
|
|
|
|
.changes-file-status--modified {
|
|
color: var(--color-info);
|
|
}
|
|
|
|
.changes-file-status--deleted {
|
|
color: var(--color-error-dark);
|
|
}
|
|
|
|
.changes-file-status--unknown {
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
/* Stat summary in changes header */
|
|
.changes-stat-summary {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 2px;
|
|
margin-left: var(--space-sm);
|
|
font-size: 12px;
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
.changes-stat-summary .diff-add {
|
|
color: var(--color-success);
|
|
}
|
|
|
|
.changes-stat-summary .diff-del {
|
|
color: var(--color-error-dark);
|
|
}
|
|
|
|
/* Task-specific changes header: stacked title + stats layout */
|
|
.task-changes-tab .task-changes-header-title {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2px;
|
|
}
|
|
|
|
.task-changes-tab .task-changes-header-title h4 {
|
|
margin: 0;
|
|
}
|
|
|
|
.task-changes-tab .task-changes-stats {
|
|
margin-left: calc(var(--space-lg) + var(--space-sm)); /* align with text after icon + gap */
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.task-changes-tab .changes-header {
|
|
align-items: stretch;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.task-changes-tab .changes-header-actions-wrapper {
|
|
width: 100%;
|
|
flex-direction: row;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
justify-content: flex-start;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.task-changes-tab .changes-header-actions,
|
|
.task-changes-tab .changes-header-actions-secondary {
|
|
flex-wrap: wrap;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.task-changes-tab .changes-header-actions {
|
|
flex: 1 1 auto;
|
|
min-width: 0;
|
|
}
|
|
|
|
.task-changes-tab .changes-header-actions-secondary {
|
|
margin-left: auto;
|
|
}
|
|
|
|
.task-changes-tab .task-changes-header-title {
|
|
gap: var(--space-xs);
|
|
}
|
|
|
|
.task-changes-tab .task-changes-stats {
|
|
margin-left: calc(var(--space-lg) + var(--space-xs));
|
|
}
|
|
}
|
|
|
|
/* Truncate parent dirs from the LEFT so the filename stays visible. JSX
|
|
* wraps the path in `<bdo dir="ltr">` to preserve readable left-to-right
|
|
* display while `direction: rtl` flips the ellipsis to the start. */
|
|
.changes-file-path {
|
|
flex: 1;
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
direction: rtl;
|
|
font-family: var(--font-mono);
|
|
font-size: 12px;
|
|
}
|
|
|
|
.changes-file-stat {
|
|
flex-shrink: 0;
|
|
font-family: var(--font-mono);
|
|
font-size: calc(var(--space-sm) + var(--space-xs) * 0.75);
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.changes-file-content {
|
|
border-top: 1px solid var(--border);
|
|
}
|
|
|
|
.changes-diff-patch {
|
|
margin: 0;
|
|
padding: var(--space-sm) 0;
|
|
background: color-mix(in srgb, var(--bg) 86%, var(--text));
|
|
font-family: var(--font-mono);
|
|
font-size: 11px;
|
|
line-height: 1.5;
|
|
overflow-x: auto;
|
|
white-space: pre-wrap;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.changes-diff-patch.changes-diff-patch--wrap {
|
|
white-space: pre-wrap;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.changes-diff-patch.changes-diff-patch--nowrap {
|
|
white-space: pre;
|
|
word-break: normal;
|
|
}
|
|
|
|
/* Summary section - styled for done tasks with success accent */
|
|
.detail-summary {
|
|
background: color-mix(in srgb, var(--color-success) 8%, transparent);
|
|
border: 1px solid color-mix(in srgb, var(--color-success) 25%, transparent);
|
|
border-radius: var(--radius-md);
|
|
padding: var(--space-lg);
|
|
}
|
|
|
|
.detail-summary h4 {
|
|
color: var(--color-success);
|
|
margin-bottom: var(--space-md);
|
|
}
|
|
|
|
.detail-summary .markdown-body {
|
|
font-size: 14px;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.detail-summary .markdown-body p:first-child {
|
|
margin-top: 0;
|
|
}
|
|
|
|
.detail-summary .markdown-body p:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
/*
|
|
FNXC:TaskDetailSummaryTab 2026-06-27-00:00:
|
|
The done-task Summary tab is a scrollable overview composed from existing detail data. Reuse detail-section/markdown conventions and tokenized spacing/colors so the new landing tab preserves modal hierarchy across desktop and mobile.
|
|
*/
|
|
.detail-section--summary {
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.task-summary-tab {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-lg);
|
|
}
|
|
|
|
.task-summary-section {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-sm);
|
|
padding: var(--space-lg);
|
|
background: var(--card);
|
|
border: var(--btn-border-width) solid var(--border);
|
|
border-radius: var(--radius-lg);
|
|
}
|
|
|
|
.task-summary-section h4,
|
|
.task-summary-section h5 {
|
|
margin: 0;
|
|
}
|
|
|
|
.task-summary-section h5 {
|
|
color: var(--text-muted);
|
|
font-size: calc(var(--space-sm) + var(--space-xs) * 0.75);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.task-summary-markdown {
|
|
color: var(--text);
|
|
}
|
|
|
|
.task-summary-empty {
|
|
margin: 0;
|
|
color: var(--text-muted);
|
|
font-size: calc(var(--space-sm) + var(--space-xs) * 0.75);
|
|
}
|
|
|
|
.task-summary-stats {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(calc(var(--space-2xl) * 3), 1fr));
|
|
gap: var(--space-sm);
|
|
margin: 0;
|
|
}
|
|
|
|
.task-summary-stats > div {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-xs);
|
|
min-width: 0;
|
|
padding: var(--space-sm);
|
|
background: var(--surface);
|
|
border: var(--btn-border-width) solid var(--border);
|
|
border-radius: var(--radius-md);
|
|
}
|
|
|
|
.task-summary-stats dt {
|
|
color: var(--text-muted);
|
|
font-size: calc(var(--space-sm) + var(--space-xs) * 0.5);
|
|
text-transform: uppercase;
|
|
letter-spacing: calc(var(--btn-border-width) * 0.5);
|
|
}
|
|
|
|
.task-summary-stats dd {
|
|
margin: 0;
|
|
color: var(--text);
|
|
font-family: var(--font-mono);
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.task-summary-diff-add {
|
|
color: var(--color-success);
|
|
}
|
|
|
|
.task-summary-diff-del {
|
|
color: var(--color-error);
|
|
}
|
|
|
|
/*
|
|
FNXC:TaskDetailSummaryTokenCost 2026-06-27-00:00:
|
|
The done-task Summary token-cost section must reuse task-summary card hierarchy while showing per-model counts and cost without hardcoded colors or spacing. Mobile converts table rows to stacked cards so the modal and right dock do not trap horizontal scrolling.
|
|
|
|
FNXC:TaskDetailSummaryTokenCost 2026-06-28-00:00:
|
|
The desktop table needs a token-scale min-width and non-anywhere model-name wrapping so narrow right-dock containers scroll horizontally instead of collapsing MODEL values to one character per line.
|
|
*/
|
|
.task-summary-token-table-wrap {
|
|
width: 100%;
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.task-summary-token-table {
|
|
width: 100%;
|
|
min-width: calc(var(--space-2xl) * 16);
|
|
border-collapse: collapse;
|
|
color: var(--text);
|
|
}
|
|
|
|
.task-summary-token-table th,
|
|
.task-summary-token-table td {
|
|
padding: var(--space-sm);
|
|
border-bottom: var(--btn-border-width) solid var(--border);
|
|
text-align: left;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.task-summary-token-table th {
|
|
color: var(--text-muted);
|
|
font-size: calc(var(--space-sm) + var(--space-xs) * 0.5);
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: calc(var(--btn-border-width) * 0.5);
|
|
}
|
|
|
|
.task-summary-token-table tbody td:not(:first-child),
|
|
.task-summary-token-table tfoot td {
|
|
font-family: var(--font-mono);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.task-summary-token-table tfoot th,
|
|
.task-summary-token-table tfoot td {
|
|
border-bottom: 0;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.task-summary-model-label {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-xs);
|
|
min-width: 0;
|
|
}
|
|
|
|
.task-summary-model-label span:last-child {
|
|
overflow-wrap: normal;
|
|
word-break: normal;
|
|
}
|
|
|
|
.task-summary-cost-unavailable {
|
|
color: var(--color-warning);
|
|
}
|
|
|
|
.task-summary-file-list,
|
|
.task-summary-work-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-xs);
|
|
margin: 0;
|
|
padding: 0;
|
|
list-style: none;
|
|
}
|
|
|
|
.task-summary-file-list li,
|
|
.task-summary-work-list li {
|
|
min-width: 0;
|
|
padding: var(--space-sm);
|
|
background: var(--surface);
|
|
border: var(--btn-border-width) solid var(--border);
|
|
border-radius: var(--radius-md);
|
|
color: var(--text);
|
|
}
|
|
|
|
.task-summary-file-list li {
|
|
font-family: var(--font-mono);
|
|
font-size: calc(var(--space-sm) + var(--space-xs) * 0.75);
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.task-summary-subsection {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.task-summary-work-list li {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.task-summary-status {
|
|
flex-shrink: 0;
|
|
padding: var(--space-xs) var(--space-sm);
|
|
border-radius: var(--radius-full);
|
|
background: var(--surface-muted);
|
|
color: var(--text-muted);
|
|
font-size: calc(var(--space-sm) + var(--space-xs) * 0.5);
|
|
font-weight: 600;
|
|
text-transform: capitalize;
|
|
}
|
|
|
|
.task-summary-status--done,
|
|
.task-summary-status--passed {
|
|
background: color-mix(in srgb, var(--color-success) 16%, transparent);
|
|
color: var(--color-success);
|
|
}
|
|
|
|
.task-summary-status--skipped,
|
|
.task-summary-status--advisory_failure,
|
|
.task-summary-status--pending {
|
|
background: color-mix(in srgb, var(--color-warning) 16%, transparent);
|
|
color: var(--color-warning);
|
|
}
|
|
|
|
.task-summary-status--failed {
|
|
background: color-mix(in srgb, var(--color-error) 16%, transparent);
|
|
color: var(--color-error);
|
|
}
|
|
|
|
.task-summary-retries {
|
|
margin: 0;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.detail-section--summary {
|
|
padding-inline: var(--space-sm);
|
|
}
|
|
|
|
.task-summary-tab {
|
|
gap: var(--space-md);
|
|
}
|
|
|
|
.task-summary-section {
|
|
padding: var(--space-md);
|
|
}
|
|
|
|
.task-summary-stats {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.task-summary-token-table-wrap {
|
|
overflow-x: visible;
|
|
}
|
|
|
|
.task-summary-token-table,
|
|
.task-summary-token-table thead,
|
|
.task-summary-token-table tbody,
|
|
.task-summary-token-table tfoot,
|
|
.task-summary-token-table tr,
|
|
.task-summary-token-table th,
|
|
.task-summary-token-table td {
|
|
display: block;
|
|
min-width: 0;
|
|
}
|
|
|
|
.task-summary-token-table thead {
|
|
display: none;
|
|
}
|
|
|
|
.task-summary-token-table tbody tr,
|
|
.task-summary-token-table tfoot tr {
|
|
padding: var(--space-sm);
|
|
background: var(--surface);
|
|
border: var(--btn-border-width) solid var(--border);
|
|
border-radius: var(--radius-md);
|
|
}
|
|
|
|
.task-summary-token-table tbody,
|
|
.task-summary-token-table tfoot {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-xs);
|
|
}
|
|
|
|
.task-summary-token-table td,
|
|
.task-summary-token-table tfoot th {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: var(--space-sm);
|
|
padding: var(--space-xs) 0;
|
|
border-bottom: 0;
|
|
text-align: right;
|
|
}
|
|
|
|
.task-summary-token-table td::before {
|
|
content: attr(data-label);
|
|
color: var(--text-muted);
|
|
font-family: var(--font-sans);
|
|
font-weight: 600;
|
|
text-align: left;
|
|
}
|
|
|
|
.task-summary-token-table tfoot td::before {
|
|
content: none;
|
|
}
|
|
|
|
.task-summary-token-table tfoot th {
|
|
color: var(--text);
|
|
text-align: left;
|
|
text-transform: none;
|
|
letter-spacing: normal;
|
|
}
|
|
|
|
.task-summary-token-table tfoot th::after {
|
|
content: ":";
|
|
}
|
|
|
|
.task-summary-work-list li {
|
|
align-items: flex-start;
|
|
}
|
|
}
|
|
|
|
/* Spec tab layout - allows SpecEditor to fill available vertical space */
|
|
.detail-section--spec {
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 1;
|
|
min-height: 0;
|
|
margin-top: 0;
|
|
}
|
|
|
|
/* Back button for changed-files modal - hidden on desktop */
|
|
.changed-files-back-button {
|
|
display: none;
|
|
}
|
|
|
|
/* Changed-files loading spinner */
|
|
.changed-files-loading-spinner {
|
|
display: inline-block;
|
|
width: 16px;
|
|
height: 16px;
|
|
border: 2px solid var(--border);
|
|
border-top-color: var(--text-muted);
|
|
border-radius: 50%;
|
|
animation: changed-files-spin 0.6s linear infinite;
|
|
}
|
|
|
|
@keyframes changed-files-spin {
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
|
|
/* Changed-files empty state */
|
|
.changed-files-empty {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: var(--space-sm);
|
|
padding: var(--space-xl) var(--space-lg);
|
|
color: var(--text-muted);
|
|
font-size: 14px;
|
|
text-align: center;
|
|
}
|
|
|
|
.changed-files-empty-icon {
|
|
font-size: 24px;
|
|
opacity: 0.6;
|
|
}
|
|
|
|
/* Changed-files error state */
|
|
.changed-files-error {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.changed-files-error-icon {
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* Renamed file label */
|
|
.changed-files-renamed {
|
|
color: var(--text-muted);
|
|
font-size: 12px;
|
|
}
|
|
|
|
/* Mobile responsive for changed-files modal */
|
|
@media (max-width: 768px) {
|
|
.changed-files-modal .changed-files-layout {
|
|
grid-template-columns: 1fr;
|
|
grid-template-rows: 1fr;
|
|
}
|
|
|
|
/* Mobile two-state view: show only list or diff at a time */
|
|
.changed-files-sidebar.mobile {
|
|
display: none;
|
|
}
|
|
|
|
.changed-files-sidebar.mobile.active {
|
|
display: flex;
|
|
flex: 1;
|
|
flex-direction: column;
|
|
border-right: none;
|
|
border-bottom: none;
|
|
max-height: none;
|
|
overflow-y: auto;
|
|
padding: 0;
|
|
background: var(--surface);
|
|
}
|
|
|
|
.changed-files-sidebar.mobile.active .file-browser-list {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
-webkit-overflow-scrolling: touch;
|
|
}
|
|
|
|
.changed-files-sidebar.mobile.active .gm-diff-loading,
|
|
.changed-files-sidebar.mobile.active .changed-files-loading {
|
|
margin: var(--space-lg);
|
|
}
|
|
|
|
.changed-files-sidebar.mobile.active .gm-diff-error,
|
|
.changed-files-sidebar.mobile.active .changed-files-error {
|
|
margin: var(--space-lg);
|
|
}
|
|
|
|
.changed-files-sidebar.mobile.active .file-browser-empty,
|
|
.changed-files-sidebar.mobile.active .changed-files-empty {
|
|
flex: 1;
|
|
}
|
|
|
|
/* Larger touch targets for file entries on mobile */
|
|
.changed-files-sidebar.mobile .changed-files-entry {
|
|
padding: calc(var(--space-sm) + var(--space-xs) / 2) var(--space-md);
|
|
min-height: 36px;
|
|
}
|
|
|
|
/* Clearer active state on mobile */
|
|
.changed-files-sidebar.mobile .changed-files-entry.active {
|
|
background: var(--card-hover);
|
|
border-left: calc(var(--btn-border-width) * 3) solid var(--in-progress);
|
|
}
|
|
|
|
.changed-files-content.mobile {
|
|
display: none;
|
|
}
|
|
|
|
.changed-files-content.mobile.active {
|
|
display: flex;
|
|
flex: 1;
|
|
flex-direction: column;
|
|
padding: var(--space-sm);
|
|
overflow-y: auto;
|
|
-webkit-overflow-scrolling: touch;
|
|
background: var(--bg);
|
|
}
|
|
|
|
.changed-files-modal .file-browser-file-info {
|
|
flex-wrap: wrap;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.changed-files-modal .file-browser-file-info strong {
|
|
font-size: 12px;
|
|
word-break: break-all;
|
|
}
|
|
|
|
/* Diff viewer fills available space on mobile */
|
|
.changed-files-content.mobile.active .changed-files-diff-section {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
}
|
|
|
|
.changed-files-content.mobile.active .gm-diff-viewer {
|
|
flex: 1;
|
|
min-height: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.changed-files-content.mobile.active .gm-diff-patch {
|
|
flex: 1;
|
|
max-height: none;
|
|
overflow: auto;
|
|
-webkit-overflow-scrolling: touch;
|
|
}
|
|
|
|
/* Back button styles for mobile */
|
|
.changed-files-back-button {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
min-height: calc(var(--space-2xl) + var(--space-xs));
|
|
padding: 0 var(--space-md);
|
|
background: transparent;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-md);
|
|
color: var(--text);
|
|
font-size: 13px;
|
|
cursor: pointer;
|
|
transition: background var(--transition-fast);
|
|
margin-right: var(--space-sm);
|
|
}
|
|
|
|
.changed-files-back-button:hover {
|
|
background: var(--card-hover);
|
|
}
|
|
|
|
.changed-files-back-button:focus-visible {
|
|
outline: none;
|
|
box-shadow: var(--focus-ring-strong);
|
|
}
|
|
|
|
.detail-section--spec {
|
|
flex: 1;
|
|
min-height: 0;
|
|
}
|
|
}
|
|
|
|
.detail-section h4 {
|
|
font-size: 12px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
color: var(--text-muted);
|
|
margin-bottom: var(--space-sm);
|
|
}
|
|
|
|
.detail-prompt {
|
|
padding: calc(var(--space-md) + var(--space-xs) / 2);
|
|
font-size: 13px;
|
|
line-height: 1.6;
|
|
font-family: var(--font-mono);
|
|
white-space: pre-wrap;
|
|
word-break: break-word;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.spec-loading {
|
|
padding: calc(var(--space-md) + var(--space-xs) / 2);
|
|
font-size: 13px;
|
|
color: var(--text-muted);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.spec-loading::before {
|
|
content: "";
|
|
display: inline-block;
|
|
width: 14px;
|
|
height: 14px;
|
|
border: 2px solid var(--border);
|
|
border-top-color: var(--text-muted);
|
|
border-radius: 50%;
|
|
animation: task-detail-spec-spinner-spin 0.8s linear infinite;
|
|
}
|
|
|
|
@keyframes task-detail-spec-spinner-spin {
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
|
|
/* === Modal Edit Mode Styles === */
|
|
|
|
.modal-header-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.task-detail-mobile-back {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-xs);
|
|
min-height: calc(var(--space-2xl) + var(--space-xs));
|
|
padding: 0 var(--space-sm);
|
|
font-size: calc(var(--space-sm) + var(--space-xs) * 0.625);
|
|
line-height: 1;
|
|
}
|
|
|
|
.task-detail-mobile-back svg {
|
|
width: 1em;
|
|
height: 1em;
|
|
}
|
|
|
|
.modal-edit-btn {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 28px;
|
|
height: 28px;
|
|
padding: 0;
|
|
background: transparent;
|
|
border: none;
|
|
border-radius: var(--radius-sm);
|
|
color: var(--text-muted);
|
|
cursor: pointer;
|
|
transition:
|
|
background var(--transition-fast),
|
|
color var(--transition-fast);
|
|
}
|
|
|
|
.modal-edit-btn:hover {
|
|
background: var(--border);
|
|
color: var(--text);
|
|
}
|
|
|
|
.modal-edit-btn:focus-visible {
|
|
outline: none;
|
|
box-shadow: var(--focus-ring-strong);
|
|
}
|
|
|
|
.modal-edit-form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-md);
|
|
}
|
|
|
|
.modal-edit-form .form-group textarea {
|
|
min-height: 160px;
|
|
}
|
|
|
|
.modal-edit-input {
|
|
width: 100%;
|
|
padding: var(--space-sm) var(--space-md);
|
|
background: var(--bg);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-md);
|
|
color: var(--text);
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
font-family: inherit;
|
|
outline: none;
|
|
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
|
|
}
|
|
|
|
.modal-edit-input:focus {
|
|
border-color: var(--todo);
|
|
box-shadow: var(--focus-ring);
|
|
}
|
|
|
|
.modal-edit-input::placeholder {
|
|
color: var(--text-dim);
|
|
font-weight: 400;
|
|
}
|
|
|
|
.modal-edit-input:disabled {
|
|
opacity: 0.6;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.modal-edit-textarea {
|
|
width: 100%;
|
|
padding: var(--space-sm) var(--space-md);
|
|
background: var(--bg);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-md);
|
|
color: var(--text);
|
|
font-size: 14px;
|
|
font-family: inherit;
|
|
outline: none;
|
|
resize: vertical;
|
|
min-height: 80px;
|
|
line-height: 1.5;
|
|
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
|
|
}
|
|
|
|
.modal-edit-textarea:focus {
|
|
border-color: var(--todo);
|
|
box-shadow: var(--focus-ring);
|
|
}
|
|
|
|
.modal-edit-textarea::placeholder {
|
|
color: var(--text-dim);
|
|
}
|
|
|
|
.modal-edit-textarea:disabled {
|
|
opacity: 0.6;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
/* Edit-mode hint text now lives in modal-actions footer */
|
|
.modal-edit-hint {
|
|
font-size: 12px;
|
|
color: var(--text-dim);
|
|
}
|
|
|
|
.modal-edit-hint kbd {
|
|
background: var(--card);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-sm);
|
|
padding: 2px 6px;
|
|
font-family: var(--font-mono);
|
|
font-size: calc(var(--space-sm) + var(--space-xs) * 0.75);
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
/* Card saving state */
|
|
.card.card-saving {
|
|
opacity: 0.7;
|
|
}
|
|
|
|
/* === Detail Tabs === */
|
|
/*
|
|
FNXC:TaskDetailTabs 2026-06-21-00:00:
|
|
The mobile global `* { touch-action: pan-y; }` lock from FN-6365 prevents horizontal swipe gestures unless each known horizontal scroller opts back into pan-x.
|
|
The overflowing task-detail tab strip must keep horizontal touch panning enabled so conditional and plugin tabs remain reachable on narrow touch viewports (FN-6864), matching the FN-6450 agent-detail tab precedent.
|
|
|
|
FNXC:TaskDetailTabs 2026-06-22-18:00:
|
|
Remove the divider between the tab selector and the detail area below. Keep the active-tab underline as the only local selection affordance.
|
|
|
|
FNXC:TaskDetailTabs 2026-06-25-16:55:
|
|
Task-detail tabs must remain reachable as a one-row horizontal scroller on mobile across the Board modal and List embedded pane. The tab strip is the scroller, opts out of the global mobile pan-y lock with pan-x pan-y, and keeps tab children non-shrinking so conditional and plugin tabs overflow-scroll instead of clipping or compressing.
|
|
|
|
FNXC:TaskDetailTabs 2026-06-26-00:35:
|
|
`touch-action` is not inherited, so the tab buttons must also opt into pan-x because they are the real touch targets. A container-only opt-in leaves touches that start on a `.detail-tab` under the global mobile `* { touch-action: pan-y; }` lock and blocks horizontal swipes.
|
|
*/
|
|
.detail-tabs {
|
|
display: flex;
|
|
gap: 0;
|
|
width: 100%;
|
|
max-inline-size: 100%;
|
|
min-width: 0;
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
overscroll-behavior-inline: contain;
|
|
touch-action: pan-x pan-y;
|
|
-webkit-overflow-scrolling: touch;
|
|
scrollbar-width: thin;
|
|
margin-bottom: var(--space-md);
|
|
}
|
|
|
|
.detail-tab {
|
|
flex-shrink: 0;
|
|
touch-action: pan-x pan-y;
|
|
padding: var(--space-sm) var(--space-lg);
|
|
background: none;
|
|
border: none;
|
|
border-bottom: 2px solid transparent;
|
|
color: var(--text-muted);
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
font-weight: 400;
|
|
font-family: inherit;
|
|
transition:
|
|
color var(--transition-fast),
|
|
border-color var(--transition-fast);
|
|
}
|
|
|
|
.detail-tab:hover {
|
|
color: var(--text);
|
|
}
|
|
.detail-tab:focus-visible {
|
|
box-shadow: var(--focus-ring-strong);
|
|
outline: none;
|
|
border-radius: var(--radius-sm) var(--radius-sm) 0 0;
|
|
}
|
|
|
|
.detail-tab-active {
|
|
border-bottom-color: var(--in-progress);
|
|
color: var(--text);
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* === Activity Segmented Control === */
|
|
/*
|
|
FNXC:TaskDetailActivity 2026-06-30-23:55:
|
|
The Activity top-level tab owns Live (internal `current`), Feed, and Raw Logs as an in-content segmented control. Keep this selector visually quieter than the top-level tab strip and horizontally reachable on narrow modal and embedded task-detail surfaces; the Activity-wide expand control must sit beside it on every segment.
|
|
|
|
FNXC:TaskDetailActivity 2026-06-30-12:00:
|
|
Selected Activity segments must stay the same height as inactive siblings while using a slightly smaller label. Keep sizing on the base segment contract so visual active-state styling cannot alter the Live/Feed/Raw Logs row height.
|
|
*/
|
|
.activity-toolbar {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: var(--space-sm);
|
|
margin-bottom: var(--space-md);
|
|
}
|
|
|
|
.activity-segmented-control {
|
|
display: inline-flex;
|
|
max-inline-size: 100%;
|
|
gap: 0;
|
|
background: var(--card);
|
|
border: var(--border-width) solid var(--border);
|
|
border-radius: var(--radius-md);
|
|
padding: calc(var(--space-xs) / 4);
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
overscroll-behavior-inline: contain;
|
|
touch-action: pan-x pan-y;
|
|
-webkit-overflow-scrolling: touch;
|
|
scrollbar-width: thin;
|
|
}
|
|
|
|
.activity-segment {
|
|
box-sizing: border-box;
|
|
flex: 0 0 auto;
|
|
min-block-size: var(--space-2xl);
|
|
padding: calc(var(--space-xs) / 2) var(--space-md);
|
|
background: none;
|
|
border: none;
|
|
border-radius: var(--radius-sm);
|
|
color: var(--text-muted);
|
|
cursor: pointer;
|
|
font-size: var(--font-size-xs);
|
|
font-weight: 500;
|
|
line-height: var(--line-height-tight);
|
|
font-family: inherit;
|
|
touch-action: pan-x pan-y;
|
|
transition: color var(--transition-fast), background var(--transition-fast);
|
|
}
|
|
|
|
.activity-segment:hover {
|
|
color: var(--text);
|
|
background: var(--card-hover);
|
|
}
|
|
|
|
.activity-segment:focus-visible {
|
|
outline: none;
|
|
box-shadow: var(--focus-ring-strong);
|
|
}
|
|
|
|
.activity-segment-active {
|
|
color: var(--text);
|
|
background: var(--surface);
|
|
box-shadow: var(--shadow-sm);
|
|
}
|
|
|
|
.activity-expand-toggle {
|
|
flex: 0 0 auto;
|
|
min-inline-size: var(--space-2xl);
|
|
min-block-size: var(--space-2xl);
|
|
padding: 0;
|
|
}
|
|
|
|
.detail-log-loading {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
color: var(--text-muted);
|
|
min-height: calc(var(--space-2xl) + var(--space-md));
|
|
}
|
|
|
|
.detail-log-loading svg {
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.activity-toolbar {
|
|
align-items: stretch;
|
|
}
|
|
|
|
.activity-segmented-control {
|
|
flex: 1 1 auto;
|
|
}
|
|
|
|
.activity-expand-toggle {
|
|
min-inline-size: calc(var(--space-2xl) + var(--space-sm));
|
|
min-block-size: calc(var(--space-2xl) + var(--space-sm));
|
|
}
|
|
|
|
.detail-log-loading {
|
|
min-height: calc(var(--space-2xl) + var(--space-lg));
|
|
}
|
|
|
|
|
|
.detail-tab {
|
|
min-height: 36px;
|
|
touch-action: pan-x pan-y;
|
|
}
|
|
|
|
.detail-source-grid,
|
|
.detail-source-edit-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.detail-github-tracking-repo-row {
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.detail-priority-select {
|
|
min-height: var(--detail-priority-control-min-height);
|
|
}
|
|
|
|
.detail-source-header {
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.detail-source-summary {
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.detail-source-section .detail-source-summary {
|
|
flex: 1 1 auto;
|
|
min-width: 0;
|
|
}
|
|
|
|
.detail-github-tracking-section .detail-source-header {
|
|
flex-wrap: nowrap;
|
|
min-width: 0;
|
|
}
|
|
|
|
.detail-github-tracking-section .detail-source-summary {
|
|
flex: 1 1 auto;
|
|
flex-wrap: nowrap;
|
|
min-width: 0;
|
|
}
|
|
|
|
.detail-github-tracking-section .detail-github-tracking-enable {
|
|
margin-left: auto;
|
|
min-width: calc(var(--space-lg) + var(--space-xl) - var(--space-xs));
|
|
min-height: calc(var(--space-lg) + var(--space-xl) - var(--space-xs));
|
|
padding-block: var(--space-xs);
|
|
justify-content: center;
|
|
}
|
|
|
|
.detail-github-tracking-section .detail-github-tracking-spinner {
|
|
margin-left: auto;
|
|
}
|
|
|
|
.detail-github-tracking-section .detail-source-header .detail-source-toggle {
|
|
margin-left: 0;
|
|
}
|
|
|
|
.detail-body {
|
|
padding: calc(var(--space-md) + var(--space-xs) / 2);
|
|
overflow-x: hidden;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.detail-title {
|
|
font-size: 16px;
|
|
}
|
|
|
|
.modal-actions {
|
|
flex-wrap: wrap;
|
|
gap: var(--space-sm);
|
|
padding: var(--space-md) calc(var(--space-md) + var(--space-xs) / 2) calc(var(--space-md) + env(safe-area-inset-bottom, 0px));
|
|
}
|
|
|
|
.modal-actions .btn {
|
|
min-width: 0;
|
|
}
|
|
|
|
/* Mobile dropdown menus — position above action bar, constrained to viewport */
|
|
.detail-actions-menu,
|
|
.detail-move-menu {
|
|
bottom: calc(100% + var(--space-xs));
|
|
max-width: calc(100vw - calc(var(--space-lg) + var(--space-md)));
|
|
max-height: calc(100dvh - 120px);
|
|
overflow-y: auto;
|
|
-webkit-overflow-scrolling: touch;
|
|
}
|
|
|
|
.modal-header {
|
|
padding: var(--space-md) calc(var(--space-md) + var(--space-xs) / 2);
|
|
}
|
|
|
|
.detail-tabs {
|
|
display: flex;
|
|
width: 100%;
|
|
max-inline-size: 100%;
|
|
min-width: 0;
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
overscroll-behavior-inline: contain;
|
|
touch-action: pan-x pan-y;
|
|
-webkit-overflow-scrolling: touch;
|
|
scrollbar-width: none;
|
|
}
|
|
|
|
.detail-tabs::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
.detail-tab {
|
|
touch-action: pan-x pan-y;
|
|
padding: var(--space-sm) var(--space-md);
|
|
font-size: 13px;
|
|
}
|
|
|
|
/* Task detail modal: prevent header clipping + full-screen refine flow */
|
|
.detail-title-row {
|
|
flex-wrap: wrap;
|
|
gap: var(--space-xs);
|
|
}
|
|
|
|
.modal-header-actions {
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.detail-refine-overlay {
|
|
align-items: stretch;
|
|
justify-content: stretch;
|
|
}
|
|
|
|
.detail-refine-modal {
|
|
width: 100%;
|
|
max-width: 100%;
|
|
max-height: 100dvh;
|
|
border-radius: 0;
|
|
border: none;
|
|
}
|
|
|
|
.detail-refine-textarea {
|
|
font-size: 16px;
|
|
}
|
|
|
|
.modal-edit-form .form-group {
|
|
padding: 0;
|
|
}
|
|
|
|
/* Task edit modal: cap description textarea height on mobile so form stays visible */
|
|
.modal-edit-form .form-group textarea {
|
|
max-height: 200px;
|
|
overflow-y: auto;
|
|
-webkit-overflow-scrolling: touch;
|
|
}
|
|
|
|
/* Modal edit button: touch target on mobile */
|
|
.modal-edit-btn {
|
|
min-width: 36px;
|
|
min-height: 36px;
|
|
}
|
|
|
|
.task-detail-mobile-back {
|
|
min-height: calc(var(--space-2xl) + var(--space-xs));
|
|
min-width: calc(var(--space-2xl) + var(--space-xs));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
.detail-in-review-stall {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-sm);
|
|
padding: var(--space-lg);
|
|
border-radius: var(--radius-md);
|
|
background: color-mix(in srgb, var(--color-warning) 8%, transparent);
|
|
border: 1px solid color-mix(in srgb, var(--color-warning) 30%, transparent);
|
|
}
|
|
|
|
.detail-in-review-stall-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.detail-in-review-stall-headline {
|
|
font-weight: 600;
|
|
color: var(--text);
|
|
}
|
|
|
|
.detail-in-review-stall-reason {
|
|
font-family: var(--font-mono);
|
|
color: var(--text-muted);
|
|
font-size: 0.75rem;
|
|
}
|
|
|
|
.detail-in-review-stall-description,
|
|
.detail-in-review-stall-action {
|
|
color: var(--text);
|
|
}
|
|
|
|
.detail-in-review-stall-meta {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-md);
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.detail-log-entry--stall-highlight {
|
|
outline: 2px solid color-mix(in srgb, var(--color-warning) 60%, transparent);
|
|
border-radius: var(--radius-sm);
|
|
background: color-mix(in srgb, var(--color-warning) 12%, transparent);
|
|
transition: outline-color var(--transition-slow);
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.detail-in-review-stall-meta {
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
}
|
|
}
|
|
|
|
.detail-near-duplicate-banner {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-sm);
|
|
padding: var(--space-lg);
|
|
border-radius: var(--radius-md);
|
|
background: color-mix(in srgb, var(--color-warning) 8%, transparent);
|
|
border: 1px solid color-mix(in srgb, var(--color-warning) 30%, transparent);
|
|
margin-bottom: var(--space-md);
|
|
}
|
|
|
|
.detail-near-duplicate-banner__header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.detail-near-duplicate-banner__headline {
|
|
font-weight: 600;
|
|
color: var(--text);
|
|
}
|
|
|
|
.detail-near-duplicate-banner__copy {
|
|
margin: 0;
|
|
color: var(--text);
|
|
}
|
|
|
|
.detail-near-duplicate-banner__actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.detail-near-duplicate-banner__actions {
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
}
|
|
}
|
|
|
|
.detail-retries-grid dd {
|
|
font-weight: 600;
|
|
}
|
|
|
|
.detail-retries-warning {
|
|
margin: var(--space-sm) 0 0;
|
|
color: var(--color-error);
|
|
font-size: 0.75rem;
|
|
}
|
|
|
|
/*
|
|
FNXC:Workspace 2026-06-21-00:00:
|
|
Flat read-only per-sub-repo worktree list for a workspace task (U3/KTD5 dashboard floor).
|
|
Read-only list/placeholder only — not the deferred rich per-repo-status component.
|
|
*/
|
|
.workspace-worktrees-summary {
|
|
margin: var(--space-sm) 0 0;
|
|
}
|
|
.workspace-worktrees-placeholder {
|
|
font-size: 0.75rem;
|
|
font-weight: 600;
|
|
color: var(--text-muted, inherit);
|
|
margin-bottom: var(--space-xs);
|
|
}
|
|
.workspace-worktrees-list {
|
|
list-style: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-xs);
|
|
}
|
|
.workspace-worktrees-item {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: var(--space-xs) var(--space-sm);
|
|
font-size: 0.75rem;
|
|
font-family: var(--font-mono, monospace);
|
|
}
|
|
.workspace-worktrees-repo {
|
|
font-weight: 600;
|
|
}
|
|
.workspace-worktrees-branch {
|
|
color: var(--text-muted, inherit);
|
|
}
|