/* styles/jira.css — Jira chip, connection panel, sync log. Order in VulnerabilityCore.html is the cascade order. */

/* ============================================================ jira ==== */
/* The vulnerability -> Jira issue chip, in the ledger row and on the detail
   workflow bar. Two states only: linked (a key that opens the ticket) and
   unlinked (a File-issue action). Deliberately quiet — Jira's own blue would
   fight the severity colours, which are the ledger's real signal, so the chip
   borrows the accent only on hover. */
.lc-jira {
  display: flex;
  justify-content: flex-start;
  min-width: 0;
}
.jira-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-dim);
  font: 500 12px/1 var(--font);
  text-decoration: none;
  cursor: pointer;
  transition: 0.12s;
}
.jira-chip-sm {
  padding: 4px 8px;
  font-size: 11px;
  gap: 5px;
}
a.jira-chip:hover,
.jira-chip-new:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--text);
  background: var(--surface);
}
.jira-chip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.jira-chip-key {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  letter-spacing: 0.02em;
}
.jira-chip-ext {
  opacity: 0.55;
  flex: none;
}
.jira-chip-new {
  border-style: dashed;
  color: var(--text-faint);
}
.jira-chip-new:disabled {
  cursor: default;
  opacity: 0.7;
}
/* "—" placeholder for a company with no Jira connection: holds the column's
   width so rows stay aligned, without implying an action that would fail. */
.jira-chip.is-none {
  border: none;
  background: none;
  color: var(--text-faint);
  cursor: default;
  padding-left: 4px;
}
.btn-spin-sm {
  width: 11px;
  height: 11px;
  border-width: 1.5px;
}

/* ---- Administration: the Jira connection panel ---- */
.jira-panel {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
/* The panel's five panes. .tax-tabs (admin.css) supplies the track and the pill
   states; all that is left here is to place the strip and to keep the pane a
   16px-gap column like the form it replaced, so nothing inside it moved by a pixel.
   No padding: .jira-switch paints its focus ring 1px OUTSIDE its own box, and a
   padded pane would clip it. The min-height stops the card collapsing to the height
   of the shortest pane and shunting the Save row up and down as tabs change. */
.jira-tabs {
  margin-bottom: -2px;
}
.jira-pane {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-height: 220px;
}
/* Where this tenant stands, which has to survive being glanced at. The old version
   tinted the 1px border and nothing else, so "connected" and "the stored token will
   not decrypt" were separated by an edge hue you can only judge by comparing the two
   side by side — which never happens, because only one is ever on screen.
   --sc carries the state into a rail, the icon and the fill. The prose deliberately
   does NOT take it: this is a sentence, and the raw tokens are chip-grade at best
   (dark --sev-critical is 2.72:1 on --surface). Same call, same reason, as the
   comment on .admin-verify.
   Neutral is the default so an unclassed .jira-state -- the loading tick -- reads as
   "no answer yet" rather than as a verdict. */
.jira-state {
  --sc: var(--text-faint);
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 11px 14px 11px 13px;
  border: 1px solid color-mix(in oklab, var(--sc) 26%, var(--line));
  border-left: 3px solid var(--sc);
  border-radius: 10px;
  /* --bg-panel rather than --surface-2: once a 9% state tint goes on top,
     --surface-2 pushes the sentence to 3.8-4.1:1 in light on --text-dim — under the
     4.46:1 it had while it was flat, on the one sentence in this panel that has to
     be read. On --bg-panel the same tint measures 4.3-4.6:1 light and 13:1+ dark,
     and it is the inset fill .admin-form and .admintbl-wrap already use inside this
     card, so the banner joins that family instead of being a third surface. */
  background: color-mix(in oklab, var(--sc) 9%, var(--bg-panel));
  font: 13px/1.45 var(--font);
  color: var(--text-dim);
}
.jira-state b {
  color: var(--text);
}
.jira-state .ic {
  flex: none;
  color: var(--sc);
  /* The sentence wraps on a narrow card; pin the glyph to the first line. */
  margin-top: 1px;
}
/* --st-done, not --sev-low: in dark that token is #00cccc, the data-viz cyan, and a
   working connection has to read as the same green .admin-ok uses one block down. */
.jira-state.is-ok { --sc: var(--st-done); }
.jira-state.is-warn { --sc: var(--sev-high); }
/* Saved, deliberately switched off. Amber on .admin-verify's reading -- a chosen
   state, not a fault -- and above all NOT green, which is what the old single
   "Connected…" sentence was, with "Currently switched off." stuck on the end of it. */
.jira-state.is-off { --sc: var(--st-prog); }
/* Nothing configured yet. Accent rather than a warning colour: an empty tenant is
   the starting point of this card, not a problem with it. */
.jira-state.is-new { --sc: var(--accent-2); }
.jira-state-spin { animation: spin 1.1s linear infinite; }
.jira-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-panel);
}
/* A standalone field is a flex-column child at default stretch, so a single 44px
   input would span the whole card. :not(.tax-check) is required —
   .jira-panel is applied twice (the outer div AND the inner form), and the two
   checkbox rows are direct .field children of that form. */
