/* ---------------------------------------------------------------------------
   Board — light by default, dark on request.

   Almost nothing here draws a line. Grouping comes from whitespace and a quiet
   tinted well behind each column; cards are plain white with a soft shadow.
   Colour is spent only where it carries meaning: the tone dot on a column, the
   accent on the column a role cares about, and red for blocked.
--------------------------------------------------------------------------- */

:root {
  --bg:        #fafaf8;
  --well:      #f2f2ef;
  --surface:   #ffffff;
  --raised:    #ffffff;

  --ink:       #17181c;
  --ink-2:     #5b6070;
  --ink-3:     #8e93a1;
  --line:      #e9e9e4;

  --accent:    #2b62d9;
  --accent-sf: #eaf0fd;
  --on-accent: #ffffff;   /* ink for anything sitting ON --accent */

  --quiet:     #9aa0ae;
  --cool:      #7681d4;
  --go:        #bd840d;
  --active:    #16916b;
  --check:     #4a73d8;
  --bug:       #c2410c;   /* distinct from --stop, which stays reserved for blocked */
  --jira:      #2684ff;
  --stop:      #d81f1f;
  --off:       #b4b8c2;

  --shadow:    0 1px 2px rgba(20, 22, 40, 0.06), 0 2px 6px rgba(20, 22, 40, 0.04);
  --shadow-up: 0 4px 12px rgba(20, 22, 40, 0.10), 0 1px 3px rgba(20, 22, 40, 0.06);

  --sans: "Noto Sans Georgian", ui-sans-serif, -apple-system, BlinkMacSystemFont,
          "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas,
          "Liberation Mono", monospace;

  --pad: 18px;
  --radius: 10px;
}

[data-theme="dark"] {
  --bg:        #0f1116;
  --well:      #14171e;
  --surface:   #191d25;
  --raised:    #1e222b;

  --ink:       #e9ebf0;
  --ink-2:     #a3aab8;
  --ink-3:     #6e7585;
  --line:      #242932;

  --accent:    #6f9bff;
  --accent-sf: #1a2334;
  --on-accent: #0f1116;

  --quiet:     #79808f;
  --cool:      #98a2ea;
  --go:        #e0a92f;
  --active:    #3ec39a;
  --check:     #7b9bf0;
  --bug:       #f0834a;
  --jira:      #579dff;
  --stop:      #ff5a5a;
  --off:       #4a5261;

  --shadow:    0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-up: 0 6px 18px rgba(0, 0, 0, 0.5);
}

* { box-sizing: border-box; }

/* Author `display` rules otherwise beat the hidden attribute, which silently
   leaves overlays like the standup view on screen. */
[hidden] { display: none !important; }

html { color-scheme: light; }
html[data-theme="dark"] { color-scheme: dark; }

body {
  margin: 0;
  height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 13.5px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

button, input, select { font: inherit; color: inherit; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--line); border-radius: 6px; }
::-webkit-scrollbar-thumb:hover { background: var(--ink-3); }

/* -------------------------------------------------------------------- chrome */

.bar {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 14px var(--pad) 10px;
  flex-shrink: 0;
}

.brand { display: flex; align-items: baseline; gap: 8px; flex-shrink: 0; }

.brand-key {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--ink-3);
}

.brand-name { font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }

/* Role switcher. A role decides which part of the pipeline is expanded into
   columns and which collapses away. */
.roles {
  display: flex;
  gap: 2px;
  padding: 2px;
  background: var(--well);
  border-radius: 8px;
}

.role {
  border: 0;
  background: none;
  color: var(--ink-2);
  padding: 4px 13px;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
}
.role:hover { color: var(--ink); }
.role[aria-selected="true"] {
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow);
}

.tools { display: flex; align-items: center; gap: 8px; margin-left: auto; }

.find input {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 5px 12px;
  font-size: 13px;
  width: 190px;
  color: var(--ink);
}
.find input::placeholder { color: var(--ink-3); }
.find input:focus { border-color: var(--accent); }

.pill {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 5px 12px;
  font-size: 13px;
  color: var(--ink-2);
  cursor: pointer;
  white-space: nowrap;
}
.pill:hover { color: var(--ink); }
.pill[aria-pressed="true"] {
  background: var(--accent-sf);
  border-color: var(--accent);
  color: var(--accent);
}
.pill-n { font-family: var(--mono); font-size: 11px; opacity: 0.7; margin-left: 3px; }

.pill-select { padding: 5px 6px 5px 10px; max-width: 170px; }
.pill-select:not([value=""]) { color: var(--ink); }

/* Masked without type=password, which is what draws password managers in. */
.masked { -webkit-text-security: disc; text-security: disc; }

.icon {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  font-size: 14px;
  color: var(--ink-2);
  cursor: pointer;
}
.icon:hover { color: var(--ink); }

.subbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 var(--pad) 12px;
  font-size: 12px;
  color: var(--ink-3);
  flex-shrink: 0;
}
.spacer { flex: 1; }
.sync { font-family: var(--mono); font-size: 11px; }
.sync.is-error { color: var(--stop); }

.subbar-sep { width: 1px; height: 14px; background: var(--line); }

/* People strip: Everyone, then one labelled cluster per role. Bottom-aligned so
   Everyone sits level with the chips rather than with the labels above them. */
.people { display: flex; align-items: flex-end; gap: 14px; flex-wrap: wrap; min-width: 0; }

.who-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  border: 1px solid transparent;
  background: none;
  border-radius: 20px;
  padding: 2px 9px 2px 3px;
  font-size: 12px;
  color: var(--ink-3);
  cursor: pointer;
  white-space: nowrap;
}
.who-chip:hover { color: var(--ink); background: var(--well); }
.who-chip[aria-pressed="true"] {
  background: var(--accent-sf);
  border-color: var(--accent);
  color: var(--accent);
}
.who-chip .who { width: 19px; height: 19px; font-size: 8px; }
.who-chip .n { font-family: var(--mono); font-size: 10.5px; opacity: 0.7; }

/* One cluster per role: the label sits above its people, so the grouping reads
   as a heading rather than as one more chip in the row. Selection is additive,
   so several chips can be lit at once. */
/* No divider: the heading does the grouping, so a rule would be one more line
   for nothing. Spacing separates the clusters. */
.team-group {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
}

.team-chips { display: flex; align-items: center; gap: 3px; }

