/* ═══════════════════════════════════════════════════════════════════════════
   programme_board.css — C4 / ORG11 drag-drop Programme of Works
   The Reactor voice: black void, one gold light. Hand-rolled Gantt; tokens-only.

   DESIGN LAW honoured:
     • Every colour is var(--kh-*, <fallback>). The real landed token (tokens.css)
       ALWAYS wins; the literal hex is a fallback so the board still themes if the
       host has not linked tokens.css yet. THE ONLY raw hex in this file lives in the
       single ALIAS BLOCK below (the sanctioned "tokens fallback block").
     • Gold surfaces carry ink var(--kh-gold-ink) — never white.
     • RUST (--kh-crit) is danger/loss ONLY: a compliance BLOCK or a BREACHED SLA.
       Caution (capacity pressure, a dependency nudge, an at-risk SLA) is AMBER.
     • Numerals are tabular (font-variant-numeric). 10px is the floor (mono micro
       labels only); anything a user acts on is ≥ 11px.
     • One motion curve var(--kh-swift); durations 120/160/240ms; reduced-motion is
       honoured centrally by the token collapse in tokens.css.
   Token var names are provisional against DESIGN-REVIEW-DISTILLED where the landed
   tokens.css had not synced; reconcile at integration (see NOTES / openIssues).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── ALIAS BLOCK — the one place raw hex lives, always behind a token ───────────
   .khpb-modal-root is listed alongside the board host because the O4b save gate is
   mounted on <body> (the host is overflow:hidden, and a cockpit ancestor with a
   transform would trap a position:fixed child). Same aliases, one hex block. */
[data-kh-programme],
.khpb-modal-root{
  --p-void0: var(--kh-void-0);
  --p-void1: var(--kh-void-1);
  --p-void2: var(--kh-void-2);
  --p-void3: var(--kh-void-3);
  --p-ink:   var(--kh-ink);
  --p-dim:   var(--kh-ink-dim);
  --p-gold:  var(--kh-gold-1);
  --p-gold2: var(--kh-gold-2);
  --p-gold3: var(--kh-gold-3);
  --p-gold0: var(--kh-gold-0);
  --p-goldink: var(--kh-gold-ink);
  --p-line:  var(--kh-line);
  --p-ok:    var(--kh-ok);
  --p-warn:  var(--kh-warn);
  --p-crit:  var(--kh-crit);
  --p-ui:    var(--kh-font-ui);
  --p-mono:  var(--kh-font-mono);
  --p-swift: var(--kh-swift);
  --p-r1: var(--kh-r-1);
  --p-r2: var(--kh-r-2);
  --p-r3: var(--kh-r-3);

  /* grid metrics — JS sets --p-daw (day-column width) and --p-track (= span·daw) so the
     day header, bars and dependency arrows all share ONE coordinate system */
  --p-daw: 34px;
  --p-track: calc(15 * var(--p-daw));
  --p-rail: 208px;
}

/* the board host's own box (the gate is a separate surface — see the save gate below) */
[data-kh-programme]{
  display:block;
  font-family:var(--p-ui);
  color:var(--p-ink);
  background:var(--p-void1);
  border:1px solid var(--p-line);
  border-radius:var(--p-r3);
  overflow:hidden;
}

/* ── header ──────────────────────────────────────────────────────────────────── */
.khpb-head{
  display:flex; align-items:center; gap:var(--kh-s-3); flex-wrap:wrap;
  padding:14px 18px; background:var(--p-void2);
  border-bottom:1px solid var(--p-line);
}
.khpb-eyebrow{
  font-family:var(--p-mono); font-weight:500; font-size:var(--kh-fs-10);
  letter-spacing:var(--kh-mono-track); text-transform:uppercase; color:var(--p-gold0);
}
.khpb-jobno{ font-family:var(--p-mono); font-weight:500; font-size:var(--kh-fs-12-5);
  color:var(--p-gold); font-variant-numeric:tabular-nums; }
.khpb-title{ font-weight:800; font-size:var(--kh-fs-17); color:var(--p-ink); margin:0; }
.khpb-anchor{ font-size:var(--kh-fs-11); color:var(--p-dim); }
.khpb-spacer{ margin-left:auto; }

