/* The Tasks app: the task table, the rendered task, the editor with its preview. */

.task-button {
    display: inline-block;
    background: var(--color-accent);
    color: var(--color-on-accent);
    border: 1px solid transparent;
    border-radius: 6px;
    padding: var(--space-sm) var(--space-lg);
    text-decoration: none;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.task-button.task-quiet {
    background: var(--color-button);
    color: var(--color-fg);
    border: 1px solid var(--color-line);
    font-weight: 500;
}

.task-actions {
    display: flex;
    gap: var(--space-md);
    align-items: center;
}

.task-head {
    display: flex;
    align-items: center;
    gap: var(--space-lg);
}

.task-head h2 {
    margin: 0;
}

/* The letter tile: today the dialog head's only thumbnail, now the
   fallback task-identicon.js swaps in when the identicon's own fetch
   fails. Sized here for the dialog head; the list row's small identicon
   below shrinks it in its own context. */
.task-tile {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    flex-shrink: 0;
    border-radius: 8px;
    background: color-mix(in srgb, var(--color-accent) 25%, var(--color-panel));
    color: var(--color-accent);
    font-size: var(--text-xl);
    font-weight: 600;
}

/* An author display always outranks the UA stylesheet's [hidden] rule, so
   without this the fallback letter shows beside a loaded identicon instead
   of only replacing it on the image's error event — see .crew-avatar-
   fallback[hidden] for the same fix. */
.task-tile[hidden] {
    display: none;
}

/* The list: one tbody of two lines per task on the shell's grid, laid out
   fixed so the table never outgrows the page. Line 1 holds the columns the
   header names, every cell on one line, the title clipping with an
   ellipsis; line 2 is one cell across the table — the phase — muted
   and a little smaller, its border to line 1 dropped so the pair reads as
   one tight row and fifteen-odd tasks still fit a screen. The whole pair
   is a click target, the title inside it a real link. */
.task-table {
    table-layout: fixed;
}

.task-table tbody {
    cursor: pointer;
}

.task-table tbody:hover td {
    background: var(--color-panel);
}

.task-table td, .task-table th {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Column widths by the column's own class (task-list.js puts one on every
   th and td), not by position: priority was inserted after status, and a
   positional rule would have handed every later column its neighbour's
   width. The title has none — it is the one column allowed to grow, now
   that the phase has moved to the second line. */
.task-table th.task-col-id {
    width: 5.5rem;
}

.task-table th.task-col-status {
    width: 6rem;
}

/* Two chips side by side: the priority and the planner's difficulty —
   sized for the widest pair, `medium` beside `medium`. */
.task-table th.task-col-priority {
    width: 9.5rem;
}

.task-table th.task-col-open {
    width: 3.6rem;
}

.task-table .task-col-title {
    font-weight: 600;
}

.task-table .task-col-title a {
    color: var(--color-accent);
    text-decoration: none;
}

.task-table .task-col-priority .task-difficulty {
    margin-left: var(--space-xs);
}

.task-table .task-col-when {
    width: 7rem;
    text-align: right;
}

/* The pair: line 1 loses its bottom border and line 2 its top one and its
   top padding, so the two read as a single row. The detail is a flex line
   holding the phase, keeping its whole text; a dot separates any
   parts. The td's own overflow: hidden under table-layout: fixed is what
   keeps a long phase name from widening the table, not anything here. */
.task-table .task-row-main td {
    border-bottom: none;
}

.task-table .task-col-detail {
    border-top: none;
    padding-top: 0;
    font-size: var(--text-md);
}

.task-detail {
    display: flex;
    gap: var(--space-md);
    min-width: 0;
}

.task-detail > span {
    white-space: nowrap;
    flex: none;
}

.task-detail > span + span::before {
    content: '·';
    margin-right: var(--space-md);
    opacity: 0.6;
}

/* The head's tools: the subject select beside New task. The select is a
   plain control, not a chip — it is a filter over the page, not a fact of a
   row. */
.task-list-tools {
    display: flex;
    align-items: center;
    gap: var(--space-md);
}

.task-subject-select {
    font: inherit;
    font-size: var(--text-sm);
    color: var(--color-fg);
    background: var(--color-bg);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-xs) var(--space-sm);
    max-width: 24rem;
}

/* The open tasks by subject: a heading naming the subject as its objref
   token, with the count, over the group's own table. */
.task-subject-group + .task-subject-group {
    margin-top: var(--space-lg);
}

.task-subject-heading {
    display: flex;
    align-items: baseline;
    gap: var(--space-sm);
    margin: 0 0 var(--space-sm);
    font-size: var(--text-md);
}

.task-subject-count {
    font-weight: 400;
    font-size: var(--text-sm);
}

/* The done lists: the newest done tasks always open under their own
   heading, the rest folded behind a quiet toggle carrying the count — both
   as a muted table, so finished work reads as secondary. */
.task-done {
    margin-top: var(--space-lg);
}

.task-done-heading {
    margin: 0;
    color: var(--color-accent);
    font-size: var(--text-md);
}

.task-done-toggle {
    background: none;
    border: none;
    color: var(--color-accent);
    font-weight: 600;
    cursor: pointer;
    padding: 0;
}

.task-table-done {
    opacity: 0.5;
    margin-top: var(--space-md);
}

.task-card-meta {
    font-size: var(--text-sm);
}

/* The auto-merge glyph beside a status badge: the fast-forward svg as a
   mask, so it takes the accent like every other icon. */
