/* ================================================================
   work-templates.css — Programs ▸ Templates
   Card grid + detail/editor modal + picker. Editor uses the canonical
   pbmf mini-form (window.WkMiniForm) for every "+ Add X" / Edit popup,
   so visuals match the rest of the plan creator.
   ================================================================ */

/* ────────────────────────────────────────────────────────
   TEMPLATE BUILDER — DESIGN TOKENS
   ────────────────────────────────────────────────────────
   The builder used to carry its own palette: the stock Tailwind slate ramp
   (#0f172a / #64748b / #e2e8f0 / #f1f5f9), thirteen different border-radius
   values, and a type scale with half-pixels in it. None of that came from
   anywhere — it read as a default theme rather than as this product, which
   is exactly what "boring" means when a screen is otherwise fine.

   These are ALIASES onto the app system in work.css, not new values. Change
   work.css and the builder follows. Only two steps are defined locally, and
   only because the global system doesn't name them: --wkt-tint (the panel
   wash one step off white) and --wkt-r-md (the middle radius, kept so a chip
   snapping 12px→16px doesn't turn into a lozenge).

   Namespaced --wkt-* and hung on :root so the builder's body-portaled bits
   (context menus, the source rail, the from-library modal) resolve them too.
   ──────────────────────────────────────────────────────── */
:root {
  /* Ink — headings through disabled, off work.css's neutral ramp */
  --wkt-ink:         var(--ink);        /* #161616  headings, primary text  */
  --wkt-ink-2:       var(--ink2);       /* #525252  body, secondary         */
  --wkt-ink-3:       var(--ink2-4);     /* #6b7280  labels, meta, captions  */
  --wkt-ink-4:       var(--ink3);       /* #8d8d8d  placeholder, disabled   */

  /* Surfaces — three steps, white → wash → pressed */
  --wkt-surf:        var(--surf);       /* #ffffff  cards, fields, popovers */
  --wkt-tint:        #fafafa;           /*          panel wash              */
  --wkt-hover:       var(--border-s);   /* #f4f4f4  hover / active fill     */

  /* Lines — hairline, border, hover border */
  --wkt-line-soft:   var(--border-s);   /* #f4f4f4  dividers, inner rules   */
  --wkt-line:        var(--border);     /* #e0e0e0  real borders            */
  --wkt-line-strong: var(--ink4);       /* #c6c6c6  hover / focus borders   */

  /* Radius — thirteen values collapsed to three plus a pill */
  --wkt-r:           var(--radius-sm);  /* 10px  controls, chips, buttons   */
  --wkt-r-md:        12px;              /*       inner panels, list rows    */
  --wkt-r-lg:        var(--radius);     /* 16px  cards, modals, stages      */
  --wkt-r-pill:      999px;             /*       pills and round toggles    */
}

/* ────────────────────────────────────────────────────────
   CARDS — report-card style: gradient hero + meta + stats.
   ──────────────────────────────────────────────────────── */
/* ONE wall of cards for the whole library (see _renderCardGrid), not a grid
   per category.

   These track and gap values only reach the apply-picker and the
   from-a-template panel — and both override them anyway. The LIBRARY grid's
   columns come from work-views.css: `.gl-view-card .wk-prog-card-grid` is two
   classes to this rule's one, so `minmax(var(--wkv-card-min), 1fr)` wins and
   Templates sits on the same 280px card frame as Work Streams, Projects and
   Accounts. Leave it there — a bespoke track width here would just make
   Templates the one Programs tab whose cards are a different size. */
.wkt-rp-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 16px;
  padding: 16px;
  align-content: start;
}
.wkt-rp-grid .wk-empty { grid-column: 1 / -1; }

/* CATEGORY BANDS — the library wall is grouped by category, and each group is
   introduced by one of these. It spans every column of the SAME grid the cards
   sit in (grid-column: 1 / -1), so a band costs one short row and nothing else:
   no nested grid, no second padding box, no rows the next category can't share.
   The negative bottom margin pulls the cards back up under their own header —
   the grid's 16px gap reads as too far when what's above is a label rather
   than another card. */
.wkt-rp-grid > .wkt-cat-band {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 9px;
  margin: 12px 0 -4px;
  padding-bottom: 8px;
  border-bottom: 1px solid #e9eef4;
}
.wkt-rp-grid > .wkt-cat-band:first-child { margin-top: 0; }
.wkt-cat-band-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.wkt-cat-band-name { font-size: 13px; font-weight: 700; color: #0f172a; letter-spacing: .01em; }
.wkt-cat-band-n {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 19px; padding: 0 7px;
  background: #f1f5f9; color: #64748b; border-radius: 10px;
  font-size: 11px; font-weight: 700;
}
/* Every card in the wall is the same height. NOT via `grid-auto-rows: 1fr` —
   the tempting one-liner does nothing here, because 1fr distributes FREE
   space and a grid that sizes to its own content has none. It's earned in the
   card: the reserved name and summary slots below bring any real card out at
   this height, and the floor then catches the dashed "New Order of
   Operations" tile, which carries neither and is usually alone on the last
   row — without it that tile sat there as a half-height stub.
   Scoped to the LIBRARY grid: the picker and the from-a-template panel reuse
   .wkt-rp-card at smaller sizes and must not inherit the floor. */
.wk-prog-card-grid.wkt-rp-grid { --wkt-card-h: 305px; }
.wk-prog-card-grid.wkt-rp-grid > .wkt-rp-card { min-height: var(--wkt-card-h); }

/* ────────────────────────────────────────────────────────
   TOOLBAR — calendar pattern. Left section is the "+ New
   Template" action visually sectioned off (same as the
   calendar's team picker). Right section is search + filter.
   ──────────────────────────────────────────────────────── */
.wkt-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding: 10px 14px; }
.wkt-toolbar-left {
  display: flex; align-items: center; gap: 14px;
  padding: 6px 14px 6px 6px;
  background: #f8fafc;
  border: 1px solid #e2e8f0;
  border-radius: 12px;
}
.wkt-toolbar-divider {
  width: 1px; height: 22px;
  background: #e2e8f0;
}
.wkt-toolbar-count-group { display: flex; align-items: baseline; gap: 8px; }
.wkt-toolbar-label { font-size: 12px; font-weight: 600; color: #475569; text-transform: uppercase; letter-spacing: .04em; }
.wkt-toolbar-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 8px;
  background: #eef2ff; color: #4338ca; border-radius: 11px;
  font-size: 12px; font-weight: 700;
}

/* ────────────────────────────────────────────────────────
   FILTER DROPDOWN — multi-select category narrow
   ──────────────────────────────────────────────────────── */
