/* static/playbook/playbook-ui.css - NEW FILE (2026-10-20).

   THE PLAYBOOK: one tab per feature, each saying what the feature is, how to
   drive it, and what to type. Read from GET /playbook.

   =========================================================================
   WHY IT IS AN OVERLAY, AND WHY IT IS NOT THE SAME SHAPE AS capability/
   =========================================================================
   It is an overlay for capability-ui.css's reason, unchanged: the two corner
   readouts are chips holding a handful of facts somebody glances at, and this
   holds seventeen features' prose. A chip that expanded to this size would
   cover the composer and the transcript anyway.

   BUT THE INSIDE IS A TWO-COLUMN LAYOUT RATHER THAN A ROW OF TABS, and that
   is a real difference rather than a preference. capability/ has SIX sections
   and a pill per section fits on one line. This has SEVENTEEN features in
   FOUR groups. Seventeen pills wrap to three ragged lines, lose their group
   headings on the way, and leave a reader scanning for the one they want -
   which is the problem the groups exist to solve. A vertical list keeps the
   headings, keeps the order, and has room for a status dot per entry.

   =========================================================================
   NO HEX COLOURS, AND IT IS A RULE RATHER THAN A HABIT
   =========================================================================
   Every value here is a brand.css token, so dark mode costs nothing - the
   same rule rag-ui.css, stack-info.css, user-info.css and capability-ui.css
   all follow.

   ONE PAIRING IS DELIBERATELY NOT COPIED FROM capability-ui.css. That file
   had `color: var(--accent-ink)` over `background: var(--accent-soft)` in two
   places - `.cap-tag.yes` and `.cap-tab[aria-selected="true"]` - and those two
   tokens are not a legible pair in either theme. brand.css documents
   --accent-ink beside its own value: "7.1:1 on --accent" in light, "9.0:1 on
   --accent" in dark. It is the ink for the SOLID accent, #ffffff and #07160d.

   MEASURED OVER --accent-soft IT IS 1.28:1 IN LIGHT AND 1.31:1 IN DARK. Not
   low contrast - effectively invisible. The pair that works in both is
   --accent ON --accent-soft: 5.63:1 light (#0d652d on #ccebd6) and 6.87:1
   dark (#57c98a on #15301f), both past AA. That is what .pb-badge.on uses
   below, and as of 2026-10-20 what both of capability-ui.css's rules use too.

   (The first draft of this comment said "three tags" and quoted 6.1 and 7.0.
   Two places, one of them a TAB rather than a tag, and the ratios above are
   computed rather than recalled.)

   =========================================================================
   STATE IS NEVER COLOUR ALONE
   =========================================================================
   Four states arrive from the endpoint - on, partial, off, unknown - and each
   renders as a DOT PLUS A WORD. capability-ui.css states the rule: "a reader
   who cannot distinguish the two colours still has to be able to read the
   answer." Here it matters more, because `partial` and `off` differ by whether
   any of the tab's prompts will work at all.

   =========================================================================
   `pointer-events` IS NOT LOAD-BEARING HERE
   =========================================================================
   Same as capability-ui.css, and worth restating because the two corner files
   carry a warning not to simplify theirs. This one is `hidden` until opened,
   and when open it is MEANT to take every click - that is what a modal is. */

/* ---------------------------------------------------------------------------
   THE OVERLAY. `hidden` on the element does the hiding; this only has to not
   fight it. `display: none` on [hidden] is restated because the flex rule
   below would otherwise win - a flex container is still displayed.
   --------------------------------------------------------------------------- */
#playbook[hidden] { display: none; }

#playbook {
  position: fixed;
  inset: 0;
  z-index: 50;                   /* above both corner readouts, which are 10 */
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 2.5rem 1rem;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  overflow-y: auto;
}

/* Wider than capability's 72rem because the body is two columns: a 15rem nav
   beside prose that still wants a comfortable measure. */
#playbook .pb-card {
  width: min(76rem, 100%);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 0.875rem;
  line-height: 1.6;
}

