/* beads-runner/web/board/board.css — T6a (claude-tools-p2m).
 * Visual direction adapted from beads-runner/ux-mocks.html v1 (the Board:
 * status strip · WAITING-ON-YOU lane · lifecycle spine · honest runner state).
 * Presentation only — the frozen INTERFACE.md v1 §4.2/§4.5 DATA contract is
 * authoritative; this file styles what board-view.js derives from it.
 * Responsive: phone-first single column → wide desktop. No build step. */

:root{
  --ink:#080a0e; --ink-2:#0b0e14; --panel:#10141c; --panel-2:#161b25;
  --line:rgba(255,255,255,.07); --line-2:rgba(255,255,255,.12);
  --text:#e8ebf1; --dim:#8b94a6; --faint:#535b6b;
  --amber:#ffb454; --amber-soft:#ffcd86; --amber-glow:rgba(255,180,84,.22);
  --mint:#4fd6a0; --coral:#ff6b6b; --sky:#74a8ff; --slate:#5b6577;
  --font-display:'Fraunces',Georgia,serif;
  --mono:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
}
*{margin:0;padding:0;box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  background:var(--ink);color:var(--text);font-family:var(--mono);
  min-height:100vh;-webkit-font-smoothing:antialiased;
  background-image:
    radial-gradient(900px 600px at 78% -5%, rgba(116,168,255,.06), transparent 60%),
    radial-gradient(800px 700px at 8% 105%, rgba(79,214,160,.05), transparent 55%);
}
::selection{background:var(--amber);color:#1a1206}

.app{display:flex;flex-direction:column;min-height:100vh;max-width:1320px;margin:0 auto}
.apphead{display:flex;align-items:center;justify-content:space-between;
  padding:max(18px,env(safe-area-inset-top)) 22px 14px;flex:none}
.apphead .t{font-family:var(--font-display);font-size:25px;font-weight:400;
  letter-spacing:-.01em;display:flex;align-items:center;gap:11px}
.apphead .t .dot{width:8px;height:8px;border-radius:50%;background:var(--mint);
  box-shadow:0 0 9px var(--mint);transition:.3s}
.apphead .t .dot.bad{background:var(--coral);box-shadow:0 0 9px var(--coral)}
.apphead .who{font-size:11px;letter-spacing:.18em;color:var(--slate);
  text-transform:uppercase}

.scroll{flex:1;overflow-y:auto;padding:0 0 24px}
.loading{padding:48px 22px;color:var(--dim);font-size:13px;letter-spacing:.08em}

/* status strip */
.strip{margin:0 14px 16px;border:1px solid var(--line);
  background:linear-gradient(180deg,var(--panel),var(--ink-2));
  border-radius:16px;padding:15px 16px;position:relative;overflow:hidden}
.strip-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
.strip-top .lbl{font-size:10px;letter-spacing:.34em;color:var(--slate)}
.strip-top .hb{font-size:10px;color:var(--mint);letter-spacing:.1em}
.strip-top .hb.bad{color:var(--coral)}
.strip-headline{font-family:var(--font-display);font-size:20px;font-weight:400;
  line-height:1.25;color:#fff;margin-bottom:13px;letter-spacing:-.01em}
.strip.bad .strip-headline{color:var(--amber-soft)}
.strip-tags{display:flex;gap:7px;flex-wrap:wrap}
.tg{font-size:10px;letter-spacing:.06em;padding:5px 9px;border-radius:7px;
  border:1px solid var(--line);color:var(--dim)}
.tg.runners{color:var(--mint);border-color:rgba(79,214,160,.3)}
.tg.warn{border-color:rgba(255,180,84,.35);color:var(--amber-soft);
  background:var(--amber-glow)}
.tg.bad{border-color:rgba(255,107,107,.35);color:var(--coral);
  background:rgba(255,107,107,.1)}

/* waiting-on-you lane */
.lane-hd{display:flex;align-items:center;gap:11px;margin:6px 20px 11px;
  font-size:10px;letter-spacing:.32em;color:var(--amber);text-transform:uppercase}
.lane-hd .pulse{width:8px;height:8px;border-radius:50%;background:var(--amber);
  flex:none;position:relative}
.lane-hd .pulse::after{content:"";position:absolute;inset:-5px;border-radius:50%;
  border:1px solid var(--amber);animation:ring 2s infinite}
@keyframes ring{0%{transform:scale(.6);opacity:.9}100%{transform:scale(1.7);opacity:0}}
.lane-hd .ln{flex:1;height:1px;background:linear-gradient(90deg,var(--amber-glow),transparent)}
.woy-empty{margin:0 20px 18px;color:var(--faint);font-size:12px}
.waitcard{display:block;text-decoration:none;margin:0 14px 10px;border-radius:18px;
  padding:16px 17px;position:relative;color:inherit;
  background:linear-gradient(155deg,rgba(255,180,84,.16),rgba(255,180,84,.03));
  border:1px solid rgba(255,180,84,.34);
  box-shadow:0 0 0 1px rgba(255,180,84,.06),0 18px 40px -22px rgba(255,180,84,.5)}
.waitcard .meta{display:flex;align-items:center;gap:9px;font-size:10px;
  letter-spacing:.1em;color:var(--amber-soft);margin-bottom:9px;flex-wrap:wrap}
.waitcard .meta .p{padding:2px 7px;border:1px solid rgba(255,180,84,.4);border-radius:5px;
  text-transform:uppercase}
.waitcard .ask{font-family:var(--font-display);font-size:19px;line-height:1.25;
  color:#fff;letter-spacing:-.01em}
.waitcard .go{margin-top:12px;font-size:11px;letter-spacing:.16em;color:var(--amber)}

/* lifecycle spine */
.spine{margin:8px 0 0;padding:14px 0 16px;border-top:1px solid var(--line)}
.spine .sl{font-size:10px;letter-spacing:.32em;color:var(--slate);padding:0 20px 13px}
.cols{display:flex;gap:9px;overflow-x:auto;padding:0 14px 4px;scrollbar-width:thin}
.col{flex:none;width:160px}
.col-h{display:flex;align-items:center;justify-content:space-between;font-size:10px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--dim);
  padding:0 3px 9px;border-bottom:1px solid var(--line);margin-bottom:9px}
.col-h .c{color:var(--faint)}
.col.gate .col-h,.col.gate .col-h .c{color:var(--amber)}
.bead{background:var(--panel);border:1px solid var(--line);border-radius:10px;
  padding:9px 10px;margin-bottom:7px}
.bead .bt{font-size:11px;line-height:1.35;color:var(--text);margin-bottom:7px}
.bead .bf{display:flex;align-items:center;justify-content:space-between;
  font-size:9px;color:var(--faint);gap:6px}
.bead .bf .wo{color:var(--dim)}
/* L3 (claude-tools-2bf): the per-card "which live workspace is running this
 * bead" badge. Rendered only when a LIVE runner has it as current_task_ref
 * (board-view.js drops it for stale runners — S-1). Same dim-text register
 * as .wo so it reads as secondary card meta, never competing with title. */
.bead .bf .rn{color:var(--dim)}
.bead.failbead{border-color:rgba(255,107,107,.32);
  background:linear-gradient(160deg,rgba(255,107,107,.1),var(--panel))}
/* G1 (claude-tools-b6y) — silent failures render LOUDER than loud ones
 * (UX principle 7: silent rots — TASK_NOT_CLOSED / TOOL_ERROR:* / etc).
 * A stronger coral border + a glow + a pulsing left edge make a silent
 * card outweigh a loud one at the same glance distance. */
.bead.failbead.silent{
  border-color:rgba(255,107,107,.62);
  background:linear-gradient(160deg,rgba(255,107,107,.22),var(--panel));
  box-shadow:0 0 0 1px rgba(255,107,107,.18),
             inset 3px 0 0 0 var(--coral);
}
.bead .warn{color:var(--coral);font-size:9px;letter-spacing:.06em;margin-top:6px;
  display:block;text-decoration:none}
/* G1: the badge is a deep-link into T6b's Inbox failure view; keep the
 * 44×44 touch target through padding, never an underline (matches the
 * waitcard idiom). A silent badge gets a brighter coral so the click
 * affordance reads as "this is the rotting one, look at it first". */
a.warn{color:var(--coral);cursor:pointer;padding:4px 0;min-height:24px}
a.warn:focus-visible{outline:2px solid var(--coral);outline-offset:2px;border-radius:4px}
.bead.failbead.silent .warn{color:#ff8a8a;font-weight:500}
.col-empty{color:var(--faint);font-size:10px;padding:4px 3px}

/* per-project runners — honest state + S-1 liveness */
.runners{display:flex;flex-wrap:wrap;gap:10px;padding:0 14px}
.runner{flex:1 1 240px;min-width:0;border:1px solid var(--line);border-radius:13px;
  background:var(--panel);padding:13px 14px}
.runner .rp{font-size:11px;color:var(--dim);letter-spacing:.06em;
  margin-bottom:9px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.runner .rstate{display:flex;align-items:center;gap:9px;font-size:13px;
  font-family:var(--font-display);letter-spacing:-.01em}
.runner .pill{width:8px;height:8px;border-radius:50%;flex:none}
.runner .pill.live{background:var(--mint);box-shadow:0 0 7px var(--mint)}
.runner .pill.attention{background:var(--amber);box-shadow:0 0 7px var(--amber)}
.runner .pill.unknown{background:var(--slate)}
/* S-1: a STALE runner is visually its OWN state — never the live green pill */
.runner.stale{border-color:rgba(255,107,107,.32);
  background:linear-gradient(160deg,rgba(255,107,107,.09),var(--panel))}
.runner .pill.stale{background:var(--coral);box-shadow:0 0 7px var(--coral)}
.runner.stale .rstate{color:var(--coral)}
.runner .rnote{margin-top:8px;font-size:10px;color:var(--faint);letter-spacing:.04em}
.runner .rcap{margin-top:8px;font-size:9px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--slate)}
.runner .rcap.over{color:var(--amber-soft)}

/* F2 (claude-tools-8fh) — per-workspace desired-state toggle row.
 * Mobile-first: each button is ≥44×44px (Apple HIG / WCAG 2.5.5 minimum),
 * no hover-only state. ACTIVE = the button matching the current ACTUAL —
 * never desired (board-view.js enforces). The pending banner is its own
 * line so it can never be mistaken for the actual pill. */
.runner .rctrls{display:flex;flex-wrap:wrap;gap:6px;margin-top:11px}
.runner .rbtn{
  flex:1 1 auto;min-width:72px;min-height:44px;
  padding:10px 12px;border-radius:9px;
  font-family:var(--mono);font-size:12px;letter-spacing:.04em;
  background:var(--panel-2);color:var(--text);
  border:1px solid var(--line-2);
  cursor:pointer;-webkit-tap-highlight-color:transparent;
  touch-action:manipulation;
  transition:background .15s, border-color .15s;
}
.runner .rbtn:focus-visible{outline:2px solid var(--sky);outline-offset:2px}
.runner .rbtn:active{background:var(--ink-2)}
.runner .rbtn.active{
  background:rgba(79,214,160,.15);
  border-color:rgba(79,214,160,.5);
  color:var(--mint);
  font-weight:500;
}
.runner.stale .rbtn.active{
  /* S-1: a stale runner has NO live actual to highlight; the renderer drops
   * `active`, but if somehow set we still suppress the green pill look. */
  background:var(--panel-2);border-color:var(--line-2);color:var(--text);
  font-weight:400;
}
.runner .rbtn.busy{opacity:.55;cursor:progress}
.runner .rbtn:disabled{opacity:.55;cursor:not-allowed}

.runner .rpending{
  margin-top:9px;font-size:11px;letter-spacing:.04em;
  padding:7px 10px;border-radius:8px;
  background:rgba(255,180,84,.1);
  border:1px solid rgba(255,180,84,.3);
  color:var(--amber-soft);
}
.runner .rstale{
  margin-top:8px;font-size:10px;letter-spacing:.04em;
  color:var(--coral);
}
.runner .rerr{
  margin-top:8px;font-size:11px;letter-spacing:.02em;
  padding:7px 10px;border-radius:8px;
  background:rgba(255,107,107,.1);
  border:1px solid rgba(255,107,107,.35);
  color:var(--coral);
}

.errbox{margin:32px 18px;border:1px solid rgba(255,107,107,.34);
  background:rgba(255,107,107,.08);border-radius:14px;padding:18px}
.err-h{color:var(--coral);font-size:13px;letter-spacing:.12em;
  text-transform:uppercase;margin-bottom:9px}
.err-b{color:var(--amber-soft);font-size:13px;line-height:1.6}

.foot{flex:none;display:flex;align-items:center;gap:9px;
  padding:13px 22px max(13px,env(safe-area-inset-bottom));
  border-top:1px solid var(--line);font-size:10px;letter-spacing:.12em;
  color:var(--faint);text-transform:uppercase}
.foot-sep{opacity:.5}

/* desktop: the strip + lane sit side-by-side; columns breathe */
@media (min-width:880px){
  .strip{margin:0 22px 18px}
  .lane-hd{margin:6px 28px 12px}
  .waitcard{margin:0 22px 10px}
  .cols{padding:0 22px 6px}
  .col{width:190px}
  .runners{padding:0 22px}
}
@media (prefers-reduced-motion:reduce){
  .lane-hd .pulse::after{animation:none}
}