.task-auto-merge {
    width: 1em;
    height: 1em;
    margin-left: var(--space-xs);
    vertical-align: -0.15em;
    color: var(--color-accent);
}

/* The editor: title across the top, the source full width below, scrolling on
   its own so the page stays put. */
.task-title {
    flex: 1;
    background: var(--color-bg);
    color: var(--color-fg);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-sm) var(--space-md);
    font: inherit;
    font-size: var(--text-lg);
    font-weight: 600;
}

.task-title:focus {
    outline: 2px solid var(--color-accent);
}

.task-source {
    display: block;
    width: 100%;
    height: calc(100vh - 11rem);
    min-height: 16rem;
    resize: vertical;
    background: var(--color-bg);
    color: var(--color-fg);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-lg);
    font: inherit;
    line-height: 1.5;
}

.task-source:focus {
    outline: 2px solid var(--color-accent);
}

/* Inline editing: a quiet pencil beside the title and at the body's corner,
   turning solid on hover; the body pane holds it and lends the room. */
.task-pencil {
    background: none;
    border: none;
    color: var(--color-fg);
    opacity: 0.55;
    cursor: pointer;
    font-size: var(--text-lg);
    padding: var(--space-xs) var(--space-sm);
    border-radius: 6px;
    line-height: 1;
}

.task-pencil:hover {
    opacity: 1;
    color: var(--color-accent);
    background: color-mix(in srgb, var(--color-accent) 12%, transparent);
}

.task-notes {
    margin-top: var(--space-md);
}

/* A quiet header row over the notes, so the pencil never sits over the text. */
.task-notes-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    border-bottom: 1px solid var(--color-line);
    padding-bottom: var(--space-xs);
    margin-bottom: var(--space-sm);
}

.task-body-edit {
    margin-top: var(--space-md);
}

.task-edit-controls {
    margin-top: var(--space-sm);
}

/* Once planned, the notes freeze into a collapsed, read-only history fold. */
.task-notes-fold {
    margin-top: var(--space-lg);
    border-top: 1px solid var(--color-line);
    padding-top: var(--space-sm);
}

.task-notes-fold > summary {
    cursor: pointer;
    color: var(--color-accent);
    font-weight: 600;
}

.task-notes-fold[open] > summary {
    margin-bottom: var(--space-md);
}

.task-actions button.task-quiet {
    background: none;
    color: var(--color-fg);
    border: 1px solid var(--color-line);
}

/* Rendered markdown. */
.task-body {
    line-height: 1.55;
    max-width: 60rem;
}

.task-body h1, .task-body h2, .task-body h3 {
    color: var(--color-accent);
}

.task-body a {
    color: var(--color-accent);
}

.task-body pre {
    background: var(--color-panel);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-lg);
    overflow-x: auto;
}

.task-body code {
    background: var(--color-panel);
    padding: 0 var(--space-xs);
    border-radius: 3px;
}

.task-body pre code {
    padding: 0;
    background: none;
}

.task-body blockquote {
    margin: 0;
    padding-left: var(--space-lg);
    border-left: 3px solid var(--color-line);
    opacity: 0.85;
}

.task-body table {
    border-collapse: collapse;
}

.task-body th, .task-body td {
    border: 1px solid var(--color-line);
    padding: var(--space-xs) var(--space-md);
}

.task-body img {
    max-width: 100%;
}

.task-confirm-text {
    margin: var(--space-sm) 0;
}

/* Where a task is in its life: a badge on the row and the head, a pick in
   the editor. */
.task-status {
    display: inline-block;
    padding: 0 var(--space-sm);
    border-radius: 999px;
    font-size: var(--text-xs);
    font-weight: 400;
    border: 1px solid var(--color-line);
    color: var(--color-fg);
    vertical-align: middle;
}

.task-status-pending {
    border-color: var(--color-accent);
    color: var(--color-accent);
}

.task-status-user-input {
    border-color: var(--color-error);
    color: var(--color-error);
}

.task-status-submitted {
    border-color: var(--color-violet);
    color: var(--color-violet);
}

.task-status-planned {
    border-color: var(--color-info);
    color: var(--color-info);
}

.task-status-developed {
    border-color: var(--color-warn);
    color: var(--color-warn);
}

.task-status-ready {
    border-color: var(--color-ok);
    color: var(--color-ok);
}

.task-status-approved {
    border-color: var(--color-ok);
    color: var(--color-ok);
    font-weight: 600;
}

.task-head-edit {
    flex: 1;
    gap: var(--space-md);
}

.task-status-pick {
    background: var(--color-bg);
    color: var(--color-fg);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-sm) var(--space-md);
    font: inherit;
}

/* How urgently a task should be worked (XD1P) — a badge on the row, a select
   in the head (the select itself is the control; there is no separate save
   step). Low is muted, medium is the default badge, high leans on the
   accent, urgent is filled so it is unmissable in a list. */
.task-priority {
    display: inline-block;
    padding: 0 var(--space-sm);
    border-radius: 999px;
    border: 1px solid var(--color-line);
    color: var(--color-fg);
    vertical-align: middle;
    background: var(--color-bg);
    /* The head's select is the same chip: `font: inherit` first, so a
       select drops the browser's own face, then the badge size on top —
       the other way round the size was reset and the chip outgrew the
       status badge beside it. */
    font: inherit;
    font-size: var(--text-xs);
    font-weight: 400;
}

.task-priority-low {
    opacity: 0.55;
}