/* conflict summary chips */
.khpb-chips{ display:flex; gap:6px; align-items:center; flex-wrap:wrap; }
.khpb-chip{
  display:inline-flex; align-items:center; gap:5px;
  font-family:var(--p-mono); font-weight:500; font-size:var(--kh-fs-11);
  padding:4px 9px; border-radius:var(--kh-r-pill);
  border:1px solid var(--p-line); color:var(--p-dim); background:transparent;
  font-variant-numeric:tabular-nums;
}
.khpb-chip[data-tone="clear"]{ color:var(--p-ok); border-color:color-mix(in srgb, var(--p-ok) 40%, transparent); }
.khpb-chip[data-tone="warn"]{ color:var(--p-warn); border-color:color-mix(in srgb, var(--p-warn) 45%, transparent); }
.khpb-chip[data-tone="block"]{ color:var(--p-crit); border-color:color-mix(in srgb, var(--p-crit) 50%, transparent); }
/* GREY = honest unknown / not-recorded (register silent). Never green, never a false amber. */
.khpb-chip[data-tone="unknown"]{ color:var(--p-dim); border-color:var(--p-line); }
.khpb-dot{ width:7px; height:7px; border-radius:50%; background:currentColor; flex:0 0 7px; }

/* ── scroll frame + grid ─────────────────────────────────────────────────────── */
.khpb-scroll{ overflow-x:auto; overflow-y:hidden; -webkit-overflow-scrolling:touch; }
.khpb-grid{ position:relative; min-width:100%; }

/* day header */
.khpb-days{
  display:grid; grid-template-columns:var(--p-rail) var(--p-track);
  position:sticky; top:0; z-index:3; background:var(--p-void2);
  border-bottom:1px solid var(--p-line);
}
.khpb-days-rail{
  padding:8px 14px; align-self:center;
  font-family:var(--p-mono); font-weight:500; font-size:var(--kh-fs-10);
  letter-spacing:var(--kh-mono-track); text-transform:uppercase; color:var(--p-dim);
}
.khpb-days-track{ display:flex; }
.khpb-day{
  width:var(--p-daw); flex:0 0 var(--p-daw); text-align:center; padding:6px 0;
  border-left:1px solid color-mix(in srgb, var(--p-line) 60%, transparent);
}
.khpb-day[data-weekend="1"]{ background:var(--p-void0); }
.khpb-day-k{ font-family:var(--p-ui); font-weight:700; font-size:var(--kh-fs-10); color:var(--p-dim); opacity:.7; }
.khpb-day-n{ font-family:var(--p-mono); font-weight:500; font-size:var(--kh-fs-11);
  color:var(--p-ink); margin-top:1px; font-variant-numeric:tabular-nums; }

/* task rows */
.khpb-row{
  display:grid; grid-template-columns:var(--p-rail) var(--p-track);
  border-bottom:1px solid color-mix(in srgb, var(--p-line) 40%, transparent);
}
.khpb-row:hover{ background:color-mix(in srgb, var(--p-gold) 4%, transparent); }
.khpb-rail{
  padding:9px 14px; display:flex; align-items:center; gap:9px; min-width:0;
  border-right:1px solid color-mix(in srgb, var(--p-line) 50%, transparent);
}
.khpb-rail-kind{ width:8px; height:8px; flex:0 0 8px; border-radius:2px;
  background:var(--p-gold); box-shadow:0 0 6px color-mix(in srgb, var(--p-gold) 55%, transparent); }
.khpb-rail-kind[data-kind="milestone"]{ transform:rotate(45deg); border-radius:1px;
  background:var(--p-gold3); }