.team-label {
  border: 1px solid transparent;
  background: none;
  border-radius: 6px;
  padding: 1px 7px;
  margin-left: 2px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--ink-3);
  cursor: pointer;
  white-space: nowrap;
}
.team-label:hover { color: var(--ink); background: var(--well); }
.team-label[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.who-chip.is-idle { opacity: 0.5; }
.who-chip.is-idle[aria-pressed="true"] { opacity: 1; }

.who-chip.is-all { padding-left: 10px; }
.who-chip.is-me { font-weight: 500; color: var(--ink-2); }
.who-chip.is-me[aria-pressed="true"] { color: var(--accent); }

/* Issue-type marks, the shapes Jira uses: a coloured tile with a glyph. The
   letter abbreviations they replace ("ST", "S") were only legible if you
   already knew the scheme. */
.type-icon {
  display: inline-grid;
  place-items: center;
  width: 16px;
  height: 16px;
  border-radius: 3px;
  flex-shrink: 0;
}
.type-icon svg { width: 11px; height: 11px; display: block; }

/* Jira mark. Small on cards, labelled in the viewer. */
.jira-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--jira);
  text-decoration: none;
  flex-shrink: 0;
  font-size: 12.5px;
}
.jira-link:hover { filter: brightness(1.15); }

.card-jira {
  display: inline-flex;
  opacity: 0;
  color: var(--jira);
  transition: opacity 110ms ease;
}
.card:hover .card-jira, .card-jira:focus-visible { opacity: 1; }

.hintkey {
  display: flex;
  align-items: center;
  gap: 5px;
  background: none;
  border: 0;
  padding: 0;
  font-size: 11.5px;
  color: var(--ink-3);
  cursor: pointer;
}
.hintkey:hover { color: var(--ink-2); }
.hintkey kbd {
  font-family: var(--mono);
  font-size: 10.5px;
  background: var(--well);
  border-radius: 4px;
  padding: 1px 5px;
}

/* ------------------------------------------------------------- standup call
   The one thing on this board allowed to shout. It is time-critical, it is
   over in fifteen minutes, and the tab it appears in is usually not the one
   being looked at — so it takes the accent, a moving dot, and the full width. */

.call {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 var(--pad) 10px;
  padding: 10px 14px;
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: var(--shadow-up);
  animation: call-in 260ms ease-out;
}
@keyframes call-in { from { opacity: 0; transform: translateY(-6px); } }

.call-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
  animation: call-pulse 1.6s ease-in-out infinite;
}
@keyframes call-pulse { 50% { opacity: 0.25; transform: scale(0.8); } }

.call-text { margin: 0; font-size: 13px; }
.call-text strong { font-weight: 600; }

.call :is(.call-meet, .call-go, .call-alerts, .call-later) {
  border: 1px solid color-mix(in srgb, currentColor 45%, transparent);
  background: none;
  color: inherit;
  border-radius: 7px;
  padding: 4px 12px;
  font-size: 12.5px;
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
}
.call :is(.call-meet, .call-go, .call-alerts, .call-later):hover {
  background: color-mix(in srgb, currentColor 14%, transparent);
}
/* Joining is the point, so it is the only solid one. */
.call-meet {
  background: var(--on-accent) !important;
  color: var(--accent) !important;
  border-color: var(--on-accent) !important;
  font-weight: 600;
}
.call-meet:hover { filter: brightness(0.94); }
.call-go { margin-left: auto; }
.call-later { border-color: transparent; opacity: 0.8; }

/* The button keeps a mark after the banner is waved off, so the board still
   says standup is happening without shouting about it a second time. */
#standup.is-due {
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}
#standup.is-due::after {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-left: 6px;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: 1.5px;
  animation: call-pulse 1.6s ease-in-out infinite;
}

.su-meet {
  background: var(--accent) !important;
  color: var(--on-accent) !important;
  border-color: var(--accent) !important;
  text-decoration: none;
  font-weight: 500;
}
.su-meet:hover { filter: brightness(1.08); }

.notice { flex-shrink: 0; }

.notice-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 var(--pad) 10px;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--accent-sf);
  color: var(--accent);
  font-size: 12px;
}
.notice-row.is-warn {
  background: color-mix(in srgb, var(--go) 13%, var(--surface));
  color: var(--go);
}
.notice-row p { margin: 0; }

.notice-act {
  margin-left: auto;
  flex-shrink: 0;
  border: 1px solid currentColor;
  background: none;
  color: inherit;
  border-radius: 7px;
  padding: 3px 11px;
  font-size: 12px;
  cursor: pointer;
  white-space: nowrap;
}
.notice-act:hover { background: color-mix(in srgb, currentColor 12%, transparent); }

/* ------------------------------------------------------------------- blocked */

.blocked {
  flex-shrink: 0;
  margin: 0 var(--pad) 12px;
  padding: 12px 14px;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--stop) 7%, var(--surface));
  max-height: 20vh;
  overflow-y: auto;
}

.blocked-title {
  margin: 0 0 9px;
  font-size: 12px;
  font-weight: 600;
  color: var(--stop);
}

.blocked-list { display: flex; flex-wrap: wrap; gap: 7px; }

.blocked-item {
  display: flex;
  align-items: baseline;
  gap: 9px;
  max-width: min(420px, 100%);
  padding: 6px 11px;
  border-radius: 8px;
  background: var(--surface);
  box-shadow: var(--shadow);
  color: var(--ink);
  text-decoration: none;
  font-size: 13px;
}
.blocked-item:hover { box-shadow: var(--shadow-up); }
.blocked-item .k { font-family: var(--mono); font-size: 11px; color: var(--stop); flex-shrink: 0; }
/* min-width:0 or the summary refuses to shrink and widens the whole row. */
.blocked-item .s { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.blocked-item .a { font-family: var(--mono); font-size: 11px; color: var(--ink-3); margin-left: auto; flex-shrink: 0; }

/* -------------------------------------------------------------------- board */

.board {
  flex: 1;
  min-height: 0;
  display: grid;
  gap: 12px;
  padding: 0 var(--pad);
  overflow-x: auto;
  overflow-y: hidden;
  align-items: stretch;
}

.col { display: flex; flex-direction: column; min-width: 0; min-height: 0; }

.col-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 4px 9px;
  flex-shrink: 0;
}

.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--tone); flex-shrink: 0; }

.col-name { font-size: 13.5px; font-weight: 600; letter-spacing: -0.005em; }

.col-n {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-3);
  background: var(--well);
  border-radius: 20px;
  padding: 1px 7px;
}