.task-priority-medium {
    border-color: var(--color-info);
    color: var(--color-info);
}

.task-priority-high {
    border-color: var(--color-warn);
    color: var(--color-warn);
}

.task-priority-urgent {
    border-color: var(--color-error);
    background: var(--color-error-bg);
    color: var(--color-error);
    font-weight: 600;
}

/* How hard a task is — the planner's own estimate, read-only here; absent
   until a plan attaches one. */
.task-difficulty {
    display: inline-block;
    padding: 0 var(--space-sm);
    border-radius: 999px;
    font-size: var(--text-xs);
    font-weight: 400;
    border: 1px dashed var(--color-line);
    color: var(--color-fg);
    opacity: 0.75;
    vertical-align: middle;
}

.task-difficulty-easy {
    border-color: var(--color-ok);
    color: var(--color-ok);
    opacity: 1;
}

.task-difficulty-medium {
    border-color: var(--color-warn);
    color: var(--color-warn);
    opacity: 1;
}

.task-difficulty-hard {
    border-color: var(--color-error);
    color: var(--color-error);
    opacity: 1;
}

/* Questions under a task, and its history. */
.task-questions {
    margin-top: var(--space-xl);
    border-top: 1px solid var(--color-line);
    padding-top: var(--space-sm);
}

.task-question {
    margin: var(--space-lg) 0;
    padding: var(--space-lg) var(--space-lg);
    background: var(--color-panel);
    border: 1px solid var(--color-line);
    border-radius: 6px;
}

.task-question h4 {
    margin: 0 0 var(--space-sm);
    color: var(--color-accent);
}

.task-question-body {
    font-size: var(--text-md);
}

.task-options {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    margin: var(--space-md) 0;
}

.task-option {
    cursor: pointer;
}

.task-answer-input {
    width: 100%;
    background: var(--color-bg);
    color: var(--color-fg);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-sm);
    font: inherit;
    margin-bottom: var(--space-md);
}

.task-question-answered {
    opacity: 0.85;
}

/* An answered question folds to its summary line: a chevron, the title and
   what was picked. Flex on a summary drops the browser's own marker, so the
   chevron is drawn here and turns with the fold. */
.task-question-answered summary {
    cursor: pointer;
    display: flex;
    align-items: baseline;
    gap: var(--space-md);
    flex-wrap: wrap;
    list-style: none;
}

.task-question-answered summary::-webkit-details-marker {
    display: none;
}

.task-question-answered summary::before {
    content: '▸';
    color: var(--color-accent);
    opacity: 0.8;
}

.task-question-answered[open] summary::before {
    content: '▾';
}

.task-question-answered summary h4 {
    margin: 0;
    display: inline;
}

.task-question-answered[open] summary {
    margin-bottom: var(--space-sm);
}

.task-answer-summary {
    font-size: var(--text-md);
}

.task-answer-text {
    margin: var(--space-xs) 0 0;
    white-space: pre-wrap;
    font: inherit;
}

.task-history {
    margin-top: var(--space-xl);
    font-size: var(--text-sm);
}

.task-history h4 {
    margin: 0 0 var(--space-xs);
    opacity: 0.7;
    font-weight: 400;
}

.task-history ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

/* The shortid: the id's last four characters, a monospace chip on the row and
   the head; its tooltip is the full id. */
.task-shortid {
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: var(--text-xs);
    letter-spacing: 0.05em;
    padding: 0 var(--space-xs);
    border-radius: 6px;
    background: color-mix(in srgb, var(--color-accent) 15%, var(--color-panel));
    color: var(--color-accent);
    vertical-align: middle;
}

/* task-identicon.js's own wrap and image, sized like the dialog head's
   .task-tile by default — the one place it renders full size. */
.task-identicon-wrap {
    display: inline-flex;
    flex-shrink: 0;
    width: 3rem;
    height: 3rem;
    vertical-align: middle;
}

.task-identicon {
    width: 3rem;
    height: 3rem;
    border-radius: 8px;
    object-fit: cover;
}

/* The list row's copy: small, before the shortid chip, both shrunk to fit
   task-col-id's own width. */
.task-shortid-wrap {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
}

.task-col-id .task-identicon-wrap,
.task-col-id .task-identicon,
.task-col-id .task-tile {
    width: 1.2rem;
    height: 1.2rem;
}

.task-col-id .task-tile {
    font-size: var(--text-xs);
    border-radius: 6px;
}

/* The plan's phases and the reviews. */
.task-plan, .task-reviews {
    margin-top: var(--space-xl);
    border-top: 1px solid var(--color-line);
    padding-top: var(--space-sm);
}

.task-phases {
    margin: var(--space-sm) 0;
    padding-left: var(--space-xl);
}

.task-phase {
    margin: var(--space-xs) 0;
}

.task-phase-current {
    font-weight: 600;
}

.task-phase-now {
    margin-left: var(--space-sm);
    font-size: var(--text-sm);
}

.task-status-started {
    border-color: var(--color-accent);
    color: var(--color-accent);
}

.task-status-done {
    border-color: var(--color-ok);
    color: var(--color-ok);
    opacity: 0.6;
}

.task-status-cancelled {
    color: var(--color-error);
    border-color: var(--color-line);
    text-decoration: line-through;
    opacity: 0.6;
}

.task-status-skipped {
    opacity: 0.6;
}