/* ---------------------------------------------------------------------------
   HEADER - title, the one-line provenance, and close.
   --------------------------------------------------------------------------- */
#playbook .pb-head {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--surface);
  border-radius: 12px 12px 0 0;
}

#playbook .pb-title { font-size: 1.05rem; font-weight: 600; margin: 0; }

#playbook .pb-sub {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--muted);
  margin-left: auto;
  text-align: right;
}

#playbook .pb-close {
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--muted);
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  padding: 0.3rem 0.55rem;
}
#playbook .pb-close:hover { color: var(--ink); border-color: var(--accent); }

/* ---------------------------------------------------------------------------
   THE TWO COLUMNS. The nav scrolls with the card rather than independently:
   seventeen entries fit in one screen at this size, and a second scrollbar
   inside a modal is a thing people lose their place in.
   --------------------------------------------------------------------------- */
#playbook .pb-body {
  display: grid;
  grid-template-columns: 15rem 1fr;
  gap: 0;
  align-items: start;
}

#playbook .pb-nav {
  border-right: 1px solid var(--line);
  padding: 0.9rem 0.75rem 1.5rem;
}

#playbook .pb-group { margin-bottom: 1rem; }

#playbook .pb-group-label {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 0.3rem 0.5rem;
}

#playbook .pb-item {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  width: 100%;
  text-align: left;
  background: none;
  border: 1px solid transparent;
  border-radius: 6px;
  color: var(--muted);
  cursor: pointer;
  font-family: var(--sans);
  font-size: 0.82rem;
  line-height: 1.35;
  padding: 0.32rem 0.5rem;
}
#playbook .pb-item:hover { color: var(--ink); border-color: var(--line); }
#playbook .pb-item[aria-selected="true"] {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: var(--accent);
  font-weight: 500;
}

/* The dot is a HINT, never the answer - the word is in the detail pane's
   badge. It exists so a reader scanning the list can see that something in it
   is not available without opening every entry. */
#playbook .pb-dot {
  flex: none;
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 999px;
  background: var(--muted);
  border: 1px solid transparent;
}
#playbook .pb-dot.on      { background: var(--accent); }
#playbook .pb-dot.partial { background: var(--warn-ink); }
#playbook .pb-dot.off     { background: var(--error); }
#playbook .pb-dot.unknown { background: none; border-color: var(--muted); }

/* ---------------------------------------------------------------------------
   THE DETAIL PANE.
   --------------------------------------------------------------------------- */
#playbook .pb-detail { padding: 1rem 1.25rem 1.75rem; min-width: 0; }

#playbook .pb-detail-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.35rem;
}

#playbook .pb-detail-title { font-size: 1rem; font-weight: 600; margin: 0; }

#playbook .pb-summary { color: var(--ink); margin: 0 0 0.9rem; }

#playbook h4.pb-h {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 1.1rem 0 0.4rem;
}

/* Numbered, because `how` is an ordered list of steps in the .ini and the
   order is the instruction. */
#playbook ol.pb-steps { margin: 0; padding-left: 1.3rem; }
#playbook ol.pb-steps li { margin-bottom: 0.3rem; }

/* ---------------------------------------------------------------------------
   PROMPTS. The point of the whole panel, so they are the only thing here with
   an action attached.
   --------------------------------------------------------------------------- */
#playbook .pb-prompt {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 0.5rem;
  align-items: center;
  padding: 0.4rem 0;
  border-top: 1px solid var(--line);
}

#playbook .pb-prompt-text {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--ink);
  background: var(--code-bg);
  border-radius: 4px;
  padding: 0.3rem 0.45rem;
  word-break: break-word;
}

#playbook .pb-act {
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--muted);
  cursor: pointer;
  font-family: var(--sans);
  font-size: 0.72rem;
  padding: 0.22rem 0.5rem;
  white-space: nowrap;
}
#playbook .pb-act:hover { color: var(--ink); border-color: var(--accent); }
#playbook .pb-act.primary { color: var(--accent); border-color: var(--accent); }
#playbook .pb-act[disabled] { opacity: 0.5; cursor: default; }