/* Sits with the label, not flung to the far edge of a wide column. */
.col-sub {
  font-size: 11.5px;
  color: var(--ink-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

/* The column a role cares about most gets the only strong colour on the board. */
.col.is-accent .col-name { color: var(--tone); }
.col.is-accent .col-n { background: color-mix(in srgb, var(--tone) 15%, transparent); color: var(--tone); }

.col-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  /* -y only. overflow-y:auto makes the browser compute overflow-x to auto as
     well, so this is a horizontal scroll container that never has anything to
     scroll — and the shorthand's `contain` on that axis swallowed every
     sideways gesture instead of letting it pan the board underneath. */
  overscroll-behavior-y: contain;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px;
  border-radius: var(--radius);
  background: var(--well);
}

.col-empty {
  font-size: 12px;
  color: var(--ink-3);
  padding: 10px 6px;
  text-align: center;
  opacity: 0.7;
}

/* An empty stage is still a fact worth showing — nobody is writing code today —
   so it keeps a labelled spine rather than a fifth of the screen. */
.col.is-spine .col-head { padding-bottom: 9px; justify-content: center; }
.col.is-spine .col-name,
.col.is-spine .col-sub { display: none; }
.col.is-spine .col-body { align-items: center; padding: 12px 0; }

.spine-label {
  writing-mode: vertical-rl;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.14em;
  color: var(--ink-3);
  text-transform: uppercase;
}

/* Two groups sharing one column. Each keeps its own heading and drop target,
   so the pairing reads as deliberate rather than as a merged pile. */
.col.is-stack .col-body { gap: 0; }

.stack-part { display: flex; flex-direction: column; }
.stack-part + .stack-part { margin-top: 14px; }

.stack-head {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 2px 4px 7px;
  position: sticky;
  top: -8px;
  background: var(--well);
  z-index: 1;
}
.stack-head .col-name { font-size: 12.5px; }
.stack-head.is-accent .col-name,
.stack-head.is-accent .col-n { color: var(--tone); }
.stack-head.is-accent .col-n { background: color-mix(in srgb, var(--tone) 15%, transparent); }

.stack-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-height: 42px;
  border-radius: 8px;
}
.stack-part .dot { background: var(--tone); }

/* -------------------------------------------------------------------- cards */

.card {
  display: block;
  background: var(--surface);
  border-radius: 9px;
  box-shadow: var(--shadow);
  padding: 11px 12px 10px;
  text-decoration: none;
  color: inherit;
}
.card:hover { box-shadow: var(--shadow-up); }
.card[draggable="true"] { cursor: grab; }
.card[draggable="true"]:active { cursor: grabbing; }

.card-top { display: flex; align-items: center; gap: 7px; margin-bottom: 6px; }

.card-key { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }
.card:hover .card-key { color: var(--accent); }


.card-age {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--ink-3);
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}
.card-age.is-warn { color: var(--go); }
.card-age.is-hot { color: var(--stop); font-weight: 600; }

.card-summary {
  font-size: 13.5px;
  line-height: 1.42;
  color: var(--ink);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}

.tag {
  display: inline-block;
  font-family: var(--mono);
  font-size: 9.5px;
  padding: 1px 5px;
  margin-right: 5px;
  border-radius: 4px;
  vertical-align: 1.5px;
  white-space: nowrap;
  background: var(--well);
  color: var(--ink-2);
}
.tag-noise { background: transparent; color: var(--ink-3); box-shadow: inset 0 0 0 1px var(--line); }

.card-foot { display: flex; align-items: center; gap: 8px; margin-top: 9px; }

.card-status {
  font-size: 11.5px;
  color: var(--ink-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.card-parent { font-family: var(--mono); font-size: 10px; color: var(--ink-3); margin-left: auto; flex-shrink: 0; }

.who {
  position: relative;
  overflow: hidden;
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-family: var(--mono);
  font-size: 8.5px;
  font-weight: 700;
  color: #16181d;
}

/* The photo covers the initials once it loads, and removes itself if it can't,
   so a blocked avatar CDN leaves a readable monogram rather than a gap. */
.who img, .stage-face img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}
.who.is-none { color: var(--ink-3); background: transparent; box-shadow: inset 0 0 0 1px var(--line); }
.who.is-me { box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--accent); }

/* Signature: the six approval gates, filled to where this idea has got to. A
   short ladder is somebody else's problem for weeks; a full one lands on you
   next. This is the detail a collapsed Intake column would otherwise hide. */
.gate { display: inline-flex; align-items: flex-end; gap: 2px; height: 10px; flex-shrink: 0; }
.gate span { display: block; width: 3px; border-radius: 1px; background: var(--line); }
.gate span:nth-child(1) { height: 2.5px; }
.gate span:nth-child(2) { height: 4px; }
.gate span:nth-child(3) { height: 5.5px; }
.gate span:nth-child(4) { height: 7px; }
.gate span:nth-child(5) { height: 8.5px; }
.gate span:nth-child(6) { height: 10px; }
.gate span.is-past { background: color-mix(in srgb, var(--cool) 55%, var(--line)); }
.gate span.is-now { background: var(--cool); }

/* Slim rows: relevance drives density, not just position. Work another team
   still owns collapses to one scannable line. */
.card.is-slim { display: flex; align-items: center; gap: 8px; padding: 7px 10px; }
.card.is-slim .card-key { flex-shrink: 0; }
.card.is-slim .card-summary {
  display: block;
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  overflow-wrap: normal;
}
.card.is-slim .card-age { font-size: 10px; margin-left: 0; }
.card.is-slim .who { width: 17px; height: 17px; font-size: 7.5px; }

/* ------------------------------------------------------------ drag and drop */

.card.is-dragging { opacity: 0.4; box-shadow: none; }
.card.is-pending { opacity: 0.55; pointer-events: none; }

/* Only columns the Jira workflow actually allows light up. */
body.is-dragging .col-body { transition: background 120ms ease, box-shadow 120ms ease; }
body.is-dragging .col:not(.drop-ok):not(.drop-src) .col-body { opacity: 0.4; }
.col.drop-ok .col-body,
.stack-part.drop-ok .stack-list {
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--tone) 55%, transparent);
}
.col.drop-over .col-body,
.stack-part.drop-over .stack-list {
  background: color-mix(in srgb, var(--tone) 12%, var(--well));
  box-shadow: inset 0 0 0 2px var(--tone);
}
body.is-dragging .stack-part:not(.drop-ok):not(.drop-src) { opacity: 0.4; }

body.is-dragging .blocked { transition: box-shadow 120ms ease; }
.blocked.drop-ok { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--stop) 45%, transparent); }
.blocked.drop-over {
  box-shadow: inset 0 0 0 2px var(--stop);
  background: color-mix(in srgb, var(--stop) 12%, var(--surface));
}

.chooser {
  position: fixed;
  z-index: 60;
  background: var(--surface);
  border-radius: 10px;
  box-shadow: var(--shadow-up);
  padding: 5px;
  min-width: 190px;
}
.chooser-head {
  font-size: 11px;
  color: var(--ink-3);
  padding: 5px 9px 6px;
}
.chooser button {
  display: block;
  width: 100%;
  text-align: left;
  border: 0;
  background: none;
  padding: 7px 9px;
  border-radius: 7px;
  font-size: 13px;
  cursor: pointer;
  color: var(--ink);
}
.chooser button:hover { background: var(--well); }