.task-review {
    margin: var(--space-md) 0;
    padding: var(--space-md) var(--space-lg);
    background: var(--color-panel);
    border: 1px solid var(--color-line);
    border-radius: 6px;
}

.task-review-comment {
    margin: var(--space-xs) 0;
}

.task-scores {
    list-style: none;
    margin: var(--space-xs) 0 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-md);
}

.task-score-pass {
    color: var(--color-ok);
}

.task-score-fail {
    color: var(--color-error);
}

/* A primary button, loud (Save, …). */
.task-move {
    background: var(--color-accent);
    color: var(--color-on-accent);
    border: none;
    font-weight: 600;
}

/* A phase shows its head (title + status) then its rendered body. */
.task-phase {
    margin: var(--space-md) 0;
}

.task-phase-head {
    display: flex;
    align-items: baseline;
    gap: var(--space-sm);
    flex-wrap: wrap;
}

.task-phase-body {
    font-size: var(--text-md);
    margin: var(--space-xs) 0 var(--space-sm);
}

/* Comments: threaded, with a floating "Add comment" over a plan selection. */
.task-comment-fab {
    position: fixed;
    z-index: 1000;
    background: var(--color-accent);
    color: var(--color-on-accent);
    border: none;
    border-radius: 6px;
    padding: var(--space-xs) var(--space-md);
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
}

.task-comments {
    margin-top: var(--space-xl);
    border-top: 1px solid var(--color-line);
    padding-top: var(--space-sm);
}

.task-comment {
    margin: var(--space-md) 0;
    padding: var(--space-md) var(--space-lg);
    background: var(--color-panel);
    border: 1px solid var(--color-line);
    border-radius: 6px;
}

.task-comment-reply {
    background: none;
    border: none;
    border-left: 2px solid var(--color-line);
    border-radius: 0;
    padding: var(--space-xs) 0 var(--space-xs) var(--space-lg);
}

.task-comment-kids {
    margin-left: var(--space-lg);
}

.task-comment-quote {
    margin: 0 0 var(--space-sm);
    padding-left: var(--space-md);
    border-left: 3px solid var(--color-accent);
    opacity: 0.85;
    font-style: italic;
}

.task-comment-meta {
    font-size: var(--text-sm);
}

.task-comment-type {
    display: inline-block;
    margin-right: var(--space-sm);
    padding: var(--space-xs) var(--space-sm);
    border-radius: 999px;
    font-size: var(--text-sm);
    text-transform: uppercase;
    background: var(--color-line);
}

.task-comment-caution .task-comment-type,
.task-comment-error .task-comment-type,
.task-comment-blocker .task-comment-type {
    background: var(--color-error);
    color: var(--color-on-accent);
}

.task-comment-blocker {
    border-color: var(--color-error);
}

/* The task dialog's comments as a GitHub-style conversation: a thread is an
   avatar beside a box — a header strip naming who and when, the body, its
   replies inside the same box, a Reply at its foot — and a line down the
   avatars joins the threads into one timeline ending at the comment box. */
.gh-comments {
    position: relative;
}

.gh-thread {
    display: grid;
    grid-template-columns: 2.5rem minmax(0, 1fr);
    gap: var(--space-lg);
    margin: 0 0 var(--space-lg);
    position: relative;
}

.gh-thread::before {
    content: "";
    position: absolute;
    left: 1.25rem;
    top: 2.5rem;
    bottom: -1rem;
    border-left: 2px solid var(--color-line);
}

.gh-composer::before {
    display: none;
}

.gh-avatar {
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    background: var(--color-panel);
    border: 1px solid var(--color-line);
    position: relative;
    z-index: 1;
}

.gh-avatar-blank {
    background: var(--color-bg);
}

.gh-box {
    border: 1px solid var(--color-line);
    border-radius: 6px;
    overflow: hidden;
    background: var(--color-bg);
}

.gh-caution, .gh-error, .gh-blocker {
    border-color: var(--color-error);
}

.gh-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-xs);
    padding: var(--space-sm) var(--space-lg);
    background: var(--color-panel);
    border-bottom: 1px solid var(--color-line);
    font-size: var(--text-sm);
}

.gh-author {
    font-weight: 600;
}

.gh-label {
    margin-left: var(--space-xs);
}

.gh-resolve {
    margin-left: auto;
}

.gh-quote {
    margin: var(--space-md) var(--space-lg) 0;
    padding: var(--space-xs) var(--space-md);
    border-left: 3px solid var(--color-line);
    opacity: 0.8;
}

.gh-body {
    padding: var(--space-xs) var(--space-lg) var(--space-md);
}

.gh-reply {
    display: grid;
    grid-template-columns: 1.8rem minmax(0, 1fr);
    gap: var(--space-md);
    padding: var(--space-md) var(--space-lg) 0;
    border-top: 1px solid var(--color-line);
}

.gh-reply .gh-avatar {
    width: 1.8rem;
    height: 1.8rem;
}

.gh-reply .gh-head {
    background: none;
    border-bottom: none;
    padding: 0 0 var(--space-xs);
}

.gh-reply .gh-body {
    padding: 0 0 var(--space-md);
}

.gh-reply-foot {
    border-top: 1px solid var(--color-line);
    padding: var(--space-sm) var(--space-lg);
    background: var(--color-panel);
}

.gh-reply-open {
    width: 100%;
    text-align: left;
    background: var(--color-bg);
    color: var(--color-fg);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-sm) var(--space-md);
    font: inherit;
    opacity: 0.75;
    cursor: text;
}

