:root {
  color-scheme: light dark;
  --auto: #2e9d5b;
  --agent: #2a8ec9;
  --approve: #c98a1a;
  --decide: #a24bc0;
  --later: #8888;
  --red: #c0392b;
}
body { font: 14px/1.55 -apple-system, system-ui, sans-serif; margin: 0; padding: 2rem;
       max-width: 60rem; }
/* Title on the left, nav on the right — but the nav is the part that gives.
   It used to be `white-space: nowrap` as a whole, which meant it could not
   shrink at all: in a window too narrow for both, flexbox squeezed the TITLE
   instead, stacking "zepsec — today" down three lines with the subtitle in a
   column beside it. So the header wraps (the nav drops to its own line before
   anything is compressed), the nav wraps within itself at the separators, and
   only the individual items stay unbroken. */
header { display: flex; align-items: flex-start; justify-content: space-between;
         gap: 1rem 1.5rem; flex-wrap: wrap;
         border-bottom: 1px solid #8886; padding-bottom: .75rem; margin-bottom: 1rem; }
header > div { flex: 0 1 auto; }
h1 { font-size: 1.25rem; margin: 0; white-space: nowrap; }
.sub { font-size: .78rem; opacity: .6; margin-top: .15rem; }
.who { font-size: .85rem; opacity: .75; text-align: right; }
/* Each item unbroken; the line breaks fall on the ` · ` between them. */
.who a, .who button, .who select, .who #who { white-space: nowrap; }
.who a { color: var(--agent); text-decoration: none; }
.who a:hover { text-decoration: underline; }
button { font: inherit; padding: .25rem .6rem; cursor: pointer; }

/* the anonymous landing page (`/` without a session). It ships no script, so
   every rule it needs is here rather than in a second stylesheet — one design
   system, and one fewer asset to open to the anonymous tier. */
.landing .lead { font-size: 1rem; }
.landing p { max-width: 46rem; }
.landing .actions { display: flex; align-items: center; gap: 1.1rem; margin: 1.6rem 0 2rem; }
.landing .landing-foot { font-size: .8rem; opacity: .6; border-top: 1px solid #8886;
                         padding-top: .75rem; max-width: 46rem; }
a.btn { display: inline-block; font: inherit; padding: .4rem .9rem; border-radius: 4px;
        background: var(--agent); color: #fff; text-decoration: none; }
a.btn:hover { filter: brightness(1.1); }

/* a sign-in GitHub completed and this service refused */
.denied { border-left: 3px solid var(--approve); padding: .1rem 0 .1rem .9rem;
          margin: 1.2rem 0 1.6rem; max-width: 46rem; }
.denied p { margin: .4rem 0; }
.denied-hint { font-size: .88rem; opacity: .7; }
.denied .actions { margin: .8rem 0 .2rem; }

/* what signing in does and does not grant — shown only to a visitor with no
   session, who is about to be asked to authorize the GitHub App */
.consent-note { font-size: .85rem; opacity: .65; max-width: 46rem;
                border-left: 2px solid #8886; padding-left: .8rem; }

/* the front door's page list: a link per page this visitor can reach, each with
   the one line that says what it is for */
.navlist { margin: 1.4rem 0 1.8rem; max-width: 46rem; }
.navrow { display: flex; align-items: baseline; gap: .6rem; padding: .3rem 0;
          border-bottom: 1px solid #8883; flex-wrap: wrap; }
.navrow a { color: var(--agent); text-decoration: none; font-weight: 600;
            min-width: 9rem; }
.navrow a:hover { text-decoration: underline; }
.navdesc { flex: 1 1 18rem; opacity: .7; font-size: .9rem; }
.navtag { font-size: .68rem; text-transform: uppercase; letter-spacing: .05em;
          opacity: .6; border: 1px solid #8886; border-radius: 3px;
          padding: 0 .3rem; }

/* the branch page's "which of yours?" chooser — an owner of several branches */
.branch-index ul { list-style: none; padding: 0; margin: .6rem 0 0; }
.branch-index li { padding: .15rem 0; }
.branch-index a { color: var(--agent); text-decoration: none; font-family: ui-monospace, monospace; }
.branch-index a:hover { text-decoration: underline; }
.landing .actions a:not(.btn) { color: var(--agent); text-decoration: none; }
.landing .actions a:not(.btn):hover { text-decoration: underline; }

/* the "as of <date>" stamp beside each page's subtitle — the server's build date,
   not the fetch time (see common.js `showAsOf`) */
.asof { opacity: .8; }
.asof:not(:empty)::before { content: " · "; }
.asof.stale { color: var(--approve); font-weight: 600; }

section { margin: 0 0 1.4rem; }
h2 { font-size: .8rem; text-transform: uppercase; letter-spacing: .05em; opacity: .65;
     margin: 0 0 .5rem; font-weight: 600; }

/* a collapsible section heading: caret + title + count badge */
h2.sec-head { display: flex; align-items: baseline; gap: .4rem; cursor: pointer;
              user-select: none; width: fit-content; }
h2.sec-head:hover { opacity: .9; }
.caret { font-size: .6rem; opacity: .6; transition: transform .12s; }
section.collapsed .caret { transform: rotate(-90deg); }
section.collapsed { margin-bottom: .5rem; }
.count { font-variant-numeric: tabular-nums; opacity: .7; font-weight: 400;
         letter-spacing: 0; text-transform: none; }

/* the action-form filter chips — a dimmed chip is a form being withheld */
.filters { display: flex; gap: .4rem; flex-wrap: wrap; margin-bottom: 1.1rem; }
.filter-chip { cursor: pointer; user-select: none; }
.filter-chip.off { background: #8883; color: inherit; opacity: .45; }
.filter-chip:hover { outline: 1px solid #8886; outline-offset: 1px; }

/* the shared loading / empty states */
.loading { opacity: .6; animation: pulse 1.2s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: .35; } 50% { opacity: .75; } }
.empty-state { font-weight: 600; }

.item { display: flex; align-items: baseline; gap: .55rem; padding: .18rem 0;
        flex-wrap: wrap; }
.text { flex: 1 1 20rem; }
.text a { color: var(--agent); text-decoration: none; border-bottom: 1px solid #8886; }
.text a:hover { border-bottom-color: currentColor; }
.note { font-family: ui-monospace, monospace; font-size: .82rem; opacity: .75;
        background: #8881; padding: .05rem .35rem; border-radius: 3px; }
.subnote { opacity: .55; font-size: .85rem; padding: .1rem 0 .1rem .2rem; }
.sec-error { color: var(--red); font-size: .85rem; }
/* a kept-empty bucket (demo "show all potential steps" mode) — dimmed */
section.empty { opacity: .5; }
section.empty .empty-note { font-style: italic; }

/* action-form chips — shared by items and the footer legend */
.chip { display: inline-block; min-width: 3.8rem; text-align: center; font-size: .7rem;
        font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
        padding: .1rem .4rem; border-radius: 3px; color: #fff; }
.chip-auto { background: var(--auto); }
.chip-agent { background: var(--agent); }
.chip-approve { background: var(--approve); }
.chip-decide { background: var(--decide); }
.chip-later { background: var(--later); }
.chip-other { background: #666; }

/* worklist next-step chips — the allocate→email→review→publish pipeline.
   `await-fix` is the external/public-CVE entry point: already disclosed, waiting
   on the fix we owe it (board only). */
.step-await-fix { background: var(--decide); }
.step-allocate-cve { background: var(--decide); }
.step-embargo-email { background: var(--approve); }
.step-notify-review { background: var(--agent); }
.step-publish-ghsa { background: var(--auto); }
.step-other { background: #666; }

/* backport pipeline stage chips — actionable stages warm, monitored cool */
.stage-assemble { background: var(--decide); }
.stage-open-bot { background: var(--approve); }
.stage-open-issue { background: var(--approve); }
.stage-port { background: var(--approve); }
.stage-fix-ci { background: var(--red); }
.stage-monitor { background: var(--agent); }
.stage-delegated { background: var(--agent); }
.stage-done { background: var(--later); }
.stage-other { background: #666; }

/* worklist table */
.worklist { border-collapse: collapse; width: 100%; font-size: .85rem; }
.worklist th { text-align: left; font-size: .68rem; text-transform: uppercase;
               letter-spacing: .04em; opacity: .6; font-weight: 600;
               padding: .3rem .6rem .3rem 0; border-bottom: 1px solid #8886; }
.worklist td { padding: .35rem .6rem .35rem 0; border-bottom: 1px solid #8884;
               vertical-align: top; }
.worklist tbody tr:hover { background: #8881; }
.worklist .mono { font-family: ui-monospace, monospace; font-size: .82rem; opacity: .85; }
.worklist .summary { opacity: .8; }
.worklist .title { max-width: 22rem; }
.worklist a { color: var(--agent); text-decoration: none; border-bottom: 1px solid #8886; }
.worklist a:hover { border-bottom-color: currentColor; }
.due { font-variant-numeric: tabular-nums; white-space: nowrap; }
.due.soon { color: var(--approve); font-weight: 600; }
.due.overdue { color: var(--red); font-weight: 700; }

/* urgency emphasis on a whole row (server-derived days_left / urgency) — an
   overdue row gets a red tint + left rule so it reads at a glance; a due-today
   row a softer amber. Cell-level .due.overdue/.soon still colours the countdown. */
.worklist tbody tr.urgent-overdue { background: #c0392b12; box-shadow: inset 3px 0 0 var(--red); }
.worklist tbody tr.urgent-due { background: #c98a1a12; box-shadow: inset 3px 0 0 var(--approve); }
.worklist tbody tr.urgent-overdue:hover,
.worklist tbody tr.urgent-due:hover { background: #8881; }

/* backports: a logical row is a <tbody> — the data <tr> plus the full-width
   next-step <tr> beneath it — so hover and the urgency emphasis are carried by
   the GROUP, not the individual <tr>. Without this the pair would tint and
   highlight in halves. (Same colours as the per-tr rules above; the later,
   equal-specificity hover wins the tie.) */
.worklist tbody.rowgroup.urgent-overdue tr { background: #c0392b12; box-shadow: inset 3px 0 0 var(--red); }
.worklist tbody.rowgroup.urgent-due tr { background: #c98a1a12; box-shadow: inset 3px 0 0 var(--approve); }
.worklist tbody.rowgroup:hover tr,
.worklist tbody.rowgroup.urgent-overdue:hover tr,
.worklist tbody.rowgroup.urgent-due:hover tr { background: #8881; }
/* The rule under the row belongs to the pair: the data row only draws one when
   it stands alone (a `done` group states no next step). */
.backports tr.data-row:not(:last-child) td { border-bottom: none; }
.backports .next-row td { padding: 0 0 .45rem 1.1rem; }
/* Branches read as bare releases (`4.4`), so all three fit on one line. */
.backports .branches { white-space: nowrap; }
/* Recessive: 37 of 51 rows say the same "monitor" boilerplate, so the
   instructions must not out-shout the data. Commands wrap rather than scroll. */
.backports .next-step { font-family: ui-monospace, monospace; font-size: .76rem;
                        opacity: .7; line-height: 1.5; overflow-wrap: anywhere; }

/* the operator note: a third <tr> in the same rowgroup, under the next steps.
   The rule under the pair now belongs to whichever <tr> is last, so the note row
   joins the "no border between the halves" rule rather than being fenced off. */
.backports tr.next-row:not(:last-child) td { border-bottom: none; }
.backports .note-row td { padding: 0 0 .5rem 1.1rem; }
/* Prose, not a command: it reads at body size while the steps above stay
   monospace, so the two are never mistaken for each other. Whitespace is
   preserved — an operator who typed two paragraphs meant two paragraphs. */
.backports .note-body { font-size: .8rem; line-height: 1.5; max-width: 70ch;
                        white-space: pre-wrap; overflow-wrap: anywhere; }
.backports .note-by { font-size: .72rem; opacity: .55; margin-top: .15rem; }
.backports .note-edit { font-size: .72rem; padding: .1rem .45rem; opacity: .6;
                        margin-top: .25rem; }
.backports .note-edit:hover { opacity: 1; }
.backports .note-input { width: 100%; max-width: 70ch; font: inherit;
                         font-size: .8rem; line-height: 1.5; }
.backports .note-controls { display: flex; align-items: center; gap: .4rem;
                            margin-top: .3rem; }
/* Says what a note is, where someone is about to write one: the reassurance that
   makes it safe to be candid about an embargoed advisory (D-N4). */
.backports .note-hint { font-size: .72rem; opacity: .5; }

/* the note, read-only, on the two pages that render a group but never edit it
   (D-N5). The board is the densest table here, so it gets a marker whose text is
   the hover title; the branch page has the room for the paragraph itself. */
.board .bp-note { cursor: help; opacity: .75; }
/* The partial-fix marker: the cited fix does not close the whole vuln. */
.partial-fix { cursor: help; color: var(--approve); font-weight: 600; }
.worklist tbody.rowgroup tr.note-row td { padding: 0 0 .5rem 0; }
/* Scoped to a rowgroup: the pair draws ONE rule, under whichever <tr> is last.
   `/worklist` is a single flat tbody and must keep its per-row rules. */
.worklist tbody.rowgroup tr:not(:last-child) td { border-bottom: none; }
.worklist .note-body { font-size: .8rem; line-height: 1.5; max-width: 70ch;
                       white-space: pre-wrap; overflow-wrap: anywhere; opacity: .85; }
.worklist .note-by { font-size: .72rem; opacity: .55; margin-top: .15rem; }

/* board: the publish ⋈ backport join.
   `.blocked` is the row the board exists to surface — publishable now, but with
   backport branches still ours to drive. It gets the amber left rule (an overdue
   row keeps its stronger red one; the ⚑ flag carries the meaning either way). */
.board .branches { white-space: nowrap; }
.board .bp { opacity: .75; }
.board .bp-act { opacity: 1; font-weight: 600; color: var(--approve); }
.board .nogroup { opacity: .5; font-style: italic; }
/* A fix spanning several origin PRs: one run per group, each named by its PR. */
.board .bp-pr { opacity: .55; }
.worklist tbody tr.blocked:not(.urgent-overdue) { box-shadow: inset 3px 0 0 var(--approve); }
.flag { display: inline-block; margin-left: .35rem; font-size: .7rem; font-weight: 700;
        color: var(--approve); white-space: nowrap; }

/* the waiting chain: what the row's next step is blocked *by* (server-sent gates,
   in pipeline order). A hard gate is enforced — the step cannot happen yet — so it
   reads plainly; a soft one is advice (an unmerged backport), so it recedes.
   Absent entirely when nothing is unmet: no chip *is* "actionable now". */
.waiting { display: block; margin-top: .2rem; font-size: .7rem; opacity: .75;
           white-space: nowrap; }
.gate-hard { font-weight: 600; }
.gate-soft { opacity: .7; font-style: italic; }

.footnote { font-size: .78rem; opacity: .55; margin-top: .8rem; }
.footnote code { font-family: ui-monospace, monospace; }

.tally { display: inline-flex; align-items: center; gap: .3rem; }
.tally-n { font-size: .8rem; opacity: .7; }

.banner { background: #f39c1220; border: 1px solid #f39c1255; padding: .5rem .75rem;
          border-radius: 4px; font-size: .85rem; margin-bottom: 1rem; }
/* A successful approval reports affirmatively rather than silently vanishing. */
.banner-ok { background: #2ecc7120; border-color: #2ecc7155; }
.clear { color: var(--auto); font-weight: 600; }
.err { color: var(--red); }

/* the inbox: proposal cards grouped by grouping-key (the §8 read-only slice).
   An actionable card (no unmet hard gate) gets a green left rule; a blocked one
   the dim rule + its waiting-chain below; a snoozed one recedes and carries its
   ⏸ badge. The only interactive controls are the three local ledger buttons. */
.inbox-group { margin: 0 0 1.3rem; }
h2.group-head { margin: 0 0 .5rem; }
/* The heading is a disclosure button: a visible ▾/▸ triangle, the group key, its
   count, and a muted "+N later" when the due filter hid some. Clicking collapses. */
.group-toggle { display: inline-flex; align-items: baseline; gap: .4rem;
                font: inherit; font-size: 1.05rem; font-weight: 600;
                background: none; border: none; padding: .1rem 0; cursor: pointer;
                color: inherit; text-align: left; }
.group-toggle:hover .group-key { text-decoration: underline; }
.group-toggle .tri { font-size: .8rem; opacity: .7; width: .9rem;
                     display: inline-block; }
.later { font-size: .72rem; font-weight: 400; color: var(--later); opacity: .8; }
.inbox-group.collapsed .group-body { display: none; }
/* The due-filter controls bar: what's shown + the Show-all toggle. */
.controls { display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
            margin: 0 0 1rem; font-size: .82rem; }
.due-summary { opacity: .7; }
.showall-btn { font: inherit; font-size: .74rem; padding: .12rem .6rem; cursor: pointer;
               border-radius: 3px; }
.showall-btn:hover { outline: 1px solid #8886; outline-offset: 1px; }
.card { border: 1px solid #8884; border-left: 3px solid var(--later);
        border-radius: 5px; padding: .5rem .7rem; margin: 0 0 .5rem; }
.card-actionable { border-left-color: var(--auto); }
.card-blocked { border-left-color: var(--later); opacity: .85; }
.card-snoozed { opacity: .6; }
.card-head { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.card-title { font-weight: 500; }
.card-title a { color: var(--agent); text-decoration: none; border-bottom: 1px solid #8886; }
.card-title a:hover { border-bottom-color: currentColor; }
.card-id { display: flex; align-items: center; gap: .4rem; margin: .25rem 0 .15rem; }
.card-id code { font-family: ui-monospace, monospace; font-size: .78rem; opacity: .8;
                background: #8881; padding: .05rem .35rem; border-radius: 3px; }
.copy-btn { font: inherit; font-size: .68rem; padding: .02rem .4rem; cursor: pointer;
            opacity: .7; }
.copy-btn:hover { opacity: 1; }
.card-cmd { font-family: ui-monospace, monospace; font-size: .8rem; opacity: .82;
            overflow-wrap: anywhere; }
.card-cmd.hint { opacity: .6; font-style: italic; font-family: inherit; }
.card-refs { font-size: .74rem; opacity: .8; margin-top: .2rem; overflow-wrap: anywhere; }
.card-refs a { white-space: nowrap; }
.snoozed-badge { font-size: .7rem; color: var(--approve); font-weight: 600;
                 white-space: nowrap; }
.card-actions { display: flex; gap: .4rem; margin-top: .45rem; flex-wrap: wrap; }
.act-btn { font: inherit; font-size: .72rem; padding: .12rem .55rem; cursor: pointer;
           border-radius: 3px; }
.act-btn:hover { outline: 1px solid #8886; outline-offset: 1px; }
footer { display: flex; gap: .4rem; flex-wrap: wrap; margin-top: 1.5rem;
         padding-top: .75rem; border-top: 1px solid #8886; }