/* The confirmation after Use or Copy. One line, replaced on the next action,
   never stacked - a panel that accumulates toasts is a panel nobody reads. */
#playbook .pb-flash {
  font-size: 0.75rem;
  color: var(--accent);
  min-height: 1.2em;
  margin: 0.45rem 0 0;
}

/* ---------------------------------------------------------------------------
   CALLOUTS. `needs` is neutral, `watch` is the one that costs money or
   changes data, so it gets the warn tokens.
   --------------------------------------------------------------------------- */
#playbook .pb-callout {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.55rem 0.75rem;
  font-size: 0.82rem;
  margin: 0.6rem 0;
}
#playbook .pb-callout .pb-callout-k {
  font-family: var(--mono);
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  display: block;
  margin-bottom: 0.15rem;
  opacity: 0.8;
}
#playbook .pb-callout.needs { background: var(--code-bg); color: var(--ink); }
#playbook .pb-callout.watch {
  background: var(--warn-bg);
  border-color: var(--warn-line);
  color: var(--warn-ink);
}

/* ---------------------------------------------------------------------------
   BADGES AND META ROWS. See the header note: --accent ON --accent-soft
   (5.63:1 light, 6.87:1 dark), never --accent-ink on --accent-soft (1.28:1).
   --------------------------------------------------------------------------- */
#playbook .pb-badge {
  font-family: var(--mono);
  font-size: 0.66rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.05rem 0.45rem;
  color: var(--muted);
  white-space: nowrap;
}
#playbook .pb-badge.on {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: var(--accent);
}
#playbook .pb-badge.partial {
  color: var(--warn-ink);
  background: var(--warn-bg);
  border-color: var(--warn-line);
}
#playbook .pb-badge.off { color: var(--error); border-color: var(--error); border-style: dashed; }
#playbook .pb-badge.unknown { border-style: dotted; }

#playbook .pb-meta { margin-top: 1.2rem; border-top: 1px solid var(--line); padding-top: 0.7rem; }

#playbook .pb-kv {
  display: grid;
  grid-template-columns: 7rem 1fr;
  gap: 0.2rem 0.75rem;
  font-size: 0.78rem;
  padding: 0.15rem 0;
}
#playbook .pb-kv-k { color: var(--muted); }
#playbook .pb-kv-v { color: var(--ink); word-break: break-word; }
#playbook .pb-kv-v code,
#playbook .pb-mono { font-family: var(--mono); font-size: 0.75rem; }

#playbook .pb-link { color: var(--note); text-decoration: none; }
#playbook .pb-link:hover { text-decoration: underline; }

#playbook .pb-warn {
  background: var(--warn-bg);
  border: 1px solid var(--warn-line);
  color: var(--warn-ink);
  border-radius: 8px;
  padding: 0.6rem 0.8rem;
  font-size: 0.8rem;
  margin-bottom: 1rem;
}

#playbook .pb-empty { color: var(--muted); font-size: 0.82rem; padding: 0.5rem 0; }

/* ---------------------------------------------------------------------------
   NARROW SCREENS. The nav moves above the detail and the groups lay out
   horizontally, which is the one place a wrapped pill row is the right
   answer: there is no second column to put them beside.
   --------------------------------------------------------------------------- */
@media (max-width: 860px) {
  #playbook { padding: 0.75rem 0.5rem; }
  #playbook .pb-body { grid-template-columns: 1fr; }
  #playbook .pb-nav {
    border-right: none;
    border-bottom: 1px solid var(--line);
    padding-bottom: 0.9rem;
  }
  #playbook .pb-group { margin-bottom: 0.6rem; }
  #playbook .pb-group-items { display: flex; flex-wrap: wrap; gap: 0.3rem; }
  #playbook .pb-item { width: auto; border-color: var(--line); border-radius: 999px; }
  #playbook .pb-prompt { grid-template-columns: 1fr; }
  #playbook .pb-act { justify-self: start; }
  #playbook .pb-kv { grid-template-columns: 1fr; }
  #playbook .pb-kv-k { font-family: var(--mono); font-size: 0.68rem; }
}