.gh-input {
    display: block;
    box-sizing: border-box;
    width: 100%;
    background: var(--color-bg);
    color: var(--color-fg);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-sm) var(--space-md);
    font: inherit;
    resize: vertical;
}

.gh-composer .gh-input {
    border: none;
    border-radius: 0;
    min-height: 6rem;
}

.gh-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-sm);
    padding: var(--space-sm) var(--space-lg);
}

.gh-reply-editing .gh-actions {
    padding: var(--space-sm) 0 0;
}

.gh-composer .gh-actions {
    border-top: 1px solid var(--color-line);
    background: var(--color-panel);
}

.gh-hint {
    margin-right: auto;
    font-size: var(--text-sm);
}

.task-comment-input {
    width: 100%;
    background: var(--color-bg);
    color: var(--color-fg);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-sm);
    font: inherit;
}

/* The new-task dialog: title above, source below — sized for a dialog frame
   rather than the full page .task-source is written for. */
.task-new-title {
    width: 100%;
    background: var(--color-bg);
    color: var(--color-fg);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-sm) var(--space-md);
    margin-bottom: var(--space-md);
    font: inherit;
    font-size: var(--text-lg);
    font-weight: 600;
}

.task-new-priority {
    display: block;
    background: var(--color-bg);
    color: var(--color-fg);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-sm) var(--space-md);
    margin-bottom: var(--space-md);
    font: inherit;
}

.task-new-body {
    display: block;
    width: 100%;
    min-height: 14rem;
    resize: vertical;
    background: var(--color-bg);
    color: var(--color-fg);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-md);
    font: inherit;
    line-height: 1.5;
}

.task-new-title:focus,
.task-new-priority:focus,
.task-new-body:focus {
    outline: 2px solid var(--color-accent);
}

/* The Agents page: one card per agent seat, its status and what it holds. A
   left rail and a status dot carry the state colour so the board reads at a
   glance — busy accented, idle quiet. */
.agent-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
    gap: var(--space-lg);
}

.agent-card {
    padding: var(--space-lg) var(--space-lg);
    background: var(--color-panel);
    border: 1px solid var(--color-line);
    border-left: 4px solid var(--color-line);
    border-radius: 8px;
}

.agent-card.agent-busy {
    border-left-color: var(--color-accent);
    background: color-mix(in srgb, var(--color-accent) 7%, var(--color-panel));
}

/* An agent something can be nudged for: the border says so on its own, since
   the mobile view has no Nudge button to carry the signal. */
.agent-card.agent-card-nudgeable {
    border-color: var(--color-warn);
}

.agent-card-clickable {
    cursor: pointer;
}

.agent-card-clickable:hover {
    border-color: var(--color-accent);
}

.agent-view .agent-card {
    margin-bottom: var(--space-lg);
}

.agent-head {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
}

.agent-icon {
    font-size: var(--text-lg);
    line-height: 1;
    flex-shrink: 0;
    color: var(--color-fg);
}

.agent-dot {
    width: 0.6rem;
    height: 0.6rem;
    border-radius: 50%;
    flex-shrink: 0;
    background: var(--color-line);
}

.agent-dot-busy {
    background: var(--color-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 25%, transparent);
}

.agent-seat {
    font-weight: 600;
    font-size: var(--text-md);
}

.agent-who {
    font-size: var(--text-sm);
    color: var(--color-accent);
}