.jira-panel > .field:not(.tax-check) {
  max-width: 320px;
}
.jira-grid .field-wide {
  grid-column: 1 / -1;
}
/* .field-hint is the same explanatory voice one level down, inside a .field. */
.jira-hint,
.field-hint {
  font: 12px/1.5 var(--font);
  color: var(--text-faint);
  margin: 0;
  /* The same measure as .tax-note. On a 1200px card this was one 220-character
     line — too long to track back to the start of. */
  max-width: 96ch;
}
/* The commit row, so it gets a rule above it: everything higher in the card is
   something you type, everything on this line is something that happens to the
   customer's tracker. Without the rule the buttons read as one more field. */
.jira-acts {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  border-top: 1px solid var(--line);
  padding-top: 16px;
  margin-top: 2px;
}
/* Test connection changes nothing on the server, so it must not carry the weight of
   one that does. It needs its own class rather than a modifier on .btn-ghost because
   .btn-ghost is not ghost in this product -- it is a filled --btn-secondary block,
   which is how five buttons of equal weight ended up on one row. */
.btn.jira-quiet {
  background: transparent;
  border-color: var(--line-2);
  color: var(--text-dim);
}
.btn.jira-quiet:hover:not(:disabled) {
  filter: none;
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--text);
}
/* .btn-spin's ring is built from --accent-ink (white), which is invisible on an
   outlined button in the light theme. Re-derive it from the button's own ink so the
   busy state survives on the two buttons that are no longer filled. */
.jira-acts .jira-quiet .btn-spin,
.jira-acts .btn-danger-outline .btn-spin {
  border-color: color-mix(in oklab, currentColor 30%, transparent);
  border-top-color: currentColor;
}
/* .btn carries no :disabled rule anywhere in the app sheets, so every control here
   looked pressable while it was inert -- and on an unconfigured tenant most of them
   are. Scoped to this row rather than added to .btn, which would restyle disabled
   buttons on every other screen in the same edit. */
.jira-acts .btn:disabled {
  opacity: 0.5;
  filter: none;
  cursor: not-allowed;
}
.jira-acts-sp {
  flex: 1;
}
/* Phone width: three buttons on one row wrapped into "Test · Disconnect" over a
   lone "Save" — the primary action orphaned bottom-left. Stack them, full width,
   so each is one row and Save keeps its trailing (last) position. */
@media (max-width: 560px) {
  .jira-acts {
    flex-direction: column;
    align-items: stretch;
  }
  .jira-acts .btn {
    justify-content: center;
  }
  .jira-acts-sp {
    display: none;
  }
}
/* ---- sync log ----
   A table that appeared under the form with no heading and no statement of what it
   was for. The reason it exists -- Jira errors are swallowed on the request path so a
   tracker outage cannot fail a triage action -- was a source comment only. */