.toast {
  position: fixed;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%);
  z-index: 70;
  background: var(--ink);
  color: var(--bg);
  padding: 9px 16px;
  border-radius: 20px;
  font-size: 13px;
  box-shadow: var(--shadow-up);
  max-width: 70vw;
}
.toast.is-error { background: var(--stop); color: #fff; }

/* ------------------------------------------------------------------ drawers */

.drawers { display: flex; flex-direction: column; flex-shrink: 0; }

.drawer-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  background: none;
  border: 0;
  padding: 10px var(--pad);
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--ink-3);
  text-align: left;
}
.drawer-toggle:hover { color: var(--ink-2); }
.caret { display: inline-block; transition: transform 130ms ease; }
.drawer-toggle[aria-expanded="true"] .caret { transform: rotate(90deg); }
.drawer-n { font-family: var(--mono); font-size: 11.5px; }

.drawer-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 var(--pad) 12px;
  max-height: 30vh;
  overflow-y: auto;
}

.drawer-item {
  display: flex;
  align-items: baseline;
  gap: 8px;
  max-width: 330px;
  padding: 4px 10px;
  border-radius: 7px;
  background: var(--well);
  color: var(--ink-3);
  text-decoration: none;
  font-size: 12px;
}
.drawer-item:hover { color: var(--ink); }
.drawer-item .k { font-family: var(--mono); font-size: 10.5px; flex-shrink: 0; }
.drawer-item .s { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.foot {
  flex-shrink: 0;
  padding: 8px var(--pad) 12px;
  font-size: 11px;
  color: var(--ink-3);
}

/* ----------------------------------------------------------------- standup
   A facilitated walkthrough: one person on stage, a countdown that turns red
   and keeps running rather than cutting anyone off, and a rail showing who has
   been and who is still to come. */

.standup {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: var(--bg);
  display: flex;
  flex-direction: column;
}

.standup-bar {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 20px var(--pad) 16px;
  flex-shrink: 0;
}

/* Takes the slack so the controls stay right-aligned when the clock is hidden. */
.standup-id { flex: 1; min-width: 0; }
.standup-title { margin: 0; font-size: 20px; font-weight: 600; letter-spacing: -0.02em; }
.standup-date { margin: 1px 0 0; font-size: 12.5px; color: var(--ink-3); }

.clock {
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1;
  padding: 6px 22px;
  border-radius: 12px;
  background: var(--well);
}
.clock-time {
  font-family: var(--mono);
  font-size: 40px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.clock-of { font-size: 11px; color: var(--ink-3); margin-top: 5px; }
.clock.is-low .clock-time { color: var(--go); }
.clock.is-over { background: color-mix(in srgb, var(--stop) 12%, var(--well)); }
.clock.is-over .clock-time { color: var(--stop); }
.clock.is-paused { opacity: 0.5; }

.standup-ctl { display: flex; align-items: center; gap: 8px; }
.standup-ctl .pill:disabled { opacity: 0.4; cursor: default; }

/* Centred while it fits — a projected standup should sit at eye level — and
   falling back to top-aligned scrolling once someone has a lot on. */
.standup-stage {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 0 var(--pad);
  display: grid;
  align-content: safe center;
}

.stage-person, .stage-summary { max-width: 1500px; margin: 0 auto; }

.stage-head { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; }

.stage-face {
  position: relative;
  overflow: hidden;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-family: var(--mono);
  font-size: 15px;
  font-weight: 700;
  color: #16181d;
  flex-shrink: 0;
}

.stage-name { margin: 0; font-size: 27px; font-weight: 600; letter-spacing: -0.02em; }
.stage-sub { margin: 6px 0 20px; font-size: 14px; color: var(--ink-2); }

.stage-cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; align-items: start; }

.stage-group { padding: 14px; border-radius: var(--radius); background: var(--well); }
.stage-group.is-stop { background: color-mix(in srgb, var(--stop) 8%, var(--well)); }

.stage-group-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.11em;
  color: var(--ink-3);
  margin-bottom: 10px;
}
.stage-group.is-stop .stage-group-label { color: var(--stop); }

.stage-item {
  display: block;
  background: var(--surface);
  border-radius: 9px;
  box-shadow: var(--shadow);
  padding: 11px 13px;
  margin-bottom: 8px;
  text-decoration: none;
  color: inherit;
}
.stage-item:last-child { margin-bottom: 0; }
.stage-item:hover { box-shadow: var(--shadow-up); }
.stage-item .k { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }
.stage-item .s { font-size: 15px; line-height: 1.4; margin-top: 3px; overflow-wrap: anywhere; }
.stage-item .m { font-size: 12px; color: var(--ink-3); margin-top: 6px; }
.stage-group.is-stop .stage-item { box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--stop) 40%, transparent); }

.person-none { font-size: 13px; color: var(--ink-3); opacity: 0.7; }

.rail {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  padding: 14px var(--pad) 18px;
  flex-shrink: 0;
}