/* A filled status pill, so idle and busy are never the same shade. */
.agent-state {
    margin-left: auto;
    padding: var(--space-xs) var(--space-md);
    border-radius: 999px;
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.agent-state-idle {
    background: color-mix(in srgb, var(--color-fg) 12%, transparent);
    color: var(--color-fg);
    opacity: 0.7;
}

.agent-state-busy {
    background: var(--color-accent);
    color: var(--color-on-accent);
}

/* The tool and model the seat's session runs on, under the name: quiet, one
   line. */
.agent-model {
    margin-top: var(--space-xs);
    font-size: var(--text-sm);
    opacity: 0.7;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.agent-message {
    margin: var(--space-md) 0 var(--space-sm);
}

.agent-foot {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-md);
    font-size: var(--text-sm);
}

.agent-holds {
    font-weight: 600;
    opacity: 0.8;
}

.agent-holding {
    margin: var(--space-sm) 0 0;
    padding-left: var(--space-xl);
    font-size: var(--text-md);
}

/* pipeline.crew's Team/Member views: a company-page card per position, avatar
   beside the body. Shares the busy/idle language .agent-* already uses, so
   the two boards read the same way. */
.crew-team {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
    gap: var(--space-lg);
}

.crew-card {
    display: flex;
    gap: var(--space-lg);
    padding: var(--space-lg) var(--space-lg);
    background: var(--color-panel);
    border: 1px solid var(--color-line);
    border-left: 4px solid var(--color-line);
    border-radius: 8px;
}

.crew-card.crew-busy {
    border-left-color: var(--color-accent);
    background: color-mix(in srgb, var(--color-accent) 7%, var(--color-panel));
}

.crew-card-clickable {
    cursor: pointer;
}

.crew-card-clickable:hover {
    border-color: var(--color-accent);
}

.crew-nudge {
    margin-top: var(--space-sm);
    padding: var(--space-xs) var(--space-md);
    font-size: var(--text-sm);
}

.pipeline-nudge-jobs {
    margin: var(--space-xs) 0 var(--space-md);
    padding-left: var(--space-xl);
}

.crew-member .crew-card {
    margin-bottom: var(--space-lg);
}

.crew-avatar-wrap {
    flex-shrink: 0;
    width: 3rem;
    height: 3rem;
}

.crew-avatar {
    width: 3rem;
    height: 3rem;
    border-radius: 50%;
    background: color-mix(in srgb, var(--color-fg) 12%, transparent);
    object-fit: cover;
}

.crew-avatar-fallback {
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 600;
    color: var(--color-fg);
}

/* An author display always outranks the UA stylesheet's [hidden] rule, so
   without this the fallback initial shows beside a loaded avatar instead of
   only replacing it on the image's error event. */
.crew-avatar-fallback[hidden] {
    display: none;
}

.crew-body {
    min-width: 0;
    flex: 1;
}

.crew-head {
    display: flex;
    align-items: baseline;
    gap: var(--space-sm);
    flex-wrap: wrap;
}

.crew-name {
    font-weight: 600;
    font-size: var(--text-md);
}

.crew-seat {
    font-size: var(--text-sm);
    color: var(--color-accent);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.crew-status {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin-top: var(--space-xs);
    font-size: var(--text-sm);
}

.crew-dot {
    width: 0.6rem;
    height: 0.6rem;
    border-radius: 50%;
    flex-shrink: 0;
    background: var(--color-line);
}

.crew-dot-busy {
    background: var(--color-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 25%, transparent);
}

.crew-state-word {
    text-transform: uppercase;
    letter-spacing: 0.04em;
    opacity: 0.7;
}

.crew-holds {
    margin-left: auto;
    opacity: 0.8;
}

.crew-role {
    margin-top: var(--space-xs);
    font-size: var(--text-sm);
    opacity: 0.6;
}

.crew-description {
    margin-top: var(--space-xs);
    font-size: var(--text-sm);
    opacity: 0.7;
}

.crew-message {
    margin-top: var(--space-sm);
    font-size: var(--text-md);
}

.crew-tasks {
    margin: var(--space-sm) 0 0;
    padding-left: var(--space-xl);
}

/* The Report list view: a row of filters, then totals and two breakdown
   tables. Token inputs (agents/tasks) show their picks as removable chips
   beside a free-typing box with datalist autocomplete. */
.usage-filters {
    display: flex;
    flex-direction: column;
    gap: var(--space-lg);
    margin-bottom: var(--space-lg);
    padding-bottom: var(--space-lg);
    border-bottom: 1px solid var(--color-line);
}

/* One row of the filters: the dates and presets, then the token fields
   under them — a column of rows, so the two never sit side by side. */
.usage-filter-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xl);
    align-items: flex-start;
}

.usage-presets {
    padding-top: var(--space-xs);
}

.usage-field {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    font-size: var(--text-sm);
    opacity: 0.85;
}

.usage-field input[type="date"], .usage-field input[type="text"], .usage-tokens input {
    background: var(--color-bg);
    color: var(--color-fg);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-xs) var(--space-sm);
    font: inherit;
}

.usage-tokens {
    min-width: 14rem;
}

.usage-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
    margin-bottom: var(--space-xs);
}

.usage-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    background: var(--color-panel);
    border: 1px solid var(--color-line);
    border-radius: 999px;
    padding: var(--space-xs) var(--space-xs) var(--space-xs) var(--space-md);
    font-size: var(--text-sm);
}

/* The chip's remove ×: with no colour of its own a button renders in the
   browser's default black, invisible on the dark panel. */
.usage-chip button {
    background: none;
    border: none;
    padding: 0 var(--space-xs);
    cursor: pointer;
    color: var(--color-fg);
    font: inherit;
    opacity: 0.7;
}

.usage-chip button:hover {
    opacity: 1;
}

.usage-totals {
    font-weight: 600;
    margin-bottom: var(--space-lg);
}

.usage-table {
    margin-bottom: var(--space-xl);
}

.usage-table th.usage-sortable {
    cursor: pointer;
    user-select: none;
}

.usage-table th.usage-sortable:hover {
    color: var(--color-fg);
}

.usage-table th.usage-sort-asc::after {
    content: ' ▲';
}

.usage-table th.usage-sort-desc::after {
    content: ' ▼';
}

/* Attachments: the list of a task's files and the drop zone under it, in the
   new-task dialog (pending, read at pick time) and the task dialog (live). The
   file input is hidden; the button and a drop anywhere on the dialog body open
   it. */
.task-attach {
    margin-top: var(--space-md);
}

.task-attach-list {
    list-style: none;
    margin: 0 0 var(--space-sm);
    padding: 0;
}

.task-attach-row {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding: var(--space-xs) var(--space-sm);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    margin-bottom: var(--space-xs);
    background: var(--color-panel);
}

.task-attach-name {
    background: none;
    border: none;
    padding: 0;
    color: var(--color-fg);
    font: inherit;
    font-weight: 600;
    text-align: left;
}

button.task-attach-name {
    cursor: pointer;
    text-decoration: underline;
}

.task-attach-meta {
    flex: 1;
    font-size: var(--text-sm);
}

.task-attach-remove {
    background: none;
    border: none;
    color: var(--color-fg);
    font: inherit;
    font-size: var(--text-lg);
    cursor: pointer;
    opacity: 0.6;
}

.task-attach-remove:hover {
    opacity: 1;
}

.task-attach-zone {
    padding: var(--space-sm);
    border: 1px dashed var(--color-line);
    border-radius: 6px;
    font-size: var(--text-md);
}

