/* Vibe Check. The category's own app shell at Linear's level of polish: a left pane of repos
   that folds to the mark, and the board on an inset sheet. True neutrals, one grotesque,
   1px rules. One accent, Heron Preston orange, and it means needs you; green is live and red
   is failing. Every state has its own lamp shape, so colour never carries it alone. */

@font-face {
  font-family: "Public Sans";
  src: url("/static/fonts/public-sans.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ---------- tokens: one list, light and dark side by side ---------- */
:root {
  color-scheme: light dark;
  /* True neutrals: every grey has zero chroma (r = g = b) in both themes. */
  --frame: light-dark(#f4f4f4, #0d0d0d);
  --sheet: light-dark(#ffffff, #141414);
  --panel: light-dark(#ffffff, #191919);
  --hover: light-dark(#f2f2f2, #1f1f1f);
  --active: light-dark(#e9e9e9, #272727);
  --border: light-dark(#e4e4e4, #272727);
  --rule: light-dark(#efefef, #202020);
  --control: light-dark(#d4d4d4, #3b3b3b);
  --text: light-dark(#111111, #f4f4f4);
  --soft: light-dark(#404040, #c9c9c9);
  --muted: light-dark(#606060, #a2a2a2);
  --faint: light-dark(#6c6c6c, #8f8f8f);
  --live: light-dark(#1f7a4c, #43c47f);
  --live-fill: light-dark(#23a05f, #43c47f);
  --fail: light-dark(#c42a36, #f0647a);
  --fail-bg: light-dark(#fdecee, #2c171c);
  --need: #f1713b; /* Heron Preston orange: needs you, and nothing else */
  --need-ink: light-dark(#b2471b, #f58a5c); /* the same orange, deep enough to read as text */
  --on-need: #141414;
  --moved: light-dark(#efefef, #2a2a2a); /* light enough that every word on it keeps 4.5:1 */
  --select: light-dark(#dedede, #3b3b3b);
  --shadow: light-dark(rgb(17 17 17 / 0.12), rgb(0 0 0 / 0.55));
  --scrim: light-dark(rgb(17 17 17 / 0.28), rgb(0 0 0 / 0.6));

  --pane-w: 248px;
  --bar-h: 56px;
  --pad: 32px;
  --gap: 16px;
  --radius: 8px;
  --radius-panel: 10px;
  --radius-sheet: 12px;
  --font: "Public Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
:root[data-theme="light"] {
  color-scheme: light;
}
:root[data-theme="dark"] {
  color-scheme: dark;
}
:root[data-pane="collapsed"] {
  --pane-w: 64px;
}

/* ---------- base ---------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scrollbar-color: var(--control) transparent;
}

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--frame);
  color: var(--text);
  font: 400 14px/20px var(--font);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  caret-color: var(--text);
}

h1,
h2,
h3,
p,
ol,
ul {
  margin: 0;
  padding: 0;
}

ol,
ul {
  list-style: none;
}

a {
  color: inherit;
  text-decoration: none;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

input {
  font: inherit;
  color: inherit;
}

::selection {
  background: var(--select);
  color: var(--text);
}

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

[hidden] {
  display: none !important;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.i {
  width: 16px;
  height: 16px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.i-dots circle {
  fill: currentColor;
  stroke: none;
}

.i-gh {
  stroke: none;
}

.icon-btn {
  display: inline-grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius);
  color: var(--muted);
  transition: background-color 0.12s, color 0.12s;
}

.icon-btn:hover,
details[open] > .icon-btn {
  background: var(--hover);
  color: var(--text);
}

/* ---------- the shell ---------- */
.shell {
  display: grid;
  grid-template-columns: var(--pane-w) minmax(0, 1fr);
  min-height: 100dvh;
}

.pane {
  position: sticky;
  top: 0;
  height: 100dvh;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 8px;
  /* The pane sits on the frame, so its hover and current-repo fills are a step deeper
     than the sheet's; its menus sit on a panel and take the sheet's fills back. */
  --hover: light-dark(#eaeaea, #1f1f1f);
  --active: light-dark(#e2e2e2, #272727);
}

.pane .menu {
  --hover: light-dark(#f2f2f2, #1f1f1f);
  --active: light-dark(#e9e9e9, #272727);
}

.pane-head {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 40px;
  padding: 0 4px 0 12px;
}

.brand {
  display: flex;
  align-items: center;
  height: 32px;
  color: var(--text);
}

.brand .logo {
  display: block;
  width: auto;
  height: 19px;
}

.brand-mark {
  position: relative;
  display: none;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius);
  color: var(--text);
  transition: background-color 0.12s;
}

.brand-mark:hover {
  background: var(--hover);
}

.brand-mark .mark,
.topbar-mark .mark {
  display: block;
  width: 26px;
  height: 26px;
}

/* What needs you in the other repos, on the mark, wherever the mark stands in for the pane. */
.mark-n {
  position: absolute;
  top: 1px;
  right: 0;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--need);
  color: var(--on-need);
  box-shadow: 0 0 0 2px var(--frame);
  font-size: 11px;
  line-height: 18px;
  font-weight: 600;
  text-align: center;
}

.topbar-mark .mark-n {
  box-shadow: 0 0 0 2px var(--sheet);
}

.mark-n:empty {
  display: none;
}

.pane-nav {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 4px 0 12px;
  scrollbar-width: thin;
}

.pane-foot {
  flex: none;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}

/* Folded on a desk: the pane is just the mark, and the mark opens it again. */
:root[data-pane="collapsed"] .pane-nav,
:root[data-pane="collapsed"] .pane-foot,
:root[data-pane="collapsed"] .brand,
:root[data-pane="collapsed"] .pane-collapse {
  display: none;
}

:root[data-pane="collapsed"] .brand-mark {
  display: grid;
}

:root[data-pane="collapsed"] .pane-head {
  justify-content: center;
  padding: 0;
}

/* ---------- the pane's repo list ---------- */
.group {
  margin-top: 18px;
}

.group:first-child {
  margin-top: 6px;
}

.group-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 28px;
  padding: 0 0 0 12px;
}

.group-head h2,
.folder-name {
  font-size: 12px;
  line-height: 16px;
  font-weight: 500;
  color: var(--muted);
}

.group-head .icon-btn {
  width: 28px;
  height: 28px;
}

.group-empty {
  padding: 6px 12px;
  font-size: 12px;
  color: var(--muted);
}

.repos {
  display: grid;
  gap: 1px;
  margin-top: 2px;
}

.repo {
  position: relative;
  border-radius: var(--radius);
}

.repo-link {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  padding: 0 8px 0 12px;
  border-radius: var(--radius);
  color: var(--soft);
  transition: background-color 0.12s, color 0.12s;
}

.repo-link:hover {
  background: var(--hover);
  color: var(--text);
}

.repo-link[aria-current="page"] {
  background: var(--active);
  color: var(--text);
  font-weight: 500;
}

.repo-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.repo-n,
.needs-n {
  flex: none;
  min-width: 20px;
  height: 18px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--need);
  color: var(--on-need);
  font-size: 11px;
  line-height: 18px;
  font-weight: 600;
  text-align: center;
}

.repo-n:empty {
  display: none;
}

.repo-quiet {
  flex: none;
  font-size: 12px;
  color: var(--faint);
}

.repo-link[aria-current] .repo-quiet {
  color: var(--muted);
}

/* A quiet repo that comes to need you shows the count instead. */
.repo-n:not(:empty) ~ .repo-quiet {
  display: none;
}

.repo .repo-menu {
  position: absolute;
  top: 2px;
  right: 2px;
}

.repo-menu > summary {
  width: 28px;
  height: 28px;
  opacity: 0;
}

.repo:hover .repo-menu > summary,
.repo:focus-within .repo-menu > summary,
.repo-menu[open] > summary {
  opacity: 1;
}

/* With a mouse, the count gives way to the options button on hover. */
@media (hover: hover) {
  .repo:hover .repo-n,
  .repo:hover .repo-quiet {
    visibility: hidden;
  }
}

/* With the keyboard, the count stays (and stays in the link's name); the button sits beside it. */
.repo:focus-within .repo-link,
.repo:has(.repo-menu[open]) .repo-link {
  padding-right: 36px;
}

/* On touch, the button is always there and the count sits beside it. */
@media (hover: none) {
  .repo-link {
    padding-right: 36px;
  }

  .repo-menu > summary {
    opacity: 1;
  }
}

/* Quiet repos (no push in 90 days, nothing waiting) read quieter, and say so. */
.repo.quiet .repo-link:not([aria-current], :hover) {
  color: var(--faint);
}

.repo.dragging {
  opacity: 0.45;
}

.repo[draggable="true"] {
  cursor: grab;
}

.quiet-note {
  display: grid;
  gap: 4px;
  margin: 10px 4px 0;
  padding: 10px 12px;
  border-radius: var(--radius);
  background: var(--hover);
  font-size: 12px;
  line-height: 16px;
  color: var(--muted);
}

.text-btn {
  justify-self: start;
  font-weight: 500;
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--control);
  text-underline-offset: 3px;
}

.text-btn:hover {
  text-decoration-color: currentColor;
}

.folder {
  margin-top: 18px;
}

.folder > summary {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 12px 0 8px;
  border-radius: var(--radius);
  list-style: none;
  cursor: pointer;
}

.folder > summary::-webkit-details-marker {
  display: none;
}

.folder > summary:hover {
  background: var(--hover);
}

.folder .i-chev {
  color: var(--muted);
  transition: transform 0.15s;
}

.folder[open] > summary .i-chev {
  transform: rotate(90deg);
}

.folder-n {
  margin-left: auto;
  font-size: 12px;
  color: var(--muted);
}

/* ---------- menus ---------- */
details[data-menu] {
  position: relative;
}

details[data-menu] > summary {
  list-style: none;
  cursor: pointer;
}

details[data-menu] > summary::-webkit-details-marker {
  display: none;
}

.menu {
  position: absolute;
  z-index: 60;
  top: calc(100% + 4px);
  left: 0;
  min-width: 208px;
  padding: 4px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-panel);
  box-shadow: 0 12px 32px var(--shadow);
  animation: menu-in 0.14s cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* Menus inside the scrolling pane float free of it; app.js sets left and top, and nothing
   else may pull an edge (a leftover right: 0 stretched the sort menu across the board). */
.pane-nav .menu {
  position: fixed;
  right: auto;
  bottom: auto;
}

.menu-end {
  left: auto;
  right: 0;
}

.menu-up {
  top: auto;
  bottom: calc(100% + 4px);
}

.menu-label {
  padding: 8px 10px 6px;
  font-size: 12px;
  line-height: 16px;
  color: var(--muted);
}

.menu-label strong {
  color: var(--text);
  font-weight: 500;
}

.menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  height: 32px;
  padding: 0 10px;
  border-radius: 6px;
  color: var(--soft);
  font-size: 13px;
  text-align: left;
  white-space: nowrap;
}

.menu-item:hover,
.menu-item:focus-visible {
  background: var(--hover);
  color: var(--text);
  outline: none;
}

.menu-item .i {
  color: var(--muted);
}

.sort-menu .menu-item .i-check {
  visibility: hidden;
}

.sort-menu .menu-item[aria-pressed="true"] {
  color: var(--text);
}

.sort-menu .menu-item[aria-pressed="true"] .i-check {
  visibility: visible;
  color: var(--text);
}

@keyframes menu-in {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
}

/* ---------- the account ---------- */
.me > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 8px;
  border-radius: var(--radius);
  color: var(--soft);
}

.me > summary:hover,
.me[open] > summary {
  background: var(--hover);
}

.avatar {
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: 50%;
}

.avatar-initial {
  display: grid;
  place-items: center;
  background: var(--active);
  color: var(--text);
  font-size: 12px;
  font-weight: 600;
}

.me-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
  font-weight: 500;
}

.me > summary .i-dots {
  color: var(--muted);
}

.me .menu {
  right: 0;
  min-width: 0;
}

/* ---------- the sheet ---------- */
.sheet {
  min-width: 0;
  margin: 8px 8px 8px 0;
  display: flex;
  flex-direction: column;
  background: var(--sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-sheet);
}

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 12px;
  height: var(--bar-h);
  padding: 0 14px 0 var(--pad);
  background: var(--sheet);
  border-bottom: 1px solid var(--border);
  border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
}

.topbar-mark {
  position: relative;
  display: none;
  place-items: center;
  flex: none;
  width: 40px;
  height: 40px;
  margin-left: -6px;
  border-radius: var(--radius);
  color: var(--text);
}

.search {
  position: relative;
  flex: 1;
  max-width: 440px;
  display: flex;
  align-items: center;
}

.search > .i {
  position: absolute;
  left: 10px;
  color: var(--muted);
  pointer-events: none;
}

.search input {
  width: 100%;
  height: 34px;
  padding: 0 32px 0 34px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--frame);
  font-size: 13px;
  transition: border-color 0.12s, background-color 0.12s;
}

.search input::placeholder {
  color: var(--faint);
}

.search input:hover {
  border-color: var(--control);
}

.search input:focus {
  outline: none;
  border-color: var(--muted);
  background: var(--sheet);
  box-shadow: 0 0 0 3px var(--select);
}

.search input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

.search kbd {
  position: absolute;
  right: 8px;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--sheet);
  color: var(--muted);
  font: 500 11px/18px var(--font);
  text-align: center;
  pointer-events: none;
}

.search input:focus + kbd,
.search input:not(:placeholder-shown) + kbd {
  display: none;
}

.search-clear {
  position: absolute;
  right: 4px;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 6px;
  color: var(--muted);
}

.search-clear:hover {
  background: var(--hover);
  color: var(--text);
}

.fresh {
  margin-left: auto;
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
}

.theme-toggle .i-sun {
  display: none;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .i-sun {
    display: block;
  }

  :root:not([data-theme="light"]) .theme-toggle .i-moon {
    display: none;
  }
}

:root[data-theme="dark"] .theme-toggle .i-sun {
  display: block;
}

:root[data-theme="dark"] .theme-toggle .i-moon {
  display: none;
}

/* ---------- the board ---------- */
.view {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 28px;
  width: 100%;
  max-width: 1360px;
  min-width: 0;
  padding: 28px var(--pad) 48px;
}

.head {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 6px;
}

.head-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 12px;
}

.head h1 {
  font-size: 24px;
  line-height: 32px;
  font-weight: 600;
  letter-spacing: -0.012em;
}

.need-pill {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 10px;
  border-radius: 999px;
  background: var(--need);
  color: var(--on-need);
  font-size: 12px;
  font-weight: 600;
}

.need-pill:hover {
  text-decoration: underline;
}

.clear-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 10px;
  border-radius: 999px;
  background: var(--hover);
  color: var(--soft);
  font-size: 12px;
  font-weight: 500;
}

.gh-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  font-size: 12px;
  color: var(--muted);
}

.gh-link:hover {
  color: var(--text);
}

.finding {
  max-width: 80ch;
  color: var(--soft);
}

.finding strong {
  color: var(--text);
  font-weight: 600;
}

.fresh-m {
  display: none;
  font-size: 12px;
  color: var(--muted);
}

.notice {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--fail-bg);
  font-size: 13px;
}

.notice .lamp {
  color: var(--fail);
}

.notice a {
  margin-left: auto;
  font-weight: 500;
  text-decoration: underline;
  white-space: nowrap;
}

.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-panel);
}

.panel-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 16px 12px;
}

.panel-head h2,
.section-h {
  font-size: 15px;
  line-height: 20px;
  font-weight: 600;
}

.needs-n {
  height: 20px;
  font-size: 12px;
  line-height: 20px;
}

.needs-list li {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: 12px;
  padding: 12px 16px;
  border-top: 1px solid var(--rule);
}

.need-n {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 20px;
  font-size: 13px;
  font-weight: 600;
  color: var(--need-ink);
}

.need-n::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: var(--need);
}

.need-body {
  min-width: 0;
}

.need-link {
  font-weight: 500;
  color: var(--text);
}

.need-link:hover {
  text-decoration: underline;
}

.need-sub,
.need-also {
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
  color: var(--muted);
}

.need-also {
  font-size: 12px;
}

.needs-empty {
  padding: 0 16px 16px;
  color: var(--soft);
}

/* What's live, one panel per lane. */
.live {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
}

.lanes {
  display: grid;
  gap: var(--gap);
}

.lanes-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.lanes-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.lanes-4 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.lane {
  display: grid;
  align-content: start;
  gap: 8px;
  padding: 14px 16px 16px;
}

.lane-body {
  display: grid;
  gap: 8px;
  min-width: 0;
}

.lane-name {
  font-size: 12px;
  line-height: 16px;
  font-weight: 500;
  color: var(--muted);
}

.lane-pr {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-height: 40px;
  color: var(--text);
}

a.lane-pr:hover .lane-title {
  text-decoration: underline;
}

.lane-n {
  flex: none;
  font-weight: 600;
}

.lane-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-weight: 500;
}

.lane-facts {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 13px;
  color: var(--soft);
}

.lane-facts .lamp {
  margin-top: 6px;
}

.lane-which {
  flex: 1;
  min-width: 0;
}

.lane-when {
  margin-left: auto;
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
}

.lane-note,
.live-note,
.lane-none {
  font-size: 12px;
  color: var(--muted);
}

.lane-none {
  font-size: 13px;
}

/* Every change, one row each. */
.changes {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
  min-width: 0;
  --lanes-n: 3;
  --lane-w: 132px;
  --cols: minmax(0, 1fr) repeat(var(--lanes-n), var(--lane-w)) 72px;
}

.changes.cols-1 {
  --lanes-n: 1;
  --lane-w: 148px;
}

.changes.cols-2 {
  --lanes-n: 2;
  --lane-w: 140px;
}

.changes.cols-4 {
  --lanes-n: 4;
  --lane-w: 120px;
}

.changes-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px 16px;
}

.scope {
  margin-top: 2px;
  font-size: 12px;
  color: var(--muted);
}

.tabs {
  display: inline-flex;
  gap: 2px;
  max-width: 100%;
  padding: 2px;
  border-radius: 9px;
  background: var(--hover);
}

.tabs button {
  height: 28px;
  padding: 0 10px;
  border-radius: 7px;
  font-size: 13px;
  font-weight: 500;
  color: var(--muted);
  white-space: nowrap;
  transition: background-color 0.12s, color 0.12s;
}

.tabs button:hover {
  color: var(--text);
}

.tabs button .n {
  margin-left: 2px;
  color: var(--faint);
  font-weight: 400;
}

.tabs button[aria-pressed="true"] {
  background: var(--sheet);
  color: var(--text);
  box-shadow: 0 0 0 1px var(--border);
}

/* clip, not hidden: hidden would make the table a scroller and unstick its legend. */
.table {
  overflow: clip;
}

.cols,
.line {
  display: grid;
  grid-template-columns: var(--cols);
  column-gap: 16px;
  align-items: center;
}

.cells {
  display: contents;
}

/* The lane legend sticks under the top bar, so a long board never loses its column names. */
.cols {
  position: sticky;
  top: var(--bar-h);
  z-index: 5;
  padding: 10px 16px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  font-size: 12px;
  line-height: 16px;
  color: var(--muted);
}

.c-lane {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.c-ago,
.ago {
  text-align: right;
}

.line {
  padding: 12px 16px;
  border-top: 1px solid var(--rule);
  transition: background-color 0.12s;
}

.lines > li:first-child {
  border-top: 0;
}

.line:hover {
  background: var(--hover);
}

.what,
.what-top {
  min-width: 0;
}

/* The phone's end of the title line (tool and age); wider screens have them in the meta line. */
.aside {
  display: none;
}

.title {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
  color: var(--text);
}

.title:hover {
  text-decoration: underline;
}

/* The meta line: "#307 #308 · Johnnie with Claude · Session". */
.by {
  display: flex;
  gap: 6px;
  margin-top: 2px;
  overflow: hidden;
  white-space: nowrap;
  font-size: 12px;
  line-height: 16px;
  color: var(--muted);
}

.by > * {
  flex: none;
}

.by > * + *::before {
  content: "·";
  content: "·" / "";
  display: inline-block;
  margin-right: 6px;
  color: var(--faint);
}

.by .nums {
  font-weight: 600;
  color: var(--soft);
}

.nums-narrow {
  display: none;
}

.line.need .by .nums {
  color: var(--need-ink);
}

.by .who {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.by-link {
  color: var(--soft);
  text-decoration: underline;
  text-decoration-color: var(--control);
}

.by-link:hover {
  text-decoration-color: currentColor;
}

.by-ago {
  display: none;
}

.ago {
  font-size: 12px;
  color: var(--muted);
}

.cell {
  display: grid;
  gap: 2px;
  min-width: 0;
  margin: -4px -6px;
  padding: 4px 6px;
  border-radius: 6px;
  font-size: 13px;
}

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

.cell .w {
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}

.cell .word {
  font-weight: 500;
}

.cell .short {
  display: none;
}

.cell .note {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding-left: 16px;
  font-size: 12px;
  line-height: 16px;
  color: var(--muted);
}

a.cell:hover .word {
  text-decoration: underline;
}

.t-plain .word {
  color: var(--text);
}

.t-live .word {
  color: var(--live);
}

.t-fail .word {
  color: var(--fail);
}

.t-need .word {
  color: var(--need-ink);
}

.t-mute .word {
  color: var(--muted);
  font-weight: 400;
}

.t-none .dash {
  color: var(--faint);
}

.lines-empty {
  padding: 28px 16px;
  color: var(--muted);
  text-align: center;
}

.lines-empty .text-btn {
  margin-left: 6px;
}

/* ---------- lamps: shape says the state, colour says how much it matters ---------- */
.lamp {
  display: inline-block;
  flex: none;
  width: 8px;
  height: 8px;
  border: 1.5px solid currentColor;
  color: var(--muted);
}

.lamp.sq {
  border-radius: 2px;
}

.lamp.ci {
  border-radius: 50%;
}

.lamp.on {
  background: currentColor;
}

.lamp.half {
  background: linear-gradient(90deg, currentColor 50%, transparent 50%);
}

.lamp.x {
  border: 0;
  background:
    linear-gradient(45deg, transparent 43%, currentColor 43% 57%, transparent 57%),
    linear-gradient(-45deg, transparent 43%, currentColor 43% 57%, transparent 57%);
}

.lamp.bar {
  width: 10px;
  height: 2px;
  border: 0;
  border-radius: 1px;
  background: currentColor;
}

.t-plain .lamp {
  color: var(--text);
}

.t-live .lamp,
.lane-facts .lamp {
  color: var(--live-fill);
}

.t-fail .lamp {
  color: var(--fail);
}

.t-need .lamp {
  color: var(--need);
}

.t-mute .lamp,
.lamp.dim {
  color: var(--faint);
}

/* A lane cell that changed since the last refresh flashes once, like a line move. A new
   change flashes its whole row. With reduced motion the tint holds until the next refresh. */
.moved {
  animation: moved 1.8s cubic-bezier(0.2, 0.7, 0.2, 1);
}

@keyframes moved {
  from {
    background-color: var(--moved);
  }
  to {
    background-color: transparent;
  }
}

/* ---------- sign-in, setup and messages ---------- */
.solo {
  display: grid;
  place-items: center;
  min-height: 100dvh;
  padding: 24px 16px;
}

.solo-card {
  display: grid;
  gap: 16px;
  width: min(100%, 440px);
  padding: 32px;
  background: var(--sheet);
  border: 1px solid var(--border);
  border-radius: 14px;
}

.solo-logo {
  width: fit-content;
  color: var(--text);
}

.solo-logo .logo {
  display: block;
  width: auto;
  height: 22px;
}

.solo h1 {
  margin-top: 12px;
  font-size: 22px;
  line-height: 28px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.solo-copy {
  color: var(--soft);
}

.solo-alert {
  padding: 10px 12px;
  border-radius: var(--radius);
  background: var(--fail-bg);
  font-size: 13px;
}

.solo-note {
  font-size: 12px;
  color: var(--muted);
}

.steps {
  display: grid;
  gap: 10px;
  padding-left: 20px;
  list-style: decimal;
  color: var(--soft);
}

.steps li::marker {
  color: var(--muted);
  font-weight: 600;
}

.steps strong {
  color: var(--text);
  font-weight: 600;
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 40px;
  padding: 0 16px;
  border-radius: var(--radius);
  background: var(--text);
  color: var(--sheet);
  font-size: 14px;
  font-weight: 500;
  transition: background-color 0.12s;
}

.button:hover {
  background: var(--soft);
}

.scrim {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: var(--scrim);
  animation: fade-in 0.18s ease-out;
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
}

@keyframes drawer-in {
  from {
    opacity: 0;
    transform: translateX(-16px);
  }
}

/* ---------- tablet: the pane folds to a rail with the mark, and opens over the board ---------- */
@media (max-width: 1099px) {
  :root,
  :root[data-pane="collapsed"] {
    --pane-w: 64px;
    --pad: 24px;
  }

  .pane .pane-nav,
  .pane .pane-foot,
  .pane .brand,
  .pane .pane-collapse {
    display: none;
  }

  .pane .brand-mark {
    display: grid;
  }

  .pane-head {
    justify-content: center;
    padding: 0;
  }

  :root.pane-open .pane {
    position: fixed;
    z-index: 50;
    inset: 0 auto 0 0;
    width: min(296px, 86vw);
    height: 100dvh;
    background: var(--frame);
    border-right: 1px solid var(--border);
    box-shadow: 0 0 48px var(--shadow);
    animation: drawer-in 0.2s cubic-bezier(0.2, 0.8, 0.2, 1);
  }

  :root.pane-open .pane .pane-nav,
  :root.pane-open .pane .pane-foot {
    display: block;
  }

  :root.pane-open .pane .brand,
  :root.pane-open .pane .pane-collapse {
    display: flex;
  }

  :root.pane-open .pane .brand-mark {
    display: none;
  }

  :root.pane-open .pane-head {
    justify-content: space-between;
    padding: 0 4px 0 12px;
  }

  /* The title gets the room: narrower lane columns with short words, and the age moves
     into the meta line. */
  .changes {
    --lane-w: 100px;
    --cols: minmax(0, 1fr) repeat(var(--lanes-n), var(--lane-w));
  }

  .changes.cols-1 {
    --lane-w: 120px;
  }

  .changes.cols-2 {
    --lane-w: 104px;
  }

  .changes.cols-4 {
    --lane-w: 84px;
  }

  .cols,
  .line {
    column-gap: 12px;
  }

  .c-ago,
  .ago {
    display: none;
  }

  .title {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    white-space: normal;
  }

  .by-ago {
    display: inline;
  }

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

  .word .short {
    display: inline;
  }

  .cell .w {
    gap: 6px;
  }

  .cell .note {
    padding-left: 14px;
  }

  /* Live now: one divided list, each lane's name beside what's live in it. */
  .lanes,
  .lanes-2,
  .lanes-3,
  .lanes-4 {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: var(--radius-panel);
  }

  .lanes > .lane {
    grid-template-columns: 112px minmax(0, 1fr);
    column-gap: 16px;
    padding: 12px 16px;
    background: none;
    border: 0;
    border-radius: 0;
  }

  .lanes > .lane + .lane {
    border-top: 1px solid var(--rule);
  }

  .lane-name {
    padding-top: 2px;
  }

  .lane-body {
    gap: 6px;
  }

  .lane-pr {
    min-height: 0;
  }
}

/* ---------- phone: one column; the mark in the top bar opens the pane ---------- */
@media (max-width: 640px) {
  :root,
  :root[data-pane="collapsed"] {
    --pad: 16px;
  }

  .shell {
    grid-template-columns: minmax(0, 1fr);
  }

  :root:not(.pane-open) .pane {
    display: none;
  }

  .sheet {
    margin: 0;
    border: 0;
    border-radius: 0;
  }

  .topbar {
    gap: 8px;
    height: 56px;
    padding: 0 10px 0 12px;
    border-radius: 0;
  }

  .topbar-mark {
    display: grid;
  }

  .fresh,
  .search kbd,
  .gh-link {
    display: none;
  }

  .search {
    max-width: none;
  }

  .search input {
    height: 38px;
    font-size: 16px;
  }

  .theme-toggle {
    width: 40px;
    height: 40px;
  }

  .view {
    gap: 24px;
    padding: 20px var(--pad) 40px;
  }

  .head h1 {
    font-size: 22px;
    line-height: 28px;
  }

  .fresh-m {
    display: block;
  }

  .lanes > .lane {
    grid-template-columns: minmax(0, 1fr);
    gap: 6px;
    padding: 12px;
  }

  .needs-list li {
    grid-template-columns: 56px minmax(0, 1fr);
    padding: 12px;
  }

  .changes-head {
    flex-direction: column;
    align-items: stretch;
  }

  .tabs {
    overflow-x: auto;
    scrollbar-width: none;
  }

  /* Changes: two lines each. The title, ending in the tool (linked to its Claude session or
     Codex task) and the age; then the PR numbers beside one lamp and word per lane, in fixed
     columns under the sticky legend. A note that changes how a lane reads ("running", "not
     live", "12 days") adds a short line under its word; "via #n" and who made the change stay
     for screen readers. */
  .changes {
    --lane-w: 64px;
    --cols: minmax(0, 1fr) repeat(var(--lanes-n), var(--lane-w));
  }

  .changes.cols-1 {
    --lane-w: 80px;
  }

  .changes.cols-2 {
    --lane-w: 72px;
  }

  .changes.cols-4 {
    --lane-w: 54px;
  }

  .cols,
  .line {
    column-gap: 8px;
  }

  .cols {
    align-items: end;
    padding: 8px 12px;
    font-size: 11px;
  }

  /* A long lane name wraps rather than losing its end. */
  .c-lane {
    overflow: visible;
    white-space: normal;
    line-height: 13px;
  }

  .line {
    row-gap: 4px;
    padding: 10px 12px;
  }

  .what {
    display: contents;
  }

  .what-top {
    grid-column: 1 / -1;
    display: flex;
    align-items: baseline;
    gap: 8px;
  }

  .title {
    flex: 1 1 auto;
    min-width: 0;
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .aside {
    display: flex;
    flex: none;
    align-items: baseline;
    gap: 6px;
    font-size: 12px;
    line-height: 16px;
    color: var(--muted);
    white-space: nowrap;
  }

  .aside > * + *::before {
    content: "·";
    content: "·" / "";
    display: inline-block;
    margin-right: 6px;
    color: var(--faint);
  }

  /* A real tap target: 24px tall without moving the line. */
  a.aside-tool {
    display: inline-block;
    padding: 4px 0;
    margin: -4px 0;
    color: var(--soft);
    text-decoration: underline;
    text-decoration-color: var(--control);
  }

  /* The age the aside shows is for the eye; this one is for screen readers. */
  .ago {
    display: block;
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .by {
    grid-column: 1;
    margin-top: 0;
  }

  .by .nums {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .by .by-ago {
    display: none;
  }

  .by .who,
  .cell .note-via,
  .note .long {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .note .short {
    display: inline;
  }

  .cell .note {
    padding-left: 14px;
    font-size: 11px;
    line-height: 14px;
  }

  .by-link {
    display: none;
  }

  .cell {
    margin: -3px -4px;
    padding: 3px 4px;
    font-size: 12px;
  }

  .cell .w {
    gap: 6px;
  }

  .solo-card {
    padding: 24px 20px;
  }
}

/* The smallest phones: a little more room for the meta beside the lanes. */
@media (max-width: 360px) {
  .changes {
    --lane-w: 58px;
  }

  .changes.cols-4 {
    --lane-w: 50px;
  }

  .cols,
  .line {
    column-gap: 6px;
  }

  /* "#256 +2" in place of "#256 #257 #258". */
  .nums-wide {
    display: none;
  }

  .nums-narrow {
    display: inline;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  /* The flash becomes a held tint, cleared at the next refresh, so the moment isn't lost. */
  .moved {
    animation: none !important;
    background-color: var(--moved);
  }
}