.rail-item {
  border: 0;
  background: var(--well);
  color: var(--ink-3);
  border-radius: 20px;
  padding: 5px 14px;
  font-size: 12.5px;
  cursor: pointer;
}
.rail-item:hover { color: var(--ink); }
.rail-item.is-done { color: var(--ink-2); text-decoration: line-through; text-decoration-thickness: 1px; }
.rail-item.is-now {
  background: var(--ink);
  color: var(--bg);
  font-weight: 500;
  text-decoration: none;
}
.rail-item.has-blocked::after { content: " ●"; color: var(--stop); font-size: 9px; vertical-align: 1.5px; }
.rail-item.is-now.has-blocked::after { color: #ff8f8f; }
.rail-item.is-end { margin-left: auto; }

@media (max-width: 1000px) {
  .stage-cols { grid-template-columns: 1fr; }
  .clock-time { font-size: 30px; }
}
/* ------------------------------------------------------------ ticket viewer */

.ticket {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: color-mix(in srgb, var(--ink) 24%, transparent);
  display: grid;
  justify-items: center;
  align-content: start;
  padding: 6vh 20px 20px;
  --tbox: min(740px, calc(100vw - 40px));
}

.ticket-box {
  position: relative;
  z-index: 2;
  width: var(--tbox);
  max-height: 86vh;
  background: var(--surface);
  border-radius: 14px;
  box-shadow: var(--shadow-up);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.ticket-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 18px;
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}
.t-age { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }

/* Copy sits with the Jira mark because they are the same errand: take this
   issue somewhere else. */
.t-copy {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border: 0;
  background: none;
  border-radius: 6px;
  color: var(--ink-3);
  cursor: pointer;
  flex-shrink: 0;
}
.t-copy:hover { background: var(--well); color: var(--ink); }
.t-copy.is-done { color: var(--active); }

.ticket-body { flex: 1; min-height: 0; overflow-y: auto; padding: 18px; }
.t-loading { padding: 40px 0; text-align: center; color: var(--ink-3); font-size: 13px; }

.t-summary { margin: 0 0 6px; font-size: 19px; font-weight: 600; line-height: 1.35; letter-spacing: -0.01em; }

/* Ancestry, the way Jira shows it: every level above this issue, each one a
   route you can take. The last entry is where you are, so it is not a link. */
.t-chain {
  display: flex;
  align-items: center;
  gap: 2px;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.t-chain::-webkit-scrollbar { display: none; }
.t-crumb, .t-sep { flex-shrink: 0; }

.t-crumb {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: 0;
  background: none;
  border-radius: 6px;
  padding: 2px 6px;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-3);
  cursor: pointer;
}
.t-crumb:hover { background: var(--well); color: var(--ink); }
.t-crumb.is-current { color: var(--ink); font-size: 13px; font-weight: 600; cursor: default; }
.t-crumb.is-current:hover { background: none; color: var(--ink); }
.t-sep { color: var(--ink-3); font-size: 11px; opacity: 0.7; }

.t-back { padding: 3px 10px; }

/* ------------------------------------------------------------- peek, as depth
   The issue either side of this one, drawn as the same card pushed back into
   the stack — same shape, smaller, faded, tucked behind the one in front. It
   reads as a position in a sequence rather than as two more buttons. */

.tpeek {
  position: absolute;
  top: 6vh;
  z-index: 1;
  width: var(--tbox);
  border: 0;
  padding: 0;
  /* A button centres its content vertically. These have to read as a card, so
     the bar belongs at the top of it. */
  display: flex;
  flex-direction: column;
  align-items: stretch;
  text-align: left;
  background: var(--surface);
  border-radius: 14px;
  /* Deeper than the front card's, because this one is casting onto the scrim
     rather than onto a page — it is what says the card is above the board. */
  box-shadow: 0 10px 30px rgba(20, 22, 40, 0.22);
  overflow: hidden;
  cursor: pointer;
  transition: transform 180ms cubic-bezier(0.2, 0.7, 0.3, 1);
}

/* Veiled rather than made transparent: a translucent card lets the board show
   through its own text, which reads as broken instead of distant.
   The veil has to land *between* two known depths, not on one of them. The
   backdrop dims the board by 24%, so veiling these by 26% put them at exactly
   the board's brightness — 195 against its 199 — and they read as part of it.
   12% sits them at 227, clearly above the board and clearly below the card in
   front, which is the layer they actually occupy. */
.tpeek::after {
  content: "";
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--ink) 12%, transparent);
  transition: background 150ms ease;
}
.tpeek:hover::after { background: color-mix(in srgb, var(--ink) 2%, transparent); }
.tpeek:focus-visible::after { background: color-mix(in srgb, var(--ink) 2%, transparent); }
/* Scaled about the edge facing the front card, so shrinking pushes it away
   rather than sliding it along.
   The offset wants to do two things at once: tuck the inner edge 80px behind
   the card in front, and keep the outer edge on screen. Anchoring only to the
   centre satisfies the first and loses the second on a 1600px window, where the
   card runs off the side and takes its own key with it. So: the centre-relative
   position, floored at what keeps a 16px margin. 1030 = 290 tuck + 740 layout
   width; -58 = that 16px margin less the 74px the 0.9 scale gives back. Below
   1180px neither fits and the flat rail takes over. */
.tpeek.is-prev {
  left: max(-58px, calc(50% - 1030px));
  transform-origin: right center;
  transform: scale(0.9);
}
.tpeek.is-next {
  right: max(-58px, calc(50% - 1030px));
  transform-origin: left center;
  transform: scale(0.9);
}

/* Each card faces its own side of the screen: the half that shows is the outer
   one, so that is the half the content has to be in. */
.tpeek.is-next { text-align: right; }
.tpeek.is-next .tpeek-bar { flex-direction: row-reverse; }
.tpeek.is-next .tpeek-fields { justify-content: flex-end; }
.tpeek.is-prev:hover { transform: scale(0.93); }
.tpeek.is-next:hover { transform: scale(0.93); }
.tpeek:focus-visible { outline-offset: -2px; }

/* The card's own miniature of the viewer: bar, summary, the two fields. */
.tpeek-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 13px 18px;
  border-bottom: 1px solid var(--line);
}
.tpeek-key { font-family: var(--mono); font-size: 13px; font-weight: 600; color: var(--ink); }
.tpeek-dir { font-size: 16px; color: var(--ink-3); }
.tpeek-body { padding: 18px; }
.tpeek-sum {
  margin: 0 0 14px;
  font-size: 19px;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.01em;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.tpeek-fields { display: flex; gap: 14px; align-items: center; }
.tpeek-field {
  display: flex;
  align-items: center;
  gap: 7px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 5px 10px;
  font-size: 13px;
  color: var(--ink-2);
}

/* Landing in another group changes which status you are looking at, not just
   which issue, so the card says so before you take it. */
.tpeek-group {
  font-size: 9.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent);
  background: var(--accent-sf);
  border-radius: 5px;
  padding: 2px 7px;
}

/* Stepping through the stack. Short and directional: long enough to say which
   way you went, over before you would wait for it. The whole stack moves as one
   — the card arriving and the two behind it — so it reads as the stack sliding
   rather than the contents being swapped in place.

   `translate` rather than `transform`, so it composes with the scale the peeks
   already carry instead of overwriting it. */
@keyframes step-front {
  from { translate: var(--step-from, 0) 0; opacity: 0; }
}
@keyframes step-behind {
  from { translate: calc(var(--step-from, 0px) * 1.6) 0; }
}
.ticket.is-step .ticket-box { animation: step-front 175ms cubic-bezier(0.2, 0.7, 0.3, 1); }
.ticket.is-step .tpeek { animation: step-behind 195ms cubic-bezier(0.2, 0.7, 0.3, 1); }

/* Peek: where you would land, before you go. The flat rail is the fallback for
   windows too narrow to seat a card either side. */
.t-peek {
  display: none;
  gap: 8px;
  padding: 8px 18px;
  border-bottom: 1px solid var(--line);
  background: var(--well);
  flex-shrink: 0;
}

.peek {
  display: flex;
  align-items: center;
  gap: 7px;
  flex: 1;
  min-width: 0;
  border: 0;
  background: none;
  border-radius: 8px;
  padding: 5px 8px;
  color: var(--ink-3);
  cursor: pointer;
  text-align: left;
}
.peek:hover { background: var(--surface); color: var(--ink-2); box-shadow: var(--shadow); }
.peek.is-next { flex-direction: row-reverse; text-align: right; }
.peek.is-next .peek-line, .peek.is-next .peek-body { align-items: flex-end; }
.peek:only-child.is-next { margin-left: auto; }