.task-attach-input {
    display: none;
}

.task-attach-over {
    outline: 2px dashed var(--color-accent);
    outline-offset: -4px;
}

.task-attachments {
    margin-top: var(--space-lg);
}

.task-attachments h4 {
    margin: 0 0 var(--space-xs);
    opacity: 0.7;
    font-weight: 400;
}

/* pipeline.job's Jobs list and Job view: headed tables of jobs, the caller's
   own above everyone else's folded by stage and the finished ones folded shut;
   a job's next moves as a row of buttons, forward moves loud and the rest
   quiet, a position picker riding beside a move that has more than one taker;
   the facts beside the row the job starts from; and its moves, newest first. */
.pipeline-job-list section {
    margin-bottom: var(--space-xl);
}

.pipeline-job-list h3 {
    margin: 0 0 var(--space-sm);
}

.pipeline-list-head {
    display: flex;
    justify-content: flex-end;
    margin-bottom: var(--space-sm);
}

.pipeline-start {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--space-lg);
    padding: var(--space-lg);
    margin-bottom: var(--space-xl);
    border: 1px solid var(--color-line);
    border-radius: 6px;
}

.pipeline-start label {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    font-size: var(--text-sm);
}

.pipeline-start-row select {
    max-width: 32rem;
}

.pipeline-start-note input {
    width: 16rem;
}

.pipeline-start .engy-errors {
    flex-basis: 100%;
}

.pipeline-fold > summary {
    cursor: pointer;
    font-weight: 600;
    padding: var(--space-xs) 0;
}

.pipeline-table {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
    margin-bottom: var(--space-sm);
}

.pipeline-table th {
    text-align: left;
    font-weight: 400;
    font-size: var(--text-sm);
    color: var(--color-muted, inherit);
    opacity: 0.75;
    border-bottom: 1px solid var(--color-line);
    padding: var(--space-xs) var(--space-md);
}

.pipeline-table td {
    padding: var(--space-sm) var(--space-md);
    border-bottom: 1px solid var(--color-line);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: middle;
}

.pipeline-table tbody tr[data-job] {
    cursor: pointer;
}

.pipeline-table tbody tr[data-job]:hover td {
    background: var(--color-panel);
}

.pipeline-col-id {
    width: 4.5rem;
}

.pipeline-col-title {
    font-weight: 600;
}

.pipeline-col-stage {
    width: 9rem;
}

.pipeline-col-priority {
    width: 6rem;
}

.pipeline-col-holder {
    width: 15rem;
}

.pipeline-col-when {
    width: 6.5rem;
    text-align: right;
}

.pipeline-stage {
    display: inline-block;
    padding: 0 var(--space-sm);
    border-radius: 999px;
    font-size: var(--text-sm);
    border: 1px solid var(--color-accent);
    color: var(--color-accent);
    white-space: nowrap;
}

.pipeline-job-head {
    display: flex;
    align-items: center;
    gap: var(--space-md);
}

.pipeline-job-head h2 {
    margin: 0;
}

.pipeline-next {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-md);
    margin: var(--space-lg) 0;
    padding: var(--space-md) 0;
    border-top: 1px solid var(--color-line);
    border-bottom: 1px solid var(--color-line);
}

.pipeline-position {
    background: var(--color-bg);
    color: var(--color-fg);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-xs) var(--space-sm);
    font: inherit;
}

.pipeline-note {
    flex: 1 1 14rem;
}

.pipeline-last-note {
    margin: var(--space-md) 0 0;
    padding: var(--space-sm) var(--space-md);
    border-left: 3px solid var(--color-accent);
    background: var(--color-panel);
    border-radius: 6px;
}

.pipeline-next-none {
    margin: var(--space-lg) 0;
}

.pipeline-move {
    display: inline-flex;
    gap: var(--space-xs);
    align-items: center;
}

.pipeline-job-body {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    gap: var(--space-xl);
    align-items: start;
}

.pipeline-facts dd .engy-muted {
    font-size: var(--text-sm);
    margin-top: var(--space-xs);
}

.pipeline-input {
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-md) var(--space-lg);
    min-width: 0;
}

.pipeline-input-head {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
}

.pipeline-input-body {
    max-height: 18rem;
    overflow: auto;
}

.pipeline-moves td {
    white-space: normal;
}

.pipeline-moves .pipeline-col-when {
    width: 6rem;
    text-align: left;
}

/* The cell views: a color's swatch over a checkerboard, so a translucent one
   shows as translucent, beside its text; a boolean's check or cross. */
.color-cell {
    display: inline-flex;
    align-items: center;
    gap: var(--space-sm);
}

.color-swatch {
    display: inline-block;
    width: 1.1rem;
    height: 1.1rem;
    border-radius: 3px;
    border: 1px solid var(--color-line);
    background: repeating-conic-gradient(#999 0% 25%, #eee 0% 50%) 50% / 8px 8px;
    overflow: hidden;
    flex-shrink: 0;
}

.color-swatch-fill {
    display: block;
    width: 100%;
    height: 100%;
}

.bool-cell-true {
    color: #3fb950;
    font-weight: 600;
}

.bool-cell-false {
    opacity: 0.55;
}

/* pipeline.status-map's Map: one table per pipeline, a move's mapping beside it. */
.pipeline-map {
    margin-bottom: var(--space-xl);
}

.pipeline-map tr[data-map] {
    cursor: pointer;
}

.pipeline-map tr[data-map]:hover td {
    background: var(--color-panel);
}

.pipeline-map-set + .pipeline-map-set::before {
    content: " · ";
}

/* The task dialog's place in the pipelines: its open job's stage, or a select
   of the pipelines it could be submitted to. */
.task-pipeline {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-sm);
    margin: var(--space-sm) 0 var(--space-lg);
    padding: var(--space-sm) var(--space-md);
    border: 1px solid var(--color-line);
    border-radius: 6px;
}