.khpb-rail-txt{ min-width:0; }
.khpb-rail-name{ font-weight:600; font-size:var(--kh-fs-14); color:var(--p-ink);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.khpb-rail-trade{ font-family:var(--p-mono); font-weight:500; font-size:var(--kh-fs-10);
  letter-spacing:.04em; text-transform:uppercase; color:var(--p-dim); margin-top:2px; }

.khpb-lane{ position:relative; height:38px; }

/* a task bar — the void card with the single gold light on its leading edge */
.khpb-bar{
  position:absolute; top:6px; bottom:6px;
  background:var(--p-void3); border:1px solid var(--p-line); border-radius:var(--p-r1);
  display:flex; align-items:center; gap:6px; padding:0 8px 0 10px; overflow:hidden;
  cursor:grab; touch-action:none; user-select:none;
  transition:box-shadow var(--kh-t-1) var(--p-swift),
             border-color var(--kh-t-1) var(--p-swift),
             transform var(--kh-t-2) var(--p-swift);
  box-shadow:var(--kh-e1);
}
.khpb-bar::before{
  content:""; position:absolute; left:0; top:0; bottom:0; width:3px;
  background:linear-gradient(180deg, var(--p-gold2), var(--p-gold));
}
.khpb-bar:focus-visible{ outline:2px solid var(--p-gold3); outline-offset:1px; }
.khpb-bar:hover{ border-color:color-mix(in srgb, var(--p-gold) 55%, var(--p-line)); }
.khpb-bar[data-dragging="1"]{ cursor:grabbing; border-color:var(--p-gold);
  box-shadow:var(--kh-e3), 0 0 0 1px var(--p-gold);
  transform:translateY(-1px); z-index:5; }
.khpb-bar[data-ghost="1"]{ opacity:.5; }
/* flag states recolour the border only — bar stays a void card */
.khpb-bar[data-flag="warn"]{ border-color:var(--p-warn); }
.khpb-bar[data-flag="warn"]::before{ background:var(--p-warn); }
.khpb-bar[data-flag="block"]{ border-color:var(--p-crit); }
.khpb-bar[data-flag="block"]::before{ background:var(--p-crit); }
/* GREY (not-recorded) — a muted rail, never amber-alarm, never the gold light */
.khpb-bar[data-flag="unknown"]{ border-color:color-mix(in srgb, var(--p-dim) 55%, var(--p-line)); }
.khpb-bar[data-flag="unknown"]::before{ background:var(--p-dim); }

.khpb-bar-name{ font-weight:600; font-size:var(--kh-fs-11); color:var(--p-ink);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.khpb-bar-dur{ margin-left:auto; font-family:var(--p-mono); font-weight:500;
  font-size:var(--kh-fs-10); color:var(--p-gold0); font-variant-numeric:tabular-nums; opacity:.9; }

/* milestone marker — a gold diamond instead of a bar */
.khpb-diamond{
  position:absolute; top:50%; width:16px; height:16px; margin-top:-8px; margin-left:-8px;
  background:linear-gradient(180deg, var(--p-gold3), var(--p-gold)); transform:rotate(45deg);
  border-radius:2px; cursor:grab; touch-action:none;
  box-shadow:0 0 8px color-mix(in srgb, var(--p-gold) 60%, transparent);
}
.khpb-diamond:focus-visible{ outline:2px solid var(--p-gold3); outline-offset:2px; }

/* landing-day highlight — the day column the dragged bar will drop into. One gold light,
   kept subtle: a faint tint fill + a brighter leading hairline. Lives in the grid content
   coordinate space (JS sets `left` to calc(var(--p-rail) + laneLeft)), so it scrolls with the
   track during edge-autoscroll. Behind the arrows and bars; shown only while a pointer drag runs. */
.khpb-landing{
  position:absolute; top:0; bottom:0; width:var(--p-daw); z-index:1;
  left:var(--p-rail);
  background:color-mix(in srgb, var(--p-gold) 9%, transparent);
  border-left:1px solid color-mix(in srgb, var(--p-gold) 50%, transparent);
  border-right:1px solid color-mix(in srgb, var(--p-gold) 12%, transparent);
  pointer-events:none; opacity:0;
  transition:opacity var(--kh-t-1) var(--p-swift), left var(--kh-t-1) var(--p-swift);
}
.khpb-landing[data-show="1"]{ opacity:1; }

/* dependency arrow layer (hand-rolled SVG) */
.khpb-arrows{ position:absolute; inset:0; pointer-events:none; z-index:2; overflow:visible; }
.khpb-arrow{ fill:none; stroke:var(--p-line); stroke-width:1.25; }
.khpb-arrow[data-violated="1"]{ stroke:var(--p-warn); stroke-dasharray:3 3; }
.khpb-arrowhead{ fill:var(--p-line); }
.khpb-arrowhead[data-violated="1"]{ fill:var(--p-warn); }

/* SLA deadline marker — a vertical gold hairline down the track */
.khpb-sla{ position:absolute; top:0; bottom:0; width:0; z-index:1;
  border-left:1px dashed color-mix(in srgb, var(--p-warn) 70%, transparent); }
.khpb-sla[data-status="breached"]{ border-left-color:color-mix(in srgb, var(--p-crit) 80%, transparent); }
.khpb-sla-tag{
  position:absolute; top:46px; transform:translateX(-50%);   /* clear the sticky day header */
  font-family:var(--p-mono); font-weight:500; font-size:var(--kh-fs-10);
  color:var(--p-goldink); background:var(--p-warn);
  padding:2px 6px; border-radius:var(--p-r1); white-space:nowrap;
}
.khpb-sla[data-status="breached"] .khpb-sla-tag{ background:var(--p-crit); color:var(--p-ink); }

/* footer: conflict detail + ripple note */
.khpb-foot{ padding:12px 18px; background:var(--p-void2); border-top:1px solid var(--p-line);
  display:flex; flex-direction:column; gap:6px; }
.khpb-conf{ display:flex; gap:8px; align-items:flex-start; font-size:var(--kh-fs-11); color:var(--p-dim); }
.khpb-conf b{ color:var(--p-ink); font-weight:700; }
.khpb-conf[data-tone="warn"] .khpb-conf-k{ color:var(--p-warn); }
.khpb-conf[data-tone="block"] .khpb-conf-k{ color:var(--p-crit); }
.khpb-conf[data-tone="unknown"] .khpb-conf-k{ color:var(--p-dim); }
.khpb-conf-k{ font-family:var(--p-mono); font-weight:500; font-size:var(--kh-fs-10);
  letter-spacing:.06em; text-transform:uppercase; flex:0 0 auto; padding-top:1px; }
.khpb-note{ font-size:var(--kh-fs-10); color:var(--p-dim); opacity:.8; font-style:italic; }

/* empty / error states — an invitation, never an alarm */
.khpb-empty{ padding:38px 24px; text-align:center; color:var(--p-dim); }
.khpb-empty-k{ font-family:var(--p-mono); font-weight:500; font-size:var(--kh-fs-11);
  letter-spacing:.1em; text-transform:uppercase; color:var(--p-gold0); }
.khpb-empty-m{ font-size:var(--kh-fs-14); color:var(--p-ink); margin-top:8px; font-weight:600; }
.khpb-empty-s{ font-size:var(--kh-fs-11); margin-top:5px; }

/* toast for a committed ripple (bottom-centre, one manager elsewhere; local fallback) */
.khpb-toast{
  position:absolute; left:50%; bottom:14px; transform:translateX(-50%);
  background:var(--p-void3); color:var(--p-ink); border:1px solid var(--p-line);
  border-radius:var(--kh-r-pill); padding:8px 16px;
  font-size:var(--kh-fs-11); box-shadow:var(--kh-e3);
  opacity:0; pointer-events:none; transition:opacity var(--kh-t-2) var(--p-swift); z-index:9;
}
.khpb-toast[data-show="1"]{ opacity:1; }
.khpb-toast b{ color:var(--p-gold); font-weight:700; }
/* tokened gold dot in place of a glyph bullet — on-voice, no arbitrary box char */
.khpb-toast-dot{ display:inline-block; margin-right:7px; vertical-align:middle;
  background:var(--p-gold); box-shadow:0 0 6px color-mix(in srgb, var(--p-gold) 55%, transparent); }

/* ── O4b · THE SAVE GATE — drag → server change summary → explicit confirm → apply ────
   An approve gate, so it reads as one: the veil takes the whole viewport and swallows
   every pointer event behind it, the discard button holds first focus, and only the one
   gold button applies. Nothing here is decorative — a change summary the director cannot
   read is a save they cannot judge. */
.khpb-modal-root{
  /* the house modal layer (kh-ui.css: --kh-z-modal 600, above the portal overlay at 500);
     the literal is that same landed value, so a standalone board stacks identically */
  position:fixed; inset:0; z-index:var(--kh-z-modal, 600);
  font-family:var(--p-ui); color:var(--p-ink);
}
.khpb-gate-veil{
  position:absolute; inset:0;
  background:color-mix(in srgb, var(--p-void0) 74%, transparent);
}
.khpb-gate{
  position:absolute; left:50%; top:50%; transform:translate(-50%, -50%);
  width:min(520px, calc(100vw - 32px)); max-height:calc(100vh - 48px); overflow-y:auto;
  background:var(--p-void1); border:1px solid var(--p-line); border-radius:var(--p-r3);
  box-shadow:var(--kh-e3);
}
.khpb-gate-top{ padding:15px 20px 13px; background:var(--p-void2);
  border-bottom:1px solid var(--p-line); }
.khpb-gate-k{ font-family:var(--p-mono); font-weight:500; font-size:var(--kh-fs-10);
  letter-spacing:var(--kh-mono-track); text-transform:uppercase; color:var(--p-gold0); }
.khpb-gate-t{ font-weight:800; font-size:var(--kh-fs-17); color:var(--p-ink); margin:4px 0 0; }

.khpb-gate-body{ padding:15px 20px 2px; }
/* the request being approved — the client's own fact (what will be POSTed), kept visually
   distinct from the server-composed lines below so the two are never confused */
.khpb-gate-action{
  font-family:var(--p-mono); font-weight:500; font-size:var(--kh-fs-11);
  color:var(--p-gold); font-variant-numeric:tabular-nums;
  padding:8px 11px; border-radius:var(--p-r1);
  border:1px solid color-mix(in srgb, var(--p-gold) 30%, var(--p-line));
  background:color-mix(in srgb, var(--p-gold) 6%, transparent);
}
.khpb-gate-head{ font-weight:600; font-size:var(--kh-fs-14); color:var(--p-ink); margin-top:13px; }
/* GREY = the honest unknown (the summary could not be read). Never amber-alarm, never a
   green "all clear" — the same law the conflict chips follow. */
.khpb-gate-head[data-tone="unknown"]{ color:var(--p-dim); }

.khpb-gate-lines{ list-style:none; margin:10px 0 0; padding:0;
  display:flex; flex-direction:column; gap:5px; }
.khpb-gate-line{
  position:relative; padding-left:14px; line-height:1.45;
  font-size:var(--kh-fs-12-5); color:var(--p-ink); font-variant-numeric:tabular-nums;
}
.khpb-gate-line::before{
  content:""; position:absolute; left:0; top:.62em; width:5px; height:5px; border-radius:50%;
  background:var(--p-gold);
}
.khpb-gate-more{ padding-left:14px; margin-top:2px;
  font-family:var(--p-mono); font-weight:500; font-size:var(--kh-fs-10);
  letter-spacing:.06em; text-transform:uppercase; color:var(--p-dim); }
.khpb-gate-basis{ margin-top:13px; line-height:1.5;
  font-size:var(--kh-fs-11); color:var(--p-dim); }

.khpb-gate-foot{
  display:flex; gap:9px; justify-content:flex-end; align-items:center;
  padding:14px 20px 16px; margin-top:15px;
  border-top:1px solid color-mix(in srgb, var(--p-line) 55%, transparent);
}
.khpb-btn{
  font-family:var(--p-ui); font-weight:700; font-size:var(--kh-fs-12-5);
  padding:9px 17px; border-radius:var(--kh-r-pill); cursor:pointer;
  color:var(--p-ink); background:transparent; border:1px solid var(--p-line);
  transition:border-color var(--kh-t-1) var(--p-swift),
             background var(--kh-t-1) var(--p-swift);
}
.khpb-btn:hover{ border-color:color-mix(in srgb, var(--p-gold) 55%, var(--p-line)); }
.khpb-btn:focus-visible{ outline:2px solid var(--p-gold3); outline-offset:2px; }
/* the one light source — and gold carries gold-ink, never white */
.khpb-btn[data-kind="gold"]{
  background:linear-gradient(180deg, var(--p-gold2), var(--p-gold));
  border-color:var(--p-gold0); color:var(--p-goldink);
}
.khpb-btn[data-kind="gold"]:hover{ background:linear-gradient(180deg, var(--p-gold3), var(--p-gold2)); }

/* ── reduced motion — honoured centrally by tokens.css, but self-sufficient here too so the
   board keeps the accessibility promise even before tokens.css is linked (durations only,
   no colour/hex) ──────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce){
  [data-kh-programme] .khpb-bar,
  [data-kh-programme] .khpb-landing,
  [data-kh-programme] .khpb-toast,
  .khpb-modal-root .khpb-btn{ transition-duration:0ms; }
  [data-kh-programme] *,
  .khpb-modal-root *{ animation-duration:0ms !important; }
}