.peek-arrow { font-size: 15px; flex-shrink: 0; opacity: 0.8; }
.peek-body { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.peek-line { display: flex; align-items: center; gap: 6px; min-width: 0; }
.peek-key { font-family: var(--mono); font-size: 11px; flex-shrink: 0; }
.peek-sum {
  font-size: 12px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The one thing on the rail that carries information rather than direction. */
.peek-group {
  font-size: 9.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent);
}
.peek.is-shift { color: var(--ink-2); }

/* -- comments, in their own box below the issue ------------------------------
   Its own scroller so the conversation stays on screen while the issue above
   it is read, rather than sitting at the bottom of one long page. */
.t-talk {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-top: 1px solid var(--line);
  background: var(--well);
  padding: 10px 18px 14px;
}
.t-talk-h { margin: 0 0 6px; }
.t-comments {
  overflow-y: auto;
  overscroll-behavior-y: contain;
  max-height: 26vh;
  min-height: 0;
  padding-right: 4px;
}
.t-comments .t-comment:first-child { padding-top: 0; }

/* Children read as a list of routes too, so the same row shape as a comment
   would be misleading — these are compact and clickable end to end. */
.t-child {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  border: 0;
  background: var(--surface);
  box-shadow: var(--shadow);
  border-radius: 8px;
  padding: 8px 11px;
  margin-bottom: 6px;
  cursor: pointer;
  text-align: left;
  color: inherit;
}
.t-child:hover { box-shadow: var(--shadow-up); }
.t-child .k { font-family: var(--mono); font-size: 11px; color: var(--ink-3); flex-shrink: 0; }
.t-child .s { flex: 1; min-width: 0; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.t-child .st { font-size: 11.5px; color: var(--ink-3); flex-shrink: 0; }
.t-child .p-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.t-child .who { width: 20px; height: 20px; font-size: 8px; }

.t-fields { display: flex; flex-wrap: wrap; gap: 14px; margin: 16px 0 4px; }
.t-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.t-field-label {
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink-3);
}
.t-reporter { display: flex; align-items: center; gap: 7px; font-size: 13px; padding: 6px 0; }

/* Trigger + picker. A native select cannot show a face or be typed into, and
   with a hundred people it is unusable — this is the pattern Jira itself uses. */
.combo-trigger {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 190px;
  max-width: 260px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 5px 10px 5px 7px;
  font-size: 13px;
  color: var(--ink);
  cursor: pointer;
  text-align: left;
}
.combo-trigger:hover:not(:disabled) { border-color: var(--ink-3); }
.combo-trigger[aria-expanded="true"] { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-sf); }
.combo-trigger:disabled { opacity: 0.55; cursor: not-allowed; }
.combo-trigger .combo-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.combo-trigger .combo-caret { color: var(--ink-3); font-size: 10px; flex-shrink: 0; }
.combo-trigger .who { width: 21px; height: 21px; font-size: 8.5px; }
.combo-trigger .p-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; margin-left: 3px; }

.picker {
  position: fixed;
  z-index: 100;
  width: 290px;
  max-height: 340px;
  background: var(--surface);
  border-radius: 11px;
  box-shadow: var(--shadow-up);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.picker-search { display: block; border-bottom: 1px solid var(--line); }
.picker-search input {
  width: 100%;
  border: 0;
  background: none;
  padding: 11px 14px;
  font-size: 13.5px;
  color: var(--ink);
  outline: none;
}
.picker-search input::placeholder { color: var(--ink-3); }
.picker-search[hidden] { display: none; }

.picker-list { overflow-y: auto; padding: 5px; flex: 1; min-height: 0; }

.picker-item {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  border: 0;
  background: none;
  text-align: left;
  padding: 7px 9px;
  border-radius: 7px;
  cursor: pointer;
  color: var(--ink);
  font-size: 13px;
}
.picker-item.is-active { background: var(--well); }
.picker-item .who { width: 22px; height: 22px; font-size: 8.5px; }
.picker-item .p-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; margin: 0 7px; }
.picker-item .pk-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.picker-item .pk-note { font-size: 11px; color: var(--ink-3); flex-shrink: 0; }
.picker-item .pk-tick { color: var(--accent); flex-shrink: 0; font-size: 12px; }
.picker-empty { padding: 18px 12px; text-align: center; color: var(--ink-3); font-size: 12.5px; }

/* Separates the configured roster from the hundred other people on the site.
   No top margin on the first one — it is a caption, not a divider. */
.picker-group {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ink-3);
  padding: 9px 9px 4px;
}
.picker-group:first-child { padding-top: 3px; }

.t-readonly {
  margin: 14px 0 0;
  padding: 8px 12px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--go) 13%, var(--surface));
  color: var(--go);
  font-size: 12px;
}

.t-section { margin-top: 22px; }
.t-h {
  margin: 0 0 9px;
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink-3);
}
.t-count { font-family: var(--mono); letter-spacing: 0; }

/* Jira's own HTML, already sanitised server-side. */
.t-rich { font-size: 13.5px; line-height: 1.6; overflow-wrap: anywhere; }
.t-rich p { margin: 0 0 9px; }
.t-rich :is(h1, h2, h3, h4, h5, h6) { font-size: 14px; margin: 14px 0 6px; }
.t-rich a { color: var(--accent); }
/* A mention should read as a person, not as a link off the page. */
.t-rich a.mention {
  display: inline-block;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
  border-radius: 4px;
  padding: 0 4px;
  text-decoration: none;
  font-weight: 500;
}
.t-rich a.mention::before { content: "@"; opacity: 0.65; }
.t-rich a.mention:hover { background: color-mix(in srgb, var(--accent) 20%, transparent); }
.t-rich code {
  font-family: var(--mono);
  font-size: 12px;
  background: var(--well);
  border-radius: 4px;
  padding: 1px 4px;
}
.t-rich pre { background: var(--well); border-radius: 8px; padding: 10px 12px; overflow-x: auto; }
.t-rich pre code { background: none; padding: 0; }
.t-rich blockquote {
  margin: 0 0 9px;
  padding-left: 12px;
  border-left: 2px solid var(--line);
  color: var(--ink-2);
}
.t-rich :is(ul, ol) { margin: 0 0 9px; padding-left: 20px; }
.t-rich table { border-collapse: collapse; font-size: 12.5px; }
.t-rich :is(th, td) { border: 1px solid var(--line); padding: 5px 8px; text-align: left; }
.t-rich:empty::after { content: "No description."; color: var(--ink-3); font-size: 13px; }

.t-comment { display: flex; gap: 10px; padding: 10px 0; border-top: 1px solid var(--line); }
.t-talk .t-compose textarea { background: var(--surface); }
.t-comment:first-child { border-top: 0; padding-top: 0; }
.t-comment .who { width: 26px; height: 26px; font-size: 9.5px; }
.t-comment-main { flex: 1; min-width: 0; }
.t-comment-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 3px; }
.t-comment-who { font-size: 13px; font-weight: 600; }
.t-comment-when { font-size: 11.5px; color: var(--ink-3); }
.t-none { font-size: 13px; color: var(--ink-3); }