/* Its own class, not the glyph's .task-auto-merge: that one is a 1em square,
   which squeezed the label into a column and pushed it out of the box. */
.task-auto-merge-toggle {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    white-space: nowrap;
}

.task-auto-merge-editable {
    cursor: pointer;
}

/* The facts bar under a task's head: what it is for, what it is part of,
   who holds it, who wrote it — one quiet line of labelled cells, each
   value a link, the editable ones with a pencil that turns the cell into
   an input in place. */
.task-facts {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-sm) var(--space-xl);
    margin: var(--space-sm) 0 var(--space-md);
    padding: var(--space-sm) var(--space-md);
    border-radius: 6px;
    background: color-mix(in srgb, var(--color-fg) 5%, transparent);
    font-size: var(--text-sm);
}

.task-fact {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    min-height: 1.8rem;
}

.task-fact-label {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-right: var(--space-xs);
}

.task-fact .task-pencil {
    font-size: var(--text-sm);
    padding: 0 var(--space-xs);
}

.task-fact-by {
    margin-left: auto;
}

.task-fact-edit .task-fact-input {
    font: inherit;
    font-size: var(--text-sm);
    background: var(--color-bg);
    color: var(--color-fg);
    border: 1px solid var(--color-accent);
    border-radius: 6px;
    padding: 0 var(--space-sm);
    min-width: 16rem;
}

.task-fact-edit .task-move, .task-fact-edit .task-quiet {
    font-size: var(--text-xs);
}

/* A principal — who wrote, holds or acted on a task — as a chip: the crew
   face beside a short name that opens the row. */
.task-principal {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    vertical-align: middle;
}

.task-principal-avatar {
    width: 1.4rem;
    height: 1.4rem;
    border-radius: 50%;
    background: color-mix(in srgb, var(--color-fg) 12%, transparent);
    object-fit: cover;
    vertical-align: middle;
}

.task-principal-name {
    text-decoration: none;
    font-weight: 600;
}

.task-principal-name:hover {
    text-decoration: underline;
}

/* The assignee select is the control itself, drawn as a chip like the
   priority select; nobody reads quieter than someone. */
.task-assignee {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
}

.task-assignee-select {
    font: inherit;
    font-size: var(--text-sm);
    font-weight: 600;
    background: var(--color-bg);
    color: var(--color-accent);
    border: 1px solid var(--color-line);
    border-radius: 999px;
    padding: 0 var(--space-sm);
    cursor: pointer;
}

.task-assignee-none {
    color: var(--color-fg);
    opacity: 0.6;
    font-weight: 400;
}

/* The parent, as an arrow up to its shortid. */
.task-parent-link {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    color: var(--color-fg);
    cursor: pointer;
}

.task-parent-link:hover .task-shortid {
    text-decoration: underline;
}

/* The subtasks: one compact row each, the whole row a button into the
   subtask's own dialog. */
.task-subtasks {
    margin-top: var(--space-lg);
}

.task-subtasks-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
}

.task-subtasks-head h4 {
    margin: 0;
}

.task-subtask-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    margin-top: var(--space-sm);
}

.task-subtask {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    width: 100%;
    text-align: left;
    background: none;
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-xs) var(--space-sm);
    font: inherit;
    color: var(--color-fg);
    cursor: pointer;
}

.task-subtask:hover {
    background: color-mix(in srgb, var(--color-accent) 8%, transparent);
}

.task-subtask .task-identicon-wrap, .task-subtask .task-identicon, .task-subtask .task-tile {
    width: 1.2rem;
    height: 1.2rem;
    font-size: var(--text-xs);
}

.task-subtask-title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.task-subtask-holder {
    margin-left: auto;
}

/* The list's second line holds a principal chip; keep it on the line. */
.task-detail-holder .task-principal {
    vertical-align: baseline;
}

.task-detail-holder .task-principal-avatar {
    width: 1.1rem;
    height: 1.1rem;
}

/* The history: when, who, what, then the change and the row it touched. */
.task-history-kind {
    font-weight: 600;
}

.task-history-change {
    color: var(--color-fg);
}

/* The new-task dialog's second line: what the task is for and its rank. */
.task-new-line {
    display: flex;
    gap: var(--space-md);
    margin-bottom: var(--space-md);
}

.task-new-field {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}

.task-new-field:first-child {
    flex: 1;
}

.task-new-label {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.task-new-line .task-new-priority {
    margin-bottom: 0;
}

.task-new-subject {
    background: var(--color-bg);
    color: var(--color-fg);
    border: 1px solid var(--color-line);
    border-radius: 6px;
    padding: var(--space-sm) var(--space-md);
    font: inherit;
}

.task-new-subject:focus {
    outline: none;
    border-color: var(--color-accent);
}

.task-new-parent {
    margin: 0 0 var(--space-sm);
    font-size: var(--text-sm);
}

/* The task as a page: the dialog body at a reading width, not the window's. */
.viz-view-host .task-view {
    max-width: 1100px;
}