.jira-logsec {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.jira-logsec-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.jira-logsec-head h4 {
  margin: 0;
  font: 600 14px/1.1 var(--font);
  color: var(--text);
}
/* The outcome was plain uppercase text in the raw token, so "failed" rendered in
   --sev-critical: #b91c1c on the panel in dark, 2.72:1 -- the one word in this table
   you have to be able to find, in the worst colour available. It takes the
   .admin-verify chip instead, ink mixed 72% toward --text. That is the OPPOSITE call
   from the severity chips and deliberately so: a severity band has to stay the
   product's red, but nobody asked for a specific hue on a status label, and a status
   label has to be legible first. Same reasoning, same recipe, as the verify chip. */
.jira-log-outcome {
  display: inline-flex;
  align-items: center;
  padding: 3px 8px;
  border-radius: 5px;
  font: 600 10px/1.5 var(--font);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: color-mix(in oklab, var(--sc) 72%, var(--text));
  background: color-mix(in oklab, var(--sc) 12%, transparent);
  border: 1px solid color-mix(in oklab, var(--sc) 24%, transparent);
  white-space: nowrap;
}
/* Neutral fallback on the ROW, so an outcome the backend adds later still renders a
   chip instead of losing its fill and border to an undefined --sc -- the same guard
   .tax-panel .admintbl makes for DB-driven severity bands. */
.jira-log tbody tr.jira-logrow { --sc: var(--text-faint); }
.jira-log tbody tr.is-ok { --sc: var(--st-done); }
.jira-log tbody tr.is-failed { --sc: var(--sev-critical); }
/* Long selectors on purpose, exactly as for the band rows: the generic rail is
   .admintbl tbody td:first-child (0,0,2,2) and its hover twin is (0,0,3,3). The first
   line here is (0,0,3,3) and the hover line (0,0,4,3), so the outcome rail wins in
   both states -- and this block sits after the .admintbl rules in source order, which
   settles the tie the non-hover pair would otherwise have. */
.jira-log tbody tr.jira-logrow td:first-child,
.jira-log tbody tr.jira-logrow:hover td:first-child {
  box-shadow: inset 3px 0 0 var(--sc);
}
/* toLocaleString() ran to ~20 characters and pushed Detail -- the only column with
   anything to read in it -- off the right edge. This table answers "did the last one
   work", not "exactly which second did it fail". */
.jira-log-when {
  white-space: nowrap;
  color: var(--text-faint);
  font-size: 12px;
}
/* A Jira error body is allowed to be long; it is not allowed to make the table wider
   than the card. Truncated, with the whole string on the title attribute. */
.jira-log-detail {
  font: 12px/1.45 var(--font);
  color: var(--text-dim);
  max-width: 42ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* toLocaleString() ran to ~20 characters and pushed Detail -- the only column with
   anything to read in it -- off the right edge. Shortened, and left on .admintbl's own
   --text-dim: dropping it to --text-faint measures 3.31:1 in light, and nowrap plus the
   shorter format already does all the de-emphasis this column needs. */
.jira-log-when {
  white-space: nowrap;
  font-size: 12px;
}
/* A Jira error body is allowed to be long; it is not allowed to make the table wider
   than the card. The clamp has to live on an inner block, not on the <td>: max-width
   does not apply to table cells (CSS 2.1 s10.4), so an ellipsis set on the cell itself
   is silently ignored under border-collapse and the table widens anyway. */
.jira-log-detail > span {
  display: block;
  max-width: 42ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 12px/1.45 var(--font);
  color: var(--text-dim);
}

/* The one table here that has no upper bound, sitting directly above the taxonomy
   card. Capped and scrolled in place so a tenant with 200 sync events does not
   bury the rest of the page; ~9 rows is enough to see the shape of a problem and
   the rest is one scroll away. Deliberately a modifier, not a change to
   .admintbl-wrap: the other six tables are bounded by their own data and should
   scroll with the page.
   The header sticks and paints its own bottom rule as an inset shadow — under
   border-collapse the <th>'s border-bottom belongs to the collapsed grid and is
   left behind the moment the cell sticks. */
.admintbl-scroll {
  max-height: 320px;
  overflow-y: auto;
}
.admintbl-scroll thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  border-bottom: none;
  box-shadow: inset 0 -1px 0 var(--line-2);
}
@media (max-width: 720px) {
  .jira-grid {
    grid-template-columns: 1fr;
  }
}

/* ---- readiness line under "Post comments as the person who wrote them" ----
   That switch is the only one on this panel that can be ON, saved, and still do
   nothing: it needs Jira__OAuth__ClientId/ClientSecret on the service AND each
   teammate to have consented in their own browser. Neither absence is an error, so
   neither is drawn as one — but both have to be visible, because the alternative
   way to discover them is reading the author of a comment in Jira.
   Ink is mixed toward --text on the .admin-verify precedent: the raw state tokens
   measure under 3:1 on their own tint in the light theme, and this is a sentence
   that has to be read, not a dot that has to be noticed. */
.jira-ready {
  display: flex;
  align-items: flex-start;
  gap: 7px;
  margin-top: 2px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  font: 12px/1.5 var(--font);
  --sc: var(--st-prog);
  color: color-mix(in oklab, var(--sc) 72%, var(--text));
  background: color-mix(in oklab, var(--sc) 10%, transparent);
  border: 1px solid color-mix(in oklab, var(--sc) 22%, transparent);
}
/* The glyph sits on the first line rather than centred on a wrapped block. */
.jira-ready > .ic {
  flex: none;
  margin-top: 2px;
}
.jira-ready b {
  color: var(--text);
  font-weight: 600;
}
.jira-ready.is-ok {
  --sc: var(--st-done);
}
/* Not --sev-critical: a service that has not been given an OAuth app is unfinished
   setup, not a vulnerability, and spending the severity ramp here would put it on
   the same scale as a CVE. */
.jira-ready.is-bad {
  --sc: var(--sev-high);
}