.t-compose { margin-top: 10px; flex-shrink: 0; }
.t-compose textarea {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 10px 12px;
  font-size: 13.5px;
  font-family: inherit;
  color: var(--ink);
  resize: vertical;
}
.t-compose textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-sf); }
.t-compose textarea:disabled { opacity: 0.6; }
.t-compose-foot { display: flex; align-items: center; gap: 12px; margin-top: 8px; }
.t-hint { font-size: 11.5px; color: var(--ink-3); }
.t-compose-foot .primary { margin-left: auto; }

/* ----------------------------------------------------------------- palette */

.palette {
  position: fixed;
  inset: 0;
  z-index: 95;
  background: color-mix(in srgb, var(--ink) 22%, transparent);
  display: grid;
  justify-items: center;
  align-content: start;
  padding: 12vh 20px 20px;
}

.palette-box {
  width: 100%;
  max-width: 620px;
  background: var(--surface);
  border-radius: 14px;
  box-shadow: var(--shadow-up);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  max-height: 70vh;
}

.palette-box > input {
  border: 0;
  border-bottom: 1px solid var(--line);
  background: none;
  padding: 15px 18px;
  font-size: 15px;
  color: var(--ink);
  outline: none;
}
.palette-box > input::placeholder { color: var(--ink-3); }

.palette-results { overflow-y: auto; padding: 6px; flex: 1; min-height: 0; }

.palette-group {
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ink-3);
  padding: 10px 12px 5px;
}

.palette-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  border: 0;
  background: none;
  text-align: left;
  padding: 8px 12px;
  border-radius: 8px;
  cursor: pointer;
  color: var(--ink);
  font-size: 13.5px;
}
.palette-item.is-active { background: var(--well); }
.palette-item .p-key {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-3);
  flex-shrink: 0;
}
.palette-item .p-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.palette-item .p-hint {
  font-size: 11.5px;
  color: var(--ink-3);
  flex-shrink: 0;
  max-width: 40%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.palette-item .p-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.palette-item .who { width: 18px; height: 18px; font-size: 8px; }

.palette-empty { padding: 22px 14px; text-align: center; color: var(--ink-3); font-size: 13px; }

.palette-foot {
  display: flex;
  gap: 16px;
  padding: 9px 16px;
  border-top: 1px solid var(--line);
  font-size: 11px;
  color: var(--ink-3);
}
.palette-foot kbd {
  font-family: var(--mono);
  background: var(--well);
  border-radius: 4px;
  padding: 1px 5px;
  margin-right: 3px;
}

/* ------------------------------------------------------------------- setup */

.setup {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: var(--bg);
  display: grid;
  place-items: start center;
  overflow-y: auto;
  padding: 6vh 20px 40px;
}

.setup-card {
  width: 100%;
  max-width: 520px;
  background: var(--surface);
  border-radius: 14px;
  box-shadow: var(--shadow-up);
  padding: 28px 30px 24px;
}

.setup-title { margin: 0 0 6px; font-size: 21px; font-weight: 600; letter-spacing: -0.02em; }
.setup-lede { margin: 0 0 22px; font-size: 13px; color: var(--ink-2); line-height: 1.55; }

.field { display: block; margin-bottom: 16px; }
.field-label { display: block; font-size: 12.5px; font-weight: 600; margin-bottom: 5px; }
.field input {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 13.5px;
  color: var(--ink);
}
.field input:focus { border-color: var(--accent); outline: none; box-shadow: 0 0 0 3px var(--accent-sf); }
.field-hint { display: block; font-size: 11.5px; color: var(--ink-3); margin-top: 4px; }

/* Fixed domain sits inside the field, so only the part that varies is typed. */
.combo {
  display: flex;
  align-items: stretch;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
}
.combo:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-sf); }
.combo input {
  flex: 1;
  min-width: 0;
  border: 0;
  border-radius: 0;
  background: none;
  text-align: right;
}
.combo input:focus { box-shadow: none; }
.combo-suffix {
  display: flex;
  align-items: center;
  padding-right: 12px;
  font-size: 13.5px;
  color: var(--ink-3);
  white-space: nowrap;
}
.combo.is-full .combo-suffix { display: none; }
.combo.is-full input { text-align: left; }

.howto {
  border-radius: 10px;
  background: var(--well);
  padding: 14px 15px 4px;
  margin-bottom: 16px;
}
.howto-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.howto-open { font-size: 12.5px; color: var(--accent); text-decoration: none; font-weight: 500; }
.howto-open:hover { text-decoration: underline; }

.choice { display: grid; gap: 10px; }

.choice-opt {
  background: var(--surface);
  border-radius: 9px;
  padding: 11px 13px 12px;
}
.choice-opt.is-rec { box-shadow: inset 0 0 0 1.5px var(--accent); }
.choice-opt h3 { margin: 0 0 4px; font-size: 12.5px; font-weight: 600; display: flex; align-items: center; gap: 7px; }
.choice-opt p { margin: 0 0 6px; font-size: 12px; color: var(--ink-2); line-height: 1.5; }
.choice-opt .warn { color: var(--go); }
.choice-opt code {
  font-family: var(--mono);
  font-size: 11.5px;
  background: var(--well);
  border-radius: 4px;
  padding: 1px 4px;
}

.badge {
  font-size: 9.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--accent);
  background: var(--accent-sf);
  border-radius: 20px;
  padding: 2px 7px;
}

.scopes { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
/* width:0 (not just min-width:0) is what stops this scroller demanding the full
   width of the scope list and dragging the whole card wider than the screen.
   flex-grow gives the space back. */
.scopes code {
  flex: 1;
  width: 0;
  min-width: 0;
  overflow-x: auto;
  white-space: nowrap;
  padding: 5px 8px;
}

.setup-error {
  margin: 0 0 14px;
  padding: 9px 12px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--stop) 10%, var(--surface));
  color: var(--stop);
  font-size: 12.5px;
  line-height: 1.5;
}

.setup-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

.prefs { margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--line); }
.prefs-title { margin: 0 0 4px; font-size: 14px; font-weight: 600; }
.prefs-note { margin: 0 0 14px; font-size: 12px; color: var(--ink-2); line-height: 1.55; }
.prefs-row { display: flex; align-items: flex-end; gap: 12px; }
.prefs-row .field { margin-bottom: 0; }
.prefs-row .field input { width: 110px; }
.prefs-row .pill { padding: 8px 14px; }

.primary {
  background: var(--accent);
  border: 1px solid var(--accent);
  color: #fff;
  border-radius: 8px;
  padding: 8px 20px;
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer;
}
.primary:hover { filter: brightness(1.08); }
.primary:disabled { opacity: 0.6; cursor: default; }