.wkt-filter-menu {
  position: absolute; top: calc(100% + 6px); right: 0;
  min-width: 240px; max-height: 360px; overflow: auto;
  background: #fff;
  border: 1px solid #e2e8f0; border-radius: 10px;
  box-shadow: 0 12px 32px -8px rgba(15,23,42,.18);
  z-index: 100;
  animation: wkt-popin .14s cubic-bezier(.2,.8,.2,1);
}
.wkt-filter-menu-head {
  padding: 12px 14px 8px;
  font-size: 11px; font-weight: 700; color: #64748b;
  text-transform: uppercase; letter-spacing: .04em;
  border-bottom: 1px solid #f1f5f9;
}
.wkt-filter-menu-list { padding: 6px; display: flex; flex-direction: column; gap: 1px; }
.wkt-filter-row {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; border-radius: 8px; cursor: pointer;
  transition: background .12s;
}
.wkt-filter-row:hover { background: #f8fafc; }
.wkt-filter-row input[type="checkbox"] { margin: 0; cursor: pointer; }
.wkt-filter-row-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.wkt-filter-row-name { font-size: 13px; color: #0f172a; flex: 1; }
/* Per-row count — the number the category scorecards used to carry, now
   sitting next to the filter that actually uses it. */
.wkt-filter-row-n {
  font-size: 11px; font-weight: 700; color: #64748b;
  background: #f1f5f9; border-radius: 999px;
  min-width: 20px; padding: 1px 6px; text-align: center;
  flex-shrink: 0;
}
/* A category with nothing in it still lists — the gap is worth seeing —
   but reads as a gap rather than an option. */
.wkt-filter-row.is-empty .wkt-filter-row-name,
.wkt-filter-row.is-empty .wkt-filter-row-n { color: #b6c0cd; }
.wkt-filter-row.is-empty .wkt-filter-row-dot { opacity: .35; }
.wkt-filter-menu-foot {
  padding: 8px 10px; border-top: 1px solid #f1f5f9;
  display: flex; justify-content: flex-end;
}
.wk-btn--ghost-sm {
  padding: 5px 12px; font-size: 11.5px; font-weight: 600;
  background: transparent; color: #475569; border: 0; cursor: pointer;
  border-radius: 6px;
}
.wk-btn--ghost-sm:hover { background: #f1f5f9; color: #0f172a; }

/* Grouped view — used when no scorecard / search filter narrows the list.
   Each category gets its own section with a header. */
.wkt-rp-groups { display: flex; flex-direction: column; gap: 22px; padding: 16px; }
.wkt-rp-group { display: flex; flex-direction: column; gap: 10px; }
.wkt-rp-group-head {
  display: flex; align-items: center; gap: 10px;
  font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: #475569;
}
.wkt-rp-group-dot { width: 10px; height: 10px; border-radius: 50%; }
.wkt-rp-group-name { color: #0f172a; font-size: 13.5px; }
.wkt-rp-group-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 8px;
  background: #f1f5f9; color: #64748b; border-radius: 11px;
  font-size: 11px; font-weight: 700; letter-spacing: 0; text-transform: none;
}
.wkt-rp-group .wkt-rp-grid { padding: 0; }

.wkt-rp-card {
  background: #fff;
  border: 1px solid #e2e8f0;
  border-radius: 14px;
  overflow: hidden;
  cursor: pointer;
  display: flex; flex-direction: column;
  transition: box-shadow .2s cubic-bezier(.2,.8,.2,1), transform .2s cubic-bezier(.2,.8,.2,1), border-color .2s ease;
  position: relative;
}
.wkt-rp-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 32px -10px rgba(15,23,42,.18);
  border-color: var(--rp-card-c, #6366f1);
}
.wkt-rp-card:focus-visible {
  outline: 2px solid var(--rp-card-c, #6366f1); outline-offset: 2px;
}
/* 76px, not 100px. On a 460px-wide card the gradient hero was a banner; on a
   280px card four-across it only has to be enough to carry the category
   colour and the icon, and the height it gives back is what lets a row of
   cards fit on screen. Matches the hero .wkt-from-grid already uses. */
.wkt-rp-card-thumb {
  height: 76px;
  background: linear-gradient(135deg, var(--rp-card-c, #6366f1) 0%, color-mix(in srgb, var(--rp-card-c, #6366f1) 70%, #000) 100%);
  position: relative; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.wkt-rp-card-thumb::after {
  content: ''; position: absolute; inset: 0;
  background:
    radial-gradient(circle at 18% 28%, rgba(255,255,255,.18) 0%, transparent 35%),
    radial-gradient(circle at 80% 75%, rgba(255,255,255,.12) 0%, transparent 40%),
    repeating-linear-gradient(45deg, transparent 0 8px, rgba(255,255,255,.04) 8px 10px);
  pointer-events: none;
}
.wkt-rp-card-thumb-icon {
  position: relative; z-index: 1;
  width: 46px; height: 46px;
  background: rgba(255,255,255,.18);
  border: 1.5px solid rgba(255,255,255,.32);
  border-radius: 13px;
  display: flex; align-items: center; justify-content: center;
  color: #fff; backdrop-filter: blur(6px);
}
/* _categoryIcon() hard-codes width/height="34" on the <svg> for the old 60px
   tile. Overridden here rather than changed at the source, because the same
   helper draws the detail hero where 34 is still right. */
.wkt-rp-card-thumb-icon svg { width: 24px; height: 24px; }
.wkt-rp-card-body { padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.wkt-rp-card-tags { display: flex; gap: 6px; flex-wrap: wrap; }
.wkt-rp-card-tag {
  display: inline-flex; padding: 3px 10px; border-radius: 11px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
}
/* Name and summary both hold TWO LINES whether or not they need two. That is
   what makes a row of cards line up: a one-line name next to a two-line one
   used to push the stats strips out of step by 20px, and reserving the space
   costs less than the stagger did. Clamped as well as reserved, so a long
   name can't run the card taller than its neighbours either. */
.wkt-rp-card-name {
  font-size: 15px; font-weight: 700; color: #0f172a; line-height: 1.3;
  min-height: calc(15px * 1.3 * 2);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.wkt-rp-card-desc {
  font-size: 12.5px; color: #475569; line-height: 1.5;
  min-height: calc(12.5px * 1.5 * 2);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.wkt-rp-card-pills { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 2px; }
.wkt-rp-pill {
  display: inline-flex; align-items: center; padding: 3px 9px;
  font-size: 11px; font-weight: 600; color: #475569;
  background: #f1f5f9; border-radius: 6px; border: 1px solid #e2e8f0;
}
.wkt-rp-pill--light { background: rgba(255,255,255,.22); color: #fff; border-color: rgba(255,255,255,.32); }
/* DRAFT — never saved to the library, so nothing can apply it. Amber, because
   it's a state to finish rather than a problem to fix. */
.wkt-rp-pill--draft {
  background: #fffbeb; color: #92400e; border-color: #fcd34d;
  font-weight: 800; letter-spacing: .03em; text-transform: uppercase; font-size: 10px;
}
.wkt-rp-card-stats {
  display: flex; gap: 12px;
  padding-top: 10px; margin-top: auto;
  border-top: 1px solid #f1f5f9;
}
.wkt-rp-stat { display: flex; flex-direction: column; gap: 1px; }
.wkt-rp-stat-val { font-size: 18px; font-weight: 800; color: #0f172a; line-height: 1.1; }
.wkt-rp-stat-lbl { font-size: 10px; font-weight: 600; color: #64748b; text-transform: uppercase; letter-spacing: .05em; }

/* Bottom-right delete affordance on each template card. Sits at the end of
   the stats row so it can't collide with the stat blocks. Hidden until the
   card is hovered/focused on pointer devices (keeps the grid calm); always
   visible on touch, where there is no hover. */
.wkt-rp-card-del {
  margin-left: auto; align-self: center; flex: none;
  width: 30px; height: 30px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: #fff; color: #94a3b8;
  border: 1px solid #e2e8f0; border-radius: 8px;
  cursor: pointer;
  transition: opacity .16s ease, color .16s ease, background .16s ease, border-color .16s ease;
}
.wkt-rp-card-del:hover {
  color: #dc2626; background: #fef2f2; border-color: #fecaca;
}
.wkt-rp-card-del:focus-visible {
  outline: 2px solid #dc2626; outline-offset: 2px;
}
@media (hover: hover) and (pointer: fine) {
  .wkt-rp-card-del { opacity: 0; }
  .wkt-rp-card:hover .wkt-rp-card-del,
  .wkt-rp-card:focus-within .wkt-rp-card-del { opacity: 1; }
}

/* ────────────────────────────────────────────────────────
   GRID ENTRY ANIMATION — runs on every render. innerHTML
   swap on scorecard click / search / filter recreates the
   nodes, so the animation replays naturally and the panel
   no longer feels like it snaps between states.
   ──────────────────────────────────────────────────────── */
@keyframes wkt-card-in {
  from { opacity: 0; transform: translateY(10px) scale(.985); }
  to   { opacity: 1; transform: none; }
}
.wkt-rp-card  { animation: wkt-card-in .26s cubic-bezier(.2,.8,.2,1) both; }
.wkt-rp-card:nth-child(1)   { animation-delay: 0s; }
.wkt-rp-card:nth-child(2)   { animation-delay: .025s; }
.wkt-rp-card:nth-child(3)   { animation-delay: .05s; }
.wkt-rp-card:nth-child(4)   { animation-delay: .075s; }
.wkt-rp-card:nth-child(5)   { animation-delay: .10s; }
.wkt-rp-card:nth-child(6)   { animation-delay: .125s; }
.wkt-rp-card:nth-child(7)   { animation-delay: .15s; }
.wkt-rp-card:nth-child(8)   { animation-delay: .175s; }
.wkt-rp-card:nth-child(9)   { animation-delay: .20s; }
.wkt-rp-card:nth-child(n+10){ animation-delay: .22s; }

.wkt-rp-group { animation: wkt-card-in .30s cubic-bezier(.2,.8,.2,1) both; }
.wkt-rp-group:nth-child(1)   { animation-delay: 0s; }
.wkt-rp-group:nth-child(2)   { animation-delay: .06s; }
.wkt-rp-group:nth-child(3)   { animation-delay: .12s; }
.wkt-rp-group:nth-child(4)   { animation-delay: .18s; }
.wkt-rp-group:nth-child(n+5){ animation-delay: .22s; }
/* Don't double-animate cards already covered by their parent group fade */
.wkt-rp-groups .wkt-rp-card { animation: none; }
@media (prefers-reduced-motion: reduce) {
  .wkt-rp-card, .wkt-rp-group { animation: none !important; }
}

/* Required/Optional/Conditional pill on cards + hero */
.wkt-badge {
  display: inline-flex; align-items: center; height: 20px; padding: 0 9px;
  border-radius: 10px; font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
}
.wkt-badge--required    { background: #fef2f2; color: #b91c1c; }
.wkt-badge--optional    { background: #f1f5f9; color: #475569; }
.wkt-badge--conditional { background: #fef3c7; color: #92400e; }

/* ────────────────────────────────────────────────────────
   DETAIL / EDITOR MODAL — opens when a card is clicked.
   Hero with edit pencil; body has + Add buttons + step list.
   No wizard, no Back/Next, no invented fields.
   ──────────────────────────────────────────────────────── */
.wkt-detail {
  /* Top-of-stack. The Work app's modal layers run all the way to 300000
     (wk-modal-overlay 250000, value-tracker 300000) and the focus system
     dynamically bumps the active overlay to 60000+. The template editor
     must clear ALL of them or it opens hidden behind whatever's underneath. */
  position: fixed; inset: 0; z-index: 2000000;
  display: none; align-items: center; justify-content: center;
}
/* Item popups (task / work stream / deliverable) are the app's REAL popups now
   and float THEMSELVES above this one by reading what's on screen
   (window._wkFloatOnTop), so nothing here needs a hard-coded tier. The old
   .pbmf-bg mini-form is gone. */
.wkt-detail.is-open { display: flex; }
body.wkt-wiz-open { overflow: hidden; }
.wkt-detail-backdrop { position: absolute; inset: 0; background: rgba(15,23,42,.55); }
/* A POPUP that takes up the whole page — the same thing the projects tab does
   when you open a project. Building a template is the whole job while you're
   doing it (a stage lane is wide), so it claims the viewport; but it stays a
   popup: rounded, lifted off a dimmed page you can still see the edge of, and
   dismissed by clicking out of it. */
.wkt-detail-card {
  position: relative;
  width: calc(100vw - 32px); height: calc(100vh - 32px); max-height: none;
  background: var(--wkt-surf); border-radius: var(--wkt-r-lg); overflow: hidden;
  box-shadow: 0 32px 80px rgba(15,23,42,.42), 0 0 0 1px rgba(15,23,42,.06);
  display: flex; flex-direction: column;
  animation: wkt-popin .18s cubic-bezier(.2,.8,.2,1);
}
/* Mobile chrome eats part of 100vh — dvh where it exists. */
@supports (height: 100dvh) { .wkt-detail-card { height: calc(100dvh - 32px); } }
@media (max-width: 640px) {
  .wkt-detail-card { width: 100vw; height: 100vh; border-radius: 0; }
  @supports (height: 100dvh) { .wkt-detail-card { height: 100dvh; } }
}
@keyframes wkt-popin { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }
.wkt-detail-hero-actions {
  position: absolute; top: 14px; right: 14px;
  z-index: 2;
  display: flex; align-items: center; gap: 8px;
}
.wkt-detail-close {
  width: 32px; height: 32px;
  border-radius: var(--wkt-r); border: 0;
  color: var(--wkt-surf); background: rgba(0,0,0,.18);
  cursor: pointer; font-size: 22px; line-height: 1;
}
.wkt-detail-close:hover { background: rgba(0,0,0,.32); }
/* ── Edit / Preview segmented control ─────────────────────────────────
   Sits on the coloured hero next to the ×, so the track is a translucent
   scrim rather than the usual var(--wkt-hover) slate: the selected segment goes
   solid white with dark ink, the other stays washed white on the hero.
   32px tall to line up with the × beside it. */
.wkt-detail-modeseg {
  display: inline-flex; gap: 2px;
  height: 32px; padding: 2px;
  border-radius: var(--wkt-r);
  border: 1px solid rgba(255,255,255,.30);
  background: rgba(0,0,0,.18);
}
.wkt-detail-modebtn {
  display: inline-flex; align-items: center;
  padding: 0 11px;
  border: 0; border-radius: var(--wkt-r);
  background: transparent;
  color: rgba(255,255,255,.82);
  /* font-family longhand, not the `font:` shorthand — a shorthand carrying an
     `inherit` component is invalid and the whole declaration gets dropped. */
  font-family: inherit;
  font-size: 12px; font-weight: 600; line-height: 1;
  cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.wkt-detail-modebtn:hover { background: rgba(255,255,255,.18); color: var(--wkt-surf); }
.wkt-detail-modebtn.is-active {
  background: var(--wkt-surf); color: var(--wkt-ink);
  box-shadow: var(--shadow-sm);
}
/* Hover must not repaint the lit segment — it already reads as selected. */
.wkt-detail-modebtn.is-active:hover { background: var(--wkt-surf); color: var(--wkt-ink); }
/* The hero is this popup's drag handle (window._wkMakeDraggable) — same grab
   cursor as .tp-header / .wk-modal-head. Drags that start on one of its own
   inputs are ignored by the helper, so the fields still work. */
.wkt-detail-hero { cursor: grab; }
.wkt-detail-hero:active { cursor: grabbing; }
.wkt-detail-hero input, .wkt-detail-hero textarea, .wkt-detail-hero select { cursor: auto; }
.wkt-detail-hero {
  position: relative; padding: 26px 28px;
  display: flex; align-items: flex-start; gap: 20px;
  color: var(--wkt-surf); min-height: 120px;
}
.wkt-detail-hero::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(circle at 18% 28%, rgba(255,255,255,.18) 0%, transparent 35%),
    radial-gradient(circle at 80% 75%, rgba(255,255,255,.12) 0%, transparent 40%);
}
.wkt-detail-hero-icon {
  position: relative; z-index: 1;
  width: 64px; height: 64px;
  background: rgba(255,255,255,.18);
  border: 1.5px solid rgba(255,255,255,.32);
  border-radius: var(--wkt-r-lg); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--wkt-surf); backdrop-filter: blur(6px);
}
.wkt-detail-hero-titles { position: relative; z-index: 1; flex: 1; min-width: 0; }
.wkt-detail-hero-cat { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; opacity: .9; }
.wkt-detail-hero-name { font-size: 22px; font-weight: 800; line-height: 1.2; margin-top: 2px; }
.wkt-detail-hero-desc { font-size: 13px; line-height: 1.55; opacity: .92; margin-top: 8px; max-width: 560px; }

/* ────────────────────────────────────────────────────────
   WIDE MINI-FORM — for richer popups (Task / Project)
   Uses the same pbmf-* shell as the canonical mini-form, just
   bigger with a 2-column field grid. Single-column on narrow.
   ──────────────────────────────────────────────────────── */
.pbmf-card.pbmf-card--wide {
  width: min(640px, 92vw);
  max-width: 92vw;
}
.pbmf-card.pbmf-card--wide .pbmf-body {
  display: grid; grid-template-columns: 1fr 1fr; gap: 14px 18px;
}
.pbmf-card.pbmf-card--wide .pbmf-field {
  /* Textareas + the title (first field) span both columns */
}
.pbmf-card.pbmf-card--wide .pbmf-field:first-child,
.pbmf-card.pbmf-card--wide .pbmf-field:has(textarea) {
  grid-column: 1 / -1;
}
.pbmf-card.pbmf-card--wide .pb-input,
.pbmf-card.pbmf-card--wide .pb-select { width: 100%; box-sizing: border-box; }

@media (max-width: 540px) {
  .pbmf-card.pbmf-card--wide .pbmf-body { grid-template-columns: 1fr; }
}

/* ────────────────────────────────────────────────────────
   EDIT-MODE INLINE INPUTS in the hero
   When the modal is in edit mode, name/category/color/desc
   become editable fields directly on the colored hero. No
   separate popup.
   ──────────────────────────────────────────────────────── */
.wkt-detail-card.is-edit .wkt-detail-hero-titles {
  display: flex; flex-direction: column; gap: 8px; max-width: 600px;
}
.wkt-hero-cat-input,
.wkt-hero-name-input,
.wkt-hero-desc-input {
  font-family: inherit;
  background: rgba(255,255,255,.16);
  border: 1px solid rgba(255,255,255,.34);
  color: var(--wkt-surf);
  border-radius: var(--wkt-r);
  outline: 0;
  transition: background .15s, border-color .15s;
}
.wkt-hero-cat-input:focus,
.wkt-hero-name-input:focus,
.wkt-hero-desc-input:focus {
  background: rgba(255,255,255,.24);
  border-color: rgba(255,255,255,.65);
}
.wkt-hero-cat-input::placeholder,
.wkt-hero-name-input::placeholder,
.wkt-hero-desc-input::placeholder { color: rgba(255,255,255,.62); }

/* The TAG picker. It is a required choice, so it has to LOOK like a control
   you operate — a native select with the OS chrome stripped reads as a static
   chip, which is exactly why it used to sit there saying "OTHER" and nobody
   touched it. Hence: our own caret, room for it, and an untagged state that
   says "Select a tag…" in a dashed outline until a real one is picked. */
.wkt-hero-cat-input {
  align-self: flex-start;
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
  padding: 5px 26px 5px 10px;
  cursor: pointer;
  -webkit-appearance: none; -moz-appearance: none; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 8px center;
  background-size: 10px 10px;
}
.wkt-hero-cat-input option { color: var(--wkt-ink); background: var(--wkt-surf); }
/* Untagged — reads as an unfilled required field, not as a tag named "blank". */
.wkt-hero-cat-input.is-untagged {
  border-style: dashed;
  border-color: rgba(255,255,255,.7);
  background-color: rgba(255,255,255,.10);
}
/* Bounced off Create/Done with no tag picked. */
.wkt-hero-cat-input.is-missing {
  animation: wkt-cat-nudge .5s ease;
  border-style: solid;
  border-color: var(--wkt-surf);
  box-shadow: 0 0 0 3px rgba(255,255,255,.35);
}
@keyframes wkt-cat-nudge {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-5px); }
  40% { transform: translateX(5px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(3px); }
}
@media (prefers-reduced-motion: reduce) {
  .wkt-hero-cat-input.is-missing { animation: none; }
  .wkt-detail-card { animation: none; }
}

.wkt-hero-name-input {
  font-size: 22px; font-weight: 800; line-height: 1.2;
  padding: 6px 10px;
}

.wkt-hero-desc-input {
  font-size: 13px; line-height: 1.55;
  padding: 8px 10px;
  resize: vertical; min-height: 56px;
}

/* (color chip row removed — color now derives from category) */
.wkt-detail-hero-edit {
  position: relative; z-index: 1;
  align-self: flex-start; flex-shrink: 0;
  padding: 6px 12px; border-radius: var(--wkt-r);
  border: 1px solid rgba(255,255,255,.32);
  background: rgba(255,255,255,.18); color: var(--wkt-surf);
  font-size: 12px; font-weight: 600; cursor: pointer;
  margin-right: 38px;
}
.wkt-detail-hero-edit:hover { background: rgba(255,255,255,.28); }

.wkt-detail-body {
  flex: 1; overflow: auto;
  padding: 22px 28px;
  background: var(--wkt-tint);
}
/* No centered column any more: a stage LANE runs the full width and scrolls
   sideways from its own left edge. Capping the map at 1120px would have put an
   inch of dead grey either side of the thing being built. The empty state is
   prose, so that one still reads in a column. */
.wkt-detail-body > .wkt-detail-empty { max-width: 900px; margin-left: auto; margin-right: auto; }
/* Full page means no dragging it aside — there is nowhere to drag it to. */
.wkt-detail-hero { cursor: default; }
.wkt-detail-hero:active { cursor: default; }

.wkt-detail-addrow {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 12px 14px;
  background: var(--wkt-surf); border: 1px solid var(--wkt-line); border-radius: var(--wkt-r-md);
  margin-bottom: 16px;
}
.wkt-detail-add {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 7px 14px; border-radius: var(--wkt-r); cursor: pointer;
  font-size: 13px; font-weight: 600;
  background: color-mix(in srgb, var(--_k, #6366f1) 8%, var(--wkt-surf));
  color: var(--_k, #6366f1);
  border: 1px solid color-mix(in srgb, var(--_k, #6366f1) 28%, transparent);
  transition: background .15s, transform .12s;
}
.wkt-detail-add:hover { background: color-mix(in srgb, var(--_k, #6366f1) 16%, var(--wkt-surf)); transform: translateY(-1px); }

.wkt-detail-empty {
  padding: 32px 24px; text-align: center;
  color: var(--wkt-ink-4); font-size: 13px;
  background: var(--wkt-surf); border: 1.5px dashed var(--wkt-line-strong); border-radius: var(--wkt-r-md);
}

.wkt-detail-section { margin-bottom: 18px; }
.wkt-detail-section-head { font-size: 13px; font-weight: 700; color: var(--wkt-ink); margin-bottom: 10px; }

/* ────────────────────────────────────────────────────────
   PLAN-STYLE BUILDER — building a template looks/feels like the
   project Plan: one + button at the top tier, work-stream groups
   with an accent rail, the deliverables each stream owes nested
   inside it, and the tasks behind each deliverable under that.
   Same visual language as the Plan tab — minus the group-by lens,
   which a thing you are BUILDING has no use for.
   ──────────────────────────────────────────────────────── */
/* The builder's one action bar — what to add, how far out to stand, the AI that
   drafts it, and the "that'll do" that commits. STICKY, because the map grows
   down and every one of those is needed from the bottom of it too. */
.wkt-plan-toolbar {
  position: sticky; top: 0; z-index: 6;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: -22px -28px 14px; padding: 12px 28px;
  background: rgba(248,250,252,.92);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  border-bottom: 1px solid #e8edf3;
}
.wkt-plan-toolbar-gap { flex: 1 1 auto; min-width: 8px; }

/* ── Zoom ─────────────────────────────────────────────────
   There is no zoom control. The − / 100% / + pill is gone: the map is a canvas,
   so it zooms the way canvases zoom — pinch the trackpad, or ⌘/Ctrl + scroll,
   anchored on the pointer (see ZOOM in work-templates.js). All that's left is
   one line saying so, once per session, on a map that is actually scaled down;
   it sits above the footer, ignores the mouse, and fades out. */
.wkt-zoom-hint {
  position: absolute; left: 50%; bottom: 84px; z-index: 7;
  padding: 7px 14px; border-radius: var(--wkt-r-pill);
  background: rgba(15,23,42,.88); color: var(--wkt-surf);
  font-size: 12px; font-weight: 600; letter-spacing: .01em; white-space: nowrap;
  box-shadow: 0 8px 24px rgba(15,23,42,.3);
  pointer-events: none; opacity: 0;
  transform: translate(-50%, 6px);
  transition: opacity .22s ease, transform .22s ease;
}
.wkt-zoom-hint.is-on { opacity: 1; transform: translate(-50%, 0); }
.wkt-zoom-hint[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) { .wkt-zoom-hint { transition: none; } }
.wkt-plan-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; font-size: 13px; font-weight: 600;
  color: var(--wkt-ink-2); background: var(--wkt-surf); border: 1px solid var(--wkt-line-strong); border-radius: var(--wkt-r);
  cursor: pointer; transition: background .12s, border-color .12s, box-shadow .12s;
}
.wkt-plan-btn:hover { background: var(--wkt-tint); border-color: var(--wkt-ink-4); }
.wkt-plan-btn--primary { color: var(--wkt-surf); background: #16a34a; border-color: #16a34a; }
.wkt-plan-btn--primary:hover { background: #15803d; border-color: #15803d; }
.wkt-plan-btn--xs { padding: 4px 10px; font-size: 12px; border-radius: var(--wkt-r); }

/* + Add deliverable — purple (the deliverable KIND_COLOR, #7c3aed), sitting in
   the work stream's own body under its rows rather than as a head action, so
   "what goes in this stream next" is one obvious click and not a small grey
   button off to the side. */
.wkt-plan-addrow { padding: 4px 0 2px; }
.wkt-plan-btn--deliv {
  width: 100%; justify-content: center;
  color: var(--wkt-surf); background: #7c3aed; border-color: #7c3aed;
  box-shadow: 0 1px 2px rgba(124,58,237,.28);
}
.wkt-plan-btn--deliv:hover { background: #6d28d9; border-color: #6d28d9; }
.wkt-plan-btn--deliv:active { background: #5b21b6; border-color: #5b21b6; }
.wkt-plan-btn--deliv:focus-visible { outline: 2px solid #c4b5fd; outline-offset: 2px; }

/* The add-the-next-tier buttons, each wearing its own tier's KIND_COLOR so the
   cascade reads down the tree: stage teal → work stream indigo → deliverable
   purple → task blue. Same full-width shape at every tier, so "what goes in
   this thing next" is always the same gesture. */
.wkt-plan-btn--stage {
  color: var(--wkt-surf); background: #0f766e; border-color: #0f766e;
  box-shadow: 0 1px 2px rgba(15,118,110,.28);
}
.wkt-plan-btn--stage:hover { background: #0d5f59; border-color: #0d5f59; }
.wkt-plan-btn--stage:active { background: #0b4f4a; border-color: #0b4f4a; }
.wkt-plan-btn--stage:focus-visible { outline: 2px solid #5eead4; outline-offset: 2px; }
.wkt-plan-btn--ws {
  flex: 1; justify-content: center;
  color: var(--wkt-surf); background: #4338ca; border-color: #4338ca;
  box-shadow: 0 1px 2px rgba(67,56,202,.28);
}
.wkt-plan-btn--ws:hover { background: #3730a3; border-color: #3730a3; }
.wkt-plan-btn--ws:active { background: #312e81; border-color: #312e81; }
.wkt-plan-btn--ws:focus-visible { outline: 2px solid #a5b4fc; outline-offset: 2px; }
/* The stream's footer row holds ONE move: the outcome it owes. (There is no
   task tier in a template any more, so nothing sits beside it.) It's inside the
   stream's BODY, so a shut stream doesn't show it. */
.wkt-plan-addrow--stream { display: flex; gap: 6px; align-items: stretch; }

/* ── THE COLLAPSE BUTTON ──────────────────────────────────
   One control, used at both levels that hold anything: the stage line ("Hide 2
   work streams") and the work stream header ("Hide 3 deliverables"). It says
   what it hides, in words, with the count — so you know what you are about to
   lose and, once it's shut, exactly what is behind it. That label is why there
   is no separate "what's in here" caption on a collapsed row: the button IS the
   caption.

   Always visible, never hover-only: this is the one control on the map that has
   to be findable by someone who has not used the screen before. */
.wkt-foldpill {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 5px;
  height: 24px; padding: 0 9px 0 7px;
  border: 1px solid var(--wkt-line); border-radius: var(--wkt-r-pill);
  background: var(--wkt-surf); color: var(--wkt-ink-2);
  font: inherit; font-size: 12px; font-weight: 700; line-height: 1;
  white-space: nowrap; cursor: pointer;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.wkt-foldpill:hover { background: var(--wkt-hover); border-color: #c7d2de; color: var(--wkt-ink); }
.wkt-foldpill:focus-visible { outline: 2px solid #0f766e; outline-offset: 1px; }
.wkt-foldpill-chev { flex: 0 0 auto; transition: transform .16s ease; }
.wkt-foldpill.is-folded .wkt-foldpill-chev { transform: rotate(-90deg); }
/* Shut reads as the state it is — a filled pill, not the same white as open. */
.wkt-foldpill.is-folded { background: var(--wkt-hover); border-color: var(--wkt-line-strong); color: var(--wkt-ink-2); }

/* A WORK STREAM HAS NO FOLD. Neither the shared renderer's bare chevron nor a
   labelled pill ever reaches a stream header — the card holds nothing that can
   drop out of it, so a control offering to open it would be a lie. The stage
   line keeps its pill; that is the one collapsible tier left. */
.wkt-wscol > .ep-plan-group > .ep-plan-group-head > .ep-plan-fold,
.wkt-wscol > .ep-plan-group > .ep-plan-group-head > .wkt-foldpill { display: none; }

/* CLICK THE CARD TO OPEN THE STREAM — the whole header is the target, and what
   opens is the stream's popup, where its deliverables and their delivery data
   are read. */
.wkt-wscol > .ep-plan-group > .ep-plan-group-head { cursor: pointer; }
/* NOTHING IS EVER DONE IN A TEMPLATE. The shared stream header carries a
   progress bar and a "0%" because on a live plan that number is the point; here
   it is 0% on every card, for ever, and it was the widest thing on a shut card.
   Hidden in the builder only — the live plan's own header is untouched. */
.wkt-wscol .ep-plan-group-progress { display: none; }

/* Who owns it, as a face, pinned to the top-right of the header — a fact about
   the stream rather than a control, so it is never hover-only. Absolute, so it
   sits on the eyebrow line instead of being wrapped onto the actions row. */
.wkt-wscol > .ep-plan-group > .ep-plan-group-head { position: relative; }
.wkt-owner-face {
  position: absolute; top: 9px; right: 11px; z-index: 2;
  display: inline-flex; align-items: center;
}
.wkt-owner-face .wk-assignee-av,
.wkt-owner-face .wk-assignee-stack .wk-assignee-av { width: 22px; height: 22px; font-size: 10px; }
/* Open all / Shut all — a quiet sibling of the zoom pill. */
.wkt-plan-btn--ghost { color: var(--wkt-ink-2); background: var(--wkt-surf); border-color: #d7dfe8; font-size: 12px; padding: 6px 12px; }
.wkt-plan-btn--ghost:hover { background: var(--wkt-hover); color: var(--wkt-ink); }
.wkt-plan-btn--ghost[hidden] { display: none; }
/* Dragging a task INTO a deliverable highlights that deliverable's own list —
   the live plan only ever highlights a work-stream body, so the blue twin of
   that dashed outline lives here. */
.ep-plan-delivblock-work.ep-plan-drop-into {
  background: rgba(59,130,246,.07);
  outline: 2px dashed rgba(59,130,246,.55);
  outline-offset: -4px;
  border-radius: 10px;
}

/* ────────────────────────────────────────────────────────
   STAGES — STRUCTURE, not a record. A stage is a band across the map: a
   number in the left rail, a name typed straight into the line, and the
   LANE the work streams run in. It has no bubble of its own, no fields, no
   popup — it exists to give the map somewhere to put things and an order to
   read them in. Everything worth saying about a phase belongs to the work
   streams inside it.
   ──────────────────────────────────────────────────────── */
/* A STAGE IS A BLOCK YOU CAN SEE THE EDGES OF. It used to be a hairline rule
   with work loosely under it, and once a stage held more than one ROW of work
   streams (see the lane, below) you could no longer tell where one phase ended
   and the next began — the map read as one long field of cards with numbers
   scattered down the side of it. So the stage now owns a panel: its own
   surface, its own border, a tinted title bar and a teal cap across the top.
   Read the map at arm's length and the phases are the first thing you see. */
.wkt-srow { display: flex; gap: 14px; padding: 0 0 22px; }
/* The rail: the number, and the line that carries the eye to the next stage. */
.wkt-srow-rail {
  flex: 0 0 34px;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding-top: 10px;
}
.wkt-srow-num {
  width: 30px; height: 30px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 800;
  color: #0f766e; background: var(--wkt-surf);
  border: 1.5px solid rgba(15,118,110,.32);
  box-shadow: var(--shadow-sm);
}
.wkt-srow-num--loose { color: var(--wkt-ink-4); border-color: var(--wkt-line); font-size: 18px; }
/* The through-line. Drawn on the rail, stopped at the last stage. */
.wkt-srow-rail::after {
  content: ''; flex: 1; width: 2px; min-height: 12px;
  background: linear-gradient(180deg, rgba(15,118,110,.28), rgba(15,118,110,.06));
  border-radius: 2px;
}
.wkt-srow:last-child .wkt-srow-rail::after,
.wkt-srow:has(+ .wkt-stageseam:last-child) .wkt-srow-rail::after { background: linear-gradient(180deg, rgba(148,163,184,.24), transparent); }
/* The panel. Nothing is clipped (the hover Edit / Remove pair rides on the seam
   under a card and has to be allowed out of the lane), so the rounding is put
   on the head and the lane instead of on an overflow:hidden wrapper. */
.wkt-srow-main {
  flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0;
  background: var(--wkt-surf);
  border: 1px solid #d8e2ec; border-radius: var(--wkt-r-md);
  box-shadow: var(--shadow-sm), 0 10px 24px -18px rgba(15,23,42,.35);
}
/* The cap: a stage's colour, and the thing that says "a new one starts here"
   from across the room. */
.wkt-srow-main::before {
  content: ''; display: block; flex: 0 0 auto; height: 3px;
  border-radius: var(--wkt-r-md) var(--wkt-r-md) 0 0;
  background: linear-gradient(90deg, #0f766e, rgba(15,118,110,.14));
}
/* The line itself: name, rule, and the ⋯ that adds a stage above or below.
   Now a title BAR — tinted, ruled off the lane — rather than a line floating
   above loose cards. */
.wkt-srow-head {
  display: flex; align-items: center; gap: 10px; min-height: 30px;
  padding: 9px 14px;
  background: #f5f9fc;
  border-bottom: 1px solid var(--wkt-line);
}
.wkt-srow-name {
  font-size: 15px; font-weight: 800; color: var(--wkt-ink);
  letter-spacing: -.01em;
  border: 0; background: transparent; padding: 3px 6px; margin-left: -6px;
  border-radius: var(--wkt-r); min-width: 120px; max-width: 340px;
  font-family: inherit;
}
.wkt-srow-name::placeholder { color: var(--wkt-ink-4); font-weight: 700; }
.wkt-srow-name:hover { background: rgba(15,23,42,.04); }
.wkt-srow-name:focus { outline: none; background: var(--wkt-surf); box-shadow: 0 0 0 2px rgba(15,118,110,.35); }
.wkt-srow-name.is-static { padding-left: 0; margin-left: 0; }
.wkt-srow-name.is-loose { color: var(--wkt-ink-4); font-size: 12px; text-transform: uppercase; letter-spacing: .09em; }
.wkt-srow-rule { flex: 1; height: 1px; background: linear-gradient(90deg, var(--wkt-line), rgba(219,227,236,.25)); }
.wkt-srow-kebab,
.wkt-srow-trash {
  flex: 0 0 auto; width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: var(--wkt-r); cursor: pointer;
  color: var(--wkt-ink-4); background: transparent;
}
.wkt-srow-kebab:hover { color: var(--wkt-ink); background: rgba(15,23,42,.06); }
/* The head's 10px gap is for name-vs-rule-vs-controls; the two controls are a
   pair and sit closer, without touching. */
.wkt-srow-trash + .wkt-srow-kebab { margin-left: -6px; }
/* One click, no menu, no dialog. It goes red only under the cursor, so a stage
   line reads as a line — not as a row with a warning parked on the end of it. */
.wkt-srow-trash:hover { color: #dc2626; background: rgba(220,38,38,.10); }
.wkt-srow-trash:active { background: rgba(220,38,38,.18); }
/* Both controls stay on EVERY stage, dimmed. Revealing them only on hover kept
   a busy page quiet, but it also hid the only way to delete a stage behind a
   gesture you had to already know about. Dimmed keeps the lane calm; they go
   solid on the row you're pointing at. */
.wkt-srow-kebab,
.wkt-srow-trash { opacity: .5; transition: opacity .12s ease, color .12s ease, background .12s ease; }
.wkt-srow:hover .wkt-srow-kebab,
.wkt-srow:hover .wkt-srow-trash,
.wkt-srow:focus-within .wkt-srow-kebab,
.wkt-srow:focus-within .wkt-srow-trash,
.wkt-srow-kebab:hover,
.wkt-srow-trash:hover,
.wkt-srow-kebab:focus-visible,
.wkt-srow-trash:focus-visible { opacity: 1; }

/* ── Collapse a stage ─────────────────────────────────────
   The button sits right after the stage name, so the line reads as a sentence:
   ① Discovery — Hide 2 work streams. A shut stage keeps its number and its name
   and drops the lane, and the button itself says what came off screen. */
.wkt-srow-head > .wkt-foldpill { margin-left: 2px; }
.wkt-srow.is-folded .wkt-srow-lane { display: none; }
.wkt-srow.is-folded { padding-bottom: 8px; }

/* ── + Stage, in the seam between two stages ──────────────
   NOT part of either panel. A stage is a band across the map; the gap under it
   belongs to no phase, and that gap is what "put one here" means. On the
   panel's foot the same button read as an add INSIDE that stage — the tier
   below, next to + Work stream — which is the opposite of what it does.

   It is the toolbar's old small green + Stage pill, at every boundary instead
   of once at the top, and it lines up with the dashed ＋ New stage rail a drag
   paints on this same line: both start 48px in, past the number rail. */
.wkt-stageseam {
  display: flex; align-items: center;
  padding: 0 0 22px 48px;
  /* Ride IN the gap the band above already leaves rather than adding to it, so
     putting a button on every seam doesn't stretch the map out. */
  margin-top: -16px;
}
/* Full strength, on every seam. It is the toolbar's button, unchanged — dimming
   it until you hover the right boundary would put the one add on the map behind
   a gesture you have to already know about, which is most of what was wrong
   with having it in one place. */
.wkt-stageseam-btn { box-shadow: 0 1px 2px rgba(15,118,110,.28); }
/* A drag paints its own ＋ New stage on these lines — see wkt-is-dragging. */
.wkt-is-dragging .wkt-stageseam { opacity: 0; pointer-events: none; }
/* The standalone one — a plan with no stages on it at all (an old template, or
   one emptied out). Nothing above it to ride under, and nothing else on the map
   to press, so it stands at full strength in its own space. */
.wkt-stageseam--first { margin-top: 0; }

/* ── Hover-only Edit / Remove ─────────────────────────────
   A Remove button parked permanently on every work stream and every
   deliverable is a delete you can hit while reading, and four streams side by
   side turned the map into a wall of grey buttons. They belong to the thing
   you're pointing at.

   OUT OF FLOW, both tiers (see the two placement rules further down). They used
   to be laid out: reserved space at the end of a deliverable's row, which cost
   every deliverable in the map ~130px of card width to hold a slot that is
   empty until you point at it. Absolute costs nothing and reflows nothing.

   HIDDEN, not just transparent. An opacity-0 button still takes clicks, so the
   old rule left an invisible Remove parked on the seam of every card — a delete
   you could hit without ever seeing it. `visibility` + `pointer-events` make
   the thing genuinely absent until it is genuinely on screen.

   `.wkt-acts:hover` is what keeps it up once it IS on screen. The pill
   overhangs the top edge of the card that reveals it, so the moment the cursor
   travels onto that overhang the card's own :hover stops matching. The pill
   sustaining its own hover is the bridge — and it can only ever match while
   already revealed, because `pointer-events: none` makes it unhoverable at
   rest.

   THE CARD IS THE TRIGGER, not the column. Pointing anywhere in a work stream
   used to light the stream's pair, so hovering a deliverable inside an open
   stream put TWO of these on screen at once — one on the deliverable and one
   on the card above it, neither obviously the one you were aiming at. Each
   card now answers only for itself. */
.wkt-acts {
  opacity: 0; visibility: hidden; pointer-events: none;
  transform: translateY(3px);
  transition: opacity .13s ease, transform .13s ease, visibility 0s linear .13s;
}
.wkt-wscol > .ep-plan-group > .ep-plan-group-head:hover .wkt-acts,
.wkt-wscol > .ep-plan-group > .ep-plan-group-head:focus-within .wkt-acts,
.ep-plan-delivblock > .ep-plan-delivblock-head:hover .wkt-acts,
.ep-plan-delivblock > .ep-plan-delivblock-head:focus-within .wkt-acts,
.wkt-acts:hover,
.wkt-acts:focus-within {
  opacity: 1; visibility: visible; pointer-events: auto;
  transform: none;
  transition-delay: 0s;
}
/* Touch has no hover — never hide an action behind a gesture that device
   doesn't have. */
@media (hover: none) {
  .wkt-acts { opacity: 1; visibility: visible; pointer-events: auto; transform: none; }
}

/* ── The pill ─────────────────────────────────────────────
   ONE piece of chrome, in ONE place, whatever it is attached to: a work stream
   and a deliverable both get the same two verbs in the same corner of the same
   kind of card, so the gesture is learned once. Two loose buttons sitting on
   the page read as debris; grouped on a single raised surface they read as a
   toolbar that belongs to the card under them. */
.wkt-plan .wkt-acts {
  display: inline-flex; align-items: center; gap: 0;
  padding: 3px;
  border: 1px solid #e7ecf3; border-radius: var(--wkt-r);
  background: var(--wkt-surf);
  box-shadow: 0 6px 16px rgba(15, 23, 42, .13), 0 1px 3px rgba(15, 23, 42, .07);
}
/* The buttons stop being buttons and become items in the pill — the pill is
   the object with an edge now, so a border on each one inside it is a box in a
   box. (Longhand font properties: the `font: … inherit` shorthand this file is
   full of is illegal and gets dropped whole.) */
.wkt-plan .wkt-acts > .ep-btn {
  height: 22px; padding: 0 9px;
  display: inline-flex; align-items: center;
  border: 0; border-radius: var(--wkt-r);
  background: transparent; box-shadow: none;
  font-family: inherit; font-size: 11px; font-weight: 600; line-height: 1;
  letter-spacing: .01em; white-space: nowrap;
  color: var(--wkt-ink-2);
  transition: background .12s ease, color .12s ease;
}
.wkt-plan .wkt-acts > .ep-btn:hover { background: var(--wkt-line-soft); color: var(--wkt-ink); }
.wkt-plan .wkt-acts > .ep-btn.ep-btn-danger { color: #dc2626; }
.wkt-plan .wkt-acts > .ep-btn.ep-btn-danger:hover { background: #fef2f2; color: #b91c1c; }
.wkt-plan .wkt-acts > .ep-btn:focus-visible { outline: 2px solid #6366f1; outline-offset: 1px; }
/* A hairline between them. Remove is the destructive half of the pair and has
   to read as its own decision, not as the right-hand end of Edit. */
.wkt-plan .wkt-acts > .ep-btn + .ep-btn { position: relative; margin-left: 5px; }
.wkt-plan .wkt-acts > .ep-btn + .ep-btn::before {
  content: ''; position: absolute; left: -3px; top: 3px; bottom: 3px;
  width: 1px; background: #e7ecf3;
}
/* A WORK STREAM'S ONE VERB, AS A BIN. The card opens itself now, so there is
   no Edit to sit beside — and a pill containing the single word "Remove" is
   wider than the card's whole title well for a control that only has to be
   recognisable. The glyph is the same bin a stage wears (_trashSvgHTML), so
   "delete this" looks like one thing at both tiers.

   A DISC, WITH ITS OWN SURFACE. It sits INSIDE the card now, in the corner
   where the footer's "0/1 deliverables delivered" ends (see the placement rule
   further down) — so it has to be opaque and it has to have an edge, or a bin
   would print straight over that line and read as neither. White fill, hairline
   ring, one soft shadow: it lands ON the card the way the fold chevron lands on
   the seam, and lifts off again the moment you stop pointing.

   Grey at rest and red only under the cursor, because a permanently red thing
   in the corner of every card in a four-stream lane is an alarm nobody is
   sounding. */
.wkt-plan .wkt-acts > .wkt-ws-trash {
  width: 24px; height: 24px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid #e6ebf2; border-radius: var(--wkt-r-pill);
  background: var(--wkt-surf);
  box-shadow: 0 2px 6px rgba(15, 23, 42, .13);
  color: var(--wkt-ink-3); cursor: pointer;
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.wkt-plan .wkt-acts > .wkt-ws-trash svg { display: block; }
.wkt-plan .wkt-acts > .wkt-ws-trash:hover { background: #fef2f2; border-color: #fecaca; color: #dc2626; }
.wkt-plan .wkt-acts > .wkt-ws-trash:active { background: #fee2e2; color: #b91c1c; }
.wkt-plan .wkt-acts > .wkt-ws-trash:focus-visible { outline: 2px solid #dc2626; outline-offset: 1px; }
/* Growing a row / column in (and collapsing one out) animates a measured
   max-height / max-width, so it has to clip while it runs. */
.wkt-srow.is-entering, .wkt-wscol.is-entering { overflow: hidden; }

/* ── The lane ─────────────────────────────────────────────
   Work streams sit SIDE BY SIDE, left to right in priority order — that is
   what the stage is for. More than fits, and the lane scrolls sideways
   rather than stacking, because stacking is the thing the stage replaced. */
/* The padding is HEADROOM: sideways scrolling forces `overflow-y: hidden` on
   this box, so anything a column hangs outside itself gets clipped at this
   edge — and the Edit / Remove pill straddles the top edge of every card in
   the lane. The top is 26px for that reason and the negative margin does NOT
   grow to match it: the extra 18px stays as real space, so the first row of
   cards starts clear of the stage's title bar and the pill has somewhere to be
   that isn't on top of it. Pulling the lane further up instead would have cost
   nothing in layout and taken the bottom few pixels of the fold pill's hit
   area with it — the lane's own empty padding, sitting over the bar. */
.wkt-srow-lane {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 26px 8px 8px; margin: -8px;
  overflow-x: auto; overflow-y: hidden;
  border-radius: var(--wkt-r-md);
  scrollbar-width: thin;
}
.wkt-srow-lane::-webkit-scrollbar { height: 8px; }
.wkt-srow-lane::-webkit-scrollbar-thumb { background: var(--wkt-line-strong); border-radius: 4px; }
/* Dragging a work stream over a stage lights the whole BAND up — you aim at a
   stage, so the stage is what has to answer, not a strip inside it. */
.wkt-srow.wkt-lane-drop { background: rgba(15,118,110,.045); border-radius: var(--wkt-r-md); }
.wkt-srow.wkt-lane-drop .wkt-srow-num { border-color: #0f766e; background: #0f766e; color: var(--wkt-surf); }
.wkt-srow.wkt-lane-drop .wkt-srow-lane {
  background: rgba(15,118,110,.06);
  outline: 2px dashed rgba(15,118,110,.5);
  outline-offset: -3px;
}
.wkt-lane-empty { font-size: 13px; color: var(--wkt-ink-4); padding: 6px 2px; }
/* ── Dragging a whole STAGE ───────────────────────────
   The band is its own grip: the number on the rail, and the title bar beside
   it. Everything IN that bar which does something else — the name field, the
   fold pill, the ⋯ / trash — keeps its own cursor, so the row still reads as
   type-here / press-here while it is also a handle. */
.wkt-srow.is-draggable > .wkt-srow-rail,
.wkt-srow.is-draggable > .wkt-srow-main > .wkt-srow-head { cursor: grab; }
.wkt-srow.is-draggable > .wkt-srow-main > .wkt-srow-head:active { cursor: grabbing; }
.wkt-srow.is-draggable > .wkt-srow-main > .wkt-srow-head input { cursor: text; }
.wkt-srow.is-draggable > .wkt-srow-main > .wkt-srow-head button,
.wkt-srow.is-draggable > .wkt-srow-main > .wkt-srow-head a { cursor: pointer; }
.wkt-srow-dragging { opacity: .5; }
/* While anything is in flight the stage rows stand their buttons down. They
   cannot be pressed mid-drag anyway, and the merge tag needs the end of the
   title bar to itself. */
.wkt-is-dragging .wkt-srow-kebab,
.wkt-is-dragging .wkt-srow-trash { opacity: 0; pointer-events: none; }

/* The stage a dragged phase is about to be merged INTO. The ring goes round the
   whole panel — you are dropping a phase into a phase, so the phase is what has
   to answer, not a strip inside it — and its title bar prints what the drop will
   do. Same teal and same pill as the seam rail, because it is one gesture
   answering two questions: between the bands is "move it here", on a band is
   "fold it into this one". */
.wkt-srow.wkt-stage-merge > .wkt-srow-main {
  outline: 2px dashed rgba(15,118,110,.55);
  outline-offset: 2px;
  background: rgba(15,118,110,.05);
}
.wkt-srow.wkt-stage-merge .wkt-srow-num { border-color: #0f766e; background: #0f766e; color: var(--wkt-surf); }
.wkt-srow.wkt-stage-merge .wkt-srow-head::after {
  content: attr(data-wkt-merge);
  flex: 0 0 auto;
  font-size: 12px; font-weight: 800; letter-spacing: .02em;
  color: var(--wkt-surf); background: #0f766e;
  padding: 3px 9px; border-radius: var(--wkt-r-pill);
  box-shadow: 0 2px 6px rgba(15,118,110,.35);
  white-space: nowrap;
}

/* ── The seam between two stages ──────────────────────
   Let a work stream go in the gap between two stage bands and the phase it
   belongs to gets created there (see _seamAt in work-templates.js). This is the
   rail that says so, drawn on the boundary the stage will land on.

   ABSOLUTE, and pointer-events: none. An indicator that opened a real gap would
   push the rows out from under the cursor, which moves the pointer out of the
   band that was showing it — the drop target would blink itself off. This one
   changes no layout and swallows no events, so the row underneath still answers
   the drag. .ep-plan-groups is the offset parent it is measured against. */
.wkt-plan .ep-plan-groups { position: relative; }
.wkt-seam {
  position: absolute; left: 0; right: 0; top: 0; height: 0; z-index: 4;
  display: flex; align-items: center; gap: 10px;
  padding-left: 48px;                 /* clears the number rail (34px) + its gap (14px) */
  transform: translateY(-50%);
  pointer-events: none;
}
.wkt-seam-tag {
  flex: 0 0 auto;
  /* LIFTED off the line, into the padding the row above ends with: the boundary
     between two bands sits ~2px above the lower one's head, so a label centred
     on it would print straight over that stage's name.
     11px, NOT 14 — the tag is 19px tall and the tightest the band ever gets is
     17px either side of the line (SEAM_BAND in work-templates.js, which is what
     applies once the pointer is inside a stage panel; out in the gutter it is
     SEAM_GUTTER and the pill is nowhere near the edge of it). At 14 the top
     third of the pill sat outside the zone it was advertising; at 11 all but
     ~3px of it is live, and it still clears the name below.
     _seamAt() also holds the seam open across the tag's whole drawn rect, so
     the two can't drift apart again. */
  position: relative; top: -11px;
  font-size: 12px; font-weight: 800; letter-spacing: .02em;
  color: var(--wkt-surf); background: #0f766e;
  padding: 3px 9px; border-radius: var(--wkt-r-pill);
  box-shadow: 0 2px 6px rgba(15,118,110,.35);
  white-space: nowrap;
}
.wkt-seam-line {
  flex: 1; height: 0;
  border-top: 2px dashed rgba(15,118,110,.6);
}
.wkt-seam.is-on { animation: wkt-seam-in .14s ease both; }
@keyframes wkt-seam-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .wkt-seam.is-on { animation: none; } }

/* The name of a stage that appeared because a work stream was dropped between
   two others — nobody asked for it by name, so it asks for one. The caret is
   already in it; this is what makes that visible when your eye is still on the
   column you just moved. It stops asking the moment you type. */
.wkt-srow-name.is-asking {
  background: var(--wkt-surf);
  box-shadow: 0 0 0 2px rgba(15,118,110,.45);
  animation: wkt-ask 1.1s ease-in-out 2;
}
@keyframes wkt-ask {
  0%, 100% { box-shadow: 0 0 0 2px rgba(15,118,110,.45); }
  50%      { box-shadow: 0 0 0 4px rgba(15,118,110,.18); }
}
@media (prefers-reduced-motion: reduce) { .wkt-srow-name.is-asking { animation: none; } }

/* One work stream = one column. Fixed width so two streams read as two
   columns rather than one wide row and one narrow one. */
.wkt-wscol {
  position: relative;
  flex: 0 0 404px; width: 404px; max-width: 88vw;
  /* A card is as tall as what's in it. Stretching every column to the tallest
     one made sense when they all showed everything; now that a stream is shut
     until you open it, it meant opening ONE stream inflated the three beside it
     into empty white boxes. */
  align-self: flex-start;
}
.wkt-wscol--direct { flex-basis: 372px; width: 372px; }
/* The shared work-stream header is built for a full-width row: title, meta,
   progress and actions all on one line. In a column that line has a third of
   the room, so it WRAPS here — name and meta claim the row, progress and the
   Edit / Remove pair drop underneath — rather than colliding. */
.wkt-wscol .ep-plan-group-head { flex-wrap: wrap; gap: 8px 10px; padding-right: 14px; }
.wkt-wscol .ep-plan-group-info { flex: 1 1 100%; }
.wkt-wscol .ep-plan-group-meta { flex-wrap: wrap; row-gap: 1px; }
.wkt-wscol .ep-plan-group-progress { min-width: 0; flex: 1 1 auto; }
/* Same story one tier down. The shared deliverable / task card is a row —
   name on the left, due date and avatar on a rail to the right — and in a
   column that rail squeezed the name to literally zero pixels wide. Here the
   card STACKS: the name takes the full width, everything else drops under it.
   Column-scoped, so the live plan's cards are untouched. */
.wkt-wscol .mw-task-card { flex-wrap: wrap; }
.wkt-wscol .mw-card-left { flex: 1 1 100%; padding-bottom: 4px; }
.wkt-wscol .mw-card-content { min-width: 0; }
.wkt-wscol .mw-task-card-title { white-space: normal; overflow: visible; text-overflow: clip; }
.wkt-wscol .mw-card-desc { white-space: normal; -webkit-mask-image: none; mask-image: none; }
.wkt-wscol .mw-card-right {
  flex: 1 1 100%; justify-content: flex-start; flex-wrap: wrap; row-gap: 6px;
  padding: 0 16px 13px 16px;
}
.wkt-wscol .mw-card-right::before { display: none; }
/* The deliverable's Proposed → In progress → Delivered → Accepted track needs
   ~320px and a column has ~210: it ran off the card's right edge, half a word
   at a time. It wraps to two rows here. */
.wkt-wscol .wk-deliv-track { flex-wrap: wrap; row-gap: 4px; }

/* ────────────────────────────────────────────────────────
   THE STREAM WEARS THE CARD IT BECOMES — IN EVERY MODE
   A work stream is the WORK-STREAM CARD: the same component, markup and rules
   the Work Streams grid draws on a live project, built by
   WkCards.workstreamPreview from the template's own items. So "what will this
   look like when I apply it" is answered by looking, not by imagining.

   AND EDIT MODE IS THE SAME PICTURE. It used to draw the builder's own header —
   name as text, a fold pill, an owner face — so the map you arranged looked
   nothing like the map you were arranging it into, and the mode switch repainted
   every column into a different object. Now the two are identical at rest, and
   Edit adds only what hides until you point at it: the Edit / Remove pair on the
   seam under the card, and the grip at its top-left corner.

   The card REPLACES the header (one title, and it belongs on the card) and
   clicking it opens the stream's popup — the deliverables are read in there,
   never underneath. Everything below is layout only: the card's own look comes
   from work.css + engagement-profile.css, unedited, because a builder that
   restated those rules would be a copy that drifts.
   ──────────────────────────────────────────────────────── */
/* No frame around the frame. The card's own border IS the stream's edge, so the
   group shell steps back to being a container for what's inside. */
.wkt-wscol--card > .ep-plan-group {
  border: 0; background: transparent; overflow: visible;
}
/* The header is the card and nothing else: no gradient, no padding, no rule
   underneath, no flex row trying to lay out children it no longer has. */
.wkt-wscol > .ep-plan-group > .wkt-wscard-head,
.wkt-wscol > .ep-plan-group > .wkt-wscard-head:hover {
  display: block; padding: 0; gap: 0;
  background: none; border-bottom: 0;
}
/* The one-card grid the tuned card rules hang off (see _wsCardHead). */
.wkt-wscard-grid { margin-bottom: 0; grid-template-columns: minmax(0, 1fr); gap: 0; }
/* THE BIN, IN THE CARD'S BOTTOM-RIGHT CORNER — and INSIDE it, all of it.

   It straddled the top edge before, half on the card and half on the page
   above it. Anything that overhangs an edge belongs to two things at once: it
   read as chrome floating over the lane rather than as this card's own
   control, and on the top row of a stage the overhang crossed the stage line.
   Fully inside, in a corner, it is unambiguously part of the rectangle it
   deletes.

   BOTTOM-right, not top-right, and that corner is not empty: the card's footer
   ends there with "0/1 deliverables delivered". So the footer line GETS OUT OF
   THE WAY — see the .wk-goal-task-summary rule below, which pads it clear for
   exactly as long as the button is on screen. Parking a bin on top of a
   sentence and calling it a corner would have been the easy version of this.

   z-index 70, and the number is not free: a hovered card raises ITSELF to 60
   (.wk-goal-card:hover in work.css, .ep-project-card:hover in
   engagement-profile.css) — and the card under this button is hovered every
   single time the button is on screen. Anything meant to sit on top of one has
   to clear 60 or it prints underneath and disappears entirely.

   The wrapper keeps NO surface of its own here. Its pill (border, background,
   drop shadow — see `.wkt-plan .wkt-acts`) exists to gather Edit + Remove into
   one raised toolbar, and a work stream has neither any more: a bordered white
   pill wrapping a single bordered white disc is a box in a box. The deliverable
   tier still has the pair, so the pill rule stays for it. */
.wkt-wscol > .ep-plan-group > .wkt-wscard-head > .wkt-acts {
  position: absolute; right: 10px; bottom: 10px; top: auto; z-index: 70;
  padding: 0; border: 0; background: none; box-shadow: none;
}
/* THE FOOTER LINE STEPS ASIDE. "0/1 deliverables delivered" is right-aligned in
   the same corner the bin lands in, so the card makes room for the button for
   exactly as long as the button is there, and takes it straight back. Padding
   rather than margin or a width, so the text simply ends 30px sooner and
   nothing about the footer's layout changes; transitioned on the same .13s as
   the reveal, so the two read as one movement instead of a nudge.

   The selector list is the reveal's, one for one (see .wkt-acts above): the
   head's :hover and :focus-within, plus the button sustaining its own hover —
   the disc overhangs nothing now, but a cursor resting ON it must not let the
   sentence slide back underneath it. Scoped through .wkt-wscard-head so a work
   stream card on a LIVE plan, which has no bin, is untouched. */
.wkt-wscol > .ep-plan-group > .wkt-wscard-head .wk-goal-task-summary {
  transition: padding-right .13s ease;
}
.wkt-wscol > .ep-plan-group > .wkt-wscard-head:hover .wk-goal-task-summary,
.wkt-wscol > .ep-plan-group > .wkt-wscard-head:focus-within .wk-goal-task-summary {
  padding-right: 30px;
}
/* Touch has no hover, so the bin is always up — and the line is always short. */
@media (hover: none) {
  .wkt-wscol > .ep-plan-group > .wkt-wscard-head .wk-goal-task-summary { padding-right: 30px; }
}
/* THE SAME PLACE ON A DELIVERABLE. It was laid out AFTER the card, as the last
   item of the deliverable's flex row — which is why it appeared out to the
   right, and why every deliverable card in the map was ~130px narrower than
   its column to keep a slot that is empty until you point at it. Absolute and
   on the top edge: identical gesture, identical corner, one tier down, and the
   card gets the whole column back. */
.wkt-plan .ep-plan-delivblock > .ep-plan-delivblock-head { position: relative; }
.wkt-plan .ep-plan-delivblock > .ep-plan-delivblock-head > .ep-plan-delivblock-acts {
  position: absolute; right: 8px; top: -13px; z-index: 70;
}
/* NOTHING SITS UNDER THE CARD. The stream's body is rendered empty (see
   noGroupBody in work-templates.js) and takes no room, so a lane of streams is
   a row of cards at one height instead of columns that grow to whatever each
   one was holding.

   It keeps its box for exactly one reason: a deliverable left loose by an old
   template is dragged onto a stream by aiming at the card, and this is what
   catches it. So it opens to a landing strip while a drag is over it, and
   shuts again the moment the deliverable is inside the stream — where it is
   read from then on. */
.wkt-wscol--card > .ep-plan-group > .ep-plan-group-body {
  padding: 0; gap: 0; min-height: 0;
}
.wkt-wscol--card > .ep-plan-group > .ep-plan-group-body.ep-plan-drop-into {
  min-height: 34px; margin-top: 8px;
}
.wkt-wscol--card > .ep-plan-group > .ep-plan-group-body::before { display: none; }
.wkt-wscol-grip {
  position: absolute; top: 9px; left: -3px; z-index: 3;
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 22px; border-radius: 4px;
  color: var(--wkt-line-strong); cursor: grab; opacity: 0;
  transition: opacity .12s ease;
}
.wkt-wscol:hover .wkt-wscol-grip { opacity: 1; }
.wkt-wscol-grip:hover { color: #6366f1; background: rgba(99,102,241,.1); }
.wkt-wscol-grip:active { cursor: grabbing; }
.wkt-wscol-grip svg { fill: currentColor; }
.wkt-wscol-dragging { opacity: .55; }
/* The whole top of a column is the handle. Hover anywhere on a work stream's
   header and the cursor says "pick this up" — you shouldn't have to find a
   16px grip in the corner to move a stream between stages. The header is still
   a click target (it opens the stream), so the Edit / Remove buttons keep the
   pointer and a press that doesn't move still reads as a click. */
.wkt-wscol.is-draggable > .ep-plan-group > .ep-plan-group-head { cursor: grab; }
.wkt-wscol.is-draggable > .ep-plan-group > .ep-plan-group-head:active { cursor: grabbing; }
.wkt-wscol.is-draggable > .ep-plan-group > .ep-plan-group-head button,
.wkt-wscol.is-draggable > .ep-plan-group > .ep-plan-group-head a { cursor: pointer; }
/* Hovering anywhere on the column lights the grip, so the corner handle reads
   as a marker for "this whole top edge is grabbable" rather than as the only
   way in. */
.wkt-wscol.is-draggable:hover .wkt-wscol-grip { opacity: 1; }
/* The priority the column's slot stands for — position IS priority here, so
   the badge is a read-out of where it sits, not a second control. */
.wkt-wscol-prio {
  position: absolute; top: -7px; right: 10px; z-index: 3;
  padding: 1px 8px; border-radius: var(--wkt-r-lg);
  font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .07em;
  color: var(--wkt-surf); background: var(--wkt-ink-4);
  box-shadow: var(--shadow-sm);
}
.wkt-wscol-prio--critical { background: #dc2626; }
.wkt-wscol-prio--high     { background: #ea580c; }
.wkt-wscol-prio--medium   { background: var(--wkt-ink-3); }
.wkt-wscol-prio--low      { background: var(--wkt-ink-4); }
/* The + at the end of every lane. A ghost column, so adding a stream reads as
   "one more of these" rather than a button off to the side. */
/* TWO routes, one ghost: a blank stream, or one lifted out of the library with
   the deliverables and tasks it already owns. Stays a direct child of the lane
   (the drag code inserts columns before it), so the two buttons live INSIDE it
   rather than in a wrapper. */
.wkt-wscol-ghost {
  /* flex-start, like the columns: an open stream shouldn't stretch the ghost
     into a two-inch dashed rectangle. */
  flex: 0 0 168px; align-self: flex-start; min-height: 108px;
  display: flex; flex-direction: column; align-items: stretch; justify-content: center; gap: 4px;
  padding: 8px;
  border: 1.5px dashed var(--wkt-line-strong); border-radius: var(--wkt-r-md);
  background: transparent;
  color: var(--wkt-ink-3); font-size: 13px; font-weight: 700; font-family: inherit;
  transition: border-color .12s, background .12s;
}
.wkt-wscol-ghost:hover { border-color: #4f46e5; background: rgba(79,70,229,.04); }
.wkt-wsghost-new, .wkt-wsghost-lib {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  border: 0; border-radius: var(--wkt-r); background: transparent; cursor: pointer;
  font-family: inherit; font-weight: 700; color: inherit;
}
.wkt-wsghost-new { flex: 1 1 auto; font-size: 13px; padding: 6px; }
.wkt-wsghost-new:hover { color: #4f46e5; background: rgba(79,70,229,.07); }
.wkt-wsghost-lib {
  flex: 0 0 auto; flex-direction: row; gap: 5px;
  padding: 5px 6px; font-size: 11px; color: #7c3aed;
  border-top: 1px dashed var(--wkt-line); border-radius: 0 0 var(--wkt-r) var(--wkt-r);
}
.wkt-wsghost-lib:hover { background: rgba(124,58,237,.08); }
.wkt-wscol-ghost-plus { font-size: 20px; line-height: 1; font-weight: 400; }

/* ── Stage context menu ───────────────────────────────────
   Right-click a stage (or hit its ⋯): add a line above, add a line below,
   take this one out. Structural moves only — there is nothing else a stage
   can do. */
.wkt-ctxmenu {
  position: fixed; z-index: 2000200;
  min-width: 208px; padding: 5px;
  background: var(--wkt-surf); border: 1px solid var(--wkt-line); border-radius: var(--wkt-r);
  box-shadow: 0 16px 40px rgba(15,23,42,.22);
}
.wkt-ctxmenu-item {
  display: flex; flex-direction: column; gap: 1px;
  width: 100%; text-align: left;
  padding: 8px 10px; border: 0; border-radius: var(--wkt-r);
  background: transparent; cursor: pointer;
  font-family: inherit; font-size: 13px; font-weight: 600; color: var(--wkt-ink);
}
.wkt-ctxmenu-item:hover { background: var(--wkt-hover); }
.wkt-ctxmenu-item.is-danger { color: #b91c1c; }
.wkt-ctxmenu-item.is-danger:hover { background: #fef2f2; }
.wkt-ctxmenu-note { font-size: 11px; font-weight: 500; color: var(--wkt-ink-4); }

.wkt-plan { display: flex; flex-direction: column; gap: 16px; }
.wkt-plan-group {
  background: var(--wkt-surf); border: 1px solid var(--wkt-line); border-radius: var(--wkt-r-md); overflow: hidden;
}
.wkt-plan-group-head {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px 12px 0; position: relative; cursor: default;
  background: linear-gradient(90deg, rgba(99,102,241,.06), transparent 60%);
}
.wkt-plan-group--orphan .wkt-plan-group-head { background: var(--wkt-tint); }
.wkt-plan-group-rail { width: 4px; align-self: stretch; background: #6366f1; border-radius: 0 4px 4px 0; flex-shrink: 0; }
.wkt-plan-group--orphan .wkt-plan-group-rail { background: var(--wkt-line-strong); }
.wkt-plan-group-info { flex: 1; min-width: 0; }
.wkt-plan-group-title { font-size: 14px; font-weight: 700; color: var(--wkt-ink); }
.wkt-plan-group-meta { font-size: 12px; color: var(--wkt-ink-3); margin-top: 1px; }
.wkt-plan-group-acts { display: flex; align-items: center; gap: 6px; padding-right: 12px; }
.wkt-plan-group-body { padding: 10px 14px 14px; display: flex; flex-direction: column; gap: 8px; }
.wkt-plan-group-empty { font-size: 13px; color: var(--wkt-ink-4); padding: 8px 4px; font-style: italic; }

.wkt-plan-card {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--wkt-surf); border: 1px solid var(--wkt-line); border-radius: var(--wkt-r); padding: 10px 12px;
  cursor: pointer; transition: border-color .12s, box-shadow .12s, transform .12s;
}
.wkt-plan-card:hover { border-color: #6366f1; box-shadow: 0 6px 18px -10px rgba(15,23,42,.25); transform: translateY(-1px); }
.wkt-plan-card-check {
  width: 16px; height: 16px; margin-top: 1px; border-radius: 50%;
  border: 2px solid var(--wkt-line-strong); flex-shrink: 0;
}
.wkt-plan-card-main { flex: 1; min-width: 0; }
.wkt-plan-card-title { font-size: 14px; font-weight: 600; color: var(--wkt-ink); line-height: 1.35; }
.wkt-plan-card-meta { font-size: 12px; color: var(--wkt-ink-3); margin-top: 3px; }
.wkt-plan-card-acts { display: flex; align-items: center; gap: 4px; opacity: 0; transition: opacity .12s; }
.wkt-plan-card:hover .wkt-plan-card-acts,
.wkt-plan-mile:hover .wkt-plan-card-acts,
.wkt-plan-group-head:hover .wkt-plan-card-acts { opacity: 1; }
.wkt-plan-iconbtn {
  width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center;
  border: 0; background: var(--wkt-hover); color: var(--wkt-ink-2); border-radius: var(--wkt-r); cursor: pointer; font-size: 12px;
}
.wkt-plan-iconbtn:hover { background: var(--wkt-line); color: var(--wkt-ink); }
.wkt-plan-iconbtn--danger:hover { background: #fee2e2; color: #dc2626; }

.wkt-plan-miles {
  background: var(--wkt-surf); border: 1px solid var(--wkt-line); border-radius: var(--wkt-r-md); padding: 12px 14px;
}
.wkt-plan-miles-head { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--wkt-ink-3); margin-bottom: 10px; }
.wkt-plan-mile {
  display: flex; align-items: center; gap: 10px; padding: 8px 4px; cursor: pointer;
  border-bottom: 1px solid var(--wkt-hover);
}
.wkt-plan-mile:last-child { border-bottom: 0; }
.wkt-plan-mile-dot { width: 10px; height: 10px; border-radius: 50%; background: #0ea5e9; flex-shrink: 0; }
.wkt-plan-mile-name { font-size: 13px; font-weight: 600; color: var(--wkt-ink); flex: 1; }
.wkt-plan-mile-date { font-size: 12px; color: var(--wkt-ink-3); }

.wkt-detail-steps { display: flex; flex-direction: column; gap: 8px; }
.wkt-detail-step {
  background: var(--wkt-surf); border: 1px solid var(--wkt-line); border-radius: var(--wkt-r);
  display: flex; align-items: stretch;
  padding: 0; overflow: hidden; cursor: pointer;
  transition: box-shadow .15s, transform .12s, border-color .15s;
}
.wkt-detail-step:hover {
  box-shadow: 0 4px 14px -4px rgba(15,23,42,.12);
  transform: translateY(-1px);
  border-color: var(--_sc, var(--wkt-line-strong));
}
.wkt-detail-step:focus-visible { outline: 2px solid var(--_sc, #4338ca); outline-offset: 2px; }
.wkt-detail-step-rail { width: 4px; background: var(--_sc, var(--wkt-ink-4)); flex-shrink: 0; }
.wkt-detail-step-mid { flex: 1; padding: 12px 14px; min-width: 0; }
.wkt-detail-step-row1 { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.wkt-detail-step-kind {
  display: inline-block; padding: 2px 8px; border-radius: 4px;
  font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
}
.wkt-detail-step-name { font-size: 14px; font-weight: 600; color: var(--wkt-ink); flex: 1; min-width: 200px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wkt-detail-step-meta { font-size: 12px; color: var(--wkt-ink-3); margin-top: 4px; line-height: 1.4; }

.wkt-detail-step-actions {
  display: flex; align-items: center; gap: 4px;
  padding: 0 10px;
  opacity: 0; transition: opacity .15s;
}
.wkt-detail-step:hover .wkt-detail-step-actions,
.wkt-detail-step:focus-within .wkt-detail-step-actions { opacity: 1; }
.wkt-detail-step-btn {
  width: 26px; height: 26px; border-radius: var(--wkt-r);
  border: 1px solid var(--wkt-line); background: var(--wkt-surf); color: var(--wkt-ink-3);
  font-size: 11px; line-height: 1; cursor: pointer;
}
.wkt-detail-step-btn:hover { background: var(--wkt-hover); color: var(--wkt-ink); }
.wkt-detail-step-btn--danger:hover { background: #fef2f2; color: #b91c1c; border-color: #fecaca; }

.wkt-detail-footer {
  display: flex; align-items: center; gap: 8px;
  padding: 14px 28px; border-top: 1px solid var(--wkt-line); background: var(--wkt-surf);
}

/* ── ⋯ overflow menu (Duplicate / Delete) in the footer ─────
   Secondary actions tucked away so they don't compete with Save / Draft. */
.wkt-detail-foot-menu { position: relative; display: inline-flex; }
.wkt-detail-kebab {
  width: 38px; height: 38px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--wkt-line); border-radius: var(--wkt-r); background: var(--wkt-surf);
  color: var(--wkt-ink-3); cursor: pointer; transition: background .15s, border-color .15s, color .15s;
}
.wkt-detail-kebab:hover { background: var(--wkt-tint); color: var(--wkt-ink); border-color: var(--wkt-line-strong); }
.wkt-detail-kebab[aria-expanded="true"] { background: var(--wkt-hover); color: var(--wkt-ink); border-color: var(--wkt-line-strong); }

/* ── Undo, bottom-left ─────────────────────────────────────
   Same 38px height and border as the ⋯ it sits beside, so the footer's left
   end reads as one group of "things you do to the template" rather than a
   button someone bolted on. It is LABELLED: a bare circular arrow is guessable
   at best, and this is the control you go looking for in a hurry.

   Nothing to undo yet → disabled, not hidden. Hiding it would move the ⋯ and
   land a live button under the cursor the moment you made your first edit.
   font-family is spelled out rather than `font: inherit` — the shorthand's
   `inherit` is invalid and browsers drop the whole declaration. */
.wkt-detail-undo {
  display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0;
  height: 38px; padding: 0 13px;
  border: 1px solid var(--wkt-line); border-radius: var(--wkt-r); background: var(--wkt-surf);
  font-family: inherit; font-size: 14px; font-weight: 700; color: var(--wkt-ink-2);
  cursor: pointer; transition: background .15s, border-color .15s, color .15s, opacity .15s;
}
.wkt-detail-undo[hidden] { display: none; }
.wkt-detail-undo:hover:not(:disabled) { background: var(--wkt-tint); color: var(--wkt-ink); border-color: var(--wkt-line-strong); }
.wkt-detail-undo:active:not(:disabled) { background: var(--wkt-hover); }
.wkt-detail-undo:disabled { opacity: .42; cursor: default; }
/* The footer is tight on a phone — the icon alone carries it there, and the
   title/aria-label still say what it is. */
@media (max-width: 560px) {
  .wkt-detail-undo { padding: 0 10px; }
  .wkt-detail-undo span { display: none; }
}

.wkt-detail-menu {
  position: absolute; bottom: calc(100% + 6px); left: 0; z-index: 5;
  min-width: 168px; padding: 6px;
  background: var(--wkt-surf); border: 1px solid var(--wkt-line); border-radius: var(--wkt-r);
  box-shadow: 0 14px 34px rgba(15,23,42,.18);
}
.wkt-detail-menu[hidden] { display: none; }
.wkt-detail-menu-item {
  display: block; width: 100%; text-align: left;
  padding: 8px 10px; border: 0; border-radius: var(--wkt-r); background: transparent;
  font: inherit; font-size: 14px; color: var(--wkt-ink-2); cursor: pointer;
}
.wkt-detail-menu-item:hover { background: var(--wkt-hover); color: var(--wkt-ink); }
.wkt-detail-menu-item--danger { color: #b91c1c; }
.wkt-detail-menu-item--danger:hover { background: #fef2f2; color: #991b1b; }

/* ── Layout fix: reserve the top-right actions strip (Edit / ✓ Done editing
   + close ×) so hero content (the category / type selects) can never slide
   UNDER it — that overlap was hiding the "Done editing" button. ───────── */
.wkt-detail-hero { padding-right: 176px; }
@media (max-width: 560px) { .wkt-detail-hero { padding-right: 108px; } }

/* Category + Type selects share one wrapping row, each sized to its content
   (not stretched full-width). */
.wkt-hero-meta-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.wkt-detail-card.is-edit .wkt-hero-cat-input { max-width: 240px; width: auto; }

/* Footer slot that hosts the shared WkAIFill "Draft with AI" button. */
.wkt-detail-draftai-slot { display: inline-flex; align-items: center; }
.wkt-detail-draftai-slot:empty { display: none; }

/* The template detail modal sits at a very high z-index (2000000). The shared
   WkAIFill "Draft with AI" prompt overlay has a base z-index of 1000020, so
   without this it would open BEHIND the template editor (invisible). Lift it
   above the whole template-modal stack (detail 2000000, miniform 2000100). */
.wk-aifill-overlay { z-index: 2000200 !important; }

/* ────────────────────────────────────────────────────────
   Plan-grid template-row accent + sibling-glow
   ──────────────────────────────────────────────────────── */
.wk-pg-card-row.is-from-template,
.pb-scope-item.is-from-template {
  position: relative;
  border-left: 3px solid var(--_tpl-color, #4f46e5);
  background: color-mix(in srgb, var(--_tpl-color, #4f46e5) 4%, transparent);
  transition: box-shadow .15s ease, background .15s ease;
}
.wk-pg-card-row.is-from-template.is-tpl-hovered,
.pb-scope-item.is-from-template.is-tpl-hovered {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--_tpl-color, #4f46e5) 60%, transparent),
              0 0 14px color-mix(in srgb, var(--_tpl-color, #4f46e5) 40%, transparent);
  background: color-mix(in srgb, var(--_tpl-color, #4f46e5) 9%, transparent);
}

/* ────────────────────────────────────────────────────────
   APPLY-TEMPLATE PICKER MODAL (Program Builder + plan-grid)
   ──────────────────────────────────────────────────────── */
/* z-index must clear the engagement-profile overlay (body-portaled popups
   there sit up to ~200000), since the picker is opened from inside it. */
/* Top-of-stack — see .wkt-detail note. The apply picker is launched from
   inside other overlays (engagement profile, plan grid, builders) and must
   render in front of every one of them, up to and past value-tracker (300000). */
.wkt-picker { position: fixed; inset: 0; z-index: 2000000; display: none; align-items: center; justify-content: center; }
.wkt-picker.is-open { display: flex; }
/* Elements toggled via the [hidden] attribute set explicit display in their own
   rules (inline-flex etc.), which would otherwise beat the UA [hidden] default.
   Force-hide them so head/toolbar/footer mode switches actually take. */
.wkt-picker [hidden] { display: none !important; }
.wkt-picker-backdrop { position: absolute; inset: 0; background: rgba(15,23,42,.55); }
.wkt-picker-card { position: relative; width: min(960px, 92vw); max-height: 88vh; background: #fff; border-radius: 14px; overflow: hidden; box-shadow: 0 20px 60px rgba(15,23,42,.3); display: flex; flex-direction: column; }
/* Directory variant — bigger canvas so the card grid breathes. */
.wkt-picker-card--dir { width: min(1120px, 95vw); height: 90vh; max-height: 90vh; border-radius: 16px; animation: wkt-popin .22s cubic-bezier(.2,.8,.2,1); }
.wkt-picker-head { display: flex; align-items: center; gap: 14px; padding: 16px 20px; border-bottom: 1px solid #eef2f7; }
.wkt-picker-head-titles { flex: 1; min-width: 0; }
.wkt-picker-title { font-weight: 800; font-size: 17px; color: #0f172a; letter-spacing: -.01em; }
.wkt-picker-sub { font-size: 12.5px; color: #64748b; margin-top: 2px; }
.wkt-picker-head-acts { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.wkt-picker-new { padding: 6px 12px; font-size: 13px; font-weight: 600; }
.wkt-picker-close { width: 32px; height: 32px; border-radius: 8px; border: 0; background: transparent; color: #64748b; cursor: pointer; font-size: 22px; line-height: 1; flex-shrink: 0; }
.wkt-picker-close:hover { background: #f1f5f9; color: #0f172a; }
/* Back chip (review mode) */
.wkt-pk-back { display: inline-flex; align-items: center; gap: 5px; height: 32px; padding: 0 12px 0 9px; border: 1px solid #e2e8f0; border-radius: 8px; background: #fff; color: #475569; font-size: 12.5px; font-weight: 600; cursor: pointer; flex-shrink: 0; }
.wkt-pk-back:hover { background: #f8fafc; color: #0f172a; border-color: #cbd5e1; }

/* Toolbar — search + category chips */
.wkt-picker-toolbar { display: flex; align-items: center; gap: 14px; padding: 12px 20px; border-bottom: 1px solid #f1f5f9; flex-wrap: wrap; }
.wkt-picker-toolbar[hidden] { display: none; }
.wkt-pk-search { display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 12px; background: #f1f5f9; border: 1px solid transparent; border-radius: 9px; color: #94a3b8; width: 300px; max-width: 100%; transition: border-color .15s, background .15s; }
.wkt-pk-search:focus-within { background: #fff; border-color: #6366f1; color: #6366f1; }
.wkt-pk-search input { border: 0; background: transparent; outline: 0; font-size: 13.5px; color: #0f172a; width: 100%; }
.wkt-pk-chips { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; flex: 1; }
.wkt-pk-chip { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 11px; border: 1px solid #e2e8f0; border-radius: 16px; background: #fff; color: #475569; font-size: 12px; font-weight: 600; cursor: pointer; transition: border-color .15s, background .15s, color .15s; }
.wkt-pk-chip:hover { border-color: #cbd5e1; background: #f8fafc; }
.wkt-pk-chip.is-active { border-color: var(--pk-chip-c, #4338ca); background: color-mix(in srgb, var(--pk-chip-c, #4338ca) 9%, #fff); color: color-mix(in srgb, var(--pk-chip-c, #4338ca) 72%, #000); }
.wkt-pk-chip-dot { width: 8px; height: 8px; border-radius: 50%; }
.wkt-pk-chip-n { font-size: 10.5px; font-weight: 700; color: #94a3b8; }
.wkt-pk-chip.is-active .wkt-pk-chip-n { color: inherit; opacity: .7; }

/* Stage — scroll area holding either the grid or the review */
.wkt-picker-stage { flex: 1; min-height: 0; overflow: auto; padding: 18px 20px; background: #fafbfc; }
.wkt-pk-grid, .wkt-pk-groups { display: block; }
.wkt-pk-grid.wkt-rp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); gap: 16px; }
.wkt-pk-groups .wkt-rp-group + .wkt-rp-group { margin-top: 22px; }
.wkt-pk-groups .wkt-rp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); gap: 16px; margin-top: 12px; }

/* Empty / no-match state */
.wkt-pk-blank { text-align: center; padding: 56px 24px; color: #64748b; }
.wkt-pk-blank-icon { width: 64px; height: 64px; margin: 0 auto 16px; border-radius: 18px; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, #6366f1, #4338ca); color: #fff; }
.wkt-pk-blank-title { font-size: 16px; font-weight: 800; color: #0f172a; }
.wkt-pk-blank-sub { font-size: 13px; margin-top: 6px; line-height: 1.6; max-width: 420px; margin-inline: auto; }

/* Review — hero + two columns */
.wkt-pk-review { max-width: 940px; margin: 0 auto; }
.wkt-pk-rev-hero { display: flex; align-items: flex-start; gap: 18px; padding: 22px 24px; border-radius: 16px; color: #fff; position: relative; overflow: hidden; }
.wkt-pk-rev-hero::before { content: ''; position: absolute; inset: 0; pointer-events: none; background: radial-gradient(circle at 18% 28%, rgba(255,255,255,.18) 0%, transparent 35%), radial-gradient(circle at 82% 78%, rgba(255,255,255,.12) 0%, transparent 40%); }
.wkt-pk-rev-hero-icon { position: relative; z-index: 1; width: 56px; height: 56px; border-radius: 14px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; background: rgba(255,255,255,.18); border: 1.5px solid rgba(255,255,255,.32); }
.wkt-pk-rev-hero-titles { position: relative; z-index: 1; flex: 1; min-width: 0; }
.wkt-pk-rev-hero-cat { display: flex; align-items: center; gap: 8px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; opacity: .95; }
.wkt-pk-rev-hero-cat .wkt-badge { background: rgba(255,255,255,.22); color: #fff; }
.wkt-pk-rev-hero-name { font-size: 21px; font-weight: 800; line-height: 1.2; margin-top: 3px; }
.wkt-pk-rev-hero-desc { font-size: 13px; line-height: 1.55; opacity: .94; margin-top: 7px; max-width: 600px; }

/* Review tabs — Plan / Where it lands (room for more later) */
.wkt-pk-tabs { display: flex; gap: 2px; margin-top: 18px; border-bottom: 1px solid #e2e8f0; }
.wkt-pk-tab { position: relative; height: 40px; padding: 0 16px; border: 0; background: transparent; color: #64748b; font-size: 13.5px; font-weight: 700; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; display: inline-flex; align-items: center; gap: 7px; }
.wkt-pk-tab:hover { color: #0f172a; }
.wkt-pk-tab.is-active { color: #4338ca; border-bottom-color: #4338ca; }
.wkt-pk-tab-dot { width: 7px; height: 7px; border-radius: 50%; background: #f59e0b; animation: wkt-pulse 1s ease-in-out infinite; }
.wkt-pk-panel { padding-top: 18px; }
.wkt-pk-panel .wkt-plan { display: flex; flex-direction: column; gap: 14px; }
.wkt-pk-land { display: flex; flex-direction: column; gap: 12px; }
.wkt-pk-land-src { display: flex; gap: 8px; align-items: center; }
.wkt-pk-land-summary { background: #f8fafc; border: 1px solid #eef2f7; border-radius: 10px; padding: 12px 14px; }
.wkt-pk-land-summary .wkt-prev-reasons { margin-top: 0; }
.wkt-prev-head { margin-bottom: 12px; }
.wkt-prev-title { display: inline-block; padding: 6px 12px; border-left: 4px solid #4f46e5; font-weight: 700; font-size: 14px; color: #0f172a; }
.wkt-prev-reasons { font-size: 11px; color: #64748b; margin-top: 6px; line-height: 1.5; }
.wkt-prev-srcrow { display: flex; gap: 8px; align-items: center; margin-top: 4px; }
.wkt-prev-src { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 10px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
.wkt-prev-src--ai        { background: #ecfeff; color: #0891b2; }
.wkt-prev-src--hybrid    { background: #f3e8ff; color: #7c3aed; }
.wkt-prev-src--heuristic { background: #f1f5f9; color: #475569; }
.wkt-prev-loading { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 10px; font-size: 10px; font-weight: 600; background: #fef3c7; color: #92400e; }
.wkt-prev-loading::before { content: ''; width: 8px; height: 8px; border-radius: 50%; background: currentColor; margin-right: 5px; opacity: .6; animation: wkt-pulse 1s ease-in-out infinite; }
@keyframes wkt-pulse { 0%, 100% { opacity: .3; } 50% { opacity: 1; } }
.wkt-prev-warn { font-size: 11px; color: #92400e; background: #fef3c7; padding: 6px 10px; border-radius: 6px; margin-top: 8px; }
.wkt-prev-reason { font-size: 11px; color: #64748b; margin-top: 2px; font-style: italic; line-height: 1.4; }
.wkt-prev-list { display: flex; flex-direction: column; gap: 6px; }
.wkt-prev-row { display: flex; align-items: center; gap: 10px; padding: 8px 10px; background: #f8fafc; border: 1px solid #e5e7eb; border-radius: 8px; }
.wkt-prev-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.wkt-prev-mid { flex: 1; min-width: 0; }
.wkt-prev-name { font-size: 13px; font-weight: 500; color: #0f172a; }
.wkt-prev-kind { font-size: 11px; color: #64748b; margin-top: 1px; }
.wkt-prev-phase { font-size: 12px; padding: 4px 8px; border: 1px solid #e5e7eb; border-radius: 6px; background: #fff; }
.wkt-prev-nophase { font-size: 11px; color: #94a3b8; font-style: italic; }
.wkt-picker-footer { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 20px; border-top: 1px solid #e5e7eb; background: #fff; }
.wkt-picker-meta { font-size: 12.5px; color: #475569; font-weight: 600; }
.wkt-picker-foot-acts { display: flex; gap: 8px; }
.wkt-picker-foot-acts .wk-btn--primary[hidden] { display: none; }

/* ────────────────────────────────────────────────────────
   Local button helpers (used in detail footer + picker)
   ──────────────────────────────────────────────────────── */
.wk-btn {
  height: 34px; padding: 0 16px; font-size: 12.5px; font-weight: 600;
  border: 1px solid #e2e8f0; border-radius: 8px;
  background: #fff; color: #475569; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
}
.wk-btn:hover { background: #f8fafc; color: #0f172a; }
.wk-btn--primary { background: #4338ca; color: #fff; border-color: #4338ca; }
.wk-btn--primary:hover { background: #3730a3; color: #fff; }
.wk-btn--danger { color: #b91c1c; border-color: #fecaca; background: #fff; }
.wk-btn--danger:hover { background: #fef2f2; }

/* ────────────────────────────────────────────────────────
   ORDER OF OPERATIONS — the card group that sits beside
   Compliance / QA-QC / Discovery in the library grid.
   The builder's own styles live in wk-ooo.css; these are
   only the bits that belong to the grid itself.
   ──────────────────────────────────────────────────────── */

/* Stage trail on an OoO card — "Intake → Discovery → Analysis → +1".
   Clamped to one line: the trail is a glance, not a table of contents. */
.wkt-ooo-trail {
  margin-top: 4px;
  font-size: 11px; font-weight: 600; color: #64748b;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Note beside the group heading, explaining what makes this group different. */
.wkt-rp-group-note {
  margin-left: 8px;
  font-size: 11px; font-weight: 500; color: #94a3b8;
}
@media (max-width: 640px) { .wkt-rp-group-note { display: none; } }

/* Ghost "create" card that ends the group. A <button>, so it is reachable
   by keyboard without a tabindex and announces itself as an action rather
   than as one more template. */
.wkt-rp-card--new {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 4px;
  min-height: 150px; padding: 18px 14px; text-align: center;
  border: 2px dashed #cbd5e1; border-radius: 12px;
  background: #fbfcfe; cursor: pointer;
  transition: border-color .12s, background .12s, transform .12s;
}
.wkt-rp-card--new:hover {
  border-color: var(--rp-card-c, #0891b2);
  background: #fff;
  transform: translateY(-1px);
}
.wkt-rp-card--new:focus-visible {
  outline: 2px solid var(--rp-card-c, #0891b2); outline-offset: 2px;
}
.wkt-rp-card-new-plus {
  width: 34px; height: 34px; border-radius: 17px;
  display: inline-flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--rp-card-c, #0891b2) 12%, #fff);
  color: var(--rp-card-c, #0891b2);
  font-size: 22px; font-weight: 400; line-height: 1;
}
.wkt-rp-card-new-lbl { font-size: 13px; font-weight: 800; color: #0f172a; }
.wkt-rp-card-new-sub { font-size: 11.5px; color: #64748b; line-height: 1.45; }

@media (prefers-reduced-motion: reduce) {
  .wkt-rp-card--new:hover { transform: none; }
}
@supports not (background: color-mix(in srgb, red 50%, blue)) {
  .wkt-rp-card-new-plus { background: #eef2f7; }
}

/* ────────────────────────────────────────────────────────
   TEMPLATE BUILDER HERO (edit mode) — LIGHT CHROME

   Viewing a template and building one are two different jobs, so they get two
   different surfaces. VIEW keeps the full-bleed category colour: it is a saved
   thing, wearing its own colour, and there is nothing on it to fill in. EDIT is
   a FORM, and it looks like one — white, dark ink, labels above bordered
   fields. Two reasons it can't just be the gradient with inputs on top:

     • a label and a placeholder have to stay legible against a colour the user
       picked, and half the category palette won't hold that contrast; and
     • a form under a full-bleed gradient reads as a finished header rather than
       as the questions it is.

   Layout: the icon + title + subtitle sit on one line (padded clear of the
   Edit/Preview + × strip pinned top-right of the card), and the row of
   questions runs the FULL width underneath, unobstructed — name, category,
   then the AI button that answers them both.
   ──────────────────────────────────────────────────────── */
.wkt-detail-card.is-edit .wkt-detail-hero {
  display: block;
  padding: 26px 28px 24px;
  min-height: 0;
  color: var(--wkt-ink);
  background: var(--wkt-surf);                 /* _renderDetail also clears the gradient */
  border-bottom: 1px solid #e6ebf1;
}
/* The corner-light wash belongs to the colour block, not to paper. */
.wkt-detail-card.is-edit .wkt-detail-hero::before { display: none; }

/* Only the TITLE line yields to the top-right controls; the fields below run
   the full width. Reserving the strip across the whole hero (as view mode
   does) would have shortened every field by 176px for two buttons sitting
   above them. */
.wkt-hero-build-head {
  position: relative; z-index: 1;
  display: flex; align-items: center; gap: 16px;
  padding-right: 190px;
}
.wkt-hero-build-titles { min-width: 0; }
.wkt-detail-card.is-edit .wkt-detail-hero-icon {
  width: 56px; height: 56px; border-radius: 15px;
  background: #e7f4f1; border: 1px solid #cfe8e3; color: #0f766e;
  backdrop-filter: none;
}
.wkt-hero-builder-title {
  font-size: 26px; font-weight: 800; line-height: 1.15;
  letter-spacing: -.02em; color: var(--wkt-ink);
}
.wkt-hero-builder-sub {
  margin-top: 4px;
  font-size: 14px; font-weight: 500; line-height: 1.4;
  color: var(--wkt-ink-3);
}

/* ── The question row ───────────────────────────────────── */
.wkt-detail-card.is-edit .wkt-hero-meta-row {
  position: relative; z-index: 1;
  margin-top: 24px;
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 16px;
}
.wkt-hero-field { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
/* Capped. Left to take all the slack, a one-line name box stretched the full
   width of the card and stranded Category alone at the far right edge, so the
   two questions read as unrelated controls rather than one form row. */
.wkt-hero-field--name { flex: 1 1 320px; max-width: 640px; }
.wkt-hero-field--cat { flex: 0 1 260px; }
.wkt-hero-field-lbl {
  font-size: 14px; font-weight: 700; line-height: 1; color: var(--wkt-ink);
}
.wkt-detail-card.is-edit .wkt-hero-name-input,
.wkt-detail-card.is-edit .wkt-hero-cat-input {
  width: 100%; box-sizing: border-box;
  height: 46px; padding: 0 14px;
  border: 1px solid var(--wkt-line); border-radius: var(--wkt-r);
  background-color: var(--wkt-surf); color: var(--wkt-ink);
  font-size: 15px; font-weight: 500; line-height: 1.2;
  letter-spacing: normal; text-transform: none;
  box-shadow: var(--shadow-sm);
}
.wkt-detail-card.is-edit .wkt-hero-name-input::placeholder { color: var(--wkt-ink-4); font-weight: 400; }
.wkt-detail-card.is-edit .wkt-hero-name-input:focus,
.wkt-detail-card.is-edit .wkt-hero-cat-input:focus {
  background-color: var(--wkt-surf);
  border-color: #0f766e;
  box-shadow: 0 0 0 3px rgba(15,118,110,.14);
}
/* Same caret, drawn in ink instead of white, and room made for it. */
.wkt-detail-card.is-edit .wkt-hero-cat-input {
  align-self: auto; max-width: none;
  padding-right: 38px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-position: right 14px center;
  background-size: 13px 13px;
}
/* Nothing picked yet — an unfilled required field, not a category named blank. */
.wkt-detail-card.is-edit .wkt-hero-cat-input.is-untagged {
  border-style: dashed; border-color: var(--wkt-line-strong);
  background-color: var(--wkt-surf); color: var(--wkt-ink-4);
}
/* Bounced off Create / Save with no category picked. */
.wkt-detail-card.is-edit .wkt-hero-cat-input.is-missing {
  border-style: solid; border-color: #dc2626; color: var(--wkt-ink);
  box-shadow: 0 0 0 3px rgba(220,38,38,.18);
}

/* "Build with AI" closes the row it belongs to, matching the fields' height so
   the three read as one strip. Its own stylesheet declares size/weight with a
   `font:` shorthand ending in `inherit` — invalid, so the whole declaration is
   dropped by every browser — hence the longhands here.

   PURPLE, not teal. Anything that spends AI wears the same violet across this
   app — ✦ Find it with AI in the picker, Build with AI in the department
   wizard — so the palette itself tells you a button is about to think. This
   one was teal, the only AI offer in Work that didn't look like one. Values
   are lifted from .wkpk-ai in wk-pick-popup.js so the two match exactly. */
.wkt-hero-start-btns { flex: 0 0 auto; display: flex; align-items: center; }
.wkt-hero-start-btns .wk-aifill-top {
  height: 46px; padding: 0 20px; border-radius: var(--wkt-r);
  font-size: 15px; font-weight: 700;
  background: linear-gradient(135deg, #faf5ff, #eef2ff);
  border-color: #ddd6fe; color: #5b21b6;
}
.wkt-hero-start-btns .wk-aifill-top svg { width: 16px; height: 16px; color: #7c3aed; }
.wkt-hero-start-btns .wk-aifill-top:hover {
  background: linear-gradient(135deg, #f3e8ff, #e0e7ff);
  border-color: #a78bfa; color: #4c1d95;
  box-shadow: 0 5px 16px rgba(124, 58, 237, .18);
}
.wkt-hero-start-btns .wk-aifill-top:hover svg { color: #6d28d9; }
.wkt-hero-start-btns .wk-aifill-top:active {
  background: linear-gradient(135deg, #ede9fe, #e0e7ff);
  box-shadow: none;
}

/* ── The top-right strip, re-inked for paper ────────────── */
.wkt-detail-card.is-edit .wkt-detail-close {
  border-radius: var(--wkt-r-pill);
  background: var(--wkt-surf); border: 1px solid var(--wkt-line); color: var(--wkt-ink-2);
}
.wkt-detail-card.is-edit .wkt-detail-close:hover { background: var(--wkt-hover); color: var(--wkt-ink); }
.wkt-detail-card.is-edit .wkt-detail-modeseg { background: var(--wkt-hover); border-color: var(--wkt-line); }
.wkt-detail-card.is-edit .wkt-detail-modebtn { color: var(--wkt-ink-3); }
.wkt-detail-card.is-edit .wkt-detail-modebtn:hover { background: var(--wkt-line); color: var(--wkt-ink); }
.wkt-detail-card.is-edit .wkt-detail-modebtn.is-active {
  background: var(--wkt-surf); color: var(--wkt-ink); box-shadow: var(--shadow-sm);
}

@media (max-width: 720px) {
  .wkt-hero-build-head { padding-right: 150px; }
  .wkt-hero-builder-title { font-size: 22px; }
  /* Each question takes the full width; the button stays sized to its own
     label under them rather than stretching into a banner. */
  .wkt-hero-field--name, .wkt-hero-field--cat { flex: 1 1 100%; }
}

/* ── "From existing template" — the button, and the library it opens ────
   The second way past a blank map, next to the first. It sits between the
   questions and "Build with AI" and matches their height, so the row still
   reads as one strip: what this template is called, what it is, and the two
   ways to fill it. Inked slate rather than the AI's violet — one of these
   writes something new, the other moves something that already exists, and
   they should not look like the same offer. Longhand font properties: the
   shared button CSS in this app declares `font: … inherit`, which is invalid
   and dropped whole by every browser. */
.wkt-hero-from-row { flex: 0 0 auto; display: flex; align-items: center; }
.wkt-hero-from-btn {
  display: inline-flex; align-items: center; gap: 8px;
  height: 46px; padding: 0 18px;
  border: 1px solid var(--wkt-line); border-radius: var(--wkt-r);
  background: var(--wkt-surf); color: var(--wkt-ink-2); cursor: pointer;
  font-family: inherit; font-size: 15px; font-weight: 700; line-height: 1;
  letter-spacing: normal; text-transform: none;
  box-shadow: var(--shadow-sm);
  transition: background .12s, border-color .12s, color .12s;
}
.wkt-hero-from-btn svg { flex: 0 0 auto; color: var(--wkt-ink-3); }
.wkt-hero-from-btn:hover { background: var(--wkt-tint); border-color: var(--wkt-line-strong); color: var(--wkt-ink); }
.wkt-hero-from-btn:hover svg { color: var(--wkt-ink); }
.wkt-hero-from-btn:active { background: var(--wkt-hover); }
.wkt-hero-from-btn:focus-visible { outline: none; border-color: #0f766e; box-shadow: 0 0 0 3px rgba(15,118,110,.16); }

/* ── "Start from" — the second tier of the hero ─────────────────────────
   The two shortcuts past a blank map, on a strip of their own under a rule.
   They used to ride the same flex row as Template name and Category, which
   asked one line to hold two labelled fields and two content-sized buttons:
   at any real window width the row ran out of room and "Build with AI" was
   pushed off the right edge of the card, half-drawn. Splitting them is not
   only a fit — a field you fill in and a button that fills the page in for
   you are different KINDS of thing, and the rule between them says so.
   ───────────────────────────────────────────────────────────────────── */
.wkt-detail-card.is-edit .wkt-hero-start {
  position: relative; z-index: 1;
  margin-top: 20px; padding-top: 18px;
  border-top: 1px solid var(--wkt-line);
  display: flex; align-items: center; flex-wrap: wrap; gap: 12px 16px;
}
.wkt-hero-start-lbl {
  flex: 0 0 auto;
  font-size: 11px; font-weight: 800; line-height: 1;
  letter-spacing: .08em; text-transform: uppercase; color: var(--wkt-ink-4);
}
.wkt-hero-start-btns { flex: 0 1 auto; gap: 10px; flex-wrap: wrap; }
/* The right-hand end of the strip: the reassurance that neither button is a
   gate. Pushed away from the pair so it reads as a note, not a third option. */
.wkt-hero-start-note {
  flex: 1 1 auto; min-width: 0; text-align: right;
  font-size: 13px; font-weight: 500; color: var(--wkt-ink-4);
}
@media (max-width: 900px) {
  .wkt-hero-start-note { flex-basis: 100%; text-align: left; }
}

/* The library itself: search across the top, categories down the left,
   cards in the middle — the shape of the Templates tab, in a modal. */
.wkt-from { position: fixed; inset: 0; z-index: 2000400; display: none; }
.wkt-from.is-open { display: block; }
.wkt-from-backdrop { position: absolute; inset: 0; background: rgba(15,23,42,.48); }
/* SIZE. A library you compare things in wants room — but taking the whole
   window made it read as a SCREEN you had navigated to rather than a popup
   over the builder you are still in, and there was no way to tell by looking
   that the map was still behind it. So: big enough for five or six cards on a
   row, and a clear margin of the page showing on every side.

   And it POPS. `is-open` only un-hides the layer; `is-in` (added a frame
   later, see _openFromTemplate) is what it animates to, so the card scales up
   from just under full size while the backdrop fades in — and scales back out
   on close instead of being cut off mid-frame. transform carries the
   centring translate in every state or the card would jump to the top-left
   corner the moment the transition starts. */
.wkt-from-card {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%) scale(.96);
  width: min(1240px, calc(100vw - 96px)); height: min(860px, calc(100vh - 96px));
  display: flex; flex-direction: column;
  background: var(--wkt-surf); border-radius: var(--wkt-r-lg);
  box-shadow: 0 34px 90px rgba(15,23,42,.38);
  overflow: hidden;
  opacity: 0;
  transition: opacity .15s ease, transform .19s cubic-bezier(.22,.9,.32,1.2);
}
.wkt-from.is-in .wkt-from-card { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.wkt-from-backdrop { opacity: 0; transition: opacity .15s ease; }
.wkt-from.is-in .wkt-from-backdrop { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .wkt-from-card, .wkt-from-backdrop { transition: none; }
  .wkt-from.is-open .wkt-from-card { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  .wkt-from.is-open .wkt-from-backdrop { opacity: 1; }
}

/* ── Templates | Work streams ───────────────────────────────────────────
   Two grains of the same library. The tab is a real switch, not a filter
   chip: it sits on its own line under the heading, carries a count, and the
   active one is underlined in the app's teal so the strip reads left-to-right
   as "here is what you are looking at".
   ───────────────────────────────────────────────────────────────────── */
.wkt-from-tabs {
  display: flex; align-items: stretch; gap: 4px;
  margin: 0 20px 12px; padding: 0;
  border-bottom: 1px solid var(--wkt-line);
}
.wkt-from-tab {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 0 4px 10px; margin: 0 10px -1px 0;
  border: 0; border-bottom: 2px solid transparent; background: transparent;
  color: var(--wkt-ink-3); cursor: pointer;
  font-family: inherit; font-size: 14px; font-weight: 700; line-height: 1;
  letter-spacing: normal; text-transform: none;
  transition: color .12s ease, border-color .12s ease;
}
.wkt-from-tab:hover { color: var(--wkt-ink); }
.wkt-from-tab.is-active { color: #0f766e; border-bottom-color: #0f766e; }
.wkt-from-tab:focus-visible { outline: none; color: #0f766e; box-shadow: 0 0 0 3px rgba(15,118,110,.16); border-radius: var(--wkt-r); }
.wkt-from-tabn {
  min-width: 20px; padding: 3px 6px; border-radius: var(--wkt-r-pill, 999px);
  background: var(--wkt-hover); color: var(--wkt-ink-3);
  font-size: 11px; font-weight: 800; text-align: center;
}
.wkt-from-tab.is-active .wkt-from-tabn { background: rgba(15,118,110,.12); color: #0f766e; }

/* A work-stream card. Same card as a template's, one tier down: a neutral
   thumb (a stream has no category of its own — the tag says whose template it
   came out of), the owner beside it when there is one, and a pill that names
   what you are about to take so the two tabs can never be confused after the
   fact. */
.wkt-from-wscard { cursor: pointer; }
.wkt-from-wsown {
  background: var(--wkt-hover) !important; color: var(--wkt-ink-3) !important;
}
.wkt-from-wspill {
  background: rgba(15,118,110,.10); color: #0f766e;
}
/* `hidden` alone cannot hide an inline-flex button — the display in the rule
   below wins. The streams tab hides Find-with-AI, so it needs this partner. */
.wkt-from-aibtn[hidden] { display: none; }
.wkt-from-head { display: flex; align-items: flex-start; gap: 12px; padding: 18px 20px 12px; }
.wkt-from-heads { flex: 1; min-width: 0; }
.wkt-from-title { font-size: 16px; font-weight: 800; color: var(--wkt-ink); }
.wkt-from-sub { font-size: 13px; color: var(--wkt-ink-3); margin-top: 3px; max-width: 76ch; line-height: 1.45; }
.wkt-from-close {
  flex: 0 0 auto; width: 30px; height: 30px;
  border: 0; border-radius: var(--wkt-r); background: var(--wkt-hover); color: var(--wkt-ink-2);
  font-family: inherit; font-size: 18px; line-height: 1; cursor: pointer;
}
.wkt-from-close:hover { background: var(--wkt-line); color: var(--wkt-ink); }

/* Search and "Find with AI" share one line. The search box takes the room
   and the button is sized to its own label, so the pair reads as one control
   with two ways in rather than a field and an afterthought. */
.wkt-from-find { display: flex; align-items: center; gap: 10px; margin: 0 20px 14px; }
.wkt-from-find .wkt-from-search { flex: 1; min-width: 0; margin: 0; }

.wkt-from-search {
  display: flex; align-items: center; gap: 9px;
  margin: 0 20px 14px; padding: 0 13px; height: 40px;
  border: 1px solid #d7dfe8; border-radius: var(--wkt-r); background: var(--wkt-surf); color: var(--wkt-ink-4);
}
.wkt-from-search:focus-within { border-color: #0f766e; box-shadow: 0 0 0 3px rgba(15,118,110,.13); color: #0f766e; }
.wkt-from-search input {
  flex: 1; min-width: 0; border: 0; outline: none; background: transparent;
  font-family: inherit; font-size: 14px; font-weight: 500; color: var(--wkt-ink);
}
.wkt-from-search input::placeholder { color: var(--wkt-ink-4); font-weight: 400; }
.wkt-from-search input::-webkit-search-cancel-button { cursor: pointer; }

/* ── Find with AI ─────────────────────────────────────────────────────
   VIOLET, like every other thing in this app that spends AI — ✦ Find it
   with AI in the picker, Build with AI in the hero above. Values lifted
   from .wkpk-ai (wk-pick-popup.js) so the two are the same offer wearing
   the same coat. Longhand font properties on purpose: the shared button
   CSS declares `font: … inherit`, which is invalid and dropped whole.
   ───────────────────────────────────────────────────────────────────── */
.wkt-from-aibtn {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 8px;
  height: 40px; padding: 0 15px;
  border: 1px solid #ddd6fe; border-radius: var(--wkt-r);
  background: linear-gradient(135deg, #faf5ff, #eef2ff); color: #5b21b6; cursor: pointer;
  font-family: inherit; font-size: 13px; font-weight: 700; line-height: 1;
  letter-spacing: normal; text-transform: none; white-space: nowrap;
  transition: border-color .12s ease, box-shadow .12s ease;
}
.wkt-from-aibtn svg { flex: 0 0 auto; color: #7c3aed; }
.wkt-from-aibtn:hover { border-color: #a78bfa; box-shadow: 0 5px 16px rgba(124,58,237,.18); }
.wkt-from-aibtn.is-open {
  border-color: #a78bfa; color: #4c1d95;
  background: linear-gradient(135deg, #f3e8ff, #e0e7ff);
  box-shadow: 0 0 0 3px rgba(124,58,237,.14);
}

.wkt-from-ai {
  margin: -4px 20px 14px; padding: 12px 13px;
  border: 1px solid #ede9fe; border-radius: var(--wkt-r-md);
  background: linear-gradient(135deg, #faf5ff, #f5f3ff);
}
.wkt-from-ai[hidden] { display: none; }
.wkt-from-ai-row { display: flex; align-items: flex-start; gap: 10px; }
.wkt-from-ai-in {
  flex: 1; min-width: 0; resize: vertical; min-height: 56px;
  padding: 9px 11px; border: 1px solid #ddd6fe; border-radius: var(--wkt-r); background: var(--wkt-surf);
  font-family: inherit; font-size: 14px; font-weight: 500; line-height: 1.45;
  color: var(--wkt-ink); outline: none;
}
.wkt-from-ai-in:focus { border-color: #7c3aed; box-shadow: 0 0 0 3px rgba(124,58,237,.13); }
.wkt-from-ai-in::placeholder { color: #a5aec0; font-weight: 400; }
.wkt-from-ai-acts { flex: 0 0 auto; display: flex; flex-direction: column; gap: 6px; }
.wkt-from-ai-acts .wkt-from-btn { white-space: nowrap; }
.wkt-from-ai-note { margin-top: 7px; font-size: 12px; color: #7c6f9c; }

/* The AI's own commit button. Not .wkt-from-btn--go: teal is what "Take this
   template" wears, and the two must not read as the same weight of action. */
.wkt-from-btn--ai {
  border: 1px solid #a78bfa; background: linear-gradient(135deg, #7c3aed, #6d28d9); color: var(--wkt-surf);
}
.wkt-from-btn--ai:hover {
  background: linear-gradient(135deg, #6d28d9, #5b21b6);
  box-shadow: 0 5px 16px rgba(124,58,237,.24);
}

/* The band that says whose answer this is. It sits where a category heading
   would, so the shortlist reads as one more group in the library rather than
   a different screen. */
.wkt-from-aihead {
  display: flex; align-items: center; gap: 12px;
  padding-bottom: 11px; margin-bottom: 14px; border-bottom: 1px solid var(--wkt-line-soft);
}
.wkt-from-aihead-l { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; }
.wkt-from-aihead-icon { display: inline-flex; color: #7c3aed; }
.wkt-from-aihead-t { font-size: 14px; font-weight: 800; color: var(--wkt-ink); }
.wkt-from-aihead-q { font-weight: 500; color: var(--wkt-ink-3); }
.wkt-from-aiback {
  flex: 0 0 auto; padding: 6px 11px;
  border: 1px solid var(--wkt-line); border-radius: var(--wkt-r); background: var(--wkt-surf); color: var(--wkt-ink-2); cursor: pointer;
  font-family: inherit; font-size: 13px; font-weight: 600;
  letter-spacing: normal; text-transform: none;
}
.wkt-from-aiback:hover { background: var(--wkt-hover); color: var(--wkt-ink); }
.wkt-from-ainote { margin: -4px 0 14px; font-size: 13px; color: var(--wkt-ink-3); line-height: 1.5; }

.wkt-from-aiload { display: flex; align-items: center; gap: 10px; padding: 26px 4px; font-size: 13px; color: var(--wkt-ink-3); }
.wkt-from-aispin {
  width: 16px; height: 16px; flex: 0 0 auto;
  border: 2px solid #ddd6fe; border-top-color: #7c3aed; border-radius: 50%;
  animation: wktFromAiSpin .7s linear infinite;
}
@keyframes wktFromAiSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .wkt-from-aispin { animation-duration: 2.4s; } }

/* A hit is the card plus the reason, stacked — the reason is a caption on the
   card, not a line inside it, so the card stays identical to every other card
   in the app. */
.wkt-from-aihit { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.wkt-from-aihit .wkt-rp-card { margin: 0; }
.wkt-from-aiwhy {
  display: flex; align-items: flex-start; gap: 7px;
  padding: 8px 10px; border-radius: var(--wkt-r);
  background: #faf5ff; border: 1px solid #ede9fe;
  font-size: 12px; line-height: 1.5; color: #55467a;
}
.wkt-from-aiwhy svg { flex: 0 0 auto; margin-top: 2px; color: #7c3aed; }
.wkt-from-blank-btn { display: inline-flex; align-items: center; gap: 7px; margin-top: 14px; }

.wkt-from-main { flex: 1; min-height: 0; display: flex; border-top: 1px solid var(--wkt-line-soft); }

/* The rail. Every entry is one row: a dot in the category's own ink, its
   name, and how many are behind it — so "empty" is a number you can read
   rather than a click you waste. */
.wkt-from-rail {
  flex: 0 0 218px; min-width: 0; overflow: auto;
  padding: 12px 10px 18px; border-right: 1px solid var(--wkt-line-soft); background: #fbfdff;
}
.wkt-from-railbtn {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  padding: 8px 10px; margin-bottom: 2px;
  border: 1px solid transparent; border-radius: var(--wkt-r); background: transparent; cursor: pointer;
  font-family: inherit; font-size: 13px; font-weight: 600; color: var(--wkt-ink-2);
  letter-spacing: normal; text-transform: none;
}
.wkt-from-railbtn:hover { background: var(--wkt-hover); color: var(--wkt-ink); }
.wkt-from-railbtn.is-active { background: #e7f4f1; border-color: #cfe8e3; color: #0b5f59; font-weight: 800; }
.wkt-from-railbtn--all { font-weight: 800; color: var(--wkt-ink); }
.wkt-from-raildot { flex: 0 0 auto; width: 8px; height: 8px; border-radius: var(--wkt-r-pill); }
.wkt-from-railname { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wkt-from-railn { flex: 0 0 auto; font-size: 11px; font-weight: 700; color: var(--wkt-ink-4); }
.wkt-from-railbtn.is-active .wkt-from-railn { color: #0b5f59; }
.wkt-from-railsep { height: 1px; margin: 9px 4px; background: #e7edf4; }

.wkt-from-stage { flex: 1; min-width: 0; overflow: auto; padding: 16px 18px 22px; }
/* The library card at very nearly its full Templates-tab size. It used to be
   shrunk to fit a 1120px box; the box is wider than the tab now, so the only
   thing left to trim is the cover, and a card you can read the description of
   is the difference between picking one and opening four. */
.wkt-from-grid { grid-template-columns: repeat(auto-fill, minmax(248px, 1fr)); gap: 14px; padding: 0; }
.wkt-from-grid .wkt-rp-card-thumb { height: 76px; }
.wkt-from-grid .wkt-rp-card-thumb-icon { width: 42px; height: 42px; border-radius: 12px; }
.wkt-from-grid .wkt-rp-card-thumb-icon svg { width: 21px; height: 21px; }
.wkt-from-grid .wkt-rp-card-body { padding: 13px 15px 15px; gap: 8px; }
.wkt-from-groups { display: flex; flex-direction: column; gap: 18px; }
.wkt-from-groups .wkt-rp-group-head { margin-bottom: 9px; }
.wkt-from-blank { padding: 60px 20px; text-align: center; }
.wkt-from-blank-title { font-size: 15px; font-weight: 800; color: var(--wkt-ink-2); }
.wkt-from-blank-sub { margin-top: 6px; font-size: 13px; color: var(--wkt-ink-4); line-height: 1.55; }

.wkt-from-foot {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 20px; border-top: 1px solid var(--wkt-line-soft); background: #fbfdff;
}
.wkt-from-hint { flex: 1; min-width: 0; font-size: 12px; color: var(--wkt-ink-3); }
.wkt-from-acts { flex: 0 0 auto; display: flex; align-items: center; gap: 9px; }
.wkt-from-btn {
  height: 38px; padding: 0 18px; border-radius: var(--wkt-r); cursor: pointer;
  font-family: inherit; font-size: 14px; font-weight: 700; line-height: 1;
  letter-spacing: normal; text-transform: none;
}
.wkt-from-btn--ghost { border: 1px solid var(--wkt-line); background: var(--wkt-surf); color: var(--wkt-ink-2); }
.wkt-from-btn--ghost:hover { background: var(--wkt-hover); color: var(--wkt-ink); }
.wkt-from-btn--go { border: 0; background: #0f766e; color: var(--wkt-surf); }
.wkt-from-btn--go:hover { background: #0b5f59; }

@media (max-width: 900px) {
  /* The rail becomes a strip of chips across the top of the stage — a column
     of categories is not worth a third of a phone's width. */
  .wkt-from-card { width: calc(100vw - 16px); height: calc(100vh - 24px); }
  .wkt-from-main { flex-direction: column; }
  .wkt-from-rail {
    flex: 0 0 auto; display: flex; gap: 6px; overflow-x: auto;
    padding: 10px 12px; border-right: 0; border-bottom: 1px solid var(--wkt-line-soft);
  }
  .wkt-from-railbtn { width: auto; flex: 0 0 auto; margin-bottom: 0; border-color: var(--wkt-line); background: var(--wkt-surf); }
  .wkt-from-railsep { display: none; }
  .wkt-from-grid { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); }
}
@media (max-width: 720px) {
  /* Side by side, the AI button squeezed the search box down to about six
     visible characters. Stacked, both are full width and neither is the one
     that lost. */
  .wkt-from-find { flex-direction: column; align-items: stretch; }
  .wkt-from-aibtn { justify-content: center; }
  .wkt-from-ai-row { flex-direction: column; }
  .wkt-from-ai-acts { flex-direction: row; }
  .wkt-from-ai-acts .wkt-from-btn { flex: 1; }
  .wkt-from-aihead { flex-wrap: wrap; }
  .wkt-hero-start-btns { flex: 1 1 100%; }
  .wkt-hero-start-btns > * { flex: 1 1 auto; }
  .wkt-hero-start-btns .wk-aifill-top,
  .wkt-hero-start-btns .wkt-hero-from-btn { width: 100%; justify-content: center; }
  .wkt-hero-from-btn { width: 100%; justify-content: center; }
  .wkt-from-foot { flex-wrap: wrap; }
  .wkt-from-acts { width: 100%; }
  .wkt-from-btn--go { flex: 1; }
}

/* ── The template, opened ───────────────────────────────────────────────
   A second layer over the library (z above .wkt-from), and the biggest
   surface either popup gets: what it holds is a PLAN — stage bands running
   the full width, streams side by side in each — and a plan read through a
   letterbox is a plan you scroll instead of see. Near-full-window, with the
   library's own dimmed card just visible at the edges so the way back is
   somewhere you can see, not somewhere you remember. */
.wkt-trim { position: fixed; inset: 0; z-index: 2000500; display: none; }
.wkt-trim.is-open { display: block; }
.wkt-trim-backdrop { position: absolute; inset: 0; background: rgba(15,23,42,.56); }
.wkt-trim-card {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: calc(100vw - 24px); height: calc(100vh - 24px);
  display: flex; flex-direction: column;
  background: #f6f9fc; border-radius: var(--wkt-r-lg);
  box-shadow: 0 40px 110px rgba(15,23,42,.46);
  overflow: hidden;
}

.wkt-trim-hero { flex: 0 0 auto; padding: 14px 20px 16px; color: var(--wkt-surf); }
.wkt-trim-back {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 12px 6px 9px; margin-bottom: 12px;
  border: 1px solid rgba(255,255,255,.34); border-radius: var(--wkt-r-pill);
  background: rgba(255,255,255,.14); color: var(--wkt-surf); cursor: pointer;
  font-family: inherit; font-size: 13px; font-weight: 700; line-height: 1;
  letter-spacing: normal; text-transform: none;
}
.wkt-trim-back:hover { background: rgba(255,255,255,.24); }
.wkt-trim-heroline { display: flex; align-items: center; gap: 14px; }
.wkt-trim-heroicon {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; border-radius: var(--wkt-r-md);
  background: rgba(255,255,255,.18); color: var(--wkt-surf);
}
.wkt-trim-herotitles { flex: 1; min-width: 0; }
.wkt-trim-herocat {
  font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: rgba(255,255,255,.82);
}
.wkt-trim-heroname { margin-top: 3px; font-size: 21px; font-weight: 800; line-height: 1.2; }
.wkt-trim-herodesc { margin-top: 5px; font-size: 13px; line-height: 1.45; color: rgba(255,255,255,.86); max-width: 90ch; }
.wkt-trim-x {
  flex: 0 0 auto; align-self: flex-start; width: 32px; height: 32px;
  border: 0; border-radius: var(--wkt-r); background: rgba(255,255,255,.16); color: var(--wkt-surf);
  font-family: inherit; font-size: 19px; line-height: 1; cursor: pointer;
}
.wkt-trim-x:hover { background: rgba(255,255,255,.28); }
/* The rule of the screen, in one line under the name — the only place it can
   be said, because "no + anywhere" is not something a map can show. */
.wkt-trim-rule {
  margin-top: 12px; padding: 7px 12px; border-radius: var(--wkt-r);
  background: rgba(255,255,255,.16); color: rgba(255,255,255,.95);
  font-size: 12px; font-weight: 600; line-height: 1.4;
}

.wkt-trim-body { flex: 1; min-height: 0; overflow: auto; padding: 16px 18px 24px; }
/* The map is drawn for the builder's full-width canvas. In here a lane that
   outgrows the popup scrolls sideways on its own rather than squeezing every
   column narrower than a card. */
.wkt-trim-plan .wkt-plan-lane,
.wkt-trim-plan .wkt-srow-lane { overflow-x: auto; }
/* Remove is HOVER-ONLY on the builder's map, where you are working in one
   template all afternoon. Here it is the only verb on the screen, so it is
   always visible — a delete you have to go hunting for reads as no delete. */
.wkt-trim-plan .wkt-acts { opacity: 1; visibility: visible; pointer-events: auto; transform: none; }
.wkt-trim-plan .wkt-srow-trash { opacity: 1; }
.wkt-trim-empty { padding: 72px 20px; text-align: center; }
.wkt-trim-empty-title { font-size: 15px; font-weight: 800; color: var(--wkt-ink-2); }
.wkt-trim-empty-sub { margin-top: 6px; font-size: 13px; color: var(--wkt-ink-4); line-height: 1.55; }

.wkt-trim-foot {
  flex: 0 0 auto; display: flex; align-items: center; gap: 12px;
  padding: 12px 20px; border-top: 1px solid var(--wkt-line); background: var(--wkt-surf);
}
.wkt-trim-hint { flex: 1; min-width: 0; font-size: 12px; color: var(--wkt-ink-3); }
.wkt-trim-acts { flex: 0 0 auto; display: flex; align-items: center; gap: 9px; }
.wkt-trim-acts .wkt-from-btn[disabled] { opacity: .5; cursor: default; }

@media (max-width: 900px) {
  .wkt-trim-card { width: calc(100vw - 12px); height: calc(100vh - 12px); }
  .wkt-trim-heroname { font-size: 18px; }
  .wkt-trim-foot { flex-wrap: wrap; }
  .wkt-trim-acts { width: 100%; }
  .wkt-trim-acts .wkt-from-btn--go { flex: 1; }
}

/* ── SIDE BY SIDE — ONE popup, split down the middle ───────────────────
   Continue on the plan screen lands here. It is a single sheet: the builder
   holds the left half and stays the real builder, the template being built FROM
   holds the right, and the only thing between them is a hairline. Two separate
   floating cards is what this used to be, and two cards read as two screens
   that happened to be open at once — you had to work out which one you were in
   before you could do anything in either.

   FIFTY-FIFTY, and the two halves meet exactly on 50vw: the card runs 16px →
   50vw, the source runs 50vw → 100vw-16px, and the seam is the source's own
   1px left border. The card gives up its hairline ring on this screen so the
   middle is ONE line, and the source's drop shadow is pushed right and down so
   the sheet's outer edges lift off the page while the seam stays clean.

   The right half is BLUE — a wash on the panel and the header block — so
   "mine" and "theirs" are told apart before a word of either is read. Blue and
   only blue: the builder's map is white with each template's own colour on its
   stage bands, so the blue can never be mistaken for a piece of what you are
   building.

   It draws the same MAP, at a smaller zoom (see _splitMapHTML). The earlier
   objection to a map here — two canvases to read before you can use one — is
   answered by making this one read-only, stood back, folded shut and blue: it
   is a source you pick out of, and it looks like what it will become when you
   drop it, which the tree it replaced never did.

   z-index sits ABOVE the builder (2000000) and BELOW the tier _wkFloatOnTop
   clamps popups to (2000390). Any higher and a task popup opened out of the
   map behind would land underneath this half.
   ───────────────────────────────────────────────────────────────────────── */
:root { --wkt-split-w: calc(50vw - 16px); }
.wkt-split {
  position: fixed; z-index: 2000100;
  top: 16px; right: 16px; bottom: 16px; width: var(--wkt-split-w);
  display: none; flex-direction: column;
  background: #eaf2ff;
  border: 0; border-left: 1px solid #c7dcfb;
  border-radius: 0 var(--wkt-r-lg) var(--wkt-r-lg) 0; overflow: hidden;
  /* Offset right and down, so the lift is on the outside of the sheet and
     nothing bleeds into the seam. */
  box-shadow: 22px 32px 80px -20px rgba(15,23,42,.42);
}
.wkt-split.is-open { display: flex; }
/* The builder GIVES UP the width rather than being covered by it — a panel
   parked on top of the map would hide the lanes you are dragging into. */
.wkt-detail.wkt-is-split { justify-content: flex-start; }
.wkt-detail.wkt-is-split .wkt-detail-card {
  margin-left: 16px;
  width: calc(100vw - var(--wkt-split-w) - 32px);
  border-radius: var(--wkt-r-lg) 0 0 var(--wkt-r-lg);
  /* No hairline ring on this screen: the seam is the other half's border, once. */
  box-shadow: -22px 32px 80px -20px rgba(15,23,42,.42);
}

.wkt-split-head {
  flex: 0 0 auto; padding: 13px 16px 12px; color: var(--wkt-surf);
  background: linear-gradient(135deg, #1d4ed8 0%, #1e3a8a 100%);
}
.wkt-sp-headline { display: flex; align-items: center; gap: 10px; }
.wkt-sp-headicon {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: var(--wkt-r); color: var(--wkt-surf);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.38);
}
.wkt-sp-headicon svg { width: 17px; height: 17px; }
.wkt-sp-headtitles { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.wkt-sp-headcat {
  font-size: 10px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase;
  color: rgba(255,255,255,.78);
}
.wkt-sp-headname {
  font-size: 15px; font-weight: 800; line-height: 1.25;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.wkt-sp-x {
  flex: 0 0 auto; align-self: flex-start; width: 28px; height: 28px;
  border: 0; border-radius: var(--wkt-r); background: rgba(255,255,255,.18); color: var(--wkt-surf);
  font-family: inherit; font-size: 17px; line-height: 1; cursor: pointer;
}
.wkt-sp-x:hover { background: rgba(255,255,255,.3); }
.wkt-sp-rule {
  margin-top: 10px; padding: 6px 10px; border-radius: var(--wkt-r);
  background: rgba(255,255,255,.16); color: rgba(255,255,255,.95);
  font-size: 12px; font-weight: 600; line-height: 1.4;
}

/* The same padding the builder's own body carries, so the two maps sit at the
   same inset from their own edge and the sheet reads as one ruled page. */
.wkt-split-body { flex: 1; min-height: 0; overflow: auto; padding: 22px 20px 26px; }
/* The blue wash is on the PANEL, not on the cards: every stage band, work
   stream card and deliverable inside is the builder's own white, so what you
   are looking at is recognisably the thing it will be once you drop it. */
.wkt-sp-plan { transform-origin: 0 0; }
.wkt-sp-plan .wkt-srow-lane { padding-top: 20px; }
/* Where the map goes once everything in the source has been taken across. Not
   a failure state — the panel has done its job — so it reads as a note in the
   middle of the space the plan used to fill, with the headline in full ink so
   there is something to land on before the explanation. */
.wkt-sp-empty { padding: 40px 12px; text-align: center; font-size: 13px; color: var(--wkt-ink-3); line-height: 1.55; }
.wkt-sp-empty strong { display: inline-block; margin-bottom: 4px; font-size: 14px; color: var(--wkt-ink); }

/* ── EVERY BAND, COLUMN AND CARD IS A HANDLE ──────────────
   You are not reading a list of rows any more, you are pointing at the thing
   itself: a stage band, a work stream card, a deliverable block. Each one is
   draggable and each one carries a ＋, in the corner of the card for the two
   lower tiers and on the header line for a stage — the one tier that already
   has a line to put it on.

   ONE outline at a time. A deliverable sits inside a stream which sits inside a
   stage, so pointing at the deliverable matches all three: an ancestor whose
   descendant is hovered stands down, and the innermost thing under the cursor
   is the only thing lit. That is also the thing the drag will pick up. */
.wkt-sp-plan .wkt-sp-pick { position: relative; cursor: grab; }
.wkt-sp-plan .wkt-sp-pick:active { cursor: grabbing; }
.wkt-sp-plan .wkt-sp-pick.is-dragging { opacity: .45; }
.wkt-sp-plan .wkt-sp-pick:hover {
  outline: 2px solid rgba(37,99,235,.5); outline-offset: 3px; border-radius: var(--wkt-r-md);
}
.wkt-sp-plan .wkt-sp-pick:hover:has(.wkt-sp-pick:hover) { outline: none; }
/* THERE IS NO "already across" STATE HERE ANY MORE. A row that has been taken
   leaves this panel outright (see _splitTake), so the green outline and the ✓
   pill that used to mark one have gone with it — everything still drawn on
   this half is something you have not taken yet. */

.wkt-sp-pickbar {
  z-index: 4; display: inline-flex; align-items: center; gap: 4px;
  position: absolute; top: -9px; right: -7px;
}
/* On a stage the bar rides the header line, after the rule — in flow, because
   that line already ends in controls and a floating pill over it would sit on
   the stage above. */
.wkt-sp-pickbar--inline { position: static; margin-left: 2px; }
.wkt-sp-plan .ep-plan-delivblock { position: relative; }
/* Longhand font properties: the shared button CSS in this app declares
   `font: … inherit`, which is invalid and dropped whole by every browser. */
.wkt-sp-add {
  flex: 0 0 auto; width: 24px; height: 24px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid #bfdbfe; border-radius: var(--wkt-r); background: #eff6ff; color: #1d4ed8;
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  font-family: inherit; font-size: 13px; font-weight: 800; line-height: 1;
  letter-spacing: normal; text-transform: none;
}
.wkt-sp-add:hover { background: #1d4ed8; border-color: #1d4ed8; color: var(--wkt-surf); }

.wkt-split-foot {
  flex: 0 0 auto; display: flex; align-items: center; gap: 9px;
  padding: 10px 12px; border-top: 1px solid #cddffb; background: var(--wkt-surf);
}
.wkt-split-hint { flex: 1; min-width: 0; font-size: 12px; color: var(--wkt-ink-2); }
.wkt-split-acts { flex: 0 0 auto; display: flex; align-items: center; gap: 7px; }
.wkt-split-acts .wkt-from-btn { height: 32px; padding: 0 12px; font-size: 13px; }

/* − 70% + . The builder's map has no such control on purpose — it is the canvas
   under your hands. This half is a thing you read at arm's length in a column
   half a window wide, so the control is on screen and says where you are
   standing; the percentage itself is the button that hands control back to
   auto-fit. ⌘/Ctrl-scroll works in here too. */
.wkt-sp-zoom {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 2px;
  padding: 2px; border: 1px solid #dbeafe; border-radius: var(--wkt-r); background: #f6faff;
}
.wkt-sp-zbtn, .wkt-sp-zval {
  border: 0; background: transparent; color: #1d4ed8; cursor: pointer;
  border-radius: var(--wkt-r);
  font-family: inherit; font-weight: 800; line-height: 1;
  letter-spacing: normal; text-transform: none;
}
.wkt-sp-zbtn { width: 24px; height: 24px; font-size: 15px; }
.wkt-sp-zval { height: 24px; min-width: 46px; padding: 0 6px; font-size: 12px; }
.wkt-sp-zval.is-auto { color: var(--wkt-ink-3); font-weight: 700; }
.wkt-sp-zbtn:hover, .wkt-sp-zval:hover { background: #dbeafe; color: #1d4ed8; }

/* WHERE IT WILL LAND. One of these on screen at a time, in the same blue as
   the half the card came out of — so the answer to "where does this go" is
   drawn in the colour of the thing being dragged. */
.wkt-sp-target {
  outline: 2px dashed #2563eb; outline-offset: 2px;
  background: rgba(37,99,235,.07); border-radius: var(--wkt-r);
}
/* While something is in flight from the source, the builder's own hover
   invitations stand down — ghost columns and + Stage rails lighting up under
   the cursor are offers you cannot take mid-drag. */
.wkt-detail.wkt-sp-dragging .wkt-wscol-ghost { opacity: .25; pointer-events: none; }
/* The + Stage pill goes all the way out, not to .25: a stage coming across off
   the rail now paints the dashed .wkt-seam on this exact boundary, and the two
   printed on top of each other read as two different offers on one line. */
.wkt-detail.wkt-sp-dragging .wkt-stageseam { opacity: 0; pointer-events: none; }

@media (max-width: 1100px) {
  /* Below this a 50% column can't hold one 404px work-stream card at a zoom
     anyone would read, so the source gives some width back rather than the two
     halves both being unusable. */
  :root { --wkt-split-w: calc(44vw - 16px); }
}
@media (max-width: 640px) {
  /* No room for two columns on a phone: the source becomes a sheet across the
     bottom and the builder takes the top half. Both are still on screen at
     once, which is the whole point of the screen. The seam turns with them. */
  .wkt-split {
    top: auto; left: 0; right: 0; bottom: 0; width: auto; height: 46vh;
    border-left: 0; border-top: 1px solid #cddffb;
    border-radius: var(--wkt-r-lg) var(--wkt-r-lg) 0 0;
    box-shadow: 0 -18px 60px -22px rgba(15,23,42,.42);
  }
  .wkt-detail.wkt-is-split { align-items: flex-start; }
  .wkt-detail.wkt-is-split .wkt-detail-card {
    margin-left: 0; width: 100vw; height: 52vh; border-radius: 0;
    box-shadow: none;
  }
}