/* ------------------------------------------------------------------ narrow

   The desktop board is an app shell: a fixed-height viewport with a row of
   full-height columns you scroll sideways. That model does not survive a phone
   — sideways scrolling hides most of the pipeline, and a column with its own
   scroller inside a page that does not scroll is a trap. So below 760px the
   whole thing becomes one ordinary document that scrolls down: stages stack,
   their bodies stop scrolling independently, and the page does it all.

   Overlays go the other way. A centred box with a backdrop is a desktop idea;
   on a phone a ticket is a screen, so it takes the whole one. */

@media (max-width: 760px) {
  :root { --pad: 12px; }

  body { height: auto; min-height: 100vh; overflow: visible; }

  /* -- chrome: brand and tools on one row, the view tabs on their own ------ */
  .bar { flex-wrap: wrap; gap: 8px 10px; padding: 10px var(--pad) 8px; }
  .brand-name { display: none; }
  .tools { gap: 6px; flex: 1; min-width: 0; }
  .find { flex: 1; min-width: 0; }
  .find input { width: 100%; min-width: 0; }
  .roles { order: 3; width: 100%; }
  .role { flex: 1; white-space: nowrap; }

  .subbar { flex-wrap: wrap; gap: 6px 10px; padding: 0 var(--pad) 10px; }
  .role-sub { order: 1; flex: 1; min-width: 0; }
  .sync { order: 2; }
  /* .spacer is shared with the ticket bar, so scope it to this one. */
  .subbar-sep, .subbar .spacer, .hintkey { display: none; }   /* no ⌃K on a phone */

  /* The team strip is the one thing that may not stack: eight people down the
     screen would push the board off it. It scrolls sideways instead, bleeding
     to both edges so the cut-off chip reads as "more this way". */
  .people {
    order: 3;
    width: 100%;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    margin: 0 calc(-1 * var(--pad));
    padding: 2px var(--pad);
  }
  .people::-webkit-scrollbar { display: none; }

  .notice-row { flex-wrap: wrap; }
  .notice-act { margin-left: 0; }
  .blocked { max-height: none; overflow: visible; }

  /* -- board: one stage per row, the page doing all the scrolling ---------- */
  /* grid-template-columns is set inline per render, so this has to outrank it. */
  .board {
    grid-template-columns: 1fr !important;
    gap: 16px;
    overflow: visible;
    flex: none;
  }
  .col-body { overflow: visible; flex: none; }

  /* A stage nobody is in keeps its label, but lying down — a vertical spine is
     a way to save width, and width is not what is short here. */
  .col.is-spine .col-body { flex-direction: row; justify-content: center; padding: 9px 0; }
  .spine-label { writing-mode: horizontal-tb; letter-spacing: 0.1em; }

  /* No hover on touch, so the Jira mark cannot be hover-only or it is simply
     not reachable. */
  .card-jira { opacity: 0.5; }

  /* -- overlays become screens -------------------------------------------- */
  .ticket { padding: 0; align-content: stretch; }
  .ticket-box {
    max-width: none;
    max-height: none;
    height: 100vh;
    height: 100dvh;
    border-radius: 0;
  }
  /* "updated 7/28/2026, 12:24:46 PM" is the first thing to go when the bar has
     390px to seat a key, a type, a Jira link and a way out. Age is on the card. */
  .ticket-bar { padding: 11px var(--pad); }
  .t-peek { padding: 7px var(--pad); }
  .peek-sum { display: none; }          /* a key and its group is all that fits */
  .t-talk { padding: 9px var(--pad) 12px; }
  .t-comments { max-height: 22vh; }
  .ticket-bar .t-age { display: none; }
  .t-key { white-space: nowrap; }
  .ticket-body { padding: 14px var(--pad) 20px; }
  .t-fields { gap: 12px; margin: 14px 0 4px; }
  .t-field { width: 100%; }
  .combo-trigger { min-width: 0; max-width: none; width: 100%; }

  .picker { max-width: min(88vw, 340px); }

  .palette { padding: 8vh 12px 12px; }
  .palette-box { max-height: 76vh; }
  .palette-item { padding: 11px 12px; }
  .palette-item .p-hint { display: none; }
  .palette-foot { display: none; }        /* ↑↓ / ↵ / esc mean nothing here */

  .setup { padding: 0; place-items: start stretch; }
  .setup-card {
    border-radius: 0;
    min-height: 100vh;
    min-height: 100dvh;
    padding: 24px 18px 32px;
  }
  .howto-head { flex-wrap: wrap; }
  .howto { padding: 12px 12px 4px; }

  .standup-bar { flex-wrap: wrap; gap: 10px 14px; padding: 12px var(--pad) 8px; }
  .standup-title { font-size: 17px; }
  .clock { padding: 4px 14px; }
  .clock-time { font-size: 24px; }
  .standup-ctl { width: 100%; }
  .standup-ctl > * { flex: 1; }
  .stage-name { font-size: 21px; }
  .stage-face { width: 36px; height: 36px; font-size: 13px; }
  .rail { padding: 10px var(--pad) 16px; gap: 5px; }

  .drawer-list { max-height: none; overflow: visible; }
  .drawer-item { max-width: 100%; }
}

/* A landscape phone is the other way round: width to spare, no height at all.
   The app shell gives the board whatever the chrome leaves, and at 390px tall
   that is nothing — measured zero. So page-scroll here too, on height alone,
   which also catches a short desktop window. Columns stay side by side; they
   just grow down the page instead of fighting over a fixed viewport. */
@media (max-height: 560px) {
  body { height: auto; min-height: 100vh; overflow: visible; }
  .board { overflow: visible; flex: none; }
  .col-body { overflow: visible; flex: none; }
  .bar { padding-top: 8px; padding-bottom: 6px; }
  .blocked { max-height: none; overflow: visible; }
  .drawer-list { max-height: none; overflow: visible; }
  .ticket { padding: 2vh 16px 12px; }
  .ticket-box { max-height: 96vh; }
}

/* Touch pointers need targets they can actually hit; 30px is a mouse size. */
@media (pointer: coarse) {
  .icon { width: 36px; height: 36px; }
  .pill { padding: 8px 14px; }
  .role { padding: 8px 12px; }
  .who-chip { padding: 6px 11px 6px 4px; }
  .team-label { padding: 4px 8px; }
  .drawer-toggle { padding: 13px var(--pad); }
  .picker-item { padding: 10px 11px; }
  .t-child { padding: 11px 12px; }
}

/* A card either side needs room either side. Under this the flat rail carries
   the same two moves in a strip that costs no width. */
@media (max-width: 1180px) {
  .tpeek { display: none; }
  .t-peek { display: flex; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
