/* Klippan master design system (first draft): v2 plus every master part in one stylesheet.
   Generated by klippan-master/combined/build.py from the part folders; edit the parts, then rebuild.
   Load order: v2, prompter additions, stacks, question card, teach card, adaptive card, agent browser,
   extend, transcript, approvals, diff, runs, agents, memory, inbox, delivery, projects. */

/* ===== klippan-v2/combined/klippan.css ===== */
/* Klippan design system v2: every part in one stylesheet.
   Generated by combined/build.py from the part folders; edit the parts, then rebuild. */

/* ===== foundations/tokens.css ===== */
/* Klippan v2 foundations. Generated by build.py from one source; edit build.py, not this file.
   Light on :root, dark on any element with data-theme="dark" (the board root or <html>).
   Motion tokens (--kl-motion-*) come from the Motion part. */

:root, [data-theme="light"] {
  color-scheme: light;

  /* Colour */
  --kl-color-ground: #f6f6f6;
  --kl-color-board: #fbfbfb;
  --kl-color-board-dot: rgba(0, 0, 0, 0.10);
  --kl-color-surface: #ffffff;
  --kl-color-surface-raised: #ffffff;
  --kl-color-surface-sunken: rgba(0, 0, 0, 0.03);
  --kl-color-overlay: rgba(0, 0, 0, 0.20);
  --kl-color-text: rgba(0, 0, 0, 0.85);
  --kl-color-text-secondary: rgba(0, 0, 0, 0.60);
  --kl-color-text-tertiary: #bfbfbf;
  --kl-color-text-on-fill: #ffffff;
  --kl-color-line: rgba(0, 0, 0, 0.10);
  --kl-color-line-strong: rgba(0, 0, 0, 0.23);
  --kl-color-field-border: rgba(0, 0, 0, 0.08);
  --kl-color-control-fill: rgba(0, 0, 0, 0.05);
  --kl-color-control-fill-pressed: rgba(0, 0, 0, 0.15);
  --kl-color-button-secondary: #e6e6e6;
  --kl-color-switch-off: #e9e9e9;
  --kl-color-knob: #ffffff;
  --kl-color-primary: #0a66f0;
  --kl-color-primary-hover: #0156ce;
  --kl-color-selection: #0088ff;
  --kl-color-selection-soft: #eaf3ff;
  --kl-color-selection-ink: #0a5ad4;
  --kl-color-accent: #0091ff;
  --kl-color-control: #0d6fff;
  --kl-color-focus: #0d6fff;
  --kl-color-status-executing: #19c332;
  --kl-color-status-executing-soft: #e6f5ec;
  --kl-color-status-executing-ink: #176743;
  --kl-color-status-planning: #febc2e;
  --kl-color-status-planning-soft: #fff3dc;
  --kl-color-status-planning-ink: #8a5300;
  --kl-color-status-stopped: #ff383c;
  --kl-color-status-stopped-soft: #ffe8e6;
  --kl-color-status-stopped-ink: #b4232a;
  --kl-color-status-idle: rgba(0, 0, 0, 0.25);
  --kl-color-status-stopped-wash: color-mix(in srgb, var(--kl-color-status-stopped-soft) 55%, transparent);
  --kl-color-status-approval: var(--kl-color-hue-magenta);
  --kl-color-status-approval-soft: var(--kl-color-hue-magenta-soft);
  --kl-color-status-approval-ink: var(--kl-color-hue-magenta-ink);
  --kl-color-status-review: var(--kl-color-hue-cyan);
  --kl-color-status-review-soft: var(--kl-color-hue-cyan-soft);
  --kl-color-status-review-ink: var(--kl-color-hue-cyan-ink);
  --kl-color-neutral-soft: #efefef;
  --kl-color-neutral-ink: #5c5c5c;
  --kl-color-pip-off: rgba(0, 0, 0, 0.12);
  --kl-color-match: rgba(0, 0, 0, 0.09);
  --kl-color-meter-1: var(--kl-color-control);
  --kl-color-meter-2: color-mix(in srgb, var(--kl-color-control) 72%, var(--kl-color-surface));
  --kl-color-meter-3: color-mix(in srgb, var(--kl-color-control) 50%, var(--kl-color-surface));
  --kl-color-meter-4: color-mix(in srgb, var(--kl-color-control) 34%, var(--kl-color-surface));
  --kl-color-meter-5: color-mix(in srgb, var(--kl-color-control) 20%, var(--kl-color-surface));
  --kl-color-diff-add: color-mix(in srgb, var(--kl-color-hue-green) 13%, transparent);
  --kl-color-diff-add-word: color-mix(in srgb, var(--kl-color-hue-green) 26%, transparent);
  --kl-color-diff-add-ink: var(--kl-color-hue-green-ink);
  --kl-color-diff-del: color-mix(in srgb, var(--kl-color-hue-red) 11%, transparent);
  --kl-color-diff-del-word: color-mix(in srgb, var(--kl-color-hue-red) 24%, transparent);
  --kl-color-diff-del-ink: var(--kl-color-hue-red-ink);
  --kl-color-terminal: rgba(0, 0, 0, 0.045);
  --kl-color-terminal-err: var(--kl-color-status-stopped-ink);
  --kl-color-link: var(--kl-color-selection);
  --kl-color-link-request: var(--kl-color-link);
  --kl-color-link-tether: var(--kl-color-line-strong);
  --kl-color-notice-edge: var(--kl-color-line);
  --kl-color-notice-edge-alert: color-mix(in srgb, var(--kl-color-status-stopped) 45%, transparent);
  --kl-color-siren-red: var(--kl-color-status-stopped);
  --kl-color-siren-blue: var(--kl-color-selection);
  --kl-color-siren-glow-red: color-mix(in srgb, var(--kl-color-siren-red) 18%, transparent);
  --kl-color-siren-glow-blue: color-mix(in srgb, var(--kl-color-siren-blue) 18%, transparent);
  --kl-color-siren-edge-red: color-mix(in srgb, var(--kl-color-siren-red) 26%, transparent);
  --kl-color-siren-edge-blue: color-mix(in srgb, var(--kl-color-siren-blue) 26%, transparent);
  --kl-color-helper-builder: #ff736a;
  --kl-color-helper-builder-soft: color-mix(in srgb, var(--kl-color-helper-builder) 18%, transparent);
  --kl-color-helper-builder-ink: #b4372d;
  --kl-color-helper-researcher: #febc2e;
  --kl-color-helper-researcher-soft: color-mix(in srgb, var(--kl-color-helper-researcher) 18%, transparent);
  --kl-color-helper-researcher-ink: #8a5300;
  --kl-color-helper-cleanser: #19c332;
  --kl-color-helper-cleanser-soft: color-mix(in srgb, var(--kl-color-helper-cleanser) 18%, transparent);
  --kl-color-helper-cleanser-ink: #176743;
  --kl-color-hue-purple: #8a3fd1;
  --kl-color-hue-purple-soft: #f1e8f9;
  --kl-color-hue-purple-ink: #873ecd;
  --kl-color-hue-purple-on: #ffffff;
  --kl-color-hue-teal: #007a8a;
  --kl-color-hue-teal-soft: #e0eff1;
  --kl-color-hue-teal-ink: #00707f;
  --kl-color-hue-teal-on: #ffffff;
  --kl-color-hue-green: #1f7f3a;
  --kl-color-hue-green-soft: #e4f0e7;
  --kl-color-hue-green-ink: #1d7535;
  --kl-color-hue-green-on: #ffffff;
  --kl-color-hue-indigo: #4f4dd6;
  --kl-color-hue-indigo-soft: #eaeafa;
  --kl-color-hue-indigo-ink: #4f4dd6;
  --kl-color-hue-indigo-on: #ffffff;
  --kl-color-hue-pink: #d1195f;
  --kl-color-hue-pink-soft: #f9e3ec;
  --kl-color-hue-pink-ink: #c01757;
  --kl-color-hue-pink-on: #ffffff;
  --kl-color-hue-orange: #ff9f0a;
  --kl-color-hue-orange-soft: #fff3e2;
  --kl-color-hue-orange-ink: #995f06;
  --kl-color-hue-orange-on: #1d1d1f;
  --kl-color-hue-blue: #0a66f0;
  --kl-color-hue-blue-soft: #e2edfd;
  --kl-color-hue-blue-ink: #095edd;
  --kl-color-hue-blue-on: #ffffff;
  --kl-color-hue-cerulean: #0b74b5;
  --kl-color-hue-cerulean-soft: #e2eef6;
  --kl-color-hue-cerulean-ink: #0a6ba7;
  --kl-color-hue-cerulean-on: #ffffff;
  --kl-color-hue-graphite: #2c2c34;
  --kl-color-hue-graphite-soft: #e6e6e7;
  --kl-color-hue-graphite-ink: #2c2c34;
  --kl-color-hue-graphite-on: #ffffff;
  --kl-color-hue-amber: #febc2e;
  --kl-color-hue-amber-soft: #fff7e6;
  --kl-color-hue-amber-ink: #8e691a;
  --kl-color-hue-amber-on: #1d1d1f;
  --kl-color-hue-navy: #2f4bc0;
  --kl-color-hue-navy-soft: #e6e9f7;
  --kl-color-hue-navy-ink: #2f4bc0;
  --kl-color-hue-navy-on: #ffffff;
  --kl-color-hue-red: #d4232a;
  --kl-color-hue-red-soft: #fae5e5;
  --kl-color-hue-red-ink: #c32027;
  --kl-color-hue-red-on: #ffffff;
  --kl-color-hue-brown: #7d6244;
  --kl-color-hue-brown-soft: #efece9;
  --kl-color-hue-brown-ink: #7d6244;
  --kl-color-hue-brown-on: #ffffff;
  --kl-color-hue-coral: #d23a2a;
  --kl-color-hue-coral-soft: #fae7e5;
  --kl-color-hue-coral-ink: #b93325;
  --kl-color-hue-coral-on: #ffffff;
  --kl-color-hue-magenta: #a4168f;
  --kl-color-hue-magenta-soft: #f4e3f2;
  --kl-color-hue-magenta-ink: #a4168f;
  --kl-color-hue-magenta-on: #ffffff;
  --kl-color-hue-cyan: #00a3c4;
  --kl-color-hue-cyan-soft: #e0f4f8;
  --kl-color-hue-cyan-ink: #007289;
  --kl-color-hue-cyan-on: #1d1d1f;
  --kl-color-hue-lime: #8a9a00;
  --kl-color-hue-lime-soft: #f1f3e0;
  --kl-color-hue-lime-ink: #636f00;
  --kl-color-hue-lime-on: #1d1d1f;
  --kl-color-card-settings: var(--kl-color-hue-indigo);
  --kl-color-card-settings-soft: var(--kl-color-hue-indigo-soft);
  --kl-color-card-settings-ink: var(--kl-color-hue-indigo-ink);
  --kl-color-card-settings-on: var(--kl-color-hue-indigo-on);
  --kl-color-card-presets: var(--kl-color-hue-pink);
  --kl-color-card-presets-soft: var(--kl-color-hue-pink-soft);
  --kl-color-card-presets-ink: var(--kl-color-hue-pink-ink);
  --kl-color-card-presets-on: var(--kl-color-hue-pink-on);
  --kl-color-card-alerts: var(--kl-color-hue-orange);
  --kl-color-card-alerts-soft: var(--kl-color-hue-orange-soft);
  --kl-color-card-alerts-ink: var(--kl-color-hue-orange-ink);
  --kl-color-card-alerts-on: var(--kl-color-hue-orange-on);
  --kl-color-card-requests: var(--kl-color-hue-blue);
  --kl-color-card-requests-soft: var(--kl-color-hue-blue-soft);
  --kl-color-card-requests-ink: var(--kl-color-hue-blue-ink);
  --kl-color-card-requests-on: var(--kl-color-hue-blue-on);
  --kl-color-card-context: var(--kl-color-hue-cerulean);
  --kl-color-card-context-soft: var(--kl-color-hue-cerulean-soft);
  --kl-color-card-context-ink: var(--kl-color-hue-cerulean-ink);
  --kl-color-card-context-on: var(--kl-color-hue-cerulean-on);
  --kl-color-card-knowledge: var(--kl-color-hue-graphite);
  --kl-color-card-knowledge-soft: var(--kl-color-hue-graphite-soft);
  --kl-color-card-knowledge-ink: var(--kl-color-hue-graphite-ink);
  --kl-color-card-knowledge-on: var(--kl-color-hue-graphite-on);
  --kl-color-card-tokenomy: var(--kl-color-hue-amber);
  --kl-color-card-tokenomy-soft: var(--kl-color-hue-amber-soft);
  --kl-color-card-tokenomy-ink: var(--kl-color-hue-amber-ink);
  --kl-color-card-tokenomy-on: var(--kl-color-hue-amber-on);
  --kl-color-card-police: var(--kl-color-hue-navy);
  --kl-color-card-police-soft: var(--kl-color-hue-navy-soft);
  --kl-color-card-police-ink: var(--kl-color-hue-navy-ink);
  --kl-color-card-police-on: var(--kl-color-hue-navy-on);
  --kl-color-card-ambulance: var(--kl-color-hue-red);
  --kl-color-card-ambulance-soft: var(--kl-color-hue-red-soft);
  --kl-color-card-ambulance-ink: var(--kl-color-hue-red-ink);
  --kl-color-card-ambulance-on: var(--kl-color-hue-red-on);
  --kl-color-card-garbage: var(--kl-color-hue-brown);
  --kl-color-card-garbage-soft: var(--kl-color-hue-brown-soft);
  --kl-color-card-garbage-ink: var(--kl-color-hue-brown-ink);
  --kl-color-card-garbage-on: var(--kl-color-hue-brown-on);
  --kl-color-card-klippan: var(--kl-color-hue-blue);
  --kl-color-card-klippan-soft: var(--kl-color-hue-blue-soft);
  --kl-color-card-klippan-ink: var(--kl-color-hue-blue-ink);
  --kl-color-card-klippan-on: var(--kl-color-hue-blue-on);
  --kl-color-card-inbox: var(--kl-color-hue-indigo);
  --kl-color-card-inbox-soft: var(--kl-color-hue-indigo-soft);
  --kl-color-card-inbox-ink: var(--kl-color-hue-indigo-ink);
  --kl-color-card-inbox-on: var(--kl-color-hue-indigo-on);
  --kl-color-card-teach: var(--kl-color-hue-lime);
  --kl-color-card-teach-soft: var(--kl-color-hue-lime-soft);
  --kl-color-card-teach-ink: var(--kl-color-hue-lime-ink);
  --kl-color-card-teach-on: var(--kl-color-hue-lime-on);
  --kl-color-card-runs: var(--kl-color-hue-graphite);
  --kl-color-card-runs-soft: var(--kl-color-hue-graphite-soft);
  --kl-color-card-runs-ink: var(--kl-color-hue-graphite-ink);
  --kl-color-card-runs-on: var(--kl-color-hue-graphite-on);
  --kl-color-project-1: var(--kl-color-hue-purple);
  --kl-color-project-1-soft: var(--kl-color-hue-purple-soft);
  --kl-color-project-1-ink: var(--kl-color-hue-purple-ink);
  --kl-color-project-1-on: var(--kl-color-hue-purple-on);
  --kl-color-project-2: var(--kl-color-hue-teal);
  --kl-color-project-2-soft: var(--kl-color-hue-teal-soft);
  --kl-color-project-2-ink: var(--kl-color-hue-teal-ink);
  --kl-color-project-2-on: var(--kl-color-hue-teal-on);
  --kl-color-project-3: var(--kl-color-hue-green);
  --kl-color-project-3-soft: var(--kl-color-hue-green-soft);
  --kl-color-project-3-ink: var(--kl-color-hue-green-ink);
  --kl-color-project-3-on: var(--kl-color-hue-green-on);
  --kl-color-project-4: var(--kl-color-hue-pink);
  --kl-color-project-4-soft: var(--kl-color-hue-pink-soft);
  --kl-color-project-4-ink: var(--kl-color-hue-pink-ink);
  --kl-color-project-4-on: var(--kl-color-hue-pink-on);
  --kl-color-project-5: var(--kl-color-hue-cerulean);
  --kl-color-project-5-soft: var(--kl-color-hue-cerulean-soft);
  --kl-color-project-5-ink: var(--kl-color-hue-cerulean-ink);
  --kl-color-project-5-on: var(--kl-color-hue-cerulean-on);
  --kl-color-project-6: var(--kl-color-hue-orange);
  --kl-color-project-6-soft: var(--kl-color-hue-orange-soft);
  --kl-color-project-6-ink: var(--kl-color-hue-orange-ink);
  --kl-color-project-6-on: var(--kl-color-hue-orange-on);
  --kl-color-project-7: var(--kl-color-hue-indigo);
  --kl-color-project-7-soft: var(--kl-color-hue-indigo-soft);
  --kl-color-project-7-ink: var(--kl-color-hue-indigo-ink);
  --kl-color-project-7-on: var(--kl-color-hue-indigo-on);
  --kl-color-project-8: var(--kl-color-hue-brown);
  --kl-color-project-8-soft: var(--kl-color-hue-brown-soft);
  --kl-color-project-8-ink: var(--kl-color-hue-brown-ink);
  --kl-color-project-8-on: var(--kl-color-hue-brown-on);
  --kl-color-teach: var(--kl-color-card-teach);
  --kl-color-teach-soft: var(--kl-color-card-teach-soft);
  --kl-color-teach-ink: var(--kl-color-card-teach-ink);
  --kl-color-stack: var(--kl-color-project-1);
  --kl-color-stack-rim: color-mix(in srgb, var(--kl-color-stack) 46%, transparent);
  --kl-color-stack-rim-strong: color-mix(in srgb, var(--kl-color-stack) 78%, transparent);
  --kl-color-stack-wash: color-mix(in srgb, var(--kl-color-stack) 4%, transparent);
  --kl-color-stack-wash-named: color-mix(in srgb, var(--kl-color-stack) 9%, transparent);
  --kl-color-stack-wash-joining: color-mix(in srgb, var(--kl-color-stack) 11%, transparent);
  --kl-color-stack-slot: color-mix(in srgb, var(--kl-color-stack) 12%, transparent);
  --kl-color-stack-slot-edge: color-mix(in srgb, var(--kl-color-stack) 72%, transparent);

  /* Type */
  --kl-font-sans: Geist, -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro", system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  --kl-font-mono: "Geist Mono", ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  --kl-font-weight-regular: 400;
  --kl-font-weight-medium: 510;
  --kl-font-weight-semibold: 590;
  --kl-font-weight-bold: 700;
  --kl-font-display: 700 28px/34px var(--kl-font-sans);
  --kl-font-display-size: 28px;
  --kl-font-display-line: 34px;
  --kl-font-display-weight: 700;
  --kl-font-display-tracking: -0.6px;
  --kl-font-title: 700 20px/24px var(--kl-font-sans);
  --kl-font-title-size: 20px;
  --kl-font-title-line: 24px;
  --kl-font-title-weight: 700;
  --kl-font-title-tracking: -0.3px;
  --kl-font-headline: 700 15px/20px var(--kl-font-sans);
  --kl-font-headline-size: 15px;
  --kl-font-headline-line: 20px;
  --kl-font-headline-weight: 700;
  --kl-font-headline-tracking: 0;
  --kl-font-body: 400 15px/22px var(--kl-font-sans);
  --kl-font-body-size: 15px;
  --kl-font-body-line: 22px;
  --kl-font-body-weight: 400;
  --kl-font-body-tracking: 0;
  --kl-font-label: 510 13px/16px var(--kl-font-sans);
  --kl-font-label-size: 13px;
  --kl-font-label-line: 16px;
  --kl-font-label-weight: 510;
  --kl-font-label-tracking: 0;
  --kl-font-label-strong: 700 13px/16px var(--kl-font-sans);
  --kl-font-label-strong-size: 13px;
  --kl-font-label-strong-line: 16px;
  --kl-font-label-strong-weight: 700;
  --kl-font-label-strong-tracking: -0.26px;
  --kl-font-meta: 400 13px/18px var(--kl-font-sans);
  --kl-font-meta-size: 13px;
  --kl-font-meta-line: 18px;
  --kl-font-meta-weight: 400;
  --kl-font-meta-tracking: 0;
  --kl-font-badge: 590 12px/16px var(--kl-font-sans);
  --kl-font-badge-size: 12px;
  --kl-font-badge-line: 16px;
  --kl-font-badge-weight: 590;
  --kl-font-badge-tracking: 0;
  --kl-font-caption: 510 11px/14px var(--kl-font-sans);
  --kl-font-caption-size: 11px;
  --kl-font-caption-line: 14px;
  --kl-font-caption-weight: 510;
  --kl-font-caption-tracking: 0;
  --kl-font-code: 400 12px/20px var(--kl-font-mono);
  --kl-font-code-size: 12px;
  --kl-font-code-line: 20px;
  --kl-font-code-weight: 400;
  --kl-font-code-tracking: 0;

  /* Spacing and board grid */
  --kl-space-half: 2px;
  --kl-space-1: 4px;
  --kl-space-2: 8px;
  --kl-space-3: 12px;
  --kl-space-4: 16px;
  --kl-space-5: 20px;
  --kl-space-6: 24px;
  --kl-space-8: 32px;
  --kl-space-10: 40px;
  --kl-space-12: 48px;
  --kl-space-16: 64px;
  --kl-space-24: 96px;
  --kl-space-grid: 24px;
  --kl-space-grid-wide: 48px;
  --kl-space-stack-pad: 14px;
  --kl-space-stack-gap: 10px;

  /* Radius */
  --kl-radius-sheet: 5px;
  --kl-radius-control: 6px;
  --kl-radius-row: 8px;
  --kl-radius-tile: 10px;
  --kl-radius-groupbox: 12px;
  --kl-radius-menu: 13px;
  --kl-radius-draft: 14px;
  --kl-radius-notice: 16px;
  --kl-radius-panel: 18px;
  --kl-radius-prompter: 24px;
  --kl-radius-card: 26px;
  --kl-radius-prompter-expanded: 28px;
  --kl-radius-glass: 34px;
  --kl-radius-pill: 1000px;
  --kl-radius-round: 50%;
  --kl-radius-mark: 3px;
  --kl-radius-bubble-tail: 6px;
  --kl-radius-stack: calc(var(--kl-radius-card) + var(--kl-space-stack-pad));

  /* Elevation */
  --kl-shadow-card: 0 0 0 1px rgba(0, 0, 0, 0.08), 0 1px 3px rgba(0, 0, 0, 0.06), 0 8px 24px rgba(0, 0, 0, 0.06);
  --kl-shadow-card-hover: 0 0 0 1px rgba(0, 0, 0, 0.23), 0 1px 3px rgba(0, 0, 0, 0.06), 0 8px 24px rgba(0, 0, 0, 0.08);
  --kl-shadow-card-lifted: 0 0 0 1px rgba(0, 0, 0, 0.10), 0 4px 8px rgba(0, 0, 0, 0.08), 0 18px 40px rgba(0, 0, 0, 0.16);
  --kl-shadow-window: 0 0 0 1px rgba(0, 0, 0, 0.23), 0 16px 48px rgba(0, 0, 0, 0.35);
  --kl-shadow-window-drag: 0 0 0 1px rgba(0, 0, 0, 0.23), 0 28px 64px rgba(0, 0, 0, 0.32);
  --kl-shadow-menu: 0 0 2px rgba(0, 0, 0, 0.10), 0 0 25px rgba(0, 0, 0, 0.16);
  --kl-shadow-bubble: 0 0 0 1px var(--kl-color-notice-edge), 0 1px 3px rgba(0, 0, 0, 0.06), 0 8px 24px rgba(0, 0, 0, 0.08);
  --kl-shadow-bubble-alert: 0 0 0 1px var(--kl-color-notice-edge-alert), 0 1px 3px rgba(0, 0, 0, 0.06), 0 8px 24px rgba(0, 0, 0, 0.08);
  --kl-shadow-knob: 0 0 1px rgba(0, 0, 0, 0.05), 0 0 4px rgba(0, 0, 0, 0.05), 0 1px 4px rgba(0, 0, 0, 0.18);
  --kl-shadow-ring-selection: 0 0 0 2px var(--kl-color-selection);
  --kl-shadow-ring-target: 0 0 0 2px var(--kl-color-selection), 0 0 0 6px var(--kl-color-selection-soft);
  --kl-shadow-ring-stuck: 0 0 0 7px color-mix(in srgb, var(--kl-color-status-stopped) 12%, transparent);
  --kl-shadow-ring-focus: 0 0 0 3px var(--kl-color-selection-soft);
  --kl-shadow-cursor: 0 1px 2px rgba(0, 0, 0, 0.28);

  /* EYEos Liquid Glass */
  --kl-glass-fill: rgba(250, 250, 250, 0.80);
  --kl-glass-fill-medium: rgba(245, 245, 245, 0.67);
  --kl-glass-fill-menu: rgba(245, 245, 245, 0.67);
  --kl-glass-fill-solid: #f5f5f5;
  --kl-glass-tint: #0091ff;
  --kl-glass-blur: 15px;
  --kl-glass-blur-bar: 30px;
  --kl-glass-saturate: 180%;
  --kl-glass-filter: blur(15px) saturate(180%);
  --kl-glass-filter-bar: blur(30px) saturate(180%);
  --kl-glass-rim: inset 0 0 0 1px rgba(255, 255, 255, 0.45), inset 0 1px 1px rgba(255, 255, 255, 0.60);
  --kl-glass-shadow: 0 8px 40px rgba(0, 0, 0, 0.12);
  --kl-glass-chip: color-mix(in srgb, var(--kl-color-surface) 66%, transparent);
  --kl-glass-card: var(--kl-glass-fill);
  --kl-glass-card-projects: var(--kl-glass-card);
  --kl-glass-card-purple: color-mix(in srgb, var(--kl-color-hue-purple) 14%, var(--kl-glass-fill));
  --kl-glass-card-teal: color-mix(in srgb, var(--kl-color-hue-teal) 14%, var(--kl-glass-fill));
  --kl-glass-card-green: color-mix(in srgb, var(--kl-color-hue-green) 14%, var(--kl-glass-fill));
  --kl-glass-card-indigo: color-mix(in srgb, var(--kl-color-hue-indigo) 14%, var(--kl-glass-fill));
  --kl-glass-card-pink: color-mix(in srgb, var(--kl-color-hue-pink) 14%, var(--kl-glass-fill));
  --kl-glass-card-orange: color-mix(in srgb, var(--kl-color-hue-orange) 14%, var(--kl-glass-fill));
  --kl-glass-card-blue: color-mix(in srgb, var(--kl-color-hue-blue) 14%, var(--kl-glass-fill));
  --kl-glass-card-cerulean: color-mix(in srgb, var(--kl-color-hue-cerulean) 14%, var(--kl-glass-fill));
  --kl-glass-card-graphite: color-mix(in srgb, var(--kl-color-hue-graphite) 14%, var(--kl-glass-fill));
  --kl-glass-card-amber: color-mix(in srgb, var(--kl-color-hue-amber) 14%, var(--kl-glass-fill));
  --kl-glass-card-navy: color-mix(in srgb, var(--kl-color-hue-navy) 14%, var(--kl-glass-fill));
  --kl-glass-card-red: color-mix(in srgb, var(--kl-color-hue-red) 14%, var(--kl-glass-fill));
  --kl-glass-card-brown: color-mix(in srgb, var(--kl-color-hue-brown) 14%, var(--kl-glass-fill));
  --kl-glass-card-coral: color-mix(in srgb, var(--kl-color-hue-coral) 14%, var(--kl-glass-fill));
  --kl-glass-card-magenta: color-mix(in srgb, var(--kl-color-hue-magenta) 14%, var(--kl-glass-fill));
  --kl-glass-card-cyan: color-mix(in srgb, var(--kl-color-hue-cyan) 14%, var(--kl-glass-fill));
  --kl-glass-card-lime: color-mix(in srgb, var(--kl-color-hue-lime) 14%, var(--kl-glass-fill));
  --kl-glass-card-settings: var(--kl-glass-card-indigo);
  --kl-glass-card-presets: var(--kl-glass-card-pink);
  --kl-glass-card-alerts: var(--kl-glass-card-orange);
  --kl-glass-card-requests: var(--kl-glass-card-blue);
  --kl-glass-card-context: var(--kl-glass-card-cerulean);
  --kl-glass-card-knowledge: var(--kl-glass-card-graphite);
  --kl-glass-card-tokenomy: var(--kl-glass-card-amber);
  --kl-glass-card-police: var(--kl-glass-card-navy);
  --kl-glass-card-ambulance: var(--kl-glass-card-red);
  --kl-glass-card-garbage: var(--kl-glass-card-brown);
  --kl-glass-card-klippan: var(--kl-glass-card-blue);
  --kl-glass-card-inbox: var(--kl-glass-card-indigo);
  --kl-glass-card-teach: var(--kl-glass-card-lime);
  --kl-glass-card-runs: var(--kl-glass-card-graphite);
  --kl-glass-card-project-1: var(--kl-glass-card-purple);
  --kl-glass-card-project-2: var(--kl-glass-card-teal);
  --kl-glass-card-project-3: var(--kl-glass-card-green);
  --kl-glass-card-project-4: var(--kl-glass-card-pink);
  --kl-glass-card-project-5: var(--kl-glass-card-cerulean);
  --kl-glass-card-project-6: var(--kl-glass-card-orange);
  --kl-glass-card-project-7: var(--kl-glass-card-indigo);
  --kl-glass-card-project-8: var(--kl-glass-card-brown);
  --kl-glass-card-filter: var(--kl-glass-filter);
  --kl-glass-card-shadow: var(--kl-glass-rim), 0 0 0 1px rgba(0, 0, 0, 0.06), 0 1px 3px rgba(0, 0, 0, 0.06), 0 8px 24px rgba(0, 0, 0, 0.08);
  --kl-glass-card-shadow-hover: var(--kl-glass-rim), 0 0 0 1px rgba(0, 0, 0, 0.14), 0 1px 3px rgba(0, 0, 0, 0.06), 0 10px 28px rgba(0, 0, 0, 0.10);

  /* Icons */
  --kl-icon-size: 20px;
  --kl-icon-stroke: 1.6;
  --kl-icon-stroke-small: 2;
  --kl-icon-tile: 28px;

  /* Control sizes */
  --kl-size-control: 24px;
  --kl-size-button: 28px;
  --kl-size-button-large: 36px;
  --kl-size-target: 44px;
  --kl-size-prompter-expanded: 720px;
  --kl-size-prompter-pane: 272px;

  /* Stacking order */
  --kl-z-under: 1;
  --kl-z-card: 2;
  --kl-z-roamer: 3;
  --kl-z-rider-under: 39;
  --kl-z-prompter: 40;
  --kl-z-switcher: 41;
  --kl-z-card-open: 42;
  --kl-z-front: 43;
  --kl-z-drag: 44;
  --kl-z-link: 45;
  --kl-z-tag: 46;
  --kl-z-window: 50;
  --kl-z-home: 60;
  --kl-z-window-over-home: 65;
  --kl-z-menu: 80;
  --kl-z-scrim: 100;
  --kl-z-bubble: 900;
  --kl-z-zoom: 950;
}

/* Dark. Tokens that point at other tokens are repeated so they resolve against dark values. */
[data-theme="dark"] {
  color-scheme: dark;

  /* Colour */
  --kl-color-ground: #141414;
  --kl-color-board: #1c1c1c;
  --kl-color-board-dot: rgba(255, 255, 255, 0.08);
  --kl-color-surface: #282828;
  --kl-color-surface-raised: #303030;
  --kl-color-surface-sunken: rgba(255, 255, 255, 0.05);
  --kl-color-overlay: rgba(0, 0, 0, 0.40);
  --kl-color-text: rgba(255, 255, 255, 0.85);
  --kl-color-text-secondary: rgba(255, 255, 255, 0.60);
  --kl-color-text-tertiary: rgba(255, 255, 255, 0.35);
  --kl-color-line: rgba(255, 255, 255, 0.10);
  --kl-color-line-strong: rgba(255, 255, 255, 0.23);
  --kl-color-field-border: rgba(255, 255, 255, 0.12);
  --kl-color-control-fill: rgba(255, 255, 255, 0.12);
  --kl-color-control-fill-pressed: rgba(255, 255, 255, 0.20);
  --kl-color-button-secondary: rgba(255, 255, 255, 0.16);
  --kl-color-switch-off: rgba(255, 255, 255, 0.16);
  --kl-color-primary-hover: #2a7bff;
  --kl-color-selection-soft: rgba(0, 136, 255, 0.20);
  --kl-color-selection-ink: #6cb4ff;
  --kl-color-focus: #4c9bff;
  --kl-color-status-executing: #30d158;
  --kl-color-status-executing-soft: rgba(25, 195, 50, 0.18);
  --kl-color-status-executing-ink: #6edb8a;
  --kl-color-status-planning-soft: rgba(254, 188, 46, 0.18);
  --kl-color-status-planning-ink: #ffc95c;
  --kl-color-status-stopped-soft: rgba(255, 56, 60, 0.20);
  --kl-color-status-stopped-ink: #ff8a84;
  --kl-color-status-idle: rgba(255, 255, 255, 0.30);
  --kl-color-status-stopped-wash: color-mix(in srgb, var(--kl-color-status-stopped-soft) 55%, transparent);
  --kl-color-status-approval: var(--kl-color-hue-magenta);
  --kl-color-status-approval-soft: var(--kl-color-hue-magenta-soft);
  --kl-color-status-approval-ink: var(--kl-color-hue-magenta-ink);
  --kl-color-status-review: var(--kl-color-hue-cyan);
  --kl-color-status-review-soft: var(--kl-color-hue-cyan-soft);
  --kl-color-status-review-ink: var(--kl-color-hue-cyan-ink);
  --kl-color-neutral-soft: rgba(255, 255, 255, 0.10);
  --kl-color-neutral-ink: rgba(255, 255, 255, 0.75);
  --kl-color-pip-off: rgba(255, 255, 255, 0.16);
  --kl-color-match: rgba(255, 255, 255, 0.14);
  --kl-color-meter-1: var(--kl-color-control);
  --kl-color-meter-2: color-mix(in srgb, var(--kl-color-control) 76%, var(--kl-color-surface));
  --kl-color-meter-3: color-mix(in srgb, var(--kl-color-control) 56%, var(--kl-color-surface));
  --kl-color-meter-4: color-mix(in srgb, var(--kl-color-control) 40%, var(--kl-color-surface));
  --kl-color-meter-5: color-mix(in srgb, var(--kl-color-control) 28%, var(--kl-color-surface));
  --kl-color-diff-add: color-mix(in srgb, var(--kl-color-hue-green) 13%, transparent);
  --kl-color-diff-add-word: color-mix(in srgb, var(--kl-color-hue-green) 26%, transparent);
  --kl-color-diff-add-ink: var(--kl-color-hue-green-ink);
  --kl-color-diff-del: color-mix(in srgb, var(--kl-color-hue-red) 11%, transparent);
  --kl-color-diff-del-word: color-mix(in srgb, var(--kl-color-hue-red) 24%, transparent);
  --kl-color-diff-del-ink: var(--kl-color-hue-red-ink);
  --kl-color-terminal: rgba(255, 255, 255, 0.06);
  --kl-color-terminal-err: var(--kl-color-status-stopped-ink);
  --kl-color-link: var(--kl-color-selection);
  --kl-color-link-request: var(--kl-color-link);
  --kl-color-link-tether: var(--kl-color-line-strong);
  --kl-color-notice-edge: var(--kl-color-line);
  --kl-color-notice-edge-alert: color-mix(in srgb, var(--kl-color-status-stopped) 45%, transparent);
  --kl-color-siren-red: var(--kl-color-status-stopped);
  --kl-color-siren-blue: var(--kl-color-selection);
  --kl-color-siren-glow-red: color-mix(in srgb, var(--kl-color-siren-red) 22%, transparent);
  --kl-color-siren-glow-blue: color-mix(in srgb, var(--kl-color-siren-blue) 22%, transparent);
  --kl-color-siren-edge-red: color-mix(in srgb, var(--kl-color-siren-red) 34%, transparent);
  --kl-color-siren-edge-blue: color-mix(in srgb, var(--kl-color-siren-blue) 34%, transparent);
  --kl-color-helper-builder-soft: color-mix(in srgb, var(--kl-color-helper-builder) 18%, transparent);
  --kl-color-helper-builder-ink: #ff9b94;
  --kl-color-helper-researcher-soft: color-mix(in srgb, var(--kl-color-helper-researcher) 18%, transparent);
  --kl-color-helper-researcher-ink: #ffc95c;
  --kl-color-helper-cleanser-soft: color-mix(in srgb, var(--kl-color-helper-cleanser) 18%, transparent);
  --kl-color-helper-cleanser-ink: #6edb8a;
  --kl-color-hue-purple-soft: rgba(138, 63, 209, 0.22);
  --kl-color-hue-purple-ink: #b688e2;
  --kl-color-hue-teal-soft: rgba(0, 122, 138, 0.22);
  --kl-color-hue-teal-ink: #5caab4;
  --kl-color-hue-green-soft: rgba(31, 127, 58, 0.22);
  --kl-color-hue-green-ink: #70ad81;
  --kl-color-hue-indigo-soft: rgba(79, 77, 214, 0.22);
  --kl-color-hue-indigo-ink: #9594e6;
  --kl-color-hue-pink-soft: rgba(209, 25, 95, 0.22);
  --kl-color-hue-pink-ink: #e47aa2;
  --kl-color-hue-orange-soft: rgba(255, 159, 10, 0.22);
  --kl-color-hue-orange-ink: #ff9f0a;
  --kl-color-hue-blue-soft: rgba(10, 102, 240, 0.22);
  --kl-color-hue-blue-ink: #67a0f6;
  --kl-color-hue-cerulean-soft: rgba(11, 116, 181, 0.22);
  --kl-color-hue-cerulean-ink: #63a6d0;
  --kl-color-hue-graphite: #5a5a66;
  --kl-color-hue-graphite-soft: rgba(90, 90, 102, 0.22);
  --kl-color-hue-graphite-ink: #9c9ca3;
  --kl-color-hue-amber-soft: rgba(254, 188, 46, 0.22);
  --kl-color-hue-amber-ink: #febc2e;
  --kl-color-hue-navy: #4a66d8;
  --kl-color-hue-navy-soft: rgba(74, 102, 216, 0.22);
  --kl-color-hue-navy-ink: #8b9de6;
  --kl-color-hue-red-soft: rgba(212, 35, 42, 0.22);
  --kl-color-hue-red-ink: #e57b7f;
  --kl-color-hue-brown: #8a6d4d;
  --kl-color-hue-brown-soft: rgba(138, 109, 77, 0.22);
  --kl-color-hue-brown-ink: #b29f8a;
  --kl-color-hue-coral-soft: rgba(210, 58, 42, 0.22);
  --kl-color-hue-coral-ink: #e3857b;
  --kl-color-hue-magenta: #c030ac;
  --kl-color-hue-magenta-soft: rgba(192, 48, 172, 0.22);
  --kl-color-hue-magenta-ink: #d87fcc;
  --kl-color-hue-cyan: #2fb8d0;
  --kl-color-hue-cyan-soft: rgba(47, 184, 208, 0.22);
  --kl-color-hue-cyan-ink: #44bfd5;
  --kl-color-hue-lime: #a3b414;
  --kl-color-hue-lime-soft: rgba(163, 180, 20, 0.22);
  --kl-color-hue-lime-ink: #aaba27;
  --kl-color-card-settings: var(--kl-color-hue-indigo);
  --kl-color-card-settings-soft: var(--kl-color-hue-indigo-soft);
  --kl-color-card-settings-ink: var(--kl-color-hue-indigo-ink);
  --kl-color-card-settings-on: var(--kl-color-hue-indigo-on);
  --kl-color-card-presets: var(--kl-color-hue-pink);
  --kl-color-card-presets-soft: var(--kl-color-hue-pink-soft);
  --kl-color-card-presets-ink: var(--kl-color-hue-pink-ink);
  --kl-color-card-presets-on: var(--kl-color-hue-pink-on);
  --kl-color-card-alerts: var(--kl-color-hue-orange);
  --kl-color-card-alerts-soft: var(--kl-color-hue-orange-soft);
  --kl-color-card-alerts-ink: var(--kl-color-hue-orange-ink);
  --kl-color-card-alerts-on: var(--kl-color-hue-orange-on);
  --kl-color-card-requests: var(--kl-color-hue-blue);
  --kl-color-card-requests-soft: var(--kl-color-hue-blue-soft);
  --kl-color-card-requests-ink: var(--kl-color-hue-blue-ink);
  --kl-color-card-requests-on: var(--kl-color-hue-blue-on);
  --kl-color-card-context: var(--kl-color-hue-cerulean);
  --kl-color-card-context-soft: var(--kl-color-hue-cerulean-soft);
  --kl-color-card-context-ink: var(--kl-color-hue-cerulean-ink);
  --kl-color-card-context-on: var(--kl-color-hue-cerulean-on);
  --kl-color-card-knowledge: var(--kl-color-hue-graphite);
  --kl-color-card-knowledge-soft: var(--kl-color-hue-graphite-soft);
  --kl-color-card-knowledge-ink: var(--kl-color-hue-graphite-ink);
  --kl-color-card-knowledge-on: var(--kl-color-hue-graphite-on);
  --kl-color-card-tokenomy: var(--kl-color-hue-amber);
  --kl-color-card-tokenomy-soft: var(--kl-color-hue-amber-soft);
  --kl-color-card-tokenomy-ink: var(--kl-color-hue-amber-ink);
  --kl-color-card-tokenomy-on: var(--kl-color-hue-amber-on);
  --kl-color-card-police: var(--kl-color-hue-navy);
  --kl-color-card-police-soft: var(--kl-color-hue-navy-soft);
  --kl-color-card-police-ink: var(--kl-color-hue-navy-ink);
  --kl-color-card-police-on: var(--kl-color-hue-navy-on);
  --kl-color-card-ambulance: var(--kl-color-hue-red);
  --kl-color-card-ambulance-soft: var(--kl-color-hue-red-soft);
  --kl-color-card-ambulance-ink: var(--kl-color-hue-red-ink);
  --kl-color-card-ambulance-on: var(--kl-color-hue-red-on);
  --kl-color-card-garbage: var(--kl-color-hue-brown);
  --kl-color-card-garbage-soft: var(--kl-color-hue-brown-soft);
  --kl-color-card-garbage-ink: var(--kl-color-hue-brown-ink);
  --kl-color-card-garbage-on: var(--kl-color-hue-brown-on);
  --kl-color-card-klippan: var(--kl-color-hue-blue);
  --kl-color-card-klippan-soft: var(--kl-color-hue-blue-soft);
  --kl-color-card-klippan-ink: var(--kl-color-hue-blue-ink);
  --kl-color-card-klippan-on: var(--kl-color-hue-blue-on);
  --kl-color-card-inbox: var(--kl-color-hue-indigo);
  --kl-color-card-inbox-soft: var(--kl-color-hue-indigo-soft);
  --kl-color-card-inbox-ink: var(--kl-color-hue-indigo-ink);
  --kl-color-card-inbox-on: var(--kl-color-hue-indigo-on);
  --kl-color-card-teach: var(--kl-color-hue-lime);
  --kl-color-card-teach-soft: var(--kl-color-hue-lime-soft);
  --kl-color-card-teach-ink: var(--kl-color-hue-lime-ink);
  --kl-color-card-teach-on: var(--kl-color-hue-lime-on);
  --kl-color-card-runs: var(--kl-color-hue-graphite);
  --kl-color-card-runs-soft: var(--kl-color-hue-graphite-soft);
  --kl-color-card-runs-ink: var(--kl-color-hue-graphite-ink);
  --kl-color-card-runs-on: var(--kl-color-hue-graphite-on);
  --kl-color-project-1: var(--kl-color-hue-purple);
  --kl-color-project-1-soft: var(--kl-color-hue-purple-soft);
  --kl-color-project-1-ink: var(--kl-color-hue-purple-ink);
  --kl-color-project-1-on: var(--kl-color-hue-purple-on);
  --kl-color-project-2: var(--kl-color-hue-teal);
  --kl-color-project-2-soft: var(--kl-color-hue-teal-soft);
  --kl-color-project-2-ink: var(--kl-color-hue-teal-ink);
  --kl-color-project-2-on: var(--kl-color-hue-teal-on);
  --kl-color-project-3: var(--kl-color-hue-green);
  --kl-color-project-3-soft: var(--kl-color-hue-green-soft);
  --kl-color-project-3-ink: var(--kl-color-hue-green-ink);
  --kl-color-project-3-on: var(--kl-color-hue-green-on);
  --kl-color-project-4: var(--kl-color-hue-pink);
  --kl-color-project-4-soft: var(--kl-color-hue-pink-soft);
  --kl-color-project-4-ink: var(--kl-color-hue-pink-ink);
  --kl-color-project-4-on: var(--kl-color-hue-pink-on);
  --kl-color-project-5: var(--kl-color-hue-cerulean);
  --kl-color-project-5-soft: var(--kl-color-hue-cerulean-soft);
  --kl-color-project-5-ink: var(--kl-color-hue-cerulean-ink);
  --kl-color-project-5-on: var(--kl-color-hue-cerulean-on);
  --kl-color-project-6: var(--kl-color-hue-orange);
  --kl-color-project-6-soft: var(--kl-color-hue-orange-soft);
  --kl-color-project-6-ink: var(--kl-color-hue-orange-ink);
  --kl-color-project-6-on: var(--kl-color-hue-orange-on);
  --kl-color-project-7: var(--kl-color-hue-indigo);
  --kl-color-project-7-soft: var(--kl-color-hue-indigo-soft);
  --kl-color-project-7-ink: var(--kl-color-hue-indigo-ink);
  --kl-color-project-7-on: var(--kl-color-hue-indigo-on);
  --kl-color-project-8: var(--kl-color-hue-brown);
  --kl-color-project-8-soft: var(--kl-color-hue-brown-soft);
  --kl-color-project-8-ink: var(--kl-color-hue-brown-ink);
  --kl-color-project-8-on: var(--kl-color-hue-brown-on);
  --kl-color-teach: var(--kl-color-card-teach);
  --kl-color-teach-soft: var(--kl-color-card-teach-soft);
  --kl-color-teach-ink: var(--kl-color-card-teach-ink);
  --kl-color-stack: var(--kl-color-project-1);
  --kl-color-stack-rim: color-mix(in srgb, var(--kl-color-stack) 46%, transparent);
  --kl-color-stack-rim-strong: color-mix(in srgb, var(--kl-color-stack) 78%, transparent);
  --kl-color-stack-wash: color-mix(in srgb, var(--kl-color-stack) 4%, transparent);
  --kl-color-stack-wash-named: color-mix(in srgb, var(--kl-color-stack) 9%, transparent);
  --kl-color-stack-wash-joining: color-mix(in srgb, var(--kl-color-stack) 11%, transparent);
  --kl-color-stack-slot: color-mix(in srgb, var(--kl-color-stack) 12%, transparent);
  --kl-color-stack-slot-edge: color-mix(in srgb, var(--kl-color-stack) 72%, transparent);

  /* Type */
  --kl-font-display: 700 28px/34px var(--kl-font-sans);
  --kl-font-title: 700 20px/24px var(--kl-font-sans);
  --kl-font-headline: 700 15px/20px var(--kl-font-sans);
  --kl-font-body: 400 15px/22px var(--kl-font-sans);
  --kl-font-label: 510 13px/16px var(--kl-font-sans);
  --kl-font-label-strong: 700 13px/16px var(--kl-font-sans);
  --kl-font-meta: 400 13px/18px var(--kl-font-sans);
  --kl-font-badge: 590 12px/16px var(--kl-font-sans);
  --kl-font-caption: 510 11px/14px var(--kl-font-sans);
  --kl-font-code: 400 12px/20px var(--kl-font-mono);

  /* Radius */
  --kl-radius-stack: calc(var(--kl-radius-card) + var(--kl-space-stack-pad));

  /* Elevation */
  --kl-shadow-card: 0 0 0 1px rgba(255, 255, 255, 0.08), 0 1px 3px rgba(0, 0, 0, 0.40), 0 8px 24px rgba(0, 0, 0, 0.35);
  --kl-shadow-card-hover: 0 0 0 1px rgba(255, 255, 255, 0.23), 0 1px 3px rgba(0, 0, 0, 0.40), 0 8px 24px rgba(0, 0, 0, 0.40);
  --kl-shadow-card-lifted: 0 0 0 1px rgba(255, 255, 255, 0.12), 0 4px 8px rgba(0, 0, 0, 0.45), 0 18px 40px rgba(0, 0, 0, 0.55);
  --kl-shadow-window: 0 0 0 1px rgba(255, 255, 255, 0.12), 0 16px 48px rgba(0, 0, 0, 0.60);
  --kl-shadow-window-drag: 0 0 0 1px rgba(255, 255, 255, 0.16), 0 28px 64px rgba(0, 0, 0, 0.65);
  --kl-shadow-menu: 0 0 0 1px rgba(255, 255, 255, 0.10), 0 0 25px rgba(0, 0, 0, 0.50);
  --kl-shadow-bubble: 0 0 0 1px var(--kl-color-notice-edge), 0 1px 3px rgba(0, 0, 0, 0.40), 0 8px 24px rgba(0, 0, 0, 0.40);
  --kl-shadow-bubble-alert: 0 0 0 1px var(--kl-color-notice-edge-alert), 0 1px 3px rgba(0, 0, 0, 0.40), 0 8px 24px rgba(0, 0, 0, 0.40);
  --kl-shadow-knob: 0 0 1px rgba(0, 0, 0, 0.20), 0 0 4px rgba(0, 0, 0, 0.20), 0 1px 4px rgba(0, 0, 0, 0.45);
  --kl-shadow-ring-selection: 0 0 0 2px var(--kl-color-selection);
  --kl-shadow-ring-target: 0 0 0 2px var(--kl-color-selection), 0 0 0 6px var(--kl-color-selection-soft);
  --kl-shadow-ring-stuck: 0 0 0 7px color-mix(in srgb, var(--kl-color-status-stopped) 18%, transparent);
  --kl-shadow-ring-focus: 0 0 0 3px var(--kl-color-selection-soft);
  --kl-shadow-cursor: 0 1px 3px rgba(0, 0, 0, 0.60);

  /* EYEos Liquid Glass */
  --kl-glass-fill: rgba(10, 10, 10, 0.62);
  --kl-glass-fill-medium: rgba(8, 8, 8, 0.50);
  --kl-glass-fill-menu: rgba(30, 30, 30, 0.55);
  --kl-glass-fill-solid: #262626;
  --kl-glass-rim: inset 0 0 0 1px rgba(255, 255, 255, 0.14), inset 0 1px 1px rgba(255, 255, 255, 0.20);
  --kl-glass-shadow: 0 8px 40px rgba(0, 0, 0, 0.40);
  --kl-glass-chip: color-mix(in srgb, var(--kl-color-surface) 66%, transparent);
  --kl-glass-card: var(--kl-glass-fill);
  --kl-glass-card-projects: var(--kl-glass-card);
  --kl-glass-card-purple: color-mix(in srgb, var(--kl-color-hue-purple) 24%, var(--kl-glass-fill));
  --kl-glass-card-teal: color-mix(in srgb, var(--kl-color-hue-teal) 24%, var(--kl-glass-fill));
  --kl-glass-card-green: color-mix(in srgb, var(--kl-color-hue-green) 24%, var(--kl-glass-fill));
  --kl-glass-card-indigo: color-mix(in srgb, var(--kl-color-hue-indigo) 24%, var(--kl-glass-fill));
  --kl-glass-card-pink: color-mix(in srgb, var(--kl-color-hue-pink) 24%, var(--kl-glass-fill));
  --kl-glass-card-orange: color-mix(in srgb, var(--kl-color-hue-orange) 24%, var(--kl-glass-fill));
  --kl-glass-card-blue: color-mix(in srgb, var(--kl-color-hue-blue) 24%, var(--kl-glass-fill));
  --kl-glass-card-cerulean: color-mix(in srgb, var(--kl-color-hue-cerulean) 24%, var(--kl-glass-fill));
  --kl-glass-card-graphite: color-mix(in srgb, var(--kl-color-hue-graphite) 24%, var(--kl-glass-fill));
  --kl-glass-card-amber: color-mix(in srgb, var(--kl-color-hue-amber) 24%, var(--kl-glass-fill));
  --kl-glass-card-navy: color-mix(in srgb, var(--kl-color-hue-navy) 24%, var(--kl-glass-fill));
  --kl-glass-card-red: color-mix(in srgb, var(--kl-color-hue-red) 24%, var(--kl-glass-fill));
  --kl-glass-card-brown: color-mix(in srgb, var(--kl-color-hue-brown) 24%, var(--kl-glass-fill));
  --kl-glass-card-coral: color-mix(in srgb, var(--kl-color-hue-coral) 24%, var(--kl-glass-fill));
  --kl-glass-card-magenta: color-mix(in srgb, var(--kl-color-hue-magenta) 24%, var(--kl-glass-fill));
  --kl-glass-card-cyan: color-mix(in srgb, var(--kl-color-hue-cyan) 24%, var(--kl-glass-fill));
  --kl-glass-card-lime: color-mix(in srgb, var(--kl-color-hue-lime) 24%, var(--kl-glass-fill));
  --kl-glass-card-settings: var(--kl-glass-card-indigo);
  --kl-glass-card-presets: var(--kl-glass-card-pink);
  --kl-glass-card-alerts: var(--kl-glass-card-orange);
  --kl-glass-card-requests: var(--kl-glass-card-blue);
  --kl-glass-card-context: var(--kl-glass-card-cerulean);
  --kl-glass-card-knowledge: var(--kl-glass-card-graphite);
  --kl-glass-card-tokenomy: var(--kl-glass-card-amber);
  --kl-glass-card-police: var(--kl-glass-card-navy);
  --kl-glass-card-ambulance: var(--kl-glass-card-red);
  --kl-glass-card-garbage: var(--kl-glass-card-brown);
  --kl-glass-card-klippan: var(--kl-glass-card-blue);
  --kl-glass-card-inbox: var(--kl-glass-card-indigo);
  --kl-glass-card-teach: var(--kl-glass-card-lime);
  --kl-glass-card-runs: var(--kl-glass-card-graphite);
  --kl-glass-card-project-1: var(--kl-glass-card-purple);
  --kl-glass-card-project-2: var(--kl-glass-card-teal);
  --kl-glass-card-project-3: var(--kl-glass-card-green);
  --kl-glass-card-project-4: var(--kl-glass-card-pink);
  --kl-glass-card-project-5: var(--kl-glass-card-cerulean);
  --kl-glass-card-project-6: var(--kl-glass-card-orange);
  --kl-glass-card-project-7: var(--kl-glass-card-indigo);
  --kl-glass-card-project-8: var(--kl-glass-card-brown);
  --kl-glass-card-filter: var(--kl-glass-filter);
  --kl-glass-card-shadow: var(--kl-glass-rim), 0 0 0 1px rgba(255, 255, 255, 0.06), 0 1px 3px rgba(0, 0, 0, 0.40), 0 8px 24px rgba(0, 0, 0, 0.40);
  --kl-glass-card-shadow-hover: var(--kl-glass-rim), 0 0 0 1px rgba(255, 255, 255, 0.16), 0 1px 3px rgba(0, 0, 0, 0.40), 0 10px 28px rgba(0, 0, 0, 0.45);
}

/* Increased contrast: glass turns solid, secondary text darkens. */
/* Increased contrast, from the system setting or the app setting (data-contrast="more" on the root or the board):
   cards and glass turn opaque with an outline, secondary text and lines darken. */
@media (prefers-contrast: more) {
  :root, [data-theme] { --kl-glass-fill: var(--kl-glass-fill-solid); --kl-glass-fill-medium: var(--kl-glass-fill-solid); --kl-glass-fill-menu: var(--kl-glass-fill-solid); --kl-glass-filter: none; --kl-glass-filter-bar: none; --kl-glass-card-filter: none; --kl-glass-card-shadow: 0 0 0 1px var(--kl-color-line-strong), 0 1px 3px rgba(0, 0, 0, 0.06), 0 8px 24px rgba(0, 0, 0, 0.06); --kl-glass-card-shadow-hover: 0 0 0 1.5px var(--kl-color-line-strong), 0 1px 3px rgba(0, 0, 0, 0.06), 0 8px 24px rgba(0, 0, 0, 0.08); --kl-glass-card: var(--kl-color-surface); --kl-glass-card-projects: var(--kl-color-surface); --kl-glass-card-purple: var(--kl-color-surface); --kl-glass-card-teal: var(--kl-color-surface); --kl-glass-card-green: var(--kl-color-surface); --kl-glass-card-indigo: var(--kl-color-surface); --kl-glass-card-pink: var(--kl-color-surface); --kl-glass-card-orange: var(--kl-color-surface); --kl-glass-card-blue: var(--kl-color-surface); --kl-glass-card-cerulean: var(--kl-color-surface); --kl-glass-card-graphite: var(--kl-color-surface); --kl-glass-card-amber: var(--kl-color-surface); --kl-glass-card-navy: var(--kl-color-surface); --kl-glass-card-red: var(--kl-color-surface); --kl-glass-card-brown: var(--kl-color-surface); --kl-glass-card-coral: var(--kl-color-surface); --kl-glass-card-magenta: var(--kl-color-surface); --kl-glass-card-cyan: var(--kl-color-surface); --kl-glass-card-lime: var(--kl-color-surface); --kl-glass-card-settings: var(--kl-color-surface); --kl-glass-card-presets: var(--kl-color-surface); --kl-glass-card-alerts: var(--kl-color-surface); --kl-glass-card-requests: var(--kl-color-surface); --kl-glass-card-context: var(--kl-color-surface); --kl-glass-card-knowledge: var(--kl-color-surface); --kl-glass-card-tokenomy: var(--kl-color-surface); --kl-glass-card-police: var(--kl-color-surface); --kl-glass-card-ambulance: var(--kl-color-surface); --kl-glass-card-garbage: var(--kl-color-surface); --kl-glass-card-klippan: var(--kl-color-surface); --kl-glass-card-inbox: var(--kl-color-surface); --kl-glass-card-teach: var(--kl-color-surface); --kl-glass-card-runs: var(--kl-color-surface); --kl-glass-card-project-1: var(--kl-color-surface); --kl-glass-card-project-2: var(--kl-color-surface); --kl-glass-card-project-3: var(--kl-color-surface); --kl-glass-card-project-4: var(--kl-color-surface); --kl-glass-card-project-5: var(--kl-color-surface); --kl-glass-card-project-6: var(--kl-color-surface); --kl-glass-card-project-7: var(--kl-color-surface); --kl-glass-card-project-8: var(--kl-color-surface); }
  :root, [data-theme="light"] { --kl-color-text-secondary: rgba(0, 0, 0, 0.72); --kl-color-line: rgba(0, 0, 0, 0.20); --kl-color-line-strong: rgba(0, 0, 0, 0.40); }
  [data-theme="dark"] { --kl-color-text-secondary: rgba(255, 255, 255, 0.75); --kl-color-line: rgba(255, 255, 255, 0.22); --kl-color-line-strong: rgba(255, 255, 255, 0.45); }
}
[data-contrast="more"], [data-contrast="more"] [data-theme] { --kl-glass-fill: var(--kl-glass-fill-solid); --kl-glass-fill-medium: var(--kl-glass-fill-solid); --kl-glass-fill-menu: var(--kl-glass-fill-solid); --kl-glass-filter: none; --kl-glass-filter-bar: none; --kl-glass-card-filter: none; --kl-glass-card-shadow: 0 0 0 1px var(--kl-color-line-strong), 0 1px 3px rgba(0, 0, 0, 0.06), 0 8px 24px rgba(0, 0, 0, 0.06); --kl-glass-card-shadow-hover: 0 0 0 1.5px var(--kl-color-line-strong), 0 1px 3px rgba(0, 0, 0, 0.06), 0 8px 24px rgba(0, 0, 0, 0.08); --kl-glass-card: var(--kl-color-surface); --kl-glass-card-projects: var(--kl-color-surface); --kl-glass-card-purple: var(--kl-color-surface); --kl-glass-card-teal: var(--kl-color-surface); --kl-glass-card-green: var(--kl-color-surface); --kl-glass-card-indigo: var(--kl-color-surface); --kl-glass-card-pink: var(--kl-color-surface); --kl-glass-card-orange: var(--kl-color-surface); --kl-glass-card-blue: var(--kl-color-surface); --kl-glass-card-cerulean: var(--kl-color-surface); --kl-glass-card-graphite: var(--kl-color-surface); --kl-glass-card-amber: var(--kl-color-surface); --kl-glass-card-navy: var(--kl-color-surface); --kl-glass-card-red: var(--kl-color-surface); --kl-glass-card-brown: var(--kl-color-surface); --kl-glass-card-coral: var(--kl-color-surface); --kl-glass-card-magenta: var(--kl-color-surface); --kl-glass-card-cyan: var(--kl-color-surface); --kl-glass-card-lime: var(--kl-color-surface); --kl-glass-card-settings: var(--kl-color-surface); --kl-glass-card-presets: var(--kl-color-surface); --kl-glass-card-alerts: var(--kl-color-surface); --kl-glass-card-requests: var(--kl-color-surface); --kl-glass-card-context: var(--kl-color-surface); --kl-glass-card-knowledge: var(--kl-color-surface); --kl-glass-card-tokenomy: var(--kl-color-surface); --kl-glass-card-police: var(--kl-color-surface); --kl-glass-card-ambulance: var(--kl-color-surface); --kl-glass-card-garbage: var(--kl-color-surface); --kl-glass-card-klippan: var(--kl-color-surface); --kl-glass-card-inbox: var(--kl-color-surface); --kl-glass-card-teach: var(--kl-color-surface); --kl-glass-card-runs: var(--kl-color-surface); --kl-glass-card-project-1: var(--kl-color-surface); --kl-glass-card-project-2: var(--kl-color-surface); --kl-glass-card-project-3: var(--kl-color-surface); --kl-glass-card-project-4: var(--kl-color-surface); --kl-glass-card-project-5: var(--kl-color-surface); --kl-glass-card-project-6: var(--kl-color-surface); --kl-glass-card-project-7: var(--kl-color-surface); --kl-glass-card-project-8: var(--kl-color-surface); }
[data-contrast="more"], [data-contrast="more"] [data-theme="light"] { --kl-color-text-secondary: rgba(0, 0, 0, 0.72); --kl-color-line: rgba(0, 0, 0, 0.20); --kl-color-line-strong: rgba(0, 0, 0, 0.40); }
[data-contrast="more"][data-theme="dark"], [data-theme="dark"] [data-contrast="more"], [data-contrast="more"] [data-theme="dark"] { --kl-color-text-secondary: rgba(255, 255, 255, 0.75); --kl-color-line: rgba(255, 255, 255, 0.22); --kl-color-line-strong: rgba(255, 255, 255, 0.45); }

/* A stack recomputes its colours from its own hue: set --kl-color-stack on .kl-stack. */
.kl-stack {
  --kl-color-stack-rim: color-mix(in srgb, var(--kl-color-stack) 46%, transparent);
  --kl-color-stack-rim-strong: color-mix(in srgb, var(--kl-color-stack) 78%, transparent);
  --kl-color-stack-wash: color-mix(in srgb, var(--kl-color-stack) 4%, transparent);
  --kl-color-stack-wash-named: color-mix(in srgb, var(--kl-color-stack) 9%, transparent);
  --kl-color-stack-wash-joining: color-mix(in srgb, var(--kl-color-stack) 11%, transparent);
  --kl-color-stack-slot: color-mix(in srgb, var(--kl-color-stack) 12%, transparent);
  --kl-color-stack-slot-edge: color-mix(in srgb, var(--kl-color-stack) 72%, transparent);
}

/* Type styles as classes, for specimens and quick markup. */
.kl-display { font: var(--kl-font-display); letter-spacing: var(--kl-font-display-tracking); }
.kl-title { font: var(--kl-font-title); letter-spacing: var(--kl-font-title-tracking); }
.kl-headline { font: var(--kl-font-headline); letter-spacing: var(--kl-font-headline-tracking); }
.kl-body { font: var(--kl-font-body); letter-spacing: var(--kl-font-body-tracking); }
.kl-label { font: var(--kl-font-label); letter-spacing: var(--kl-font-label-tracking); }
.kl-label-strong { font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-meta { font: var(--kl-font-meta); letter-spacing: var(--kl-font-meta-tracking); }
.kl-badge { font: var(--kl-font-badge); letter-spacing: var(--kl-font-badge-tracking); }
.kl-caption { font: var(--kl-font-caption); letter-spacing: var(--kl-font-caption-tracking); }
.kl-code { font: var(--kl-font-code); letter-spacing: 0; font-variant-ligatures: none; }
/* The one .kl-mono: mono face inside running text, keeping the size around it. */
.kl-mono { font-family: var(--kl-font-mono); font-variant-ligatures: none; }

/* ===== motion/motion.css ===== */
/* Klippan design system v2: Motion
   Every animation and transition on the Klippan board, as --kl-motion-* tokens, keyframes and a few kl-m-* classes.
   The rules behind them (springs, the playfulness dial, the quiet rules) are in README.md; motion.js holds the
   script half (springs, pk(), the curves the dial writes, the quiet gate).

   Feel: calm and only slightly playful. The playfulness dial runs 0 (calmest) to 100 (Step 8's playful pass);
   35 is the default. --kl-motion-k is the dial as 0..1. Every squash, hop, bounce, lean, bell swing and drift below
   scales with it. Linking never does: it is light, not a line (Alban, 2026-10-13), and feels the same at every setting.

   Colours come from foundations (foundations/tokens.css). Each one falls back to the v1 name and then a literal, so
   this file also works on its own. NEEDS.md lists what is read from foundations.

   Only transform, scale, translate, rotate, opacity, clip-path, outline-offset and box-shadow animate here, with two
   exceptions asked for by the master parts: kl-m-grow glides grid-template-rows (a block opening its height) and
   kl-m-filled fades a background tint. */

:root {
  /* ---------- The dial ---------- */
  --kl-motion-k: .35;                                    /* playfulness 0..1 (dial 35); motion.js writes it */

  /* ---------- Eases ---------- */
  --kl-motion-ease-out: cubic-bezier(0.22, 1, 0.36, 1);  /* the soft ease-out for everything that is not a spring */
  --kl-motion-ease-in: cubic-bezier(0.4, 0, 1, 1);       /* things leaving */
  --kl-motion-ease-soft: var(--kl-motion-ease-out);     /* alias: v1's ease-out-soft name, used by the Foundations specimen */
  /* Spring curves at dial 35. motion.js rewrites these three for the dial's value (springCurve), and at 100 sets the
     Step 8 curves below. spring: opens, pops, landings (6% × k overshoot). soft: bigger things, windows, a card
     falling back to its tilt (3% × k). pop: the older small pops, press and badge (10% × k). */
  --kl-motion-spring: linear(0, 0.036, 0.124, 0.239, 0.363, 0.486, 0.598, 0.697, 0.78, 0.848, 0.902, 0.942, 0.972, 0.993, 1.007, 1.015, 1.02, 1.021, 1.02, 1.019, 1.016, 1.014, 1.011, 1.009, 1.007, 1.005, 1.003, 1.002, 1);
  --kl-motion-spring-soft: linear(0, 0.032, 0.11, 0.214, 0.326, 0.439, 0.544, 0.638, 0.72, 0.789, 0.845, 0.89, 0.926, 0.953, 0.973, 0.987, 0.997, 1.004, 1.008, 1.01, 1.01, 1.01, 1.01, 1.009, 1.007, 1.006, 1.005, 1.004, 1);
  --kl-motion-spring-pop: linear(0, 0.041, 0.14, 0.268, 0.406, 0.538, 0.658, 0.76, 0.844, 0.909, 0.957, 0.991, 1.014, 1.027, 1.033, 1.035, 1.033, 1.03, 1.025, 1.02, 1.016, 1.012, 1.008, 1.005, 1.003, 1.001, 1, 0.999, 1);
  /* Reference ends of the dial (motion.js picks between these and the computed ones) */
  --kl-motion-spring-calm: linear(0, 0.022, 0.076, 0.149, 0.231, 0.314, 0.396, 0.473, 0.544, 0.609, 0.666, 0.717, 0.762, 0.8, 0.833, 0.862, 0.886, 0.907, 0.924, 0.939, 0.952, 0.962, 0.971, 0.978, 0.984, 0.989, 0.994, 0.997, 1);
  --kl-motion-spring-step8: linear(0, .049, .168, .32, .478, .627, .756, .86, .94, .995, 1.031, 1.051, 1.059, 1.059, 1.053, 1.045, 1.035, 1.026, 1.018, 1.011, 1.005, 1.002, .999, .997, .997, .996, .997, .997, 1);
  --kl-motion-spring-soft-step8: linear(0, .044, .149, .283, .424, .557, .676, .776, .855, .916, .961, .991, 1.011, 1.022, 1.027, 1.028, 1.027, 1.023, 1.019, 1.015, 1.012, 1.009, 1.006, 1.004, 1.002, 1.001, 1, 1, 1);
  --kl-motion-spring-pop-step8: cubic-bezier(0.34, 1.56, 0.64, 1);
  /* The spring for permanent link lines between linked cards (request, sync): the same at every dial setting */
  --kl-motion-ease-link: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* ---------- Durations: touch ---------- */
  --kl-motion-hover: 150ms;          /* hover: shadow only */
  --kl-motion-press: 120ms;          /* click feedback on buttons and controls */
  --kl-motion-squash: 260ms;         /* a card pressed: squashes wider and shorter, soft rebound */
  --kl-motion-squash-hold: 90ms;     /* a section card or roamer held down (:active) */
  --kl-motion-lift: 300ms;           /* a card picked up for dragging grows to 1.03 */
  --kl-motion-land-drop: 440ms;      /* a dragged card set down */
  --kl-motion-land: 420ms;           /* a card something lands in (a window, a helper, a sent prompt) */
  --kl-motion-tilt: 460ms;           /* falling back to the resting tilt, on spring-soft */
  --kl-motion-lean-follow: 90ms;     /* rotate follows --kl-motion-lean while dragging */

  /* ---------- Durations: open and close ---------- */
  --kl-motion-expand: 380ms;         /* card or prompter grows */
  --kl-motion-collapse: 260ms;
  --kl-motion-reveal: 220ms;         /* each content block fades and rises */
  --kl-motion-reveal-delay: 90ms;
  --kl-motion-reveal-step: 35ms;     /* × --i per block */
  --kl-motion-reveal-shift: 6px;
  --kl-motion-fade: 120ms;           /* the one motion kept under reduced motion */
  --kl-motion-fade-out: 120ms;
  --kl-motion-win-open: 420ms;       /* on spring-soft, from .94 and 12px toward its card */
  --kl-motion-win-close: 160ms;
  --kl-motion-win-min: 260ms;        /* shrinks toward its card (scale .2) */
  --kl-motion-menu-in: 300ms;        /* on spring, from 4px above and .96 */
  --kl-motion-menu-out: 130ms;
  --kl-motion-theme: 260ms;          /* light and dark cross-fade (view transition) */
  --kl-motion-meter: 560ms;          /* a meter fills from empty as its card opens */
  --kl-motion-toast: 5s;             /* how long the Undo toast stays (e.g. after File Cleanser's Approve) */

  /* ---------- Durations: board movement ---------- */
  --kl-motion-travel: 700ms;         /* a roamer or the siren light moving to its next spot */
  --kl-motion-roam-in: 360ms;        /* a roamer arrives: .6 to 1 */
  --kl-motion-roam-out: 280ms;       /* leaves: .6, 16px up */
  --kl-motion-drift: 14s;            /* a parked roamer drifts (within about 12px × dk) */

  /* ---------- Speech bubbles ---------- */
  --kl-motion-say-in: 380ms;         /* pops from .85 and 4px toward its speaker, on spring */
  --kl-motion-say-out: 200ms;
  --kl-motion-say-late: 700ms;       /* a reply bubble waits for the first */
  --kl-motion-say-hold-news: 2600ms; /* a news tag stays this long */
  --kl-motion-say-hold-min: 2600ms;  /* other bubbles: 1600ms + 40ms a character, between min and max */
  --kl-motion-say-hold-max: 6000ms;
  --kl-motion-say-hold-warn: 1400ms; /* a warning stays this much longer */
  --kl-motion-hop: 380ms;            /* the speaker hops once */
  --kl-motion-nudge: 240ms;          /* a warning bubble nudges 2px once it has popped */
  --kl-motion-news-ring: 700ms;      /* a project card with news sends one ring out from its edge */

  /* ---------- Signals: status dot, count, siren, rays, errors ---------- */
  --kl-motion-dot-executing: 1.8s;   /* ring out and breathe */
  --kl-motion-dot-planning: 2.8s;
  --kl-motion-dot-alert: 900ms;      /* stopped and waiting: the ring runs faster */
  --kl-motion-dot-siren: 1.2s;       /* Ambulance dot: red and blue, stepped */
  --kl-motion-roamer-pulse: 1.6s;    /* the dot before a roamer's status line */
  --kl-motion-dot-colour: 260ms;     /* a dot changing colour cross-fades... */
  --kl-motion-dot-pop: 420ms;        /* ...and pops once */
  --kl-motion-roll-in: 420ms;        /* agent count: the new number rises in on spring */
  --kl-motion-roll-out: 220ms;       /* the old one slides up and out */
  --kl-motion-roll-shift: 85%;
  --kl-motion-count-pop: 360ms;      /* a badge appearing */
  --kl-motion-count-bump: 380ms;     /* a badge whose number changes */
  --kl-motion-write: 620ms;          /* a status line writes itself in, left to right */
  --kl-motion-rise: 220ms;           /* step text cross-fades with a 4px rise */
  --kl-motion-siren: 1.2s;           /* Ambulance: red lobes trade brightness */
  --kl-motion-police: 1s;            /* Police on an alarm: blue and red */
  --kl-motion-watch: 2.4s;           /* Police watching: a slow blue breath */
  --kl-motion-glow-k: 18%;           /* strength of the light pool on the board */
  --kl-motion-edge-k: 26%;           /* strength on the edge of the card they work on */
  --kl-motion-attention: 3s;         /* stopped card: the dashed rays breathe, one ring a beat */
  --kl-motion-alert-pulse: 2s;       /* Alerts card ring and bell */
  --kl-motion-shake: 360ms;          /* a card that hits an error shakes its face once (3px) */
  --kl-motion-shake-sm: 300ms;       /* the prompter when Send can't go (2px) */
  --kl-motion-flash: 300ms;          /* the empty draft field flashes red */
  --kl-motion-flash-amber: 600ms;    /* an agent count at its maximum flashes amber */

  /* ---------- Link line (fixed, never scaled by the dial) ---------- */
  /* Linking is light, not a line: the side of the source card facing the pointer glows, a soft pool of light follows the
     pointer on the board, and the target's edge lights only while the pointer is on it. */
  --kl-motion-link-snap: 200ms;      /* a glow comes on: source edge, pool, target edge */
  --kl-motion-link-cancel: 180ms;    /* a glow goes out: pointer leaves the target, the board or the window; Esc */
  --kl-motion-link-attach: 320ms;    /* click on the target: its edge stays lit this long, then fades; the card lands */
  --kl-motion-link-follow: 160ms;    /* the pool and the lit side trail the pointer this much (time constant) */
  --kl-motion-link-pool: 200px;      /* the pool's diameter (at board size; cards 224 to 264 wide) */
  --kl-motion-link-pool-k: 30%;      /* the pool's strength at its centre (42% dark) */
  --kl-motion-link-reach: 110px;     /* how far round the source card's edge the glow spreads from the point facing the pointer */
  --kl-motion-link-glow: 18px;       /* the edge glow's blur */
  /* Permanent link lines between linked cards (request, sync) still use these; Alban is deciding on them separately */
  --kl-motion-link-flow: 900ms;      /* a light runs along a permanent line */
  --kl-motion-link-settle: 280ms;
  /* Not used since the glow gesture (2026-10-13); kept so older references still resolve */
  --kl-motion-link-pickup: 160ms;    /* unused: the line's tip popping in */
  --kl-motion-link-pulse: 1800ms;    /* unused: the ring pulsing from a held link's origin */
  --kl-motion-link-rope: 600ms;      /* unused: the v1 rope settle time */
  --kl-motion-can-drop: 1.6s;        /* while a link is held, the cards it can go to breathe a faint ring (still below 50) */

  /* ---------- The quiet rules (read by motion.js, see README) ---------- */
  --kl-motion-quiet-after: 1500ms;   /* nothing ambient starts until this long after a drag, link, pull, pan or keystroke */
  --kl-motion-typing-window: 4000ms; /* typing counts as busy for this long after the last key */

  /* ---------- Asked for by the master parts (2026-10-13) ---------- */
  --kl-motion-spin: 760ms;           /* one turn of every busy spinner (kl-m-spin): connecting, signing in, a hook running */
  --kl-motion-cursor-glide: 560ms;   /* the agent browser's pointer gliding to its next target, on spring */
  --kl-motion-click-ring: 520ms;     /* the ring where that pointer clicks (kl-m-click-ring) */
  --kl-motion-caret: 1s;             /* a typing caret blinks (kl-m-caret), only while typing */
  --kl-motion-pop: 380ms;            /* a suggestion, tag or picked day arrives (kl-m-pop), on spring-pop */
  --kl-motion-filled: 1100ms;        /* a field filled from a suggestion: the selection tint fades back (kl-m-filled) */
  --kl-motion-msgtag-travel: var(--kl-motion-travel); /* a message tag travelling along its link (same at every dial value) */
  --kl-motion-row-in: 180ms;         /* a list row arriving at the tail, e.g. the transcript (kl-m-row-in) */
  --kl-motion-hunk-fold: var(--kl-motion-collapse);   /* a reverted diff hunk folding shut (kl-m-grow closing) */
  --kl-motion-hunk-unfold: var(--kl-motion-expand);   /* Undo opening it again */
  --kl-motion-ask-fold: 420ms;       /* an answered question card folds back into its asker (kl-m-fold), ease-in */
  --kl-motion-ask-fold-after: 4000ms; /* ...this long after the answer, and then only once the board is quiet */
  --kl-motion-switcher-in: var(--kl-motion-menu-in);  /* the project switcher opening, on spring */
  --kl-motion-freed: 1600ms;         /* the freed-space outline after Memory compacts, fading */
  --kl-motion-shelf-in: var(--kl-motion-say-in);      /* an output landing on the delivery shelf, on spring-pop */
  --kl-motion-shelf-shift: var(--kl-motion-expand);   /* the others sliding along, on spring-soft */
  /* Stacks: dropping a card on another to stack them, and pulling one out (KlMotion.STACK, KlMotion.stackStretch) */
  --kl-motion-stack-dwell: 280ms;    /* hold over a card this long before its slot opens */
  --kl-motion-stack-slot: 220ms;     /* the slot and the preview frame open, on spring */
  --kl-motion-stack-form: 260ms;     /* the preview frame turns into the real one on drop; also the let-go dip */
  --kl-motion-stack-stagger: 30ms;   /* between cards when a stack collapses or opens */
  --kl-motion-stack-dissolve: 180ms; /* the frame goes when one card is left */

  /* ---------- Live values the script writes ---------- */
  --kl-motion-lean: 0deg;            /* the dragged card's lean, up to 3deg × k */
}

/* Values worked out from the dial and from foundations. They are declared again on every themed element and on the
   element KlMotion.apply() writes to (.kl-m-root), so a board root with its own data-theme or dial value resolves them
   itself instead of inheriting :root's. */
:root, [data-theme], .kl-m-root {
  --kl-motion-dk: calc(.3 + .7 * var(--kl-motion-k));    /* drift and bell scale: never quite 0, so ambient things still read */
  --kl-motion-hop-h: calc(1px + 3px * var(--kl-motion-k)); /* the speaker's hop */
  --kl-motion-row-rise: calc(2px + 2px * var(--kl-motion-k)); /* an arriving row rises this much (4px at 100) */
  /* A project changing hue: every hued thing (card glass, tile, link line, stack frame, marks) cross-fades together on
     ease-out (kl-m-recolor); its status dot pops once (kl-m-dot-pop). Calmer is slower: 560ms at 0, 504ms at 35, 400ms at 100 */
  --kl-motion-recolor: calc(560ms - 160ms * var(--kl-motion-k));
  /* ---------- Colours (from foundations, falling back to v1 names) ---------- */
  --kl-motion-tint-accent: var(--kl-color-selection, var(--selection, #0088ff));
  --kl-motion-tint-accent-soft: var(--kl-color-selection-soft, var(--selection-soft, rgba(0, 136, 255, .14)));
  --kl-motion-tint-accent-ink: var(--kl-color-selection-ink, var(--selection-ink, #0068c8));
  --kl-motion-tint-stopped: var(--kl-color-status-stopped, var(--stopped, #ff383c));
  /* Waiting on Alban's approval. Foundations is picking the hue (--kl-color-status-approval); until then it is the stopped red */
  --kl-motion-tint-approval: var(--kl-color-status-approval, var(--kl-motion-tint-stopped));
  --kl-motion-tint-planning: var(--kl-color-status-planning, var(--planning, #ff8d28));
  --kl-motion-tint-planning-soft: var(--kl-color-status-planning-soft, var(--planning-soft, rgba(255, 141, 40, .16)));
  --kl-motion-tint-planning-ink: var(--kl-color-status-planning-ink, var(--planning-ink, #b25000));
  --kl-motion-tint-surface: var(--kl-color-surface, var(--surface, #fff));
  --kl-motion-radius-card: var(--kl-radius-card, var(--radius-card, 26px));
}
[data-theme="dark"] { --kl-motion-glow-k: 22%; --kl-motion-edge-k: 34%; --kl-motion-link-pool-k: 42%; }

/* Shapes the animations need (static, so outside the motion query) */
/* Siren light pool: a .kl-m-glow positioned under the vehicle (zero width, at its light bar) holds two .kl-m-lobe */
.kl-m-glow { pointer-events: none; }
.kl-m-lobe { position: absolute; top: -96px; width: var(--kl-m-lobe-w, 300px); height: var(--kl-m-lobe-h, 230px); margin-left: calc(var(--kl-m-lobe-w, 300px) / -2);
  border-radius: 50%; opacity: .25; pointer-events: none; mix-blend-mode: multiply; background: radial-gradient(closest-side, var(--kl-lobe, transparent), transparent); }
[data-theme="dark"] .kl-m-lobe { mix-blend-mode: screen; }
.kl-m-lobe:first-child { left: calc(50% - 46px); }
.kl-m-lobe + .kl-m-lobe { left: calc(50% + 46px); }
/* Count roll: the old and new numbers share one cell, clipped */
.kl-m-roll { display: inline-grid; overflow: hidden; vertical-align: bottom; line-height: inherit; font-variant-numeric: tabular-nums; }
.kl-m-roll > span { grid-area: 1 / 1; }
.kl-m-roll-old { opacity: 0; }
/* Linking glow. .kl-m-link-pool sits on the board (under the cards) and is moved to the pointer with transform
   (motion.js linkGlow). A card that can glow holds an empty .kl-m-link-edge as its last child; on the source card it is
   masked to the side facing the pointer (--kl-gx/--kl-gy: that point in the card, in px). The glow takes the card's corner
   radius; if the radius sits on an inner face instead, give .kl-m-link-edge that radius. */
.kl-m-link-pool { position: absolute; left: 0; top: 0; z-index: 0; width: var(--kl-motion-link-pool); height: var(--kl-motion-link-pool);
  margin: calc(var(--kl-motion-link-pool) / -2) 0 0 calc(var(--kl-motion-link-pool) / -2); border-radius: 50%; pointer-events: none; opacity: 0;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--kl-motion-tint-accent) var(--kl-motion-link-pool-k), transparent), transparent);
  transition: opacity var(--kl-motion-link-cancel) ease; }
.kl-m-link-pool.is-on { opacity: 1; transition-duration: var(--kl-motion-link-snap); }
.kl-m-link-edge { position: absolute; inset: calc(-1 * var(--kl-motion-link-glow)); border-radius: inherit; pointer-events: none; opacity: 0;
  transition: opacity var(--kl-motion-link-cancel) ease; }
.kl-m-link-edge::before { content: ""; position: absolute; inset: var(--kl-motion-link-glow); border-radius: inherit;
  box-shadow: 0 0 0 1.5px var(--kl-motion-tint-accent), 0 0 var(--kl-motion-link-glow) 3px color-mix(in srgb, var(--kl-motion-tint-accent) 50%, transparent); }
.kl-m-link-source > .kl-m-link-edge {
  -webkit-mask-image: radial-gradient(circle var(--kl-motion-link-reach) at calc(var(--kl-gx, 50%) + var(--kl-motion-link-glow)) calc(var(--kl-gy, 50%) + var(--kl-motion-link-glow)), #000 25%, transparent 100%);
  mask-image: radial-gradient(circle var(--kl-motion-link-reach) at calc(var(--kl-gx, 50%) + var(--kl-motion-link-glow)) calc(var(--kl-gy, 50%) + var(--kl-motion-link-glow)), #000 25%, transparent 100%); }
.kl-m-link-source.is-glowing > .kl-m-link-edge, .kl-m-target > .kl-m-link-edge { opacity: 1; transition-duration: var(--kl-motion-link-snap); }
.kl-m-attached > .kl-m-link-edge { opacity: 1; transition: opacity var(--kl-motion-link-attach) ease; }
/* A target with no .kl-m-link-edge child lights its own edge */
.kl-m-target:not(:has(> .kl-m-link-edge)) { box-shadow: 0 0 0 1.5px var(--kl-motion-tint-accent), 0 0 var(--kl-motion-link-glow) 3px color-mix(in srgb, var(--kl-motion-tint-accent) 50%, transparent); }
/* The siren reflection's ::before sits at z-index -1: the board (or card's parent) needs isolation: isolate */
.kl-m-lit { position: relative; }
/* Rays in another tint: a card waiting on Alban's approval rather than stopped */
.kl-m-rays--approval { --kl-m-rays-c: var(--kl-motion-tint-approval); }
/* Grow: a block that opens its height in place and fades in. Wrap the content in one child; add .is-in to open,
   remove it to fold shut. Height glides (ease-out in, ease-in out), never bounces. The open and shut states hold under
   reduced motion too; only the glide goes. Diff's hunks set --kl-m-grow-in/-out to the hunk tokens. */
.kl-m-grow { display: grid; grid-template-rows: 0fr; opacity: 0; }
.kl-m-grow > * { min-height: 0; overflow: hidden; }
.kl-m-grow.is-in { grid-template-rows: 1fr; opacity: 1; }
.kl-m-grow.is-in > * { overflow: visible; }
/* Step ring and click ring need a box to sit in */
.kl-m-ring { position: relative; }
.kl-m-click-ring { pointer-events: none; }

/* =====================================================================================================
   Classes. Add the class to play it once; to replay, remove it, force a reflow and add it again
   (motion.js replay(el, cls) does that). The Step 10 board used a/b twin class names for the same effect.
   ===================================================================================================== */
@media (prefers-reduced-motion: no-preference) {
  /* --- Touch --- */
  .kl-m-press { animation: kl-press var(--kl-motion-press) var(--kl-motion-spring-pop); }
  .kl-m-squash { animation: kl-squash var(--kl-motion-squash) ease-out; }
  .kl-m-hold:active { scale: calc(1 + .012 * var(--kl-motion-k)) calc(1 - .025 * var(--kl-motion-k)); transition: scale var(--kl-motion-squash-hold) ease-out; }
  .kl-m-lift { animation: kl-lift var(--kl-motion-lift) var(--kl-motion-spring) both; }
  .kl-m-land-drop { animation: kl-land-drop var(--kl-motion-land-drop) ease-out; }
  .kl-m-land { animation: kl-land var(--kl-motion-land) ease-out; }
  .kl-m-tilt { transition: rotate var(--kl-motion-tilt) var(--kl-motion-spring-soft); }
  .kl-m-dragging { rotate: var(--kl-motion-lean); transition: rotate var(--kl-motion-lean-follow) ease-out; }

  /* --- Open and close --- */
  .kl-m-reveal { animation: kl-reveal var(--kl-motion-reveal) var(--kl-motion-ease-out) calc(var(--kl-motion-reveal-delay) + var(--i, 0) * var(--kl-motion-reveal-step)) backwards; }
  .kl-m-fade-out { animation: kl-fade-out var(--kl-motion-fade-out) ease forwards; }
  .kl-m-win-open { animation: kl-win-open var(--kl-motion-win-open) var(--kl-motion-spring-soft) backwards; }
  .kl-m-win-close { animation: kl-win-close var(--kl-motion-win-close) var(--kl-motion-ease-out) forwards; pointer-events: none; }
  .kl-m-win-min { animation: kl-win-min var(--kl-motion-win-min) var(--kl-motion-ease-out) forwards; pointer-events: none; }
  .kl-m-menu-in { animation: kl-menu-in var(--kl-motion-menu-in) var(--kl-motion-spring) both; }
  .kl-m-menu-out { animation: kl-menu-out var(--kl-motion-menu-out) ease-in forwards; pointer-events: none; }
  .kl-m-meter { animation: kl-meter var(--kl-motion-meter) var(--kl-motion-ease-out) var(--kl-motion-reveal-delay) backwards; }

  /* --- Board movement --- */
  .kl-m-travel { transition: transform var(--kl-motion-travel) var(--kl-motion-ease-out); }
  .kl-m-roam-in { animation: kl-roam-in var(--kl-motion-roam-in) var(--kl-motion-spring-pop) backwards; }
  .kl-m-roam-out { animation: kl-roam-out var(--kl-motion-roam-out) var(--kl-motion-ease-out) forwards; pointer-events: none; }
  .kl-m-drift { animation: kl-drift var(--kl-motion-drift) ease-in-out var(--drift-delay, 0s) infinite alternate; }
  .kl-m-drift:hover, .kl-m-drift:focus-within { animation-play-state: paused; }

  /* --- Speech bubbles. --kl-pop-x/--kl-pop-y: the 4px it comes from (toward its speaker) --- */
  .kl-m-say-in { animation: kl-say-in var(--kl-motion-say-in) var(--kl-motion-spring) backwards; }
  .kl-m-say-in.kl-m-late { animation-delay: var(--kl-motion-say-late); }
  .kl-m-say-in.kl-m-warn { animation: kl-say-in var(--kl-motion-say-in) var(--kl-motion-spring) backwards, kl-nudge var(--kl-motion-nudge) ease-out calc(var(--kl-motion-say-in) * .8); }
  .kl-m-say-in.kl-m-warn.kl-m-late { animation-delay: var(--kl-motion-say-late), calc(var(--kl-motion-say-late) + var(--kl-motion-say-in) * .8); }
  .kl-m-say-out { animation: kl-say-out var(--kl-motion-say-out) ease-in forwards; }
  .kl-m-hop { animation: kl-hop var(--kl-motion-hop) var(--kl-motion-spring-pop); }
  .kl-m-hop.kl-m-late { animation-delay: var(--kl-motion-say-late); }
  .kl-m-news-ring::after { content: ""; position: absolute; inset: 0; border-radius: inherit; border: 2px solid var(--kl-ring, var(--kl-motion-tint-accent)); opacity: 0; pointer-events: none; animation: kl-ring var(--kl-motion-news-ring) var(--kl-motion-ease-out); }

  /* --- Status dot: put it on the dot; ::after is the ring --- */
  .kl-m-dot { position: relative; }
  .kl-m-dot::after { content: ""; position: absolute; inset: 0; border-radius: 50%; background: currentColor; opacity: 0; pointer-events: none; }
  .kl-m-dot--executing { animation: kl-dot-breathe var(--kl-motion-dot-executing) ease-in-out infinite; }
  .kl-m-dot--executing::after { animation: kl-dot-ring var(--kl-motion-dot-executing) var(--kl-motion-ease-out) infinite; }
  .kl-m-dot--planning { animation: kl-dot-breathe var(--kl-motion-dot-planning) ease-in-out infinite; }
  .kl-m-dot--planning::after { animation: kl-dot-ring var(--kl-motion-dot-planning) var(--kl-motion-ease-out) infinite; }
  .kl-m-dot--alert::after { animation: kl-dot-ring var(--kl-motion-dot-alert) var(--kl-motion-ease-out) infinite; }
  .kl-m-dot--siren { animation: kl-dot-siren var(--kl-motion-dot-siren) steps(1, end) infinite; }
  .kl-m-dot--siren::after { animation: kl-dot-ring var(--kl-motion-dot-alert) var(--kl-motion-ease-out) infinite; }
  .kl-m-dot--stopped { animation: none; }
  .kl-m-dot-colour { transition: background-color var(--kl-motion-dot-colour) var(--kl-motion-ease-out), color var(--kl-motion-dot-colour) var(--kl-motion-ease-out); } /* color: the ring is currentColor */
  .kl-m-dot-pop { animation: kl-dot-pop var(--kl-motion-dot-pop) ease-out; }
  .kl-m-dot--executing.kl-m-dot-pop { animation: kl-dot-breathe var(--kl-motion-dot-executing) ease-in-out infinite, kl-dot-pop var(--kl-motion-dot-pop) ease-out; }
  .kl-m-dot--planning.kl-m-dot-pop { animation: kl-dot-breathe var(--kl-motion-dot-planning) ease-in-out infinite, kl-dot-pop var(--kl-motion-dot-pop) ease-out; }

  /* --- Count roll: <span class="kl-m-roll"><span class="kl-m-roll-old">3</span><span class="kl-m-roll-new">4</span></span> --- */
  .kl-m-roll.is-rolling .kl-m-roll-new { animation: kl-roll-in var(--kl-motion-roll-in) var(--kl-motion-spring) both; }
  .kl-m-roll.is-rolling .kl-m-roll-old { animation: kl-roll-out var(--kl-motion-roll-out) var(--kl-motion-ease-out) both; }
  .kl-m-count-pop { animation: kl-pop-in var(--kl-motion-count-pop) var(--kl-motion-spring) backwards; }
  .kl-m-count-bump { animation: kl-count-bump var(--kl-motion-count-bump) ease-out; }
  .kl-m-write { animation: kl-write var(--kl-motion-write) var(--kl-motion-ease-out); }
  .kl-m-rise { animation: kl-rise var(--kl-motion-rise) var(--kl-motion-ease-out); }

  /* --- Siren light. .kl-m-glow is the pool on the board under Police or the Ambulance; it travels with its vehicle.
         Two .kl-m-lobe children trade brightness. .kl-m-lit is the card they work on: light on the edge facing them
         (--kl-lx/--kl-ly), never on its face. --- */
  .kl-m-glow { transition: transform var(--kl-motion-travel) var(--kl-motion-ease-out), opacity 600ms ease; }
  .kl-m-glow--siren .kl-m-lobe { --kl-lobe: color-mix(in srgb, var(--kl-motion-tint-stopped) var(--kl-motion-glow-k), transparent); animation: kl-lobe var(--kl-motion-siren) ease-in-out infinite; }
  .kl-m-glow--siren .kl-m-lobe + .kl-m-lobe { animation-delay: calc(var(--kl-motion-siren) / -2); }
  .kl-m-glow--alarm .kl-m-lobe { --kl-lobe: color-mix(in srgb, var(--kl-motion-tint-accent) var(--kl-motion-glow-k), transparent); animation: kl-lobe var(--kl-motion-police) ease-in-out infinite; }
  .kl-m-glow--alarm .kl-m-lobe + .kl-m-lobe { --kl-lobe: color-mix(in srgb, var(--kl-motion-tint-stopped) var(--kl-motion-glow-k), transparent); animation-delay: calc(var(--kl-motion-police) / -2); }
  .kl-m-glow--watch .kl-m-lobe { --kl-lobe: color-mix(in srgb, var(--kl-motion-tint-accent) calc(var(--kl-motion-glow-k) * .5), transparent); animation: kl-lobe-breathe var(--kl-motion-watch) ease-in-out infinite; }
  .kl-m-lit::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
    box-shadow: 0 0 0 1px var(--kl-lit), var(--kl-lx, 10px) var(--kl-ly, 0px) 30px -6px var(--kl-lit); animation: kl-lit var(--kl-motion-siren) ease-in-out infinite; }
  .kl-m-lit--ambulance { --kl-lit: color-mix(in srgb, var(--kl-motion-tint-stopped) var(--kl-motion-edge-k), transparent); }
  .kl-m-lit--police { --kl-lit: color-mix(in srgb, var(--kl-motion-tint-accent) var(--kl-motion-edge-k), transparent); }
  .kl-m-lit--police::before { animation-duration: var(--kl-motion-police); }
  .kl-m-bar--siren { animation: kl-bar-red var(--kl-motion-siren) ease-in-out infinite; }
  .kl-m-bar--police { animation: kl-bar-police var(--kl-motion-police) ease-in-out infinite; }
  .kl-m-bar--watch { animation: kl-bar-blue var(--kl-motion-watch) ease-in-out infinite; }

  /* --- Attention and errors --- */
  .kl-m-rays { animation: kl-attn var(--kl-motion-attention) ease-in-out infinite; }
  .kl-m-rays::after { content: ""; position: absolute; inset: -2px; border-radius: inherit; border: 2px solid var(--kl-m-rays-c, var(--kl-motion-tint-stopped)); opacity: 0; pointer-events: none; animation: kl-attn-ring var(--kl-motion-attention) var(--kl-motion-ease-out) infinite; }
  .kl-m-alerting::after { content: ""; position: absolute; inset: -1px; border-radius: inherit; pointer-events: none; animation: kl-alert-pulse var(--kl-motion-alert-pulse) var(--kl-motion-ease-out) infinite; }
  .kl-m-bell { transform-origin: 50% 20%; animation: kl-bell var(--kl-motion-alert-pulse) ease-in-out infinite; }
  .kl-m-shake { animation: kl-shake var(--kl-motion-shake) ease-out; }
  .kl-m-shake-sm { animation: kl-shake-sm var(--kl-motion-shake-sm) ease-out; }
  .kl-m-field-flash { animation: kl-field-flash var(--kl-motion-flash) ease-out; }
  .kl-m-amber-flash { border-radius: 6px; animation: kl-amber-flash var(--kl-motion-flash-amber) ease-out; }

  /* --- Link targets. The target's edge glow is in the shapes above. While a link is held, the other cards it can go to
         breathe a faint ring (.kl-m-holding on the board), and stay still below 50 on the dial (.kl-m-calm on the root). --- */
  .kl-m-target:not(:has(> .kl-m-link-edge)) { animation: kl-target-glow var(--kl-motion-link-snap) ease-out; }
  .kl-m-holding .kl-m-can-drop:not(.kl-m-target) { outline: 1px solid color-mix(in srgb, var(--kl-motion-tint-accent) 35%, transparent); outline-offset: 3px; animation: kl-can-drop var(--kl-motion-can-drop) ease-in-out infinite; }
  .kl-m-calm .kl-m-holding .kl-m-can-drop:not(.kl-m-target), .kl-m-calm.kl-m-holding .kl-m-can-drop:not(.kl-m-target) { animation: none; }

  /* --- Asked for by the master parts (2026-10-13) --- */
  /* Busy: one spinner speed everywhere. A signal, not ambient: it runs while the thing is busy */
  .kl-m-spin { animation: kl-spin var(--kl-motion-spin) linear infinite; }
  /* Arriving */
  .kl-m-grow { transition: grid-template-rows var(--kl-m-grow-out, var(--kl-motion-collapse)) var(--kl-motion-ease-in), opacity var(--kl-motion-fade) ease; }
  .kl-m-grow.is-in { transition: grid-template-rows var(--kl-m-grow-in, var(--kl-motion-expand)) var(--kl-motion-ease-out), opacity var(--kl-motion-fade) ease; }
  .kl-m-pop { animation: kl-pop-rise var(--kl-motion-pop) var(--kl-motion-spring-pop) both; }
  .kl-m-filled { animation: kl-filled var(--kl-motion-filled) var(--kl-motion-ease-out); }
  .kl-m-row-in { animation: kl-row-in var(--kl-motion-row-in) var(--kl-motion-ease-out) backwards; }
  /* A window opening from a smaller copy of itself (--kl-from-x/-y: where that copy sits, --kl-from-s its scale,
     --kl-from-origin the corner it grows from). kl-m-shrink-to plays it back to close */
  .kl-m-grow-from { animation: kl-grow-from var(--kl-motion-expand) var(--kl-motion-ease-out) both; transform-origin: var(--kl-from-origin, 0 0); }
  .kl-m-shrink-to { animation: kl-grow-from var(--kl-motion-collapse) var(--kl-motion-ease-out) reverse both; transform-origin: var(--kl-from-origin, 0 0); pointer-events: none; }
  /* Travel: FLIP. Move it in the DOM, set --kl-fly-x/--kl-fly-y to where it was, add the class (KlMotion.fly does all
     three and asks the quiet gate). --land lands it with kl-land when it gets there */
  .kl-m-fly { animation: kl-fly var(--kl-motion-travel) var(--kl-motion-spring-soft) backwards; }
  .kl-m-fly.kl-m-fly--land { animation: kl-fly var(--kl-motion-travel) var(--kl-motion-spring-soft) backwards, kl-land var(--kl-motion-land) ease-out var(--kl-motion-travel); }
  /* Leaving. kl-m-leave: out of a list (an answered ask). kl-m-row-out: a removed row slides right. kl-m-fold: back into
     its source, 24px toward it (--kl-fold-x/-y, --kl-fold-origin), after --kl-motion-ask-fold-after and the quiet gate */
  .kl-m-leave { animation: kl-leave var(--kl-motion-collapse) var(--kl-motion-ease-in) forwards; pointer-events: none; }
  .kl-m-row-out { animation: kl-row-out var(--kl-motion-collapse) var(--kl-motion-ease-in) forwards; pointer-events: none; }
  .kl-m-fold { animation: kl-fold var(--kl-motion-ask-fold) var(--kl-motion-ease-in) forwards; transform-origin: var(--kl-fold-origin, left center); pointer-events: none; }
  /* The agent browser's pointer: a ring where it clicks, the caret while it types, a ring on the current step */
  .kl-m-click-ring { animation: kl-click-ring var(--kl-motion-click-ring) var(--kl-motion-ease-out) both; }
  .kl-m-caret { animation: kl-caret var(--kl-motion-caret) steps(1) infinite; }
  .kl-m-recolor { transition: background-color var(--kl-motion-recolor) var(--kl-motion-ease-out), border-color var(--kl-motion-recolor) var(--kl-motion-ease-out), color var(--kl-motion-recolor) var(--kl-motion-ease-out), box-shadow var(--kl-motion-recolor) var(--kl-motion-ease-out), fill var(--kl-motion-recolor) var(--kl-motion-ease-out), stroke var(--kl-motion-recolor) var(--kl-motion-ease-out); }
  .kl-m-ring::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; animation: kl-step-ring var(--kl-motion-dot-executing) var(--kl-motion-ease-out) infinite; }
}

/* =====================================================================================================
   Keyframes. Amplitudes multiply by --kl-motion-k (or -dk), so 0 is calm and 1 is Step 8 exactly.
   ===================================================================================================== */
@keyframes kl-press { 0% { scale: 1; } 40% { scale: .985; } 100% { scale: 1; } }
@keyframes kl-squash { 0% { scale: 1; } 35% { scale: calc(1 + .014 * var(--kl-motion-k)) calc(1 - .028 * var(--kl-motion-k)); } 70% { scale: calc(1 - .004 * var(--kl-motion-k)) calc(1 + .008 * var(--kl-motion-k)); } 100% { scale: 1; } }
@keyframes kl-lift { from { scale: 1; } to { scale: 1.03; } }
@keyframes kl-land-drop { 0% { scale: 1.03; } 28% { scale: calc(1 + .022 * var(--kl-motion-k)) calc(1 - .032 * var(--kl-motion-k)); } 55% { scale: calc(1 - .008 * var(--kl-motion-k)) calc(1 + .012 * var(--kl-motion-k)); } 78% { scale: calc(1 + .003 * var(--kl-motion-k)) calc(1 - .002 * var(--kl-motion-k)); } 100% { scale: 1; } }
@keyframes kl-land { 0% { scale: 1; } 25% { scale: calc(1 + .035 * var(--kl-motion-k)) calc(1 - .025 * var(--kl-motion-k)); } 55% { scale: calc(1 - .01 * var(--kl-motion-k)) calc(1 + .015 * var(--kl-motion-k)); } 80% { scale: calc(1 + .004 * var(--kl-motion-k)) calc(1 - .002 * var(--kl-motion-k)); } 100% { scale: 1; } }
@keyframes kl-reveal { from { opacity: 0; translate: 0 var(--kl-motion-reveal-shift); } to { opacity: 1; translate: 0 0; } }
@keyframes kl-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes kl-fade-out { to { opacity: 0; } }
@keyframes kl-win-open { from { opacity: 0; transform: translate(var(--kl-from-x, 12px), var(--kl-from-y, 0px)) scale(.94); } to { opacity: 1; transform: none; } }
@keyframes kl-win-close { to { opacity: 0; transform: scale(.97); } }
@keyframes kl-win-min { 70% { opacity: .9; } to { opacity: 0; transform: translate(var(--kl-to-x, 160px), var(--kl-to-y, 0px)) scale(.2); } }
@keyframes kl-menu-in { from { opacity: 0; transform: translateY(-4px) scale(.96); } to { opacity: 1; transform: none; } }
@keyframes kl-menu-out { to { opacity: 0; transform: translateY(-2px) scale(.98); } }
@keyframes kl-meter { from { width: 0; } }
@keyframes kl-roam-in { from { opacity: 0; scale: .6; } to { opacity: 1; scale: 1; } }
@keyframes kl-roam-out { to { opacity: 0; scale: .6; translate: 0 -16px; } }
@keyframes kl-drift { 0% { translate: 0 0; } 25% { translate: calc(10px * var(--kl-motion-dk)) calc(-6px * var(--kl-motion-dk)); } 50% { translate: calc(4px * var(--kl-motion-dk)) calc(-12px * var(--kl-motion-dk)); } 75% { translate: calc(-10px * var(--kl-motion-dk)) calc(-4px * var(--kl-motion-dk)); } 100% { translate: calc(-6px * var(--kl-motion-dk)) calc(8px * var(--kl-motion-dk)); } }
@keyframes kl-say-in { from { opacity: 0; scale: .85; translate: var(--kl-pop-x, 0px) var(--kl-pop-y, 4px); } to { opacity: 1; scale: 1; translate: 0 0; } }
@keyframes kl-say-out { to { opacity: 0; scale: .96; } }
@keyframes kl-hop { 0% { translate: 0 0; } 40% { translate: 0 calc(-1 * var(--kl-motion-hop-h)); } 100% { translate: 0 0; } }
@keyframes kl-nudge { 0%, 100% { translate: 0 0; } 25% { translate: -2px 0; } 50% { translate: 2px 0; } 75% { translate: -1px 0; } }
@keyframes kl-ring { 0% { opacity: .7; scale: 1; } 100% { opacity: 0; scale: 1.06; } }
@keyframes kl-dot-ring { 0% { opacity: .55; transform: scale(1); } 80%, 100% { opacity: 0; transform: scale(2.6); } }
@keyframes kl-dot-breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(.82); } }
@keyframes kl-dot-siren { 0% { background-color: var(--kl-motion-tint-stopped); color: var(--kl-motion-tint-stopped); } 50% { background-color: var(--kl-motion-tint-accent); color: var(--kl-motion-tint-accent); } }
@keyframes kl-dot-pop { 0% { scale: calc(1 - .6 * var(--kl-motion-k)); } 40% { scale: calc(1 + .35 * var(--kl-motion-k)); } 70% { scale: calc(1 - .08 * var(--kl-motion-k)); } 100% { scale: 1; } }
@keyframes kl-roll-in { from { translate: 0 var(--kl-motion-roll-shift); opacity: 0; color: var(--kl-motion-tint-accent-ink); } 50% { color: var(--kl-motion-tint-accent-ink); } to { translate: 0 0; opacity: 1; } }
@keyframes kl-roll-out { from { translate: 0 0; opacity: 1; } to { translate: 0 calc(-1 * var(--kl-motion-roll-shift)); opacity: 0; } }
@keyframes kl-pop-in { from { scale: 0; opacity: 0; } to { scale: 1; opacity: 1; } }
@keyframes kl-count-bump { 0% { scale: 1; } 35% { scale: calc(1 + .18 * var(--kl-motion-k)); } 100% { scale: 1; } }
@keyframes kl-write { from { clip-path: inset(0 100% 0 0); opacity: .3; } to { clip-path: inset(0 0 0 0); opacity: 1; } }
@keyframes kl-rise { from { opacity: 0; translate: 0 4px; } to { opacity: 1; translate: 0 0; } }
@keyframes kl-lobe { 0%, 100% { opacity: .2; } 50% { opacity: 1; } }
@keyframes kl-lobe-breathe { 0%, 100% { opacity: .35; } 50% { opacity: .8; } }
@keyframes kl-lit { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
@keyframes kl-bar-red { 0%, 100% { background: var(--kl-motion-tint-stopped); box-shadow: 0 0 6px 1px color-mix(in srgb, var(--kl-motion-tint-stopped) 55%, transparent); } 50% { background: color-mix(in srgb, var(--kl-motion-tint-stopped) 40%, var(--kl-motion-tint-surface)); box-shadow: 0 0 0 0 transparent; } }
@keyframes kl-bar-police { 0%, 100% { background: var(--kl-motion-tint-accent); box-shadow: 0 0 6px 1px color-mix(in srgb, var(--kl-motion-tint-accent) 55%, transparent); } 50% { background: var(--kl-motion-tint-stopped); box-shadow: 0 0 6px 1px color-mix(in srgb, var(--kl-motion-tint-stopped) 55%, transparent); } }
@keyframes kl-bar-blue { 0%, 100% { box-shadow: 0 0 0 0 transparent; } 50% { box-shadow: 0 0 5px 1px color-mix(in srgb, var(--kl-motion-tint-accent) 45%, transparent); } }
@keyframes kl-attn { 0%, 100% { scale: 1; opacity: .55; } 50% { scale: 1.012; opacity: .4; } }
@keyframes kl-attn-ring { 0% { opacity: .7; scale: 1; } 70%, 100% { opacity: 0; scale: 1.06; } }
@keyframes kl-alert-pulse { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--kl-motion-tint-stopped) 45%, transparent); } 70%, 100% { box-shadow: 0 0 0 12px color-mix(in srgb, var(--kl-motion-tint-stopped) 0%, transparent); } }
@keyframes kl-bell { 0%, 26%, 100% { rotate: 0deg; } 4% { rotate: calc(14deg * var(--kl-motion-dk)); } 9% { rotate: calc(-11deg * var(--kl-motion-dk)); } 14% { rotate: calc(7deg * var(--kl-motion-dk)); } 19% { rotate: calc(-3deg * var(--kl-motion-dk)); } }
@keyframes kl-shake { 0%, 100% { translate: 0 0; } 20% { translate: -3px 0; } 40% { translate: 3px 0; } 60% { translate: -2px 0; } 80% { translate: 1px 0; } }
@keyframes kl-shake-sm { 0%, 100% { translate: 0 0; } 25% { translate: -2px 0; } 50% { translate: 2px 0; } 75% { translate: -1px 0; } }
@keyframes kl-field-flash { 0%, 40% { border-color: var(--kl-motion-tint-stopped); box-shadow: 0 0 0 3px color-mix(in srgb, var(--kl-motion-tint-stopped) 22%, transparent); } }
@keyframes kl-amber-flash { 0%, 65% { color: var(--kl-motion-tint-planning-ink); background: var(--kl-motion-tint-planning-soft); box-shadow: 0 0 0 3px var(--kl-motion-tint-planning-soft); } }
@keyframes kl-target-glow { from { box-shadow: 0 0 0 1.5px transparent, 0 0 0 0 transparent; } }
@keyframes kl-can-drop { 0%, 100% { outline-color: color-mix(in srgb, var(--kl-motion-tint-accent) 18%, transparent); outline-offset: 2px; } 50% { outline-color: color-mix(in srgb, var(--kl-motion-tint-accent) 42%, transparent); outline-offset: 5px; } }
/* Asked for by the master parts (2026-10-13) */
@keyframes kl-spin { to { rotate: 360deg; } }
@keyframes kl-pop-rise { from { opacity: 0; translate: 0 4px; scale: calc(1 - .1 * var(--kl-motion-k)); } to { opacity: 1; translate: 0 0; scale: 1; } }
@keyframes kl-filled { from { background-color: var(--kl-motion-tint-accent-soft); } }
@keyframes kl-row-in { from { opacity: 0; translate: 0 var(--kl-motion-row-rise); } to { opacity: 1; translate: 0 0; } }
@keyframes kl-grow-from { from { opacity: .4; transform: translate(var(--kl-from-x, 0px), var(--kl-from-y, 0px)) scale(var(--kl-from-s, .33)); } to { opacity: 1; transform: none; } }
@keyframes kl-fly { from { translate: var(--kl-fly-x, 0px) var(--kl-fly-y, 0px); } }
@keyframes kl-leave { to { opacity: 0; translate: 0 -4px; scale: .98; } }
@keyframes kl-row-out { to { opacity: 0; translate: 8px 0; } }
@keyframes kl-fold { to { opacity: 0; scale: .86; translate: var(--kl-fold-x, -24px) var(--kl-fold-y, 0px); } }
@keyframes kl-click-ring { 0% { opacity: .9; scale: .35; } 100% { opacity: 0; scale: calc(1 + .5 * var(--kl-motion-k)); } }
@keyframes kl-caret { 50% { opacity: 0; } }
@keyframes kl-step-ring { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--kl-ring, var(--kl-motion-tint-accent)) 55%, transparent); } 70%, 100% { box-shadow: 0 0 0 7px transparent; } }

/* =====================================================================================================
   Reduced motion: everything is instant except opacity fades of 120ms or less. No lean, no squash, no drift, no
   loops; a status dot is a still dot, a count shows its new number, a bubble and a window fade in. The same block
   applies under .kl-motion-reduce, so the specimen (or a setting) can turn it on without the OS switch.
   ===================================================================================================== */
@media (prefers-reduced-motion: reduce) {
  :root, [data-theme], .kl-m-root { --kl-motion-k: 0 !important; --kl-motion-dk: 0 !important; --kl-motion-hop-h: 0px !important; --kl-motion-lean: 0deg !important; --kl-motion-recolor: var(--kl-motion-fade) !important; }
  .kl-m-recolor { transition: background-color var(--kl-motion-fade) ease, border-color var(--kl-motion-fade) ease, color var(--kl-motion-fade) ease, box-shadow var(--kl-motion-fade) ease, fill var(--kl-motion-fade) ease, stroke var(--kl-motion-fade) ease; }
  .kl-m-say-in, .kl-m-win-open, .kl-m-roam-in, .kl-m-reveal, .kl-m-count-pop, .kl-m-menu-in, .kl-m-rise,
  .kl-m-pop, .kl-m-row-in, .kl-m-grow-from, .kl-m-fly { animation: kl-fade-in var(--kl-motion-fade) ease backwards; }
  .kl-m-say-out, .kl-m-win-close, .kl-m-win-min, .kl-m-roam-out, .kl-m-menu-out, .kl-m-fade-out,
  .kl-m-shrink-to, .kl-m-leave, .kl-m-row-out, .kl-m-fold, .kl-m-click-ring { animation: kl-fade-out var(--kl-motion-fade) ease forwards; }
  .kl-m-roll .kl-m-roll-old { display: none; }
  .kl-m-link-pool, .kl-m-link-edge { transition-duration: var(--kl-motion-fade) !important; }
  /* A grown block opens and shuts at once and only fades; a filled field holds the tint, then drops it with no fade.
     Spinners, carets and step rings stand still (they are only defined for no-preference above). */
  .kl-m-grow, .kl-m-grow.is-in { transition: opacity var(--kl-motion-fade) ease; }
  .kl-m-filled { animation: kl-filled var(--kl-motion-filled) steps(1, end); }
}
.kl-motion-reduce, .kl-motion-reduce :is([data-theme], .kl-m-root) { --kl-motion-k: 0 !important; --kl-motion-dk: 0 !important; --kl-motion-hop-h: 0px !important; --kl-motion-lean: 0deg !important; --kl-motion-recolor: var(--kl-motion-fade) !important; }
.kl-motion-reduce :is(.kl-m-press, .kl-m-squash, .kl-m-lift, .kl-m-land-drop, .kl-m-land, .kl-m-drift, .kl-m-hop, .kl-m-dot, .kl-m-dot-pop, .kl-m-roll-new, .kl-m-roll-old, .kl-m-count-bump, .kl-m-write, .kl-m-lobe, .kl-m-bar--siren, .kl-m-bar--police, .kl-m-bar--watch, .kl-m-rays, .kl-m-bell, .kl-m-shake, .kl-m-shake-sm, .kl-m-field-flash, .kl-m-amber-flash, .kl-m-target, .kl-m-can-drop, .kl-m-meter, .kl-m-spin, .kl-m-caret),
.kl-motion-reduce :is(.kl-m-dot, .kl-m-rays, .kl-m-lit, .kl-m-alerting, .kl-m-news-ring, .kl-m-ring)::after,
.kl-motion-reduce .kl-m-lit::before { animation: none !important; }
.kl-motion-reduce :is(.kl-m-tilt, .kl-m-dragging, .kl-m-travel, .kl-m-glow, .kl-m-hold) { transition: none !important; }
.kl-motion-reduce .kl-m-hold:active { scale: none; }
.kl-motion-reduce :is(.kl-m-say-in, .kl-m-win-open, .kl-m-roam-in, .kl-m-reveal, .kl-m-count-pop, .kl-m-menu-in, .kl-m-rise,
  .kl-m-pop, .kl-m-row-in, .kl-m-grow-from, .kl-m-fly) { animation: kl-fade-in var(--kl-motion-fade) ease backwards !important; }
.kl-motion-reduce :is(.kl-m-say-out, .kl-m-win-close, .kl-m-win-min, .kl-m-roam-out, .kl-m-menu-out, .kl-m-fade-out,
  .kl-m-shrink-to, .kl-m-leave, .kl-m-row-out, .kl-m-fold, .kl-m-click-ring) { animation: kl-fade-out var(--kl-motion-fade) ease forwards !important; }
.kl-motion-reduce .kl-m-roll .kl-m-roll-old { display: none; }
.kl-motion-reduce :is(.kl-m-link-pool, .kl-m-link-edge) { transition-duration: var(--kl-motion-fade) !important; }
.kl-motion-reduce :is(.kl-m-grow, .kl-m-grow.is-in) { transition: opacity var(--kl-motion-fade) ease !important; }
.kl-motion-reduce .kl-m-filled { animation: kl-filled var(--kl-motion-filled) steps(1, end) !important; }

/* Forced colours: glows vanish, so the link source and target keep a solid outline */
@media (forced-colors: active) {
  .kl-m-target, .kl-m-link-source.is-glowing { outline: 3px solid Highlight; }
  .kl-m-link-pool { display: none; }
  .kl-m-lit::before, .kl-m-news-ring::after { display: none; }
}

/* ===== icons/icons.css ===== */
/* Klippan v2 icons: the one class every icon uses.
   <svg class="kl-icon" aria-hidden="true"><use href="sprite.svg#kl-agent"/></svg>
   Stroke, caps and joins live here, not in the sprite, so one rule changes the whole set.
   Colour is currentColor: set `color` on the icon or its parent. */
.kl-icon {
  display: inline-block;
  flex: none;
  width: var(--kl-icon-size, 20px);
  height: var(--kl-icon-size, 20px);
  vertical-align: middle;
  fill: none;
  stroke: currentColor;
  stroke-width: var(--kl-icon-stroke, 1.6);
  stroke-linecap: round;
  stroke-linejoin: round;
  overflow: visible;
}

/* Sizes. 14 to 32 keep the 1.6 stroke (it scales with the icon).
   At 12 and below the stroke thickens so the icon still reads (step 10 used 2 to 2.4 at 10 px). */
.kl-icon--12 { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
.kl-icon--14 { --kl-icon-size: 14px; }
.kl-icon--16 { --kl-icon-size: 16px; }
.kl-icon--18 { --kl-icon-size: 18px; }
.kl-icon--20 { --kl-icon-size: 20px; }
.kl-icon--24 { --kl-icon-size: 24px; }
.kl-icon--32 { --kl-icon-size: 32px; }

/* Tiles: the rounded square an icon sits in on section, helper and roamer cards. */
.kl-icon-tile {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: var(--kl-icon-tile, 28px);
  height: var(--kl-icon-tile, 28px);
  border-radius: var(--kl-radius-tile, 8px);
  background: var(--kl-color-control-fill, rgba(0, 0, 0, 0.05));
  color: var(--kl-color-text, rgba(0, 0, 0, 0.85));
}
/* Card tints come from Foundations: --kl-color-card-<card>-soft (tile) and -ink (icon). */
.kl-icon-tile--settings  { background: var(--kl-color-card-settings-soft);  color: var(--kl-color-card-settings-ink); }
.kl-icon-tile--presets   { background: var(--kl-color-card-presets-soft);   color: var(--kl-color-card-presets-ink); }
.kl-icon-tile--alerts    { background: var(--kl-color-card-alerts-soft);    color: var(--kl-color-card-alerts-ink); }
.kl-icon-tile--requests  { background: var(--kl-color-card-requests-soft);  color: var(--kl-color-card-requests-ink); }
.kl-icon-tile--context   { background: var(--kl-color-card-context-soft);   color: var(--kl-color-card-context-ink); }
.kl-icon-tile--knowledge { background: var(--kl-color-card-knowledge-soft); color: var(--kl-color-card-knowledge-ink); }
.kl-icon-tile--tokenomy  { background: var(--kl-color-card-tokenomy-soft);  color: var(--kl-color-card-tokenomy-ink); border-radius: 50%; }
.kl-icon-tile--police    { background: var(--kl-color-card-police-soft);    color: var(--kl-color-card-police-ink); }
.kl-icon-tile--ambulance { background: var(--kl-color-card-ambulance-soft); color: var(--kl-color-card-ambulance-ink); }
.kl-icon-tile--garbage   { background: var(--kl-color-card-garbage-soft);   color: var(--kl-color-card-garbage-ink); }
.kl-icon-tile--researcher    { background: var(--kl-color-helper-researcher-soft); color: var(--kl-color-helper-researcher-ink); }
.kl-icon-tile--agent-builder { background: var(--kl-color-helper-builder-soft);    color: var(--kl-color-helper-builder-ink); }
.kl-icon-tile--file-cleanser { background: var(--kl-color-helper-cleanser-soft);   color: var(--kl-color-helper-cleanser-ink); }

/* ===== board/board.css ===== */
/* Klippan design system v2: Board pieces.
   Every component that lives on the whiteboard: project cards (four stages), helpers, roamers, small context cards,
   section cards, the Klippan brand card with the playfulness dial, link lines, speech bubbles and news tags,
   the siren light, the zoom card, the zoomed-out (mini) forms and the board surface itself.

   Built from the Step 10 board (prototype/whiteboard/playground.css + Playground.dc.html, PR #13).
   Load order: ../foundations/tokens.css, ../motion/motion.css, then this file.
   Colours, type, radii, shadows and spacing come from Foundations (--kl-color-*, --kl-font-*, --kl-radius-*,
   --kl-shadow-*, --kl-space-*). Timings come from Motion (--kl-motion-*); looping and one-shot motion is applied
   by adding Motion's kl-m-* classes. Icons: ../icons/icons.css + sprite.svg to the parts named in README.md. The only keyframes defined here are the
   link line's, which Motion does not carry (see NEEDS.md).

   Sizes are board units. The board draws them at --kl-board-scale (1.2 at 100% zoom on the 1920x1200 artboard),
   so a 264-unit card is 317 screen px at 100%. Specimens show them at 1x. */

/* =====================================================================================================
   0. Component tokens (sizes are this part's own; Foundations leaves --kl-size-* to the components)
   ===================================================================================================== */
:root {
  --kl-board-scale: 1.2;               /* board units to screen px at 100% zoom */
  --kl-board-w: 1600px;                /* board in units; artboard 1920x1200 */
  --kl-board-h: 1000px;
  --kl-board-zoom-min: .5;
  --kl-board-zoom-max: 2;

  /* Project card stages: 0 name only, 1 compact, 2 full (rest), 3 expanded */
  --kl-card-name-h: 56px;              /* width = name + 90, between 150 and 246 */
  --kl-card-name-w-min: 150px;
  --kl-card-name-w-max: 246px;
  --kl-card-compact-w: 224px;
  --kl-card-compact-h: 80px;
  --kl-card-full-w: 264px;
  --kl-card-full-h: 140px;             /* 104 + 18 per status line: 122 with one line, 140 with two */
  --kl-card-expanded-w: 360px;         /* per project: 320 to 420 (two agent columns) */
  --kl-card-expanded-h-min: 320px;
  --kl-card-expanded-h-max: 432px;
  --kl-card-expanded-w-wide: 420px;    /* the wide end: two agent columns, or an input section (adaptive card) */
  --kl-card-radius-name: 20px;         /* the radius runs 20 to 26 as the card leaves name only */
  --kl-card-web-h: 24px;               /* the web chip on a card (same as --kl-size-control) */

  /* Other card kinds, named --kl-<kind>-<form>-w|h (C6). Approvals keeps its own --kl-approval-* sizes. */
  --kl-teach-expanded-w: 380px;        /* teach card */
  --kl-teach-compact-w: 264px;
  --kl-question-expanded-w: 384px;     /* question card: grows with its questions up to 600, then scrolls inside */
  --kl-question-max-h: 600px;


  --kl-tool-tile: 36px;                /* the tile on helpers, roamers, sections and the brand card */
  --kl-helper-w: 240px;
  --kl-helper-h: 64px;
  --kl-section-w: 212px;
  --kl-section-h: 72px;
  --kl-roamer-h: 64px;
  --kl-brand-w: 296px;
  --kl-brand-h: 98px;
  --kl-mini-h: 40px;                   /* zoomed-out form: icon + name, width = name + 54 */
  --kl-mini-tile: 24px;
  --kl-ctx-chip-w-max: 184px;
  --kl-say-w-max: 280px;
  --kl-iconbtn: 36px;

  /* Who wears which colour. Step 10 uses the shared status hues; swap these for Foundations'
     --kl-color-card-* accents to get the Colourful Cards look in one place. */
  /* (declared below on :root and [data-theme]) */
}
/* Colour aliases resolve where a theme is set, not only on :root, so a dark board inside a light page gets the dark
   shades (a var() in a custom property is computed on the element that declares it). */
:root, [data-theme] {
  /* Waiting on Alban (an approval or an answer): Foundations' --kl-color-status-approval, v2 red if it is missing. */
  --kl-card-approval: var(--kl-color-status-approval, var(--kl-color-status-stopped));
  --kl-card-approval-soft: var(--kl-color-status-approval-soft, var(--kl-color-status-stopped-soft));
  --kl-card-approval-ink: var(--kl-color-status-approval-ink, var(--kl-color-status-stopped-ink));
  --kl-roamer-context: var(--kl-color-selection);
  --kl-roamer-knowledge: var(--kl-color-text-secondary);
  --kl-roamer-tokenomy: var(--kl-color-status-planning);
  --kl-roamer-police: var(--kl-color-neutral-ink);
  --kl-roamer-ambulance: var(--kl-color-status-stopped);
}

/* =====================================================================================================
   1. Board surface: the board fills the window; a dot grid runs past its edge
   ===================================================================================================== */
.kl-board {
  --kl-zoom: 1;
  --kl-vk: calc(var(--kl-board-scale) * var(--kl-zoom));
  --kl-dot: max(1px, calc(1px * var(--kl-vk)));
  --kl-grid: calc(var(--kl-space-grid) * var(--kl-vk));
  position: relative;
  overflow: hidden;
  color: var(--kl-color-text);
  font: var(--kl-font-body);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  background-color: var(--kl-color-board);
  background-image: radial-gradient(circle, var(--kl-color-board-dot) var(--kl-dot), transparent calc(var(--kl-dot) + .2px * var(--kl-vk) + .2px));
  background-size: var(--kl-grid) var(--kl-grid);
  background-position: calc(var(--kl-grid) / 2) calc(var(--kl-grid) / 2);
}
/* Zoomed out past 67%: the dots spread to every other cell so the board doesn't turn grey */
.kl-board--wide { --kl-grid: calc(var(--kl-space-grid-wide) * var(--kl-vk)); }
.kl-board.is-holding { cursor: crosshair; }

/* Board z-order (each value reads Foundations' --kl-z-* when it lands, with this number as the fallback):
   light pools, stack frames, request/helper/roamer lines 1; cards, sections, helpers 2; roamers 3;
   line riders (message tags) while a card is open 39; prompter 40; project switcher 41; an open card 42;
   the card dropped last 43; dragging 44; snapped roamer lines 45; link labels and line riders 46;
   windows 50+; Home 60; a window opened from Home 65; menus 80 (a menu opened inside a window renders in the
   board's menu layer, never inside the window, so the window cannot clip it); speech bubbles 900; zoom card 950 */
.kl-card, .kl-tool { z-index: var(--kl-z-card, 2); }
.kl-roamer { z-index: var(--kl-z-roamer, 3); }
.kl-card[data-stage="3"] { z-index: var(--kl-z-card-open, 42); }
.kl-front { z-index: var(--kl-z-front, 43); }
.kl-over-home { z-index: var(--kl-z-window-over-home, 65); }   /* a window opened from Home while Home is up */

/* =====================================================================================================
   2. Shared: icons, icon buttons, the loose-board tilt
   ===================================================================================================== */
/* Icons come from the Icons part: ../icons/icons.css (.kl-icon) and ../icons/sprite.svg (#kl-<name>).
   Board pieces only set the size (--kl-icon-size) and, below 12px, a heavier stroke (--kl-icon-stroke). */
.kl-board .kl-icon, .kl-card .kl-icon, .kl-tool .kl-icon, .kl-zoom .kl-icon { --kl-icon-size: 16px; }

/* Every card on the board rests at a slight tilt (set per card, -1deg to 1deg) and drags anywhere */
.kl-tilt { rotate: var(--kl-tilt, 0deg); }
/* A card in a stack stands straight (.is-stacked); dragging still leans it, so the drag rule outranks the stack's */
.kl-tilt.is-stacked, .kl-stack > .kl-tilt { rotate: 0deg; }
.kl-tilt.is-dragging, .kl-tilt.is-stacked.is-dragging, .kl-stack > .kl-tilt.is-dragging { rotate: var(--kl-motion-lean, 0deg); z-index: var(--kl-z-drag, 44); }
.kl-tilt.is-pulled { rotate: 0deg; }

.kl-iconbtn {
  display: inline-grid; place-items: center;
  width: var(--kl-iconbtn); height: var(--kl-iconbtn);
  padding: 0; border: 0; border-radius: var(--kl-radius-pill);
  background: transparent; color: var(--kl-color-text-secondary);
  cursor: pointer;
  transition: background-color var(--kl-motion-hover) ease, scale var(--kl-motion-press) var(--kl-motion-spring);
}
.kl-iconbtn:hover { background: var(--kl-color-control-fill); }
.kl-iconbtn:active { scale: .96; }
.kl-iconbtn:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 1px; }
.kl-iconbtn--chev { background: var(--kl-color-button-secondary); color: var(--kl-color-text); }
.kl-iconbtn--chev .kl-icon { transition: rotate var(--kl-motion-expand) var(--kl-motion-spring); }
.kl-card[data-stage="3"] .kl-iconbtn--chev .kl-icon { rotate: 180deg; }

/* =====================================================================================================
   3. Project card. Wrapper .kl-card (size, tilt, rays) > .kl-card__face (the card you see).
      Stages: data-stage 0 name only | 1 compact | 2 full | 3 expanded. In the app one continuous t (0..3) drives
      --kl-oc (controls), --kl-on (agent count), --kl-ol (status line) and the size; the stage attributes below
      are those values at rest, so a script can override the vars mid-pull and nothing jumps.
   ===================================================================================================== */
.kl-card {
  --kl-oc: 1; --kl-on: 1; --kl-ol: 1;
  --kl-card-glass: var(--kl-glass-card);   /* glass tinted with the project's hue: .kl-card--p1 to --p8 */
  --kl-ox: 0;   /* 0 up to full, 1 expanded: moves the dot from the card's middle into the name row */
  --kl-card-r: var(--kl-radius-card);
  --kl-dot-c: var(--kl-color-status-executing);
  --kl-card-hue: var(--kl-color-selection);   /* the project's hue for small marks (web chip); set by --p1 to --p8 */
  --kl-card-hue-ink: var(--kl-color-selection-ink);
  position: relative;
  width: var(--kl-card-full-w);
  height: var(--kl-card-full-h);
  flex: none;
  border-radius: var(--kl-card-r);   /* so Motion's target and lit rings follow the corners */
}
/* Liquid Glass tinted with the project's hue at every stage. Under increased contrast (prefers-contrast: more, or
   data-contrast="more" on the root or the board) Foundations turns these into the solid surface with a strong edge. */
.kl-card--p1 { --kl-card-glass: var(--kl-glass-card-project-1); --kl-card-hue: var(--kl-color-project-1); --kl-card-hue-ink: var(--kl-color-project-1-ink); }
.kl-card--p2 { --kl-card-glass: var(--kl-glass-card-project-2); --kl-card-hue: var(--kl-color-project-2); --kl-card-hue-ink: var(--kl-color-project-2-ink); }
.kl-card--p3 { --kl-card-glass: var(--kl-glass-card-project-3); --kl-card-hue: var(--kl-color-project-3); --kl-card-hue-ink: var(--kl-color-project-3-ink); }
.kl-card--p4 { --kl-card-glass: var(--kl-glass-card-project-4); --kl-card-hue: var(--kl-color-project-4); --kl-card-hue-ink: var(--kl-color-project-4-ink); }
.kl-card--p5 { --kl-card-glass: var(--kl-glass-card-project-5); --kl-card-hue: var(--kl-color-project-5); --kl-card-hue-ink: var(--kl-color-project-5-ink); }
.kl-card--p6 { --kl-card-glass: var(--kl-glass-card-project-6); --kl-card-hue: var(--kl-color-project-6); --kl-card-hue-ink: var(--kl-color-project-6-ink); }
.kl-card--p7 { --kl-card-glass: var(--kl-glass-card-project-7); --kl-card-hue: var(--kl-color-project-7); --kl-card-hue-ink: var(--kl-color-project-7-ink); }
.kl-card--p8 { --kl-card-glass: var(--kl-glass-card-project-8); --kl-card-hue: var(--kl-color-project-8); --kl-card-hue-ink: var(--kl-color-project-8-ink); }
.kl-card[data-stage="0"] { --kl-oc: 0; --kl-on: 0; --kl-ol: 0; --kl-card-r: var(--kl-card-radius-name);
  width: clamp(var(--kl-card-name-w-min), var(--kl-card-name-w, 160px), var(--kl-card-name-w-max)); height: var(--kl-card-name-h); }
.kl-card[data-stage="1"] { --kl-ol: 0; width: var(--kl-card-compact-w); height: var(--kl-card-compact-h); }
.kl-card[data-stage="2"][data-lines="1"] { height: calc(var(--kl-card-full-h) - 18px); }
.kl-card[data-stage="3"] { --kl-ox: 1; width: var(--kl-card-w, var(--kl-card-expanded-w));
  height: clamp(var(--kl-card-expanded-h-min), var(--kl-card-h, 366px), var(--kl-card-expanded-h-max)); }

.kl-card__face {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; gap: 10px;
  padding: 16px 16px 12px calc(40px - 20px * var(--kl-ox));   /* 40: dot column; 20 when expanded */
  overflow: hidden;
  background: var(--kl-card-glass);
  -webkit-backdrop-filter: var(--kl-glass-card-filter);
  backdrop-filter: var(--kl-glass-card-filter);
  border: 1px solid transparent;   /* the glass shadow draws the edge; states colour this border */
  border-radius: var(--kl-card-r);
  box-shadow: var(--kl-glass-card-shadow);
  transition: box-shadow var(--kl-motion-hover) ease, border-color var(--kl-motion-hover) ease;
}
.kl-card:hover .kl-card__face { box-shadow: var(--kl-glass-card-shadow-hover); }
.kl-card.is-dragging .kl-card__face, .kl-card.is-pulled .kl-card__face { box-shadow: var(--kl-shadow-window); }
.kl-card.is-dragging .kl-card__face { scale: 1.03; }
/* Keyboard focus (e.g. Stacks' keyboard pick-up): a calm ring in the project's hue, following the card's corners */
.kl-card:focus-visible { outline: 2px solid var(--kl-card-hue-ink); outline-offset: 3px; }
.kl-card[data-stage="0"] .kl-card__face { justify-content: center; padding: 0 16px 0 40px; }

.kl-card__head { display: flex; flex-direction: column; gap: 6px; padding-right: calc(28px + 56px * var(--kl-oc)); min-width: 0; }
.kl-card__name {
  display: flex; align-items: center; gap: 10px; margin: 0; min-width: 0; padding-left: calc(20px * var(--kl-ox));
  font: var(--kl-font-title); letter-spacing: var(--kl-font-title-tracking); color: var(--kl-color-text);
}
.kl-card__name-text { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

/* Status dot: no label, just a dot that pulses (put kl-m-dot + kl-m-dot--<state> on it) */
.kl-dot { width: 10px; height: 10px; flex: none; border-radius: var(--kl-radius-round); background: currentColor; color: var(--kl-dot-c); }
.kl-dot--executing { --kl-dot-c: var(--kl-color-status-executing); }
.kl-dot--planning  { --kl-dot-c: var(--kl-color-status-planning); }
.kl-dot--stopped   { --kl-dot-c: var(--kl-color-status-stopped); }
.kl-dot--idle      { --kl-dot-c: var(--kl-color-status-idle); }
.kl-dot--ambulance { --kl-dot-c: var(--kl-color-status-stopped); }   /* kl-m-dot--siren steps it red/blue */
/* On a project card the dot sits centred on the card's height at its left, with the name and status line stacked
   beside it (Alban, 2026-10-12). Expanded moves it into the name row. --kl-ox blends the two, so a corner pull never
   makes it jump. */
.kl-card__name > .kl-dot { position: absolute; left: 20px; top: calc((50% - 5px) * (1 - var(--kl-ox)) + 23px * var(--kl-ox)); }

/* Agent icon + count: "3/5" when the preset sets a maximum, otherwise the number deployed */
.kl-card__agents {
  display: inline-flex; align-items: center; gap: 5px;
  font: var(--kl-font-meta); font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text-secondary);
  opacity: var(--kl-on); translate: 0 calc(5px * (1 - var(--kl-on)));
}
.kl-card__agents .kl-icon { --kl-icon-size: 14px; }
.kl-count { display: inline-grid; overflow: hidden; }
.kl-count > * { grid-area: 1 / 1; }
.kl-count .kl-m-roll-old { visibility: hidden; }
.kl-count.is-rolling .kl-m-roll-old { visibility: visible; }
.kl-count.is-max { color: var(--kl-color-status-planning-ink); }

/* The short status line the project's agents write: two lines at most */
.kl-card__status {
  margin: 0;
  font: var(--kl-font-meta); color: var(--kl-color-text-secondary);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
  opacity: var(--kl-ol); translate: 0 calc(6px * (1 - var(--kl-ol)));
}
.kl-card__status.is-busy { color: var(--kl-color-status-stopped-ink); font-weight: var(--kl-font-weight-semibold); }
.kl-card[data-stage="0"] .kl-card__agents, .kl-card[data-stage="0"] .kl-card__status,
.kl-card[data-stage="1"] .kl-card__status { display: none; }

/* Gear and expand chevron, top right; they grow in from the corner as the card leaves name only */
.kl-card__ctl {
  position: absolute; top: 12px; right: 12px; display: flex; gap: 4px;
  opacity: var(--kl-oc); scale: calc(.8 + .2 * var(--kl-oc)); transform-origin: top right;
}
.kl-card[data-stage="0"] .kl-card__ctl { visibility: hidden; }

/* Corner grip: pull it to move continuously through the stages */
.kl-card__grip {
  position: absolute; right: 8px; bottom: 8px; width: 20px; height: 20px;
  display: grid; place-items: center; padding: 0; border: 0; border-radius: var(--kl-radius-control);
  background: transparent; color: var(--kl-color-text-secondary); cursor: nwse-resize;
}
.kl-card__grip .kl-icon { --kl-icon-size: 12px; }
.kl-card__grip:hover { background: var(--kl-color-control-fill); }
.kl-card__grip:active, .kl-card.is-pulled .kl-card__grip { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
.kl-card[data-stage="0"] .kl-card__grip { right: 6px; bottom: 6px; opacity: .45; }
.kl-card[data-stage="0"]:hover .kl-card__grip { opacity: 1; }

/* Expanded: meter, agent rows (how each agent runs), the deployed note */
.kl-card__more { display: none; flex-direction: column; gap: 12px; min-height: 0; overflow: auto; }
.kl-card[data-stage="3"] .kl-card__more { display: flex; }
.kl-meterline { display: flex; flex-direction: column; gap: 6px; }
.kl-meterline__row { display: flex; justify-content: space-between; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-cardmeter { height: 7px; border-radius: 4px; background: var(--kl-color-switch-off); overflow: hidden; }
.kl-cardmeter > i { display: block; height: 100%; width: var(--kl-meter, 0%); border-radius: inherit; background: var(--kl-color-control); }
.kl-cardmeter.is-near > i { background: var(--kl-color-status-planning); }   /* 85% to 99% of the handoff ceiling */
.kl-agent-list { border-top: 1px solid var(--kl-color-line); }
.kl-agent-list--grid { display: grid; grid-template-columns: 1fr 1fr; column-gap: 24px; }
.kl-agent-row {
  display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; padding: 8px 0;
  border-bottom: 1px solid var(--kl-color-line); font: var(--kl-font-meta);
}
.kl-agent-row b { font-weight: var(--kl-font-weight-bold); }
.kl-agent-row__meta { display: flex; align-items: center; gap: 8px; }
.kl-agent-row__act { grid-column: 1 / -1; color: var(--kl-color-text-secondary); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-agent-row--stuck { margin: 0 -8px; padding: 8px; border-radius: var(--kl-radius-row); background: var(--kl-color-status-stopped-soft); border-bottom-color: transparent; }
.kl-run { display: inline-flex; align-items: center; height: 18px; padding: 0 6px; border-radius: var(--kl-radius-sheet);
  background: var(--kl-color-neutral-soft); color: var(--kl-color-neutral-ink); font: var(--kl-font-caption); font-weight: var(--kl-font-weight-semibold); letter-spacing: .2px; }
.kl-effort { display: inline-flex; align-items: center; gap: 5px; font: var(--kl-font-badge); font-weight: var(--kl-font-weight-medium); color: var(--kl-color-text-secondary); }
.kl-effort::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.kl-effort--medium { color: var(--kl-color-status-planning-ink); }
.kl-effort--high { color: var(--kl-color-status-stopped-ink); }
.kl-card__deployed { padding: 8px 10px; border-radius: var(--kl-radius-row); background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); font: var(--kl-font-meta); }

/* Grows with its content (.kl-card--grow): at expanded the card is as tall as its face, and the face lets a calendar or
   a popover reach past the card's edge. Without it an expanded card stays 320 to 432 tall and scrolls inside.
   The height still glides (the content's own blocks open with Motion's kl-m-grow), it never jumps. */
.kl-card--grow[data-stage="3"] { height: auto; min-height: 0; }
.kl-card--grow[data-stage="3"] > .kl-card__face { position: relative; inset: auto; overflow: visible; }
.kl-card--grow[data-stage="3"] .kl-card__more { overflow: visible; }
.kl-card--wide[data-stage="3"] { --kl-card-w: var(--kl-card-expanded-w-wide); }

/* Card sizes for other kinds (the kind's own part adds the class next to its own) */
.kl-card--teach[data-stage="1"] { width: var(--kl-teach-compact-w); }
.kl-card--teach[data-stage="3"] { --kl-card-w: var(--kl-teach-expanded-w); }
.kl-card--question[data-stage="3"] { --kl-card-w: var(--kl-question-expanded-w); height: auto; min-height: 0; max-height: var(--kl-question-max-h); }
.kl-card--question[data-stage="3"] > .kl-card__face { position: relative; inset: auto; max-height: var(--kl-question-max-h); box-sizing: border-box; overflow: auto; }

/* Web chip: the site an agent is browsing, opening the agent browser. Under the status line at full and expanded;
   at compact an icon-only round chip (.kl-card__web--icon) inside .kl-card__agents; gone at name only.
   At full the status line drops to one line, so the card stays 140 high. States (live, paused, needs you, done, open)
   are the agent browser's (.kl-webchip.is-*). The dot is the project's hue. */
.kl-card__web {
  display: inline-flex; align-items: center; gap: 6px; align-self: flex-start; max-width: 100%;
  height: var(--kl-card-web-h); padding: 0 10px 0 6px; box-sizing: border-box; flex: none;
  border: 0; border-radius: var(--kl-radius-pill);
  background: color-mix(in srgb, var(--kl-color-surface) 72%, transparent); box-shadow: inset 0 0 0 1px var(--kl-color-line);
  color: var(--kl-color-text); font: var(--kl-font-caption); font-weight: var(--kl-font-weight-semibold); white-space: nowrap;
  cursor: pointer; opacity: var(--kl-ol);
  transition: box-shadow var(--kl-motion-hover) ease, background-color var(--kl-motion-hover) ease;
}
.kl-card__web:hover { background: var(--kl-color-surface); box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
.kl-card__web:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-card__web .kl-icon { --kl-icon-size: 14px; flex: none; color: var(--kl-card-hue-ink); }
.kl-card__web-host { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.kl-card__web-dot { width: 6px; height: 6px; flex: none; border-radius: var(--kl-radius-round); background: var(--kl-card-hue); }
.kl-card__web--icon { position: relative; width: var(--kl-card-web-h); padding: 0; justify-content: center; opacity: 1; }
.kl-card__web--icon .kl-card__web-host { display: none; }
.kl-card__web--icon .kl-card__web-dot { position: absolute; right: 1px; top: 1px; box-shadow: 0 0 0 2px var(--kl-color-surface); }
.kl-card[data-stage="0"] .kl-card__web,
.kl-card[data-stage="1"] .kl-card__web:not(.kl-card__web--icon),
.kl-card:not([data-stage="1"]) .kl-card__web--icon { display: none; }
.kl-card[data-stage="2"]:has(.kl-card__web) .kl-card__status { -webkit-line-clamp: 1; }

/* Asking: the project's agents wait on Alban to allow or answer something ("3 things wait on you").
   Waiting on Alban is never stuck: Police skips an asking card, so .is-asking wins over .is-stuck's ring and siren. */
.kl-dot.kl-dot--approval { --kl-dot-c: var(--kl-card-approval); --kl-dot: var(--kl-card-approval); }   /* Board reads --kl-dot-c, Controls --kl-dot */
.kl-card__status.is-asking { color: var(--kl-card-approval-ink); font-weight: var(--kl-font-weight-semibold); }
.kl-card.is-asking .kl-card__face,
.kl-card.is-asking.is-stuck .kl-card__face { border-color: var(--kl-card-approval); box-shadow: 0 0 0 1px var(--kl-card-approval), var(--kl-glass-card-shadow); }
.kl-card.is-asking .kl-card__rays { border-color: var(--kl-card-approval); --kl-motion-tint-stopped: var(--kl-card-approval); }

/* --- Project card states --- */
.kl-card.is-stopped .kl-card__face { border-color: var(--kl-color-status-stopped); }
/* Stuck (Police found it): a wider soft red ring */
.kl-card.is-stuck .kl-card__face { border-color: var(--kl-color-status-stopped);
  box-shadow: 0 0 0 1px var(--kl-color-status-stopped), var(--kl-shadow-ring-stuck), var(--kl-glass-card-shadow); }
/* Rays: a stopped card waiting on Alban breathes a dashed ring (add kl-m-rays). Gone once acknowledged. */
.kl-card__rays {
  position: absolute; inset: -16px; z-index: 0; pointer-events: none;
  border: 2px dashed var(--kl-color-status-stopped); border-radius: calc(var(--kl-card-r) + 14px); opacity: .55;
}
.kl-card__rays + .kl-card__face { z-index: 1; }
.kl-card__rays ~ :is(.kl-card__ctl, .kl-card__grip) { z-index: 2; }   /* the gear, chevron and grip stay above the face */
/* Link source and target: no ring on the face; Motion's kl-m-link-edge child lights up instead (section 11) */
.kl-card.is-linking .kl-card__face { box-shadow: var(--kl-glass-card-shadow-hover); }
/* Chosen as the prompter's destination */
.kl-card.is-selected .kl-card__face { border-color: var(--kl-color-selection); box-shadow: 0 0 0 1px var(--kl-color-selection), var(--kl-glass-card-shadow); }
.kl-card__check {
  position: absolute; top: -8px; right: -8px; z-index: 2; width: 24px; height: 24px; display: grid; place-items: center;
  border-radius: 50%; background: var(--kl-color-selection); color: var(--kl-color-text-on-fill); box-shadow: 0 0 0 3px var(--kl-color-surface);
}
.kl-card__check .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2.2; }
/* A roamer visiting the card: a soft ring in the roamer's colour */
.kl-visit { --kl-vc: var(--kl-roamer-context); }
.kl-visit--knowledge { --kl-vc: var(--kl-roamer-knowledge); }
.kl-visit--tokenomy { --kl-vc: var(--kl-roamer-tokenomy); }
.kl-visit--police { --kl-vc: var(--kl-roamer-police); }
.kl-card.kl-visit .kl-card__face, .kl-tool.kl-visit {
  box-shadow: 0 0 0 1.5px var(--kl-vc), 0 0 0 6px color-mix(in srgb, var(--kl-vc) 14%, transparent), var(--kl-glass-card-shadow);
  transition: box-shadow 260ms var(--kl-motion-ease-out);
}
/* News: the ring a card sends when it has news takes its phase colour (with kl-m-news-ring) */
.kl-card.is-executing { --kl-ring: var(--kl-color-status-executing); }
.kl-card.is-planning { --kl-ring: var(--kl-color-status-planning); }

/* =====================================================================================================
   4. Tool cards: the shell shared by helpers, roamers, section cards and the brand card
      (tile on the left, name, one meta line)
   ===================================================================================================== */
.kl-tool {
  --kl-mini: 0;   /* 0 full, 1 zoomed out to icon + name; springs in between */
  position: relative;
  display: grid; grid-template-columns: var(--kl-tool-tile) 1fr; column-gap: 12px; row-gap: 2px; align-items: center;
  box-sizing: border-box; padding: 12px 16px 12px 12px;
  background: var(--kl-tool-glass, var(--kl-glass-card)); color: var(--kl-color-text);
  -webkit-backdrop-filter: var(--kl-glass-card-filter); backdrop-filter: var(--kl-glass-card-filter);
  border: 1px solid transparent; border-radius: var(--kl-radius-panel); box-shadow: var(--kl-glass-card-shadow);
  font: inherit; text-align: left; cursor: pointer;
  transition: box-shadow var(--kl-motion-hover) ease, border-color var(--kl-motion-hover) ease;
}
.kl-tool:hover { box-shadow: var(--kl-glass-card-shadow-hover); }
/* Each tool card's glass takes its kind's hue */
.kl-helper { --kl-tool-glass: var(--kl-glass-card-amber); }
.kl-helper--builder { --kl-tool-glass: var(--kl-glass-card-coral); }
.kl-helper--cleanser { --kl-tool-glass: var(--kl-glass-card-green); }
.kl-roamer--context { --kl-tool-glass: var(--kl-glass-card-context); }
.kl-roamer--knowledge { --kl-tool-glass: var(--kl-glass-card-knowledge); }
.kl-roamer--tokenomy { --kl-tool-glass: var(--kl-glass-card-tokenomy); }
.kl-roamer--police { --kl-tool-glass: var(--kl-glass-card-police); }
.kl-roamer--ambulance { --kl-tool-glass: var(--kl-glass-card-ambulance); }
.kl-roamer--garbage { --kl-tool-glass: var(--kl-glass-card-garbage); }
.kl-section--settings { --kl-tool-glass: var(--kl-glass-card-settings); }
.kl-section--presets { --kl-tool-glass: var(--kl-glass-card-presets); }
.kl-section--alerts { --kl-tool-glass: var(--kl-glass-card-alerts); }
.kl-section--requests { --kl-tool-glass: var(--kl-glass-card-requests); }
.kl-brand { --kl-tool-glass: var(--kl-glass-card-klippan); }
.kl-tool:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-tool__tile {
  grid-row: 1 / span 2; width: var(--kl-tool-tile); height: var(--kl-tool-tile);
  display: grid; place-items: center; border-radius: var(--kl-radius-tile);
  background: var(--kl-color-control-fill); color: var(--kl-color-text);
}
.kl-tool__tile .kl-icon { --kl-icon-size: 18px; }
.kl-tool__name { font: var(--kl-font-headline); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.kl-tool__sub { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-tool__meta {
  display: block; min-width: 0;
  font: var(--kl-font-meta); color: var(--kl-color-text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.kl-tool__meta .kl-pulse { display: inline-block; vertical-align: 1px; margin-right: 6px; }

/* =====================================================================================================
   5. Helper cards: Researcher, Agent Builder, File Cleanser. Standalone cards tied to a project by a line
      in their colour (see .kl-link--tie)
   ===================================================================================================== */
.kl-helper { --kl-hc: var(--kl-color-helper-researcher); width: var(--kl-helper-w); min-height: var(--kl-helper-h); padding: 10px 16px 10px 10px; }
.kl-helper--builder { --kl-hc: var(--kl-color-helper-builder); }
.kl-helper--cleanser { --kl-hc: var(--kl-color-helper-cleanser); }
.kl-helper .kl-tool__tile { border-radius: var(--kl-radius-round); background: color-mix(in srgb, var(--kl-hc) 18%, transparent); }
.kl-helper__mark { width: 16px; height: 16px; border-radius: 50%; background: var(--kl-hc); }
.kl-helper.is-busy { border-color: var(--kl-hc); box-shadow: 0 0 0 1px var(--kl-hc), var(--kl-glass-card-shadow); }

/* =====================================================================================================
   6. Roamers: Context, Knowledge, Tokenomy, Police, Ambulance, Garbage. They glide to a free spot beside a card,
      link to it in their own colour, then return (kl-m-travel, kl-m-roam-in/out, kl-m-drift while parked)
   ===================================================================================================== */
.kl-roamer { --kl-rc: var(--kl-roamer-context); width: 244px; min-height: var(--kl-roamer-h); }
.kl-roamer--context .kl-tool__tile { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
.kl-roamer--knowledge { --kl-rc: var(--kl-roamer-knowledge); }
.kl-roamer--knowledge .kl-tool__tile { background: var(--kl-color-text); color: var(--kl-color-surface); font: var(--kl-font-headline); }
.kl-roamer--tokenomy { --kl-rc: var(--kl-roamer-tokenomy); width: 264px; border-radius: var(--kl-radius-pill); padding: 10px 20px 10px 10px; }
.kl-roamer--tokenomy .kl-tool__tile { border-radius: 50%; background: var(--kl-color-status-planning-soft); color: var(--kl-color-status-planning-ink); }
.kl-roamer--police { --kl-rc: var(--kl-roamer-police); width: 240px; border-radius: var(--kl-radius-menu); border-color: var(--kl-color-line-strong); }
.kl-roamer--police .kl-tool__tile { background: var(--kl-color-neutral-soft); }
.kl-roamer--ambulance { --kl-rc: var(--kl-roamer-ambulance); width: 252px; border-radius: var(--kl-radius-menu);
  box-shadow: 0 0 0 1px var(--kl-color-status-stopped-soft), var(--kl-glass-card-shadow); }
.kl-roamer--ambulance .kl-tool__tile { background: var(--kl-color-status-stopped-soft); color: var(--kl-color-status-stopped-ink); }
.kl-roamer--garbage { width: 236px; }
.kl-roamer--garbage .kl-tool__tile { background: var(--kl-color-neutral-soft); }

/* The small live dot before a roamer's status */
.kl-pulse { width: 8px; height: 8px; flex: none; border-radius: 50%; background: var(--kl-rc); }
.kl-pulse--red { background: var(--kl-color-status-stopped); }
@media (prefers-reduced-motion: no-preference) {
  .kl-pulse.is-live { animation: kl-board-pulse var(--kl-motion-roamer-pulse, 1.6s) var(--kl-motion-ease-out) infinite; }
}
@keyframes kl-board-pulse { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--kl-rc) 35%, transparent); } 100% { box-shadow: 0 0 0 7px transparent; } }

/* Visiting states */
.kl-roamer--context.is-scanning { border-color: var(--kl-color-selection); }
.kl-roamer--knowledge.is-collecting { border-color: var(--kl-color-line-strong); }
.kl-roamer--tokenomy.is-inspecting { border-color: var(--kl-color-status-planning); box-shadow: 0 0 0 1px var(--kl-color-status-planning), var(--kl-glass-card-shadow); }

/* Context keeps a stack: two cards peek out 5px and 10px below it */
.kl-roamer--context {
  box-shadow: 0 5px 0 -1px var(--kl-color-surface), 0 5px 0 0 var(--kl-color-line-strong),
              0 10px 0 -2px var(--kl-color-surface), 0 10px 0 -1px var(--kl-color-line), var(--kl-glass-card-shadow);
}
/* Knowledge: four letter tabs on its top edge; the first lights while it announces new entries */
.kl-letters { position: absolute; left: 58px; top: -13px; display: flex; gap: 3px; pointer-events: none; opacity: calc(1 - 1.6 * var(--kl-mini)); }
.kl-letters > span {
  width: 20px; height: 13px; display: grid; place-items: center; border-radius: 5px 5px 0 0;
  background: var(--kl-color-surface); box-shadow: 0 0 0 1px var(--kl-color-line);
  font: var(--kl-font-caption); font-weight: var(--kl-font-weight-bold); color: var(--kl-color-text-secondary);
  transition: background-color 200ms ease, color 200ms ease;
}
.kl-letters > span.is-lit { background: var(--kl-color-text); color: var(--kl-color-surface); }

/* Police and Ambulance: a small light bar on the top edge (add kl-m-bar--watch / --police / --siren) */
.kl-lightbar {
  position: absolute; top: -5px; left: 50%; width: 18px; height: 6px; margin-left: -9px;
  border-radius: 4px 4px 0 0; background: var(--kl-color-selection);
}
.kl-lightbar--siren { background: var(--kl-color-status-stopped); }
.kl-roamer--police.is-alarm, .kl-roamer--ambulance.is-working {
  border-color: var(--kl-color-status-stopped); box-shadow: 0 0 0 1px var(--kl-color-status-stopped), var(--kl-glass-card-shadow);
}
/* Garbage: only there while files wait. Arriving gets a blue ring; leaving goes dashed */
.kl-roamer--garbage.is-arriving { border-color: var(--kl-color-selection); box-shadow: 0 0 0 1px var(--kl-color-selection), var(--kl-glass-card-shadow); }
.kl-roamer--garbage.is-leaving { border-style: dashed; border-color: var(--kl-color-line-strong); box-shadow: none; }
.kl-roamer--garbage.is-leaving .kl-tool__name { color: var(--kl-color-text-secondary); }

/* Count badge (Requests, Garbage) and the Alerts count */
.kl-countbadge {
  position: absolute; top: -8px; right: -8px; z-index: 2;
  min-width: 22px; height: 22px; padding: 0 6px; box-sizing: border-box;
  display: grid; place-items: center; border-radius: var(--kl-radius-pill);
  background: var(--kl-color-primary); color: var(--kl-color-text-on-fill);
  font: var(--kl-font-badge); box-shadow: 0 0 0 3px var(--kl-color-surface);
}
.kl-countbadge--ink { background: var(--kl-color-text); color: var(--kl-color-surface); }
.kl-countbadge--alert { background: var(--kl-color-status-stopped); }
.kl-countbadge--approval { background: var(--kl-card-approval); }   /* "2 need you": waiting on Alban (Runs, Approvals) */

/* =====================================================================================================
   7. Small context card: one per thing Context scans, flying into its stack (offset-path, 700ms)
   ===================================================================================================== */
.kl-ctx-chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: var(--kl-ctx-chip-w-max);
  padding: 4px 9px 4px 6px; box-sizing: border-box;
  border-radius: var(--kl-radius-row); background: var(--kl-color-surface); border: 1px solid var(--kl-color-selection);
  box-shadow: var(--kl-shadow-card); color: var(--kl-color-text);
  font: var(--kl-font-caption); font-weight: var(--kl-font-weight-semibold); white-space: nowrap;
}
.kl-ctx-chip > span:last-child { overflow: hidden; text-overflow: ellipsis; }
.kl-ctx-chip__mark { width: 10px; height: 10px; flex: none; border-radius: 4px; background: var(--kl-color-accent); }
.kl-ctx-chip__mark--helper { border-radius: 50%; background: var(--kl-hc, var(--kl-color-helper-researcher)); }
.kl-ctx-chip.is-flying { offset-path: var(--kl-fly-path); offset-rotate: 0deg; }
@media (prefers-reduced-motion: no-preference) {
  .kl-ctx-chip.is-flying { animation: kl-board-fly var(--kl-motion-travel) var(--kl-motion-ease-out) 80ms both; }
}
@keyframes kl-board-fly {
  0% { offset-distance: 0%; scale: .7; opacity: 0; }
  12% { scale: 1; opacity: 1; }
  88% { opacity: 1; }
  100% { offset-distance: 100%; scale: .8; opacity: 0; }
}

/* =====================================================================================================
   8. Section cards: Settings, Presets, Alerts, Requests (Simulate uses the same shell). Each opens a window;
      linked to a project, it opens that project's version
   ===================================================================================================== */
.kl-section { width: var(--kl-section-w); min-height: var(--kl-section-h); }
.kl-section.is-open { border-color: var(--kl-color-selection); box-shadow: 0 0 0 1px var(--kl-color-selection), var(--kl-glass-card-shadow); }
.kl-section.is-open .kl-tool__tile { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
.kl-section.is-open .kl-tool__meta { color: var(--kl-color-selection-ink); }
.kl-section.is-minimized .kl-tool__tile { box-shadow: inset 0 0 0 1.5px var(--kl-color-selection); }
.kl-open-dot { position: absolute; top: 10px; right: 10px; width: 8px; height: 8px; border-radius: 50%; background: var(--kl-color-selection); }
/* Alerts while a stopped project waits for an acknowledgement (add kl-m-alerting, and kl-m-bell on the icon) */
.kl-section.is-alerting { border-color: var(--kl-color-status-stopped); box-shadow: 0 0 0 1px var(--kl-color-status-stopped), var(--kl-glass-card-shadow); --kl-motion-tint-accent: var(--kl-color-status-stopped); }
.kl-section.is-alerting .kl-tool__tile { background: var(--kl-color-status-stopped-soft); color: var(--kl-color-status-stopped-ink); }
.kl-section.is-alerting .kl-tool__meta { color: var(--kl-color-status-stopped-ink); font-weight: var(--kl-font-weight-semibold); white-space: normal; }
/* Questions waiting on Alban: a count badge in the approval colour on the top edge (.kl-countbadge--approval) and the
   meta line in the approval ink. Calm on purpose: a question is not a stop, so no ring pulse or bell unless a project
   is also stopped. With both counts, the approval badge sits just left of the red one. */
.kl-section--alerts.is-asking:not(.is-alerting) .kl-tool__tile { background: var(--kl-card-approval-soft); color: var(--kl-card-approval-ink); }
.kl-section--alerts.is-asking:not(.is-alerting) .kl-tool__meta { color: var(--kl-card-approval-ink); font-weight: var(--kl-font-weight-semibold); }
.kl-section--alerts > .kl-countbadge--alert ~ .kl-countbadge--approval { right: 18px; }

/* =====================================================================================================
   9. Klippan brand card: mark, board count, light/dark switch, and the playfulness dial (Calm 0 to Playful 100,
      default 35; 100 is Step 8 exactly). It never lifts on hover or squashes on press.
   ===================================================================================================== */
.kl-brand {
  width: var(--kl-brand-w); min-height: var(--kl-brand-h); padding: 12px;
  grid-template-columns: var(--kl-tool-tile) 1fr auto; grid-template-rows: 20px 18px auto; cursor: default;
}
.kl-brand:hover { box-shadow: var(--kl-glass-card-shadow); }
.kl-brand .kl-tool__tile { background: transparent; }
.kl-brand .kl-tool__tile svg { width: 36px; height: 36px; }
.kl-brand .kl-tool__name { font-size: 17px; line-height: 20px; letter-spacing: -.4px; }
.kl-brand .kl-tool__meta { grid-column: 2; }
.kl-theme-seg {
  grid-column: 3; grid-row: 1 / span 2; position: relative; display: inline-flex; padding: 2px;
  border-radius: var(--kl-radius-pill); background: var(--kl-color-control-fill);
}
.kl-theme-seg::before {
  content: ""; position: absolute; top: 2px; bottom: 2px; left: 2px; width: calc(50% - 2px);
  border-radius: var(--kl-radius-pill); background: var(--kl-color-surface); box-shadow: var(--kl-shadow-knob);
  transition: translate 420ms var(--kl-motion-spring);
}
.kl-theme-seg[data-value="dark"]::before { translate: 100% 0; }
.kl-theme-seg button { position: relative; padding: 5px 9px; border: 0; background: none; color: var(--kl-color-text-secondary); cursor: pointer; display: grid; }
.kl-theme-seg button[aria-pressed="true"] { color: var(--kl-color-text); }
.kl-theme-seg button[aria-pressed="true"] .kl-icon { rotate: -20deg; }
.kl-theme-seg .kl-icon { --kl-icon-size: 14px; transition: rotate 420ms var(--kl-motion-spring); }

.kl-dial {
  grid-column: 1 / -1; display: flex; align-items: center; gap: 8px;
  margin-top: 6px; padding-top: 8px; border-top: 1px solid var(--kl-color-line);
  font: var(--kl-font-badge); font-weight: var(--kl-font-weight-regular); color: var(--kl-color-text-secondary);
}
.kl-dial__n { min-width: 24px; text-align: right; color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }
.kl-dial__range {
  --kl-fill: 35%;
  flex: 1; height: 24px; margin: 0; background: none; -webkit-appearance: none; appearance: none; cursor: pointer;
}
.kl-dial__range::-webkit-slider-runnable-track { height: 4px; border-radius: var(--kl-radius-pill);
  background: linear-gradient(to right, var(--kl-color-selection) var(--kl-fill), var(--kl-color-control-fill) var(--kl-fill)); }
.kl-dial__range::-moz-range-track { height: 4px; border-radius: var(--kl-radius-pill);
  background: linear-gradient(to right, var(--kl-color-selection) var(--kl-fill), var(--kl-color-control-fill) var(--kl-fill)); }
.kl-dial__range::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; margin-top: -6px; border-radius: 50%;
  background: var(--kl-color-knob); box-shadow: var(--kl-shadow-knob); transition: scale var(--kl-motion-press) ease; }
.kl-dial__range::-moz-range-thumb { width: 16px; height: 16px; border: 0; border-radius: 50%; background: var(--kl-color-knob); box-shadow: var(--kl-shadow-knob); }
.kl-dial__range:active::-webkit-slider-thumb { scale: 1.12; }
.kl-dial__range:focus-visible { outline: none; }
.kl-dial__range:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 2px var(--kl-color-focus), var(--kl-shadow-knob); }

/* =====================================================================================================
   10. Zoomed out (semantic zoom). Below 78% projects rest at compact at most; below 60% they go name only and
       helpers, roamers and section cards spring to icon + name (--kl-mini 0 to 1). Badges stay.
       The brand card and Simulate keep their full size.
   ===================================================================================================== */
.kl-tool.is-mini { --kl-mini: 1; }
.kl-tool.is-mini, .kl-tool[style*="--kl-mini"] {
  grid-template-columns: calc(var(--kl-tool-tile) - 12px * var(--kl-mini)) 1fr;
  column-gap: calc(12px - 4px * var(--kl-mini));
  padding: calc(12px - 5px * var(--kl-mini)) calc(16px - 4px * var(--kl-mini)) calc(12px - 5px * var(--kl-mini)) calc(12px - 5px * var(--kl-mini));
}
.kl-tool.is-mini { width: auto; min-height: var(--kl-mini-h); }
.kl-tool.is-mini .kl-tool__tile { grid-row: auto; width: var(--kl-mini-tile); height: var(--kl-mini-tile); }
.kl-tool.is-mini .kl-tool__tile .kl-icon { --kl-icon-size: 14px; }
.kl-tool.is-mini .kl-tool__name { font: var(--kl-font-label-strong); font-weight: var(--kl-font-weight-bold); line-height: 18px; text-overflow: clip; }
.kl-tool[style*="--kl-mini"] :is(.kl-tool__meta, .kl-tool__sub) { max-height: calc(18px * (1 - var(--kl-mini))); opacity: calc(1 - 1.6 * var(--kl-mini)); }
.kl-tool.is-mini .kl-tool__meta, .kl-tool.is-mini .kl-tool__sub { display: none; }
.kl-tool.is-mini.kl-roamer--context { box-shadow: var(--kl-glass-card-shadow); }
.kl-tool.is-mini .kl-helper__mark { width: 12px; height: 12px; }

/* =====================================================================================================
   10b. Board rules for stacks (the Stacks part owns the frame, tab, pile and shelf look).
       - A stackable card holds <i class="kl-stack-shelf"></i> as its FIRST child; the link edge stays the LAST child.
       - Frames sit at z 1, with the light pools and resting lines, under every card.
       - Cards and frames are placed with left/top, never a transform: a transform offset would be scaled by the
         card's own scale (lift, land, pile).
       - .is-stacked (or being a child of .kl-stack) stands a card straight; dragging still leans it (section 2).
       Zoomed out: compact cards stack and pile exactly as at full. Name-only cards in a stack all take one width so the
       names line up, and a collapsed pile of name-only cards shows only its top pill with an ink count badge
       (.kl-countbadge--ink, the number of cards in it), because 56-high edges peeking out read as noise.
   ===================================================================================================== */
.kl-card > .kl-stack-shelf:first-child { pointer-events: none; }
:is(.kl-stack > .kl-card, .kl-card.is-stacked)[data-stage="0"] { width: var(--kl-stack-card-w, var(--kl-card-name-w-max)); }
.kl-stack.is-collapsed:not(.is-free) > .kl-card[data-stage="0"]:nth-of-type(n+2),
.kl-card[data-stage="0"]:is(.kl-stack-pile-1, .kl-stack-pile-2) { opacity: 0; pointer-events: none; }
.kl-stack.is-collapsed:not(.is-free):has(> .kl-card[data-stage="0"]) { padding-bottom: var(--kl-space-stack-pad); }

/* =====================================================================================================
   11. Linking and link lines.
       While a link is being made there is no line (Alban, 2026-10-13): the side of the source card facing the
       pointer glows, a soft pool of selection light follows the pointer on the board, and a target's edge lights
       up only while the pointer is inside it. Click attaches. Esc, an empty-board click, or the pointer leaving
       the board or the window clears it all.
       All of it is Motion's (motion.css "Linking glow", motion.js KlMotion.linkGlow); the board only places it.
       Markup: an empty <i class="kl-m-link-edge"></i> as the last child of every project card and every tool that
       can take a link; one <div class="kl-m-link-pool"></div> on the board.
       Classes: source .is-linking.kl-m-link-source.is-glowing with --kl-gx / --kl-gy (linkGlow's edge point);
       pool .is-on, moved to linkGlow's pool point with transform: translate(), dropped while the pointer is on a target; target
       .is-target.kl-m-target while linkGlow says over; on click the target takes kl-m-attached and kl-m-land,
       and losing kl-m-attached fades its edge over --kl-motion-link-attach.
       The glow never scales with the playfulness dial.
   ===================================================================================================== */
/* The lit edge follows each piece's own corners (name-only cards, pill roamers, panels) and sits above the face */
:is(.kl-card, .kl-tool) > .kl-m-link-edge { z-index: 3; }
:is(.kl-card, .kl-tool) > .kl-m-link-edge::before { border-radius: inherit; }
.kl-tool.kl-m-target { box-shadow: var(--kl-glass-card-shadow-hover); }

/* ---- Link lines between cards that are already linked (requests, syncs, helper ties, roamer visits). They stay.
       One SVG per line, overflow visible, placed in board units:
       path.kl-link__path, path.kl-link__flow, circle.kl-link__pulse, circle.kl-link__origin,
       polygon.kl-link__head, circle.kl-link__end (a tie's far dot).
       Geometry: a quadratic M a Q c b, bowed to one side. Link motion does not scale with the playfulness dial.
   ===================================================================================================== */
.kl-link { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible; pointer-events: none; z-index: var(--kl-z-link, 45); color: var(--kl-link-c, var(--kl-color-link)); }
.kl-link__path { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-dasharray: 2 6; }
.kl-link__flow { fill: none; stroke: var(--kl-color-text-on-fill); stroke-width: 1.5; stroke-linecap: round; stroke-dasharray: 3 37; opacity: 0; }
.kl-link__origin { fill: currentColor; stroke: var(--kl-color-surface); stroke-width: 2; }
.kl-link__pulse { fill: none; stroke: currentColor; stroke-width: 1.5; opacity: 0; transform-box: fill-box; transform-origin: center; }
.kl-link__head, .kl-link__end { fill: currentColor; }
.kl-link__end { transform-box: fill-box; transform-origin: center; }
.kl-link__head { transform-box: fill-box; transform-origin: center; }

/* Snapped (a roamer on a card): solid, an arrowhead, light runs along it */
.kl-link--snapped .kl-link__path { stroke-width: 2.5; stroke-dasharray: none; }
.kl-link--snapped .kl-link__flow { opacity: .85; }
.kl-link--snapped .kl-link__end { display: none; }

/* Request (one arrowhead) and sync (arrowheads at both ends): solid, under the cards, with a label pill */
.kl-link--request, .kl-link--sync { z-index: var(--kl-z-under, 1); }
.kl-link--request .kl-link__path, .kl-link--sync .kl-link__path { stroke-width: 2.5; stroke-dasharray: none; }
/* Helper tie: the helper's colour, a dot at each end, no arrowhead, specks running toward the project */
.kl-link--tie { z-index: var(--kl-z-under, 1); }
.kl-link--tie .kl-link__path { stroke-width: 2.5; stroke-dasharray: none; }
.kl-link--tie .kl-link__flow { opacity: .7; }
.kl-link--tie .kl-link__end { stroke: var(--kl-color-surface); stroke-width: 2; }
.kl-link--tie.is-quiet { opacity: .35; transition: opacity 200ms ease; }
.kl-link--researcher { --kl-link-c: var(--kl-color-helper-researcher); }
.kl-link--builder { --kl-link-c: var(--kl-color-helper-builder); }
.kl-link--cleanser { --kl-link-c: var(--kl-color-helper-cleanser); }
/* Roamer link: the roamer's colour, routed round the cards (bends .15 to .9) */
.kl-link--roamer { z-index: var(--kl-z-under, 1); }
.kl-link--roamer.kl-link--snapped .kl-link__path { stroke-width: 2; }
.kl-link--roamer .kl-link__flow { opacity: .75; }
.kl-link--context { --kl-link-c: var(--kl-roamer-context); }
.kl-link--knowledge { --kl-link-c: var(--kl-roamer-knowledge); }
.kl-link--knowledge.kl-link--snapped .kl-link__path { stroke-width: 1.5; }
.kl-link--knowledge .kl-link__flow { stroke-width: 1; }
.kl-link--tokenomy { --kl-link-c: var(--kl-roamer-tokenomy); }
.kl-link--police { --kl-link-c: var(--kl-roamer-police); }
.kl-link--alarm, .kl-link--ambulance { --kl-link-c: var(--kl-color-status-stopped); }
/* Project tie (--tie --p1..--p8): a tie in a project's hue, e.g. a question card to the project that asks.
   The ink shade, so the line reads on glass and on the dot grid in both themes. */
.kl-link--p1 { --kl-link-c: var(--kl-color-project-1-ink); }
.kl-link--p2 { --kl-link-c: var(--kl-color-project-2-ink); }
.kl-link--p3 { --kl-link-c: var(--kl-color-project-3-ink); }
.kl-link--p4 { --kl-link-c: var(--kl-color-project-4-ink); }
.kl-link--p5 { --kl-link-c: var(--kl-color-project-5-ink); }
.kl-link--p6 { --kl-link-c: var(--kl-color-project-6-ink); }
.kl-link--p7 { --kl-link-c: var(--kl-color-project-7-ink); }
.kl-link--p8 { --kl-link-c: var(--kl-color-project-8-ink); }
/* Teach tie (--tie --teach): a teach card to the project it teaches, in the teach hue (Foundations' --kl-color-teach,
   teal until it lands) */
.kl-link--teach { --kl-link-c: var(--kl-color-teach, var(--kl-color-hue-teal)); }

/* A line into a collapsed stack ends on the pile (the nearest edge of its top card), not on the hidden card.
   Lines from one source into one pile draw once; .kl-link-count at the end says how many cards inside it reaches.
   Opening the stack splits them back into their own lines (Motion's link draw). */
.kl-link-count {
  position: absolute; z-index: var(--kl-z-tag, 46); translate: -50% -50%;
  min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box; display: grid; place-items: center;
  border-radius: var(--kl-radius-pill); background: var(--kl-link-c, var(--kl-color-link)); color: var(--kl-color-text-on-fill);
  font: var(--kl-font-caption); font-weight: var(--kl-font-weight-bold); box-shadow: 0 0 0 2px var(--kl-color-surface);
}

/* ---- The line's path, for anything that rides it (message tags, a label that must follow a moving card).
       Whoever draws a line sets --kl-link-path on the svg (a CSS path() in board units from a to b: the same
       M a Q c b curve, untrimmed by arrowheads) and data-a / data-b with the two end points, and updates both when a
       card moves. Put the line and its riders in one .kl-link-group (set the path there) so they share it.
       A rider parks at --kl-link-at along the line (50% by default). While a card is open, riders drop under it
       (and under the prompter) so nothing sits on the open card. */
.kl-link-group { position: absolute; left: 0; top: 0; width: 0; height: 0; }
.kl-link-rider {
  position: absolute; left: 0; top: 0; z-index: var(--kl-z-tag, 46);
  offset-path: var(--kl-link-path, none); offset-distance: var(--kl-link-at, 50%); offset-rotate: 0deg;
}
.kl-board:has(.kl-card[data-stage="3"]) :is(.kl-link-rider, .kl-msgtag),
.kl-board.has-open-card :is(.kl-link-rider, .kl-msgtag) { z-index: var(--kl-z-rider-under, 39); }

@media (prefers-reduced-motion: no-preference) {
  .kl-link--snapped .kl-link__pulse { animation: kl-link-pulse var(--kl-motion-link-pulse, 1800ms) var(--kl-motion-ease-out) infinite; }
  .kl-link--snapped .kl-link__head { animation: kl-link-pop var(--kl-motion-link-snap) var(--kl-motion-ease-link) backwards; }
  .kl-link--snapped .kl-link__flow { animation: kl-link-flow var(--kl-motion-link-flow) linear infinite; }
  .kl-link--request .kl-link__path, .kl-link--tie .kl-link__path { animation: kl-link-draw var(--kl-motion-link-attach) var(--kl-motion-ease-out) backwards; }
  .kl-link--request .kl-link__head, .kl-link--sync .kl-link__head, .kl-link--tie .kl-link__end { animation: kl-link-pop var(--kl-motion-link-snap) var(--kl-motion-ease-link) var(--kl-motion-link-snap) backwards; }
  .kl-link.is-leaving .kl-link__path { animation: kl-link-undraw var(--kl-motion-link-cancel) var(--kl-motion-ease-in) forwards; }
  .kl-link.is-leaving :is(.kl-link__head, .kl-link__end) { animation: kl-link-fade var(--kl-motion-fade-out) ease forwards; }
}
@keyframes kl-link-flow { from { stroke-dashoffset: 40; } to { stroke-dashoffset: 0; } }
@keyframes kl-link-pulse { 0% { opacity: .55; scale: 1; } 70%, 100% { opacity: 0; scale: 3; } }
@keyframes kl-link-pop { from { opacity: 0; scale: .4; } to { opacity: 1; scale: 1; } }
@keyframes kl-link-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes kl-link-undraw { from { stroke-dashoffset: 0; } to { stroke-dashoffset: 1; } }
@keyframes kl-link-fade { to { opacity: 0; } }

/* The label pill on a request or sync line, centred on the curve's midpoint */
.kl-link-label {
  position: absolute; z-index: var(--kl-z-tag, 46); translate: -50% -50%;
  display: inline-flex; align-items: center; gap: 6px; height: 24px; padding: 0 10px; box-sizing: border-box;
  border-radius: var(--kl-radius-pill); background: var(--kl-color-surface); color: var(--kl-color-text);
  box-shadow: 0 0 0 1.5px var(--kl-link-c, var(--kl-color-link)), var(--kl-shadow-card);
  font: var(--kl-font-badge); white-space: nowrap;
}
.kl-link-label--removable { padding-right: 3px; z-index: 5; }
.kl-link-label.is-selected { box-shadow: 0 0 0 2px var(--kl-color-link), var(--kl-shadow-card); z-index: 6; }
.kl-link-label__x {
  width: 18px; height: 18px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%;
  background: var(--kl-color-control-fill); color: var(--kl-color-text-secondary); cursor: pointer;
}
.kl-link-label__x .kl-icon { --kl-icon-size: 10px; --kl-icon-stroke: 2.4; }
.kl-link-label__x:hover { background: var(--kl-color-control-fill-pressed); color: var(--kl-color-text); }
@media (prefers-reduced-motion: no-preference) {
  .kl-link-label { animation: kl-link-label var(--kl-motion-link-snap) var(--kl-motion-ease-out) backwards; }
  .kl-link-label--removable { animation-delay: 240ms; }
}
@keyframes kl-link-label { from { opacity: 0; translate: -50% calc(-50% + 4px); } }

/* =====================================================================================================
   12. Speech bubble and news tags. One bubble at a time, from the card the notice is about; the speaker hops
       once (kl-m-hop). Bubble: kl-m-say-in on arrival (kl-m-warn adds the nudge), kl-m-say-out on leaving.
       Side: --top means the bubble sits above its speaker (tail pointing down). --kl-tail is the tail's offset.
   ===================================================================================================== */
.kl-say {
  --kl-say-dot: var(--kl-color-selection);
  --kl-say-edge: var(--kl-color-line);
  position: absolute; z-index: var(--kl-z-bubble, 900); pointer-events: none;
  display: flex; align-items: flex-start; gap: 8px; max-width: var(--kl-say-w-max); box-sizing: border-box;
  padding: 8px 12px 8px 10px;
  border-radius: var(--kl-radius-menu); background: var(--kl-color-surface); color: var(--kl-color-text);
  box-shadow: var(--kl-shadow-card);
  font: var(--kl-font-meta);
}
.kl-say__dot { width: 7px; height: 7px; flex: none; margin-top: 5.5px; border-radius: 50%; background: var(--kl-say-dot); }
.kl-say::after {
  content: ""; position: absolute; width: 10px; height: 10px; box-sizing: border-box;
  background: inherit; border: 1px solid transparent; rotate: 45deg;
}
.kl-say--top::after    { bottom: -5.5px; left: var(--kl-tail, 24px); margin-left: -5px; border-right-color: var(--kl-say-edge); border-bottom-color: var(--kl-say-edge); }
.kl-say--bottom::after { top: -5.5px; left: var(--kl-tail, 24px); margin-left: -5px; border-left-color: var(--kl-say-edge); border-top-color: var(--kl-say-edge); }
.kl-say--left::after   { right: -5.5px; top: var(--kl-tail, 16px); margin-top: -5px; border-right-color: var(--kl-say-edge); border-top-color: var(--kl-say-edge); }
.kl-say--right::after  { left: -5.5px; top: var(--kl-tail, 16px); margin-top: -5px; border-left-color: var(--kl-say-edge); border-bottom-color: var(--kl-say-edge); }
.kl-say--top { transform-origin: var(--kl-tail, 24px) 100%; --kl-pop-x: 0px; --kl-pop-y: 4px; }
.kl-say--bottom { transform-origin: var(--kl-tail, 24px) 0; --kl-pop-x: 0px; --kl-pop-y: -4px; }
.kl-say--left { transform-origin: 100% var(--kl-tail, 16px); --kl-pop-x: 4px; --kl-pop-y: 0px; }
.kl-say--right { transform-origin: 0 var(--kl-tail, 16px); --kl-pop-x: -4px; --kl-pop-y: 0px; }
/* Kinds: info (blue dot), ok (green), warn (red dot and a red edge). There is no separate error kind. */
.kl-say--ok { --kl-say-dot: var(--kl-color-status-executing); }
.kl-say--warn {
  --kl-say-dot: var(--kl-color-status-stopped);
  --kl-say-edge: var(--kl-color-notice-edge-alert);
  box-shadow: var(--kl-shadow-bubble-alert);
}
/* News tag: the same element as a small pill a roamer says now and then, in its own colour */
.kl-say--news { align-items: center; gap: 6px; padding: 3px 10px 3px 8px; border-radius: var(--kl-radius-pill);
  font: var(--kl-font-badge); white-space: nowrap; max-width: 240px; }
.kl-say--news .kl-say__dot { width: 6px; height: 6px; margin: 0; }
.kl-say--news::after { width: 8px; height: 8px; }
.kl-say--news.kl-say--top::after { bottom: -4.5px; margin-left: -4px; }
.kl-say--news.kl-say--bottom::after { top: -4.5px; margin-left: -4px; }
.kl-say--context { --kl-say-dot: var(--kl-roamer-context); }
.kl-say--knowledge { --kl-say-dot: var(--kl-color-text); }
.kl-say--tokenomy { --kl-say-dot: var(--kl-roamer-tokenomy); }
.kl-say--police { --kl-say-dot: var(--kl-color-status-executing); }
.kl-say--teach { --kl-say-dot: var(--kl-color-teach, var(--kl-color-hue-teal)); }   /* Knowledge announcing a new skill */

/* =====================================================================================================
   13. Siren light. A pool on the board under Police or the Ambulance (two lobes that trade brightness; add
       kl-m-glow + kl-m-glow--siren / --alarm / --watch and kl-m-lobe on each lobe), and the edge of the card
       they work on (kl-m-lit + kl-m-lit--ambulance / --police; --kl-lx/--kl-ly point 10px toward the vehicle).
   ===================================================================================================== */
.kl-glow { position: absolute; z-index: var(--kl-z-under, 1); height: 64px; width: var(--kl-glow-w, 240px); pointer-events: none; opacity: 0; }
.kl-glow.is-on { opacity: 1; }
.kl-glow__lobe {
  position: absolute; top: -96px; width: 300px; height: 230px; margin-left: -150px;
  background: radial-gradient(closest-side, var(--kl-lobe, transparent), transparent);
  opacity: .25; mix-blend-mode: multiply;
}
.kl-glow__lobe:first-child { left: calc(50% - 46px); }
.kl-glow__lobe + .kl-glow__lobe { left: calc(50% + 46px); }
[data-theme="dark"] .kl-glow__lobe { mix-blend-mode: screen; }

/* =====================================================================================================
   14. Zoom card: fixed to the screen's bottom-right corner (not the board). [-] [100%] [+] | [Fit]
   ===================================================================================================== */
.kl-zoom {
  display: inline-flex; align-items: center; gap: 2px; padding: 6px;
  border-radius: var(--kl-radius-pill); background: var(--kl-color-surface);
  border: 1px solid var(--kl-color-line); box-shadow: var(--kl-shadow-card); rotate: -.4deg;
}
.kl-zoom--fixed { position: fixed; right: 28px; bottom: 28px; z-index: var(--kl-z-zoom, 950); }
.kl-zoom button {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 36px; min-width: 36px; padding: 0; border: 0; border-radius: var(--kl-radius-pill);
  background: transparent; color: var(--kl-color-text); font: var(--kl-font-label); font-weight: var(--kl-font-weight-semibold);
  cursor: pointer; transition: background-color var(--kl-motion-hover) ease, scale var(--kl-motion-press) var(--kl-motion-spring);
}
.kl-zoom button:hover { background: var(--kl-color-control-fill); }
.kl-zoom button:active { scale: .92; }
.kl-zoom button:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 1px; }
.kl-zoom button:disabled { color: var(--kl-color-text-secondary); opacity: .45; cursor: default; }
.kl-zoom .kl-icon { --kl-icon-stroke: 1.8; }
.kl-zoom__pct { min-width: 56px !important; padding: 0 6px !important; font-variant-numeric: tabular-nums; }
.kl-zoom__fit { padding: 0 12px 0 10px !important; }
.kl-zoom__sep { width: 1px; height: 20px; margin: 0 4px; background: var(--kl-color-line); }

/* =====================================================================================================
   15. Reduced motion and forced colours (Motion's kl-m-* classes handle their own)
   ===================================================================================================== */
@media (prefers-reduced-motion: reduce) {
  .kl-link *, .kl-link-label { animation: none !important; }
  .kl-card *, .kl-tool, .kl-theme-seg::before, .kl-zoom button { transition: none !important; }
}
.kl-motion-reduce :is(.kl-link *, .kl-link-label, .kl-pulse, .kl-ctx-chip) { animation: none !important; }
@media (forced-colors: active) {
  .kl-link__path { stroke: Highlight; }
  .kl-say { border: 1px solid CanvasText; }
  .kl-say::after, .kl-glow { display: none; }
  .kl-zoom, .kl-tool, .kl-card__face { border: 1px solid CanvasText; }
}

/* ===== controls/controls.css ===== */
/* Klippan design system v2 · Basic controls
   Every colour, shadow, radius, space, type and motion value is a --kl- token. Pixel sizes that belong to one
   component are component-local custom properties at its root. States work both ways: as the real pseudo-class
   or attribute (:hover, :active, :focus-visible, :disabled, aria-*) and as an is-* class for static specimens.
   Light by default; [data-theme="dark"] on any container switches through the tokens.
   Motion: colour and opacity changes always run; anything that moves or scales sits in a
   prefers-reduced-motion: no-preference block, so reduced motion gets fades only.
   Ground truth: EYEos (design system v1 bundle.css) for shapes; the step 10 board wins where they disagree. */

/* ===== 0. Shared ===== */
:where(.kl-btn,.kl-iconbtn,.kl-field,.kl-textarea,.kl-search,.kl-select,.kl-switch,.kl-checkbox,.kl-radio,.kl-seg,.kl-tabs,
  .kl-menu,.kl-badge,.kl-chip,.kl-dot,.kl-meter,.kl-check,.kl-selected,.kl-tooltip,.kl-kbd,.kl-toast,.kl-dialog,.kl-scrim,
  .kl-slider,.kl-stepper),
:where(.kl-btn,.kl-iconbtn,.kl-search,.kl-select,.kl-switch,.kl-checkbox,.kl-radio,.kl-seg,.kl-tabs,.kl-menu,.kl-badge,.kl-chip,
  .kl-dot,.kl-meter,.kl-check,.kl-selected,.kl-tooltip,.kl-toast,.kl-dialog,.kl-scrim,.kl-stepper) *,
:where(.kl-btn,.kl-iconbtn,.kl-search,.kl-select,.kl-switch,.kl-checkbox,.kl-radio,.kl-seg,.kl-tabs,.kl-menu,.kl-chip,.kl-dot,
  .kl-check,.kl-selected,.kl-toast,.kl-stepper,.kl-search__clear,.kl-chip__remove,.kl-stepper__btn)::before,
:where(.kl-btn,.kl-iconbtn,.kl-search,.kl-select,.kl-switch,.kl-checkbox,.kl-radio,.kl-seg,.kl-tabs,.kl-menu,.kl-chip,.kl-dot,
  .kl-check,.kl-selected,.kl-toast,.kl-stepper,.kl-search__clear,.kl-chip__remove,.kl-stepper__btn)::after{box-sizing:border-box}
:where(.kl-btn,.kl-iconbtn,.kl-select,.kl-switch,.kl-seg__item,.kl-tabs__tab,.kl-menu__item,.kl-chip,.kl-chip__remove,
  .kl-search__clear,.kl-stepper__btn){-webkit-appearance:none;appearance:none;margin:0;-webkit-tap-highlight-color:transparent;text-decoration:none}
:where(.kl-btn,.kl-iconbtn,.kl-select,.kl-switch,.kl-seg__item,.kl-tabs__tab,.kl-menu__item,.kl-chip,.kl-badge,.kl-tooltip,
  .kl-kbd,.kl-toast,.kl-dialog,.kl-stepper,.kl-meter,.kl-checkbox,.kl-radio,.kl-field,.kl-textarea,.kl-search__input){-webkit-font-smoothing:antialiased}
:where(.kl-btn,.kl-iconbtn,.kl-chip,.kl-seg__item,.kl-tabs__tab,.kl-menu__item,.kl-toast,.kl-stepper__btn,.kl-badge,.kl-tooltip) svg{display:block;flex:none}

/* One focus ring for every control: 2px --kl-color-focus, 2px out. Fields draw their own ring and halo instead. */
:is(.kl-btn,.kl-iconbtn,.kl-select,.kl-switch,.kl-chip,.kl-chip__remove,.kl-search__clear,.kl-stepper__btn,.kl-seg__item,.kl-tabs__tab):focus-visible,
:is(.kl-btn,.kl-iconbtn,.kl-select,.kl-switch,.kl-chip,.kl-chip__remove,.kl-search__clear,.kl-stepper__btn,.kl-seg__item,.kl-tabs__tab).is-focus{outline:2px solid var(--kl-color-focus);outline-offset:2px}
:is(.kl-seg__item,.kl-tabs__tab):focus-visible,:is(.kl-seg__item,.kl-tabs__tab).is-focus{outline-offset:1px}

/* ===== 1. Button: .kl-btn (pill, 28px, secondary grey) ===== */
.kl-btn{
  --kl-btn-h:var(--kl-size-button);--kl-btn-px:14px;--kl-btn-bg:var(--kl-color-button-secondary);--kl-btn-ink:var(--kl-color-text);--kl-btn-overlay:transparent;
  position:relative;isolation:isolate;display:inline-flex;align-items:center;justify-content:center;gap:6px;flex:none;
  height:var(--kl-btn-h);min-width:var(--kl-btn-h);padding:0 var(--kl-btn-px);border:0;border-radius:var(--kl-radius-pill);
  background:var(--kl-btn-bg);color:var(--kl-btn-ink);font:var(--kl-font-label);white-space:nowrap;cursor:pointer;user-select:none;
  transition:background-color var(--kl-motion-press) var(--kl-motion-ease-out),color var(--kl-motion-press) var(--kl-motion-ease-out),opacity var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-btn::before{content:"";position:absolute;inset:calc((var(--kl-btn-h) - var(--kl-size-target)) / 2) 0}          /* 44px hit target */
.kl-btn::after{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;background:var(--kl-btn-overlay);pointer-events:none;
  transition:background-color var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-btn__icon{width:16px;height:16px;margin-left:-3px;flex:none;display:block}
.kl-btn:hover:not(:disabled,.is-disabled,[aria-disabled="true"]),.kl-btn.is-hover{--kl-btn-overlay:var(--kl-color-control-fill)}
.kl-btn:active:not(:disabled,.is-disabled,[aria-disabled="true"]),.kl-btn.is-pressed,
.kl-btn[aria-expanded="true"],.kl-btn.is-open{--kl-btn-overlay:var(--kl-color-control-fill-pressed)}
.kl-btn:disabled,.kl-btn.is-disabled,.kl-btn[aria-disabled="true"]{opacity:.45;cursor:default}
.kl-btn--primary{--kl-btn-bg:var(--kl-color-primary);--kl-btn-ink:var(--kl-color-text-on-fill)}
.kl-btn--quiet{--kl-btn-bg:transparent;--kl-btn-ink:var(--kl-color-text-secondary);--kl-btn-px:10px}
.kl-btn--quiet:hover:not(:disabled,.is-disabled),.kl-btn--quiet.is-hover,.kl-btn--quiet.is-pressed,.kl-btn--quiet[aria-expanded="true"]{--kl-btn-ink:var(--kl-color-text)}
.kl-btn--plain{--kl-btn-bg:transparent;--kl-btn-ink:var(--kl-color-selection-ink);--kl-btn-px:8px}
.kl-btn--destructive{--kl-btn-ink:var(--kl-color-status-stopped-ink)}                              /* red ink on the grey fill */
.kl-dialog .kl-btn--destructive{--kl-btn-bg:var(--kl-color-status-stopped-soft)}                  /* red fill only inside a confirm */
.kl-btn--plain.kl-btn--destructive,.kl-btn--quiet.kl-btn--destructive{--kl-btn-bg:transparent}
.kl-btn--sm{--kl-btn-h:var(--kl-size-control);--kl-btn-px:10px}
.kl-btn--sm .kl-btn__icon{width:14px;height:14px;margin-left:-2px}
.kl-btn--lg{--kl-btn-h:var(--kl-size-button-large);--kl-btn-px:18px}
.kl-btn--lg .kl-btn__icon{width:18px;height:18px}
.kl-btn.is-selected,.kl-btn[aria-pressed="true"]{--kl-btn-bg:var(--kl-color-selection-soft);--kl-btn-ink:var(--kl-color-selection-ink)}

/* ===== 2. Icon button: .kl-iconbtn (28px circle) ===== */
.kl-iconbtn{
  --kl-iconbtn-size:var(--kl-size-button);--kl-iconbtn-glyph:16px;--kl-iconbtn-bg:var(--kl-color-control-fill);--kl-iconbtn-ink:var(--kl-color-text);--kl-iconbtn-overlay:transparent;
  position:relative;isolation:isolate;display:inline-flex;align-items:center;justify-content:center;flex:none;
  width:var(--kl-iconbtn-size);height:var(--kl-iconbtn-size);padding:0;border:0;border-radius:50%;
  background:var(--kl-iconbtn-bg);color:var(--kl-iconbtn-ink);cursor:pointer;
  transition:background-color var(--kl-motion-press) var(--kl-motion-ease-out),color var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-iconbtn::before{content:"";position:absolute;inset:min(0px,calc((var(--kl-iconbtn-size) - var(--kl-size-target)) / 2));border-radius:50%}
.kl-iconbtn::after{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;background:var(--kl-iconbtn-overlay);pointer-events:none;
  transition:background-color var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-iconbtn svg{width:var(--kl-iconbtn-glyph);height:var(--kl-iconbtn-glyph);display:block}
.kl-iconbtn:hover:not(:disabled,.is-disabled),.kl-iconbtn.is-hover{--kl-iconbtn-overlay:var(--kl-color-control-fill);--kl-iconbtn-ink:var(--kl-color-text)}
.kl-iconbtn:active:not(:disabled,.is-disabled),.kl-iconbtn.is-pressed,.kl-iconbtn[aria-expanded="true"],.kl-iconbtn.is-open{--kl-iconbtn-overlay:var(--kl-color-control-fill-pressed);--kl-iconbtn-ink:var(--kl-color-text)}
.kl-iconbtn:disabled,.kl-iconbtn.is-disabled{opacity:.45;cursor:default}
.kl-iconbtn[aria-pressed="true"],.kl-iconbtn.is-selected{--kl-iconbtn-bg:var(--kl-color-selection-soft);--kl-iconbtn-ink:var(--kl-color-selection-ink)}
.kl-iconbtn--lg{--kl-iconbtn-size:var(--kl-size-button-large);--kl-iconbtn-glyph:20px}
.kl-iconbtn--quiet{--kl-iconbtn-bg:transparent;--kl-iconbtn-ink:var(--kl-color-text-secondary)}
.kl-iconbtn--glass{--kl-iconbtn-bg:var(--kl-glass-fill);box-shadow:var(--kl-glass-shadow),var(--kl-glass-rim);
  -webkit-backdrop-filter:blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));backdrop-filter:blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate))}

/* ===== 3. Text fields: .kl-field, .kl-textarea, .kl-search, .kl-fieldlabel, .kl-fieldhint ===== */
.kl-field,.kl-textarea{
  --kl-field-ring:var(--kl-color-field-border);--kl-field-halo:0 0 0 0 transparent;
  display:block;width:var(--kl-field-w,100%);height:var(--kl-size-button);margin:0;padding:0 8px;border:0;border-radius:var(--kl-radius-control);
  background:var(--kl-color-surface);color:var(--kl-color-text);font:var(--kl-font-meta);outline:0;
  box-shadow:inset 0 0 0 1px var(--kl-field-ring),var(--kl-field-halo);
  transition:box-shadow var(--kl-motion-press) var(--kl-motion-ease-out),background-color var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-textarea{height:auto;min-height:72px;padding:6px 8px;border-radius:var(--kl-radius-menu);resize:vertical}
:is(.kl-field,.kl-textarea)::placeholder{color:var(--kl-color-text-secondary);opacity:1}
:is(.kl-field,.kl-textarea):hover:not(:disabled,:focus),:is(.kl-field,.kl-textarea).is-hover{--kl-field-ring:var(--kl-color-line-strong)}
:is(.kl-field,.kl-textarea):focus,:is(.kl-field,.kl-textarea).is-focus{--kl-field-ring:var(--kl-color-focus);--kl-field-halo:0 0 0 3px var(--kl-color-selection-soft)}
:is(.kl-field,.kl-textarea).is-error,:is(.kl-field,.kl-textarea)[aria-invalid="true"]{--kl-field-ring:var(--kl-color-status-stopped);--kl-field-halo:0 0 0 3px var(--kl-color-status-stopped-soft)}
:is(.kl-field,.kl-textarea):disabled,:is(.kl-field,.kl-textarea).is-disabled{background:var(--kl-color-surface-sunken);color:var(--kl-color-text-tertiary);cursor:default}
.kl-fieldlabel{display:block;margin:0 0 6px;font:var(--kl-font-label);color:var(--kl-color-text)}
.kl-fieldhint{display:flex;align-items:center;gap:4px;margin:6px 0 0;font:var(--kl-font-caption);color:var(--kl-color-text-secondary)}
.kl-fieldhint svg{width:12px;height:12px;flex:none}
.kl-fieldhint.is-error{color:var(--kl-color-status-stopped-ink)}

/* Search: pill, magnifier before, clear button after (hidden while empty) */
.kl-search{
  --kl-field-ring:var(--kl-color-field-border);--kl-field-halo:0 0 0 0 transparent;
  position:relative;display:flex;align-items:center;gap:6px;width:var(--kl-search-w,100%);height:32px;padding:0 8px 0 10px;
  border-radius:var(--kl-radius-pill);background:var(--kl-color-surface-sunken);color:var(--kl-color-text-secondary);
  box-shadow:inset 0 0 0 1px var(--kl-field-ring),var(--kl-field-halo);transition:box-shadow var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-search::before{content:"";flex:none;width:14px;height:14px;background:currentColor;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Ccircle cx='5.9' cy='5.9' r='4.6' fill='none' stroke='black' stroke-width='1.6'/%3E%3Cpath d='M9.3 9.3l3.4 3.4' stroke='black' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Ccircle cx='5.9' cy='5.9' r='4.6' fill='none' stroke='black' stroke-width='1.6'/%3E%3Cpath d='M9.3 9.3l3.4 3.4' stroke='black' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E") center/contain no-repeat}
.kl-search__input{flex:1 1 auto;min-width:0;height:100%;margin:0;padding:0;border:0;outline:0;background:transparent;color:var(--kl-color-text);font:var(--kl-font-meta);-webkit-appearance:none;appearance:none}
.kl-search__input::placeholder{color:var(--kl-color-text-secondary);opacity:1}
.kl-search__input::-webkit-search-cancel-button,.kl-search__input::-webkit-search-decoration{-webkit-appearance:none;display:none}
.kl-search:hover:not(:focus-within,.is-disabled),.kl-search.is-hover{--kl-field-ring:var(--kl-color-line-strong)}
.kl-search:focus-within,.kl-search.is-focus{--kl-field-ring:var(--kl-color-focus);--kl-field-halo:0 0 0 3px var(--kl-color-selection-soft)}
.kl-search.is-error{--kl-field-ring:var(--kl-color-status-stopped);--kl-field-halo:0 0 0 3px var(--kl-color-status-stopped-soft)}
.kl-search.is-disabled,.kl-search:has(.kl-search__input:disabled){opacity:.45}
.kl-search__clear{position:relative;flex:none;width:16px;height:16px;padding:0;border:0;border-radius:50%;background:var(--kl-color-text-tertiary);cursor:pointer;
  transition:background-color var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-search__clear::before{content:"";position:absolute;inset:-14px;border-radius:50%}
.kl-search__clear::after{content:"";position:absolute;inset:4px;background:var(--kl-color-surface);
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath d='M1 1l6 6M7 1L1 7' stroke='black' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath d='M1 1l6 6M7 1L1 7' stroke='black' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E") center/contain no-repeat}
.kl-search__clear:hover,.kl-search__clear.is-hover{background:var(--kl-color-text-secondary)}
.kl-search__input:placeholder-shown ~ .kl-search__clear{visibility:hidden}

/* ===== 4. Select: .kl-select (looks like a field, up-down chevron on the right; its list is a .kl-menu) ===== */
.kl-select{
  --kl-field-ring:var(--kl-color-field-border);--kl-select-tint:transparent;
  position:relative;display:inline-flex;align-items:center;gap:8px;min-width:var(--kl-select-w,120px);height:var(--kl-size-button);
  padding:0 9px 0 10px;border:0;border-radius:var(--kl-radius-control);
  background:var(--kl-color-surface) linear-gradient(var(--kl-select-tint),var(--kl-select-tint));color:var(--kl-color-text);
  box-shadow:inset 0 0 0 1px var(--kl-field-ring);font:var(--kl-font-label);text-align:left;white-space:nowrap;cursor:pointer;
  transition:box-shadow var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-select::before{content:"";position:absolute;inset:-8px 0}
.kl-select::after{content:"";flex:none;width:8px;height:11px;margin-left:auto;background:var(--kl-color-text-secondary);
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 11'%3E%3Cpath d='M1.2 3.6L4 1l2.8 2.6M1.2 7.4L4 10l2.8-2.6' fill='none' stroke='black' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 11'%3E%3Cpath d='M1.2 3.6L4 1l2.8 2.6M1.2 7.4L4 10l2.8-2.6' fill='none' stroke='black' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat}
.kl-select__label{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}
.kl-select__icon{width:16px;height:16px;flex:none;color:var(--kl-color-text-secondary)}
.kl-select:hover:not(:disabled,.is-disabled),.kl-select.is-hover{--kl-field-ring:var(--kl-color-line-strong)}
.kl-select:active:not(:disabled,.is-disabled),.kl-select.is-pressed{--kl-select-tint:var(--kl-color-control-fill-pressed)}
.kl-select[aria-expanded="true"],.kl-select.is-open{--kl-select-tint:var(--kl-color-control-fill);--kl-field-ring:var(--kl-color-line-strong)}
.kl-select[aria-expanded="true"]::after,.kl-select.is-open::after{background:var(--kl-color-text)}
.kl-select.is-error,.kl-select[aria-invalid="true"]{--kl-field-ring:var(--kl-color-status-stopped)}
.kl-select:disabled,.kl-select.is-disabled{opacity:.45;cursor:default}

/* ===== 5. Switch: .kl-switch (button role=switch) ===== */
.kl-switch{
  --kl-switch-w:36px;--kl-switch-h:20px;--kl-switch-knob:16px;--kl-switch-pad:2px;--kl-switch-grow:0px;--kl-switch-tint:transparent;
  position:relative;display:inline-flex;align-items:center;flex:none;width:var(--kl-switch-w);height:var(--kl-switch-h);
  padding:0 var(--kl-switch-pad);border:0;border-radius:var(--kl-radius-pill);
  background:var(--kl-color-switch-off) linear-gradient(var(--kl-switch-tint),var(--kl-switch-tint));cursor:pointer;
  transition:background-color var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-switch::before{content:"";position:absolute;inset:calc((var(--kl-switch-h) - var(--kl-size-target)) / 2) -4px}
.kl-switch__knob{display:block;width:calc(var(--kl-switch-knob) + var(--kl-switch-grow));height:var(--kl-switch-knob);border-radius:var(--kl-radius-pill);
  background:var(--kl-color-knob);box-shadow:var(--kl-shadow-knob);pointer-events:none}
.kl-switch[aria-checked="true"],.kl-switch.is-on{background-color:var(--kl-color-control)}
.kl-switch[aria-checked="true"] .kl-switch__knob,.kl-switch.is-on .kl-switch__knob{
  translate:calc(var(--kl-switch-w) - var(--kl-switch-knob) - var(--kl-switch-grow) - 2 * var(--kl-switch-pad)) 0}
.kl-switch:hover:not(:disabled,.is-disabled),.kl-switch.is-hover{--kl-switch-tint:var(--kl-color-control-fill)}
.kl-switch:active:not(:disabled,.is-disabled),.kl-switch.is-pressed{--kl-switch-tint:var(--kl-color-control-fill-pressed);--kl-switch-grow:4px}
.kl-switch:disabled,.kl-switch.is-disabled{opacity:.45;cursor:default}
.kl-switch--lg{--kl-switch-w:48px;--kl-switch-h:28px;--kl-switch-knob:24px}

/* ===== 6. Checkbox and radio: <label class="kl-checkbox"><input type="checkbox"><span class="kl-checkbox__box"></span> Text</label> ===== */
.kl-checkbox,.kl-radio{
  --kl-box-tint:transparent;--kl-box-ring:var(--kl-color-field-border);
  position:relative;display:inline-flex;align-items:center;gap:8px;min-height:var(--kl-size-button);font:var(--kl-font-label);color:var(--kl-color-text);cursor:pointer;user-select:none}
:is(.kl-checkbox,.kl-radio) > input{position:absolute;left:0;top:50%;width:16px;height:16px;margin:-8px 0 0;opacity:0;pointer-events:none}
.kl-checkbox__box,.kl-radio__box{
  position:relative;display:inline-flex;align-items:center;justify-content:center;flex:none;width:16px;height:16px;border-radius:5px;
  background:var(--kl-color-switch-off) linear-gradient(var(--kl-box-tint),var(--kl-box-tint));box-shadow:inset 0 0 0 1px var(--kl-box-ring);
  transition:background-color var(--kl-motion-press) var(--kl-motion-ease-out),box-shadow var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-radio__box{border-radius:50%}
.kl-checkbox__box::after{content:"";width:9.31px;height:8.93px;background:var(--kl-color-text-on-fill);opacity:0;scale:.4;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9.31 8.93'%3E%3Cpath d='M3.67605 8.93C4.04565 8.93 4.32535 8.78984 4.51515 8.49952L9.11022 1.46164C9.25007 1.24139 9.31 1.05118 9.31 0.860964C9.31 0.360404 8.93041 0 8.41097 0C8.06134 0 7.85157 0.130146 7.6318 0.460516L3.64608 6.77759L1.60827 4.22473C1.40849 3.98446 1.19871 3.87434 0.899034 3.87434C0.379592 3.87434 0 4.24475 0 4.75532C0 4.97557 0.0699249 5.1758 0.259721 5.39604L2.83695 8.53956C3.05672 8.80986 3.31644 8.93 3.66606 8.93H3.67605Z'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9.31 8.93'%3E%3Cpath d='M3.67605 8.93C4.04565 8.93 4.32535 8.78984 4.51515 8.49952L9.11022 1.46164C9.25007 1.24139 9.31 1.05118 9.31 0.860964C9.31 0.360404 8.93041 0 8.41097 0C8.06134 0 7.85157 0.130146 7.6318 0.460516L3.64608 6.77759L1.60827 4.22473C1.40849 3.98446 1.19871 3.87434 0.899034 3.87434C0.379592 3.87434 0 4.24475 0 4.75532C0 4.97557 0.0699249 5.1758 0.259721 5.39604L2.83695 8.53956C3.05672 8.80986 3.31644 8.93 3.66606 8.93H3.67605Z'/%3E%3C/svg%3E") center/contain no-repeat}
.kl-radio__box::after{content:"";width:6px;height:6px;border-radius:50%;background:var(--kl-color-text-on-fill);opacity:0;scale:.4}
:is(.kl-checkbox,.kl-radio) > input:checked + span,
:is(.kl-checkbox,.kl-radio).is-checked > span,
.kl-checkbox > input:indeterminate + span,.kl-checkbox.is-mixed > span{background-color:var(--kl-color-control);--kl-box-ring:transparent}
:is(.kl-checkbox,.kl-radio) > input:checked + span::after,:is(.kl-checkbox,.kl-radio).is-checked > span::after{opacity:1;scale:1}
.kl-checkbox > input:indeterminate + span::after,.kl-checkbox.is-mixed > span::after{-webkit-mask:none;mask:none;width:8px;height:2px;border-radius:1px;opacity:1;scale:1}
:is(.kl-checkbox,.kl-radio):hover:not(.is-disabled,:has(input:disabled)),:is(.kl-checkbox,.kl-radio).is-hover{--kl-box-tint:var(--kl-color-control-fill);--kl-box-ring:var(--kl-color-line-strong)}
:is(.kl-checkbox,.kl-radio):active:not(.is-disabled,:has(input:disabled)),:is(.kl-checkbox,.kl-radio).is-pressed{--kl-box-tint:var(--kl-color-control-fill-pressed)}
:is(.kl-checkbox,.kl-radio) > input:focus-visible + span,:is(.kl-checkbox,.kl-radio).is-focus > span{outline:2px solid var(--kl-color-focus);outline-offset:2px}
:is(.kl-checkbox,.kl-radio).is-error > span{--kl-box-ring:var(--kl-color-status-stopped);box-shadow:inset 0 0 0 1px var(--kl-box-ring),0 0 0 3px var(--kl-color-status-stopped-soft)}
:is(.kl-checkbox,.kl-radio).is-disabled,:is(.kl-checkbox,.kl-radio):has(input:disabled){color:var(--kl-color-text-tertiary);cursor:default}
:is(.kl-checkbox,.kl-radio).is-disabled > span,:is(.kl-checkbox,.kl-radio) > input:disabled + span{opacity:.5}

/* ===== 7. Segmented control: .kl-seg / .kl-seg__item[aria-pressed=true] ===== */
.kl-seg{display:inline-flex;align-items:center;gap:2px;padding:2px;border-radius:var(--kl-radius-pill);background:var(--kl-color-control-fill)}
.kl-seg--fill{display:flex;width:100%}
.kl-seg--fill .kl-seg__item{flex:1 1 0;min-width:0}
.kl-seg__item{
  position:relative;display:inline-flex;align-items:center;justify-content:center;gap:6px;height:24px;padding:0 12px;border:0;border-radius:var(--kl-radius-pill);
  background:transparent;color:var(--kl-color-text);font:var(--kl-font-label);white-space:nowrap;cursor:pointer;
  transition:background-color var(--kl-motion-press) var(--kl-motion-ease-out),box-shadow var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-seg__item::before{content:"";position:absolute;inset:-10px 0}
.kl-seg__item svg{width:14px;height:14px}
.kl-seg__item:hover:not([aria-pressed="true"],.is-selected,:disabled,.is-disabled),.kl-seg__item.is-hover{background:var(--kl-color-control-fill)}
.kl-seg__item:active:not([aria-pressed="true"],.is-selected,:disabled,.is-disabled),.kl-seg__item.is-pressed{background:var(--kl-color-control-fill-pressed)}
.kl-seg__item[aria-pressed="true"],.kl-seg__item.is-selected{background:var(--kl-color-surface);box-shadow:var(--kl-shadow-knob);font-weight:590}
.kl-seg__item:disabled,.kl-seg__item.is-disabled{opacity:.45;cursor:default}

/* ===== 8. Tabs: .kl-tabs with a sliding .kl-tabs__pill (set --kl-tab-x / --kl-tab-w in px, or --kl-tab-i / --kl-tabs-n for equal tabs) ===== */
.kl-tabs{position:relative;display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);width:100%;height:34px;padding:2px;
  border-radius:var(--kl-radius-pill);background:var(--kl-color-control-fill);isolation:isolate}
.kl-tabs__pill{position:absolute;z-index:0;top:2px;bottom:2px;left:0;
  width:var(--kl-tab-w,calc((100% - 4px) / var(--kl-tabs-n,3)));translate:var(--kl-tab-x,calc(2px + var(--kl-tab-i,0) * 100%)) 0;
  border-radius:var(--kl-radius-pill);background:var(--kl-color-surface);box-shadow:var(--kl-shadow-card);pointer-events:none}
.kl-tabs__tab{
  position:relative;z-index:1;display:inline-flex;align-items:center;justify-content:center;gap:6px;min-width:0;height:30px;padding:0 12px;border:0;
  border-radius:var(--kl-radius-pill);background:transparent;color:var(--kl-color-text-secondary);font:var(--kl-font-label);white-space:nowrap;cursor:pointer;
  transition:color var(--kl-motion-press) var(--kl-motion-ease-out),box-shadow var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-tabs__tab svg{width:16px;height:16px}
.kl-tabs__tab:hover:not(:disabled,.is-disabled),.kl-tabs__tab.is-hover{color:var(--kl-color-text)}
.kl-tabs__tab:hover:not([aria-selected="true"],:disabled,.is-disabled),.kl-tabs__tab.is-hover:not([aria-selected="true"]){box-shadow:inset 0 0 0 1px var(--kl-color-line)}
.kl-tabs__tab:active:not([aria-selected="true"],:disabled,.is-disabled),.kl-tabs__tab.is-pressed{box-shadow:inset 0 0 0 1px var(--kl-color-line-strong);color:var(--kl-color-text)}
.kl-tabs__tab[aria-selected="true"],.kl-tabs__tab.is-selected{color:var(--kl-color-text);font-weight:590}
.kl-tabs__tab:disabled,.kl-tabs__tab.is-disabled{opacity:.45;cursor:default}

/* ===== 9. Menu: .kl-menu (glass) ===== */
.kl-menu{
  display:flex;flex-direction:column;gap:1px;min-width:var(--kl-menu-w,220px);max-width:320px;margin:0;padding:6px;list-style:none;
  border-radius:var(--kl-radius-menu);background:var(--kl-glass-fill-menu);color:var(--kl-color-text);font:var(--kl-font-label);
  -webkit-backdrop-filter:blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));backdrop-filter:blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));
  box-shadow:var(--kl-shadow-menu),var(--kl-glass-rim);transform-origin:var(--kl-menu-origin,top left);isolation:isolate}
.kl-menu__label{padding:6px 10px 4px;font:var(--kl-font-caption);color:var(--kl-color-text-secondary)}
.kl-menu:has(.kl-menu__check) .kl-menu__label{padding-left:30px}                 /* line up with the item text */
.kl-menu__item{
  position:relative;display:flex;align-items:center;gap:8px;width:100%;min-height:28px;padding:4px 10px;border:0;border-radius:var(--kl-radius-row);
  background:transparent;color:var(--kl-color-text);font:var(--kl-font-label);text-align:left;cursor:pointer;outline:0}
.kl-menu__item > svg{width:16px;height:16px;flex:none;color:var(--kl-color-text-secondary)}
.kl-menu__text{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.kl-menu__desc{font:var(--kl-font-caption);color:var(--kl-color-text-secondary);white-space:normal}
.kl-menu__check{flex:none;width:12px;height:12px;display:inline-flex;align-items:center;justify-content:center}
.kl-menu__check::after{content:"";width:10px;height:9.6px;background:currentColor;opacity:0;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9.31 8.93'%3E%3Cpath d='M3.67605 8.93C4.04565 8.93 4.32535 8.78984 4.51515 8.49952L9.11022 1.46164C9.25007 1.24139 9.31 1.05118 9.31 0.860964C9.31 0.360404 8.93041 0 8.41097 0C8.06134 0 7.85157 0.130146 7.6318 0.460516L3.64608 6.77759L1.60827 4.22473C1.40849 3.98446 1.19871 3.87434 0.899034 3.87434C0.379592 3.87434 0 4.24475 0 4.75532C0 4.97557 0.0699249 5.1758 0.259721 5.39604L2.83695 8.53956C3.05672 8.80986 3.31644 8.93 3.66606 8.93H3.67605Z'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9.31 8.93'%3E%3Cpath d='M3.67605 8.93C4.04565 8.93 4.32535 8.78984 4.51515 8.49952L9.11022 1.46164C9.25007 1.24139 9.31 1.05118 9.31 0.860964C9.31 0.360404 8.93041 0 8.41097 0C8.06134 0 7.85157 0.130146 7.6318 0.460516L3.64608 6.77759L1.60827 4.22473C1.40849 3.98446 1.19871 3.87434 0.899034 3.87434C0.379592 3.87434 0 4.24475 0 4.75532C0 4.97557 0.0699249 5.1758 0.259721 5.39604L2.83695 8.53956C3.05672 8.80986 3.31644 8.93 3.66606 8.93H3.67605Z'/%3E%3C/svg%3E") center/contain no-repeat}
.kl-menu__item[aria-checked="true"] .kl-menu__check::after,.kl-menu__item.is-checked .kl-menu__check::after{opacity:1}
.kl-menu__item[aria-checked="true"],.kl-menu__item.is-checked{font-weight:590}
.kl-menu__shortcut{flex:none;margin-left:auto;padding-left:12px;font:var(--kl-font-meta);color:var(--kl-color-text-secondary);font-variant-numeric:tabular-nums}
.kl-menu__sep{flex:none;height:1px;margin:4px 10px;background:var(--kl-color-line);border:0}
.kl-menu__item:not(:disabled,.is-disabled,[aria-disabled="true"]):hover,.kl-menu__item:focus-visible,.kl-menu__item.is-active{background:var(--kl-color-selection);color:var(--kl-color-text-on-fill)}
.kl-menu__item:not(:disabled,.is-disabled,[aria-disabled="true"]):hover :is(svg,.kl-menu__shortcut,.kl-menu__desc),
.kl-menu__item:focus-visible :is(svg,.kl-menu__shortcut,.kl-menu__desc),
.kl-menu__item.is-active :is(svg,.kl-menu__shortcut,.kl-menu__desc){color:var(--kl-color-text-on-fill)}
.kl-menu__item--destructive{color:var(--kl-color-status-stopped-ink)}
.kl-menu__item--destructive > svg{color:var(--kl-color-status-stopped-ink)}
.kl-menu__item--destructive:not(:disabled,.is-disabled):hover,.kl-menu__item--destructive:focus-visible,.kl-menu__item--destructive.is-active{background:var(--kl-color-status-stopped)}
.kl-menu__item:disabled,.kl-menu__item.is-disabled,.kl-menu__item[aria-disabled="true"]{color:var(--kl-color-text-tertiary);cursor:default}
.kl-menu__item:disabled > svg,.kl-menu__item.is-disabled > svg{color:var(--kl-color-text-tertiary)}

/* ===== 10. Badges, counts, chips, status dots ===== */
.kl-badge{display:inline-flex;align-items:center;gap:5px;flex:none;height:20px;padding:0 8px;border-radius:var(--kl-radius-pill);
  background:var(--kl-color-neutral-soft);color:var(--kl-color-neutral-ink);font:var(--kl-font-badge);white-space:nowrap;font-variant-numeric:tabular-nums}
.kl-badge svg{width:12px;height:12px}
.kl-badge--execution{background:var(--kl-color-status-executing-soft);color:var(--kl-color-status-executing-ink)}
.kl-badge--planning{background:var(--kl-color-status-planning-soft);color:var(--kl-color-status-planning-ink)}
.kl-badge--stopped{background:var(--kl-color-status-stopped-soft);color:var(--kl-color-status-stopped-ink)}
.kl-badge--selected{background:var(--kl-color-selection-soft);color:var(--kl-color-selection-ink)}
.kl-badge--outline{background:transparent;color:var(--kl-color-text-secondary);box-shadow:inset 0 0 0 1px var(--kl-color-line-strong)}
.kl-badge--count,.kl-badge--count-ink{justify-content:center;min-width:22px;height:22px;padding:0 6px;background:var(--kl-color-primary);color:var(--kl-color-text-on-fill);box-shadow:0 0 0 3px var(--kl-color-surface)}
.kl-badge--count-ink{background:var(--kl-color-text);color:var(--kl-color-surface)}

.kl-chip{
  --kl-chip-tint:transparent;--kl-chip-ring:var(--kl-color-line);
  position:relative;display:inline-flex;align-items:center;gap:6px;flex:none;height:30px;padding:0 12px;border:0;border-radius:var(--kl-radius-pill);
  background:var(--kl-color-surface) linear-gradient(var(--kl-chip-tint),var(--kl-chip-tint));color:var(--kl-color-text);box-shadow:inset 0 0 0 1px var(--kl-chip-ring);
  font:var(--kl-font-label);white-space:nowrap;
  transition:background-color var(--kl-motion-press) var(--kl-motion-ease-out),box-shadow var(--kl-motion-press) var(--kl-motion-ease-out),color var(--kl-motion-press) var(--kl-motion-ease-out)}
:is(button,a,label).kl-chip{cursor:pointer}
.kl-chip::before{content:"";position:absolute;inset:-7px 0}
.kl-chip:has(.kl-chip__icon){padding-left:8px}
.kl-chip:has(.kl-chip__remove){padding-right:5px}
.kl-chip__icon{width:16px;height:16px;flex:none;display:block;color:var(--kl-color-text-secondary)}
:is(button,a,label).kl-chip:hover:not(:disabled,.is-disabled),.kl-chip.is-hover{--kl-chip-tint:var(--kl-color-control-fill)}
:is(button,a,label).kl-chip:active:not(:disabled,.is-disabled),.kl-chip.is-pressed{--kl-chip-tint:var(--kl-color-control-fill-pressed)}
.kl-chip--selected,.kl-chip[aria-pressed="true"],.kl-chip[aria-selected="true"]{--kl-chip-ring:var(--kl-color-selection);background-color:var(--kl-color-selection-soft);color:var(--kl-color-selection-ink);font-weight:590}
.kl-chip--selected .kl-chip__icon,.kl-chip[aria-pressed="true"] .kl-chip__icon{color:var(--kl-color-selection-ink)}
.kl-chip:disabled,.kl-chip.is-disabled{opacity:.45;cursor:default}
.kl-chip__remove{position:relative;display:inline-flex;align-items:center;justify-content:center;flex:none;width:20px;height:20px;padding:0;border:0;border-radius:50%;
  background:transparent;color:var(--kl-color-text-secondary);cursor:pointer;transition:background-color var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-chip__remove::before{content:"";position:absolute;inset:-6px;border-radius:50%}
.kl-chip__remove svg{width:12px;height:12px;display:block}
.kl-chip__remove:hover,.kl-chip__remove.is-hover{background:var(--kl-color-control-fill-pressed);color:var(--kl-color-text)}

.kl-dot{--kl-dot:var(--kl-color-status-executing);--kl-dot-size:10px;--kl-dot-cadence:1.8s;
  position:relative;display:inline-block;flex:none;width:var(--kl-dot-size);height:var(--kl-dot-size);border-radius:50%;background:var(--kl-dot);
  transition:background-color var(--kl-motion-hover) var(--kl-motion-ease-out)}
.kl-dot::after{content:"";position:absolute;inset:0;border-radius:50%;background:var(--kl-dot);opacity:0;pointer-events:none}
.kl-dot--execution{--kl-dot:var(--kl-color-status-executing)}
.kl-dot--planning{--kl-dot:var(--kl-color-status-planning);--kl-dot-cadence:2.8s}
.kl-dot--stopped{--kl-dot:var(--kl-color-status-stopped);--kl-dot-cadence:1.2s}
.kl-dot--idle{--kl-dot:var(--kl-color-text-tertiary)}

/* ===== 11. Token meter: .kl-meter ===== */
.kl-meter{--kl-meter-value:0%;--kl-meter-mark:75%;--kl-meter-fill:var(--kl-color-control);display:grid;gap:6px;min-width:0;color:var(--kl-color-text)}
.kl-meter__head{display:flex;align-items:baseline;gap:var(--kl-space-2);min-width:0}
.kl-meter__name{flex:1 1 auto;min-width:0;font:var(--kl-font-label-strong);letter-spacing:var(--kl-font-label-strong-tracking)}
.kl-meter__nums{flex:none;font:var(--kl-font-label);font-variant-numeric:tabular-nums;white-space:nowrap}
.kl-meter__nums span{color:var(--kl-color-text-secondary);font-weight:400}
.kl-meter__track{position:relative;height:8px;margin:2px 0;border-radius:4px;background:var(--kl-color-switch-off)}
.kl-meter__fill{position:absolute;left:0;top:0;bottom:0;width:var(--kl-meter-value);border-radius:inherit;background:var(--kl-meter-fill);
  transition:width var(--kl-motion-hover) var(--kl-motion-ease-out),background-color var(--kl-motion-hover) var(--kl-motion-ease-out)}
.kl-meter__mark{position:absolute;top:-3px;bottom:-3px;left:var(--kl-meter-mark);width:2px;margin-left:-1px;border-radius:1px;background:var(--kl-color-text);
  box-shadow:0 0 0 1.5px var(--kl-color-surface)}
.kl-meter__foot{display:flex;align-items:center;gap:var(--kl-space-2);min-height:20px;font:var(--kl-font-caption);color:var(--kl-color-text-secondary);font-variant-numeric:tabular-nums}
.kl-meter__foot .kl-badge{margin-left:auto}
.kl-meter--warn{--kl-meter-fill:var(--kl-color-status-planning)}
.kl-meter--full{--kl-meter-fill:var(--kl-color-status-stopped)}
.kl-meter--full .kl-meter__nums{color:var(--kl-color-status-stopped-ink)}

/* ===== 12. Selection: .kl-selected (2px blue edge, never a fill) + .kl-check (round blue check, top-right) ===== */
.kl-selected{position:relative}
.kl-selected::after{content:"";position:absolute;inset:0;z-index:2;border-radius:inherit;box-shadow:inset 0 0 0 2px var(--kl-color-selection);pointer-events:none}
.kl-check{display:inline-flex;align-items:center;justify-content:center;flex:none;width:24px;height:24px;border-radius:50%;
  background:var(--kl-color-selection);color:var(--kl-color-text-on-fill)}
.kl-check::after{content:"";width:10px;height:9.6px;background:currentColor;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9.31 8.93'%3E%3Cpath d='M3.67605 8.93C4.04565 8.93 4.32535 8.78984 4.51515 8.49952L9.11022 1.46164C9.25007 1.24139 9.31 1.05118 9.31 0.860964C9.31 0.360404 8.93041 0 8.41097 0C8.06134 0 7.85157 0.130146 7.6318 0.460516L3.64608 6.77759L1.60827 4.22473C1.40849 3.98446 1.19871 3.87434 0.899034 3.87434C0.379592 3.87434 0 4.24475 0 4.75532C0 4.97557 0.0699249 5.1758 0.259721 5.39604L2.83695 8.53956C3.05672 8.80986 3.31644 8.93 3.66606 8.93H3.67605Z'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9.31 8.93'%3E%3Cpath d='M3.67605 8.93C4.04565 8.93 4.32535 8.78984 4.51515 8.49952L9.11022 1.46164C9.25007 1.24139 9.31 1.05118 9.31 0.860964C9.31 0.360404 8.93041 0 8.41097 0C8.06134 0 7.85157 0.130146 7.6318 0.460516L3.64608 6.77759L1.60827 4.22473C1.40849 3.98446 1.19871 3.87434 0.899034 3.87434C0.379592 3.87434 0 4.24475 0 4.75532C0 4.97557 0.0699249 5.1758 0.259721 5.39604L2.83695 8.53956C3.05672 8.80986 3.31644 8.93 3.66606 8.93H3.67605Z'/%3E%3C/svg%3E") center/contain no-repeat}
.kl-selected > .kl-check:not(.kl-check--inline){position:absolute;z-index:3;top:-8px;right:-8px;box-shadow:0 0 0 3px var(--kl-color-surface)}
.kl-check--sm{width:20px;height:20px}
/* The check always arrives on kl-pop with fill-mode both, so opacity alone can never hide it: add or remove the element instead.
   Reduced motion (the OS setting or the app's .kl-motion-reduce) keeps it as a plain fade, still both. */
.kl-check{animation:kl-pop var(--kl-motion-hover) var(--kl-motion-spring-pop) both}
.kl-check--sm::after{width:8.4px;height:8px}

/* ===== 13. Tooltip and key hint: .kl-tooltip, .kl-kbd ===== */
.kl-tooltip{display:inline-flex;align-items:center;gap:6px;max-width:240px;min-height:22px;padding:3px 10px;border-radius:var(--kl-radius-pill);
  background:var(--kl-color-text);color:var(--kl-color-surface);font:var(--kl-font-badge);white-space:nowrap;pointer-events:none}
.kl-tooltip--glass{background:var(--kl-glass-fill-menu);color:var(--kl-color-text);box-shadow:var(--kl-shadow-menu),var(--kl-glass-rim);
  -webkit-backdrop-filter:blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));backdrop-filter:blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate))}
.kl-kbd{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:var(--kl-radius-sheet);
  background:var(--kl-color-surface);color:var(--kl-color-text);box-shadow:inset 0 0 0 1px var(--kl-color-line-strong);font:var(--kl-font-caption);white-space:nowrap}
.kl-tooltip .kl-kbd{height:16px;min-width:16px;padding:0 4px;background:transparent;color:inherit;opacity:.8;
  box-shadow:inset 0 0 0 1px color-mix(in srgb,currentColor 45%,transparent)}

/* ===== 14. Toast: .kl-toast (glass, bottom of the board) ===== */
.kl-toast{position:relative;display:inline-flex;align-items:center;gap:10px;min-height:44px;max-width:min(480px,100%);padding:6px 6px 6px 16px;
  border-radius:var(--kl-radius-pill);background:var(--kl-glass-fill);color:var(--kl-color-text);font:var(--kl-font-meta);
  -webkit-backdrop-filter:blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));backdrop-filter:blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));
  box-shadow:var(--kl-glass-shadow),var(--kl-glass-rim)}
.kl-toast__icon{width:16px;height:16px;flex:none;color:var(--kl-color-text-secondary)}
.kl-toast__msg{flex:1 1 auto;min-width:0}
.kl-toast__actions{display:inline-flex;align-items:center;gap:2px;flex:none}
.kl-toast__timer{position:absolute;left:18px;right:18px;bottom:3px;height:2px;border-radius:var(--kl-radius-pill);background:var(--kl-color-text-tertiary);
  transform-origin:left center;pointer-events:none}
.kl-toast--error .kl-toast__icon{color:var(--kl-color-status-stopped-ink)}
.kl-toast.is-leaving{opacity:0;transition:opacity var(--kl-motion-fade-out) var(--kl-motion-ease-in)}

/* ===== 15. Confirm dialog: .kl-dialog + .kl-scrim ===== */
.kl-scrim{position:var(--kl-scrim-position,fixed);inset:0;z-index:var(--kl-scrim-z,100);display:flex;align-items:center;justify-content:center;padding:var(--kl-space-4);background:var(--kl-color-overlay)}
.kl-dialog{display:flex;flex-direction:column;gap:12px;flex:0 1 auto;width:var(--kl-dialog-w,320px);max-width:100%;min-width:0;padding:16px;border-radius:var(--kl-radius-menu);
  background:var(--kl-color-surface);color:var(--kl-color-text);box-shadow:var(--kl-shadow-window)}
.kl-dialog__title{margin:0;font:var(--kl-font-headline);letter-spacing:var(--kl-font-label-strong-tracking)}
.kl-dialog__body{margin:-6px 0 0;font:var(--kl-font-meta);color:var(--kl-color-text-secondary)}
.kl-dialog__actions{display:flex;justify-content:flex-end;flex-wrap:wrap;gap:var(--kl-space-2);margin-top:4px}
.kl-dialog__actions .kl-btn{min-width:72px}

/* ===== 16. Slider (native range): .kl-slider with --kl-slider-value; stepper: .kl-stepper (− value +) ===== */
.kl-slider{--kl-slider-value:50%;--kl-slider-knob-ring:0 0 0 0 transparent;
  display:block;width:var(--kl-slider-w,160px);height:28px;margin:0;padding:0;background:transparent;cursor:pointer;touch-action:none;
  -webkit-appearance:none;appearance:none;border-radius:var(--kl-radius-pill)}
.kl-slider:focus{outline:none}
.kl-slider::-webkit-slider-runnable-track{height:4px;border-radius:var(--kl-radius-pill);
  background:linear-gradient(to right,var(--kl-color-selection) var(--kl-slider-value),var(--kl-color-switch-off) var(--kl-slider-value))}
.kl-slider::-moz-range-track{height:4px;border-radius:var(--kl-radius-pill);background:var(--kl-color-switch-off)}
.kl-slider::-moz-range-progress{height:4px;border-radius:var(--kl-radius-pill);background:var(--kl-color-selection)}
.kl-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;margin-top:-6px;border:0;border-radius:50%;
  background:var(--kl-color-knob);box-shadow:var(--kl-shadow-knob),var(--kl-slider-knob-ring)}
.kl-slider::-moz-range-thumb{width:16px;height:16px;border:0;border-radius:50%;background:var(--kl-color-knob);box-shadow:var(--kl-shadow-knob),var(--kl-slider-knob-ring)}
.kl-slider:hover:not(:disabled),.kl-slider.is-hover{--kl-slider-knob-ring:0 0 0 4px var(--kl-color-selection-soft)}
.kl-slider:focus-visible,.kl-slider.is-focus{outline:2px solid var(--kl-color-focus);outline-offset:2px}
.kl-slider:disabled,.kl-slider.is-disabled{opacity:.45;cursor:default}

.kl-stepper{display:inline-flex;align-items:center;flex:none;height:var(--kl-size-button);padding:0 2px;border-radius:var(--kl-radius-pill);background:var(--kl-color-control-fill);color:var(--kl-color-text)}
.kl-stepper__btn{position:relative;display:inline-flex;align-items:center;justify-content:center;flex:none;width:24px;height:24px;padding:0;border:0;border-radius:50%;
  background:transparent;color:var(--kl-color-text);cursor:pointer;transition:background-color var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-stepper__btn::before{content:"";position:absolute;inset:-10px -2px;border-radius:var(--kl-radius-pill)}
.kl-stepper__btn svg{width:14px;height:14px;display:block}
.kl-stepper__btn:hover:not(:disabled,.is-disabled),.kl-stepper__btn.is-hover{background:var(--kl-color-control-fill)}
.kl-stepper__btn:active:not(:disabled,.is-disabled),.kl-stepper__btn.is-pressed{background:var(--kl-color-control-fill-pressed)}
.kl-stepper__btn:disabled,.kl-stepper__btn.is-disabled{color:var(--kl-color-text-tertiary);cursor:default}
.kl-stepper__value{min-width:36px;padding:0 2px;text-align:center;font:var(--kl-font-label);font-variant-numeric:tabular-nums}
.kl-stepper.is-disabled{opacity:.45}
.kl-stepper.is-disabled .kl-stepper__btn{cursor:default}

/* ===== 16b. Date picker: .kl-ac-dates (two date boxes), .kl-ac-cal (one month), .kl-ac-usual (a range with history) =====
   Class names are the adaptive card's own (.kl-ac-*), so the card keeps working once its local copy goes.
   States: today (.is-today), range ends (.is-start / .is-end, aria-pressed="true"), in range (.is-in), past (:disabled or
   .is-past, struck), suggested (.is-sugg, a dot), days of the next or last month (.is-out), hover, focus, disabled. */
/* A value box that opens its picker (the date boxes use it) */
.kl-ac-value{
  position:relative;display:flex;align-items:center;gap:8px;min-width:0;height:32px;margin:0;padding:0 10px;
  border:0;border-radius:var(--kl-radius-row);background:var(--kl-color-surface);box-shadow:inset 0 0 0 1px var(--kl-color-field-border);
  font:var(--kl-font-meta);color:var(--kl-color-text);text-align:left;cursor:pointer;-webkit-font-smoothing:antialiased;
  transition:box-shadow var(--kl-motion-press) var(--kl-motion-ease-out),background-color var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-ac-value:hover:not(:disabled,.is-disabled),.kl-ac-value.is-hover{box-shadow:inset 0 0 0 1px var(--kl-color-line-strong)}
.kl-ac-value:focus-visible,.kl-ac-value.is-focus,.kl-ac-value.is-open,.kl-ac-value[aria-expanded="true"]{outline:0;box-shadow:inset 0 0 0 1px var(--kl-color-focus),0 0 0 3px var(--kl-color-selection-soft)}
.kl-ac-value.is-empty{color:var(--kl-color-text-secondary)}
.kl-ac-value:disabled,.kl-ac-value.is-disabled{background:var(--kl-color-surface-sunken);color:var(--kl-color-text-tertiary);cursor:default}
.kl-ac-dates{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);align-items:center;gap:6px;min-width:0}
.kl-ac-dates .kl-ac-value{height:44px;flex-direction:column;align-items:flex-start;justify-content:center;gap:0}
.kl-ac-dates__label{font:var(--kl-font-caption);color:var(--kl-color-text-secondary)}
.kl-ac-dates__val{font:var(--kl-font-label-strong);color:var(--kl-color-text);font-variant-numeric:tabular-nums}
.kl-ac-value.is-empty .kl-ac-dates__val{font-weight:var(--kl-font-weight-regular);color:var(--kl-color-text-secondary)}
:is(.kl-ac-value:disabled,.kl-ac-value.is-disabled) .kl-ac-dates__val{color:var(--kl-color-text-tertiary)}
.kl-ac-dates__to{display:inline-flex;color:var(--kl-color-text-secondary)}
.kl-ac-dates__to svg{width:14px;height:14px;display:block}

/* Calendar: one month, Monday first. A range is a soft band between two filled ends: the one place a picker fills. */
.kl-ac-cal{
  --kl-ac-day-h:32px;--kl-ac-day-d:30px;
  display:flex;flex-direction:column;gap:6px;width:var(--kl-ac-cal-w,100%);padding:10px;border-radius:var(--kl-radius-groupbox);
  background:var(--kl-color-surface);box-shadow:inset 0 0 0 1px var(--kl-color-line);color:var(--kl-color-text);font:var(--kl-font-meta);
  -webkit-font-smoothing:antialiased}
.kl-ac-cal *,.kl-ac-cal *::before,.kl-ac-cal *::after{box-sizing:border-box}
.kl-ac-cal__head{display:flex;align-items:center;gap:4px}
.kl-ac-cal__month{flex:1 1 auto;font:var(--kl-font-label-strong);color:var(--kl-color-text)}
.kl-ac-cal__grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));row-gap:2px}
.kl-ac-cal__dow{display:grid;place-items:center;height:20px;font:var(--kl-font-caption);color:var(--kl-color-text-secondary)}
.kl-ac-cal__day{
  --kl-ac-day-band:transparent;
  position:relative;display:grid;place-items:center;height:var(--kl-ac-day-h);margin:0;padding:0;border:0;
  background:linear-gradient(var(--kl-ac-day-band),var(--kl-ac-day-band));color:var(--kl-color-text);
  font:var(--kl-font-meta);font-variant-numeric:tabular-nums;cursor:pointer;-webkit-appearance:none;appearance:none;-webkit-tap-highlight-color:transparent}
.kl-ac-cal__day > span{position:relative;z-index:1;display:grid;place-items:center;width:var(--kl-ac-day-d);height:var(--kl-ac-day-d);border-radius:50%;
  transition:background-color var(--kl-motion-press) var(--kl-motion-ease-out),color var(--kl-motion-press) var(--kl-motion-ease-out)}
.kl-ac-cal__day:hover:not(:disabled,.is-disabled,.is-past) > span,.kl-ac-cal__day.is-hover > span{background:var(--kl-color-control-fill)}
.kl-ac-cal__day:focus-visible{outline:0}
.kl-ac-cal__day:focus-visible > span,.kl-ac-cal__day.is-focus > span{box-shadow:0 0 0 2px var(--kl-color-focus)}
.kl-ac-cal__day.is-out{color:var(--kl-color-text-tertiary)}
.kl-ac-cal__day.is-today > span{box-shadow:inset 0 0 0 1px var(--kl-color-line-strong)}
.kl-ac-cal__day.is-today:is(:focus-visible,.is-focus) > span{box-shadow:inset 0 0 0 1px var(--kl-color-line-strong),0 0 0 2px var(--kl-color-focus)}
/* Past (or otherwise not pickable): struck through, never hovers */
.kl-ac-cal__day:disabled,.kl-ac-cal__day.is-past,.kl-ac-cal__day.is-disabled{color:var(--kl-color-text-tertiary);cursor:default}
.kl-ac-cal__day:is(:disabled,.is-past,.is-disabled) > span{background:none;text-decoration:line-through;text-decoration-color:var(--kl-color-line-strong)}
/* The range */
.kl-ac-cal__day.is-in{--kl-ac-day-band:var(--kl-color-selection-soft)}
.kl-ac-cal__day.is-start{background:linear-gradient(90deg,transparent 50%,var(--kl-color-selection-soft) 50%)}
.kl-ac-cal__day.is-end{background:linear-gradient(90deg,var(--kl-color-selection-soft) 50%,transparent 50%)}
.kl-ac-cal__day.is-start.is-end{background:none}
.kl-ac-cal__day:is(.is-start,.is-end) > span{background:var(--kl-color-selection);color:var(--kl-color-text-on-fill);font-weight:var(--kl-font-weight-semibold)}
.kl-ac-cal__day:is(.is-start,.is-end):is(:focus-visible,.is-focus) > span{box-shadow:0 0 0 2px var(--kl-color-surface),0 0 0 4px var(--kl-color-focus)}
/* Days a suggestion covers (shown while that suggestion is hovered or focused): a small dot under the number */
.kl-ac-cal__day.is-sugg::after{content:"";position:absolute;z-index:2;left:50%;bottom:2px;width:4px;height:4px;margin-left:-2px;border-radius:50%;background:var(--kl-color-selection)}
.kl-ac-cal__day.is-sugg:is(.is-start,.is-end)::after{background:var(--kl-color-text-on-fill)}
.kl-ac-cal__foot{display:flex;align-items:center;gap:8px;font:var(--kl-font-caption);color:var(--kl-color-text-secondary)}
.kl-ac-cal__foot .kl-btn{margin-left:auto}
/* The whole picker disabled (the card is busy) */
.kl-ac-cal.is-disabled{opacity:.45;pointer-events:none}

/* A range with history: the track, the band where your earlier choices usually sit, and a dot per earlier choice.
   Set --from / --to on __band and --at on each __pt, as percentages of the track. */
.kl-ac-usual{display:flex;flex-direction:column;gap:6px;min-width:0}
.kl-ac-usual__track{position:relative;height:18px}
.kl-ac-usual__track::before{content:"";position:absolute;left:0;right:0;top:8px;height:2px;border-radius:1px;background:var(--kl-color-line)}
.kl-ac-usual__band{position:absolute;top:4px;height:10px;border-radius:5px;background:var(--kl-color-selection-soft);
  box-shadow:inset 0 0 0 1px var(--kl-color-selection);left:var(--from);width:calc(var(--to) - var(--from))}
.kl-ac-usual__pt{position:absolute;top:6px;width:6px;height:6px;margin-left:-3px;border-radius:50%;
  background:var(--kl-color-selection-ink);box-shadow:0 0 0 1.5px var(--kl-color-surface);left:var(--at)}
.kl-ac-usual__scale{display:flex;justify-content:space-between;gap:8px;font:var(--kl-font-caption);color:var(--kl-color-text-secondary);font-variant-numeric:tabular-nums}
.kl-ac-usual.is-disabled{opacity:.45}

/* ===== 17. Motion (only when the viewer allows it) ===== */
@media (prefers-reduced-motion:no-preference){
  /* Press: buttons give a little, on ease-out (calm, no bounce) */
  .kl-btn,.kl-iconbtn,.kl-chip,.kl-seg__item,.kl-stepper__btn{transition-property:background-color,color,opacity,box-shadow,scale;
    transition-duration:var(--kl-motion-press),var(--kl-motion-press),var(--kl-motion-press),var(--kl-motion-press),var(--kl-motion-press);
    transition-timing-function:var(--kl-motion-ease-out)}
  .kl-btn:active:not(:disabled,.is-disabled,[aria-disabled="true"]),.kl-btn.is-pressed,
  .kl-iconbtn:active:not(:disabled,.is-disabled),.kl-iconbtn.is-pressed,
  :is(button,a,label).kl-chip:active:not(:disabled,.is-disabled),.kl-chip.is-pressed{scale:.96}
  .kl-seg__item:active:not(:disabled,.is-disabled),.kl-seg__item.is-pressed,
  .kl-stepper__btn:active:not(:disabled,.is-disabled),.kl-stepper__btn.is-pressed{scale:.92}
  /* Small parts may spring: switch knob, check marks, tab pill, select chevron */
  .kl-switch__knob{transition:translate var(--kl-motion-press) var(--kl-motion-spring-pop),width var(--kl-motion-press) var(--kl-motion-ease-out)}
  .kl-checkbox__box::after,.kl-radio__box::after{transition:opacity var(--kl-motion-press) var(--kl-motion-ease-out),scale var(--kl-motion-press) var(--kl-motion-spring-pop)}
  :is(.kl-checkbox,.kl-radio):active:not(.is-disabled,:has(input:disabled)) > span,:is(.kl-checkbox,.kl-radio).is-pressed > span{scale:.92}
  .kl-checkbox__box,.kl-radio__box{transition:background-color var(--kl-motion-press) var(--kl-motion-ease-out),box-shadow var(--kl-motion-press) var(--kl-motion-ease-out),scale var(--kl-motion-press) var(--kl-motion-ease-out)}
  .kl-tabs__pill{transition:translate var(--kl-motion-hover) var(--kl-motion-spring-pop),width var(--kl-motion-hover) var(--kl-motion-ease-out)}
  .kl-ac-cal__day:is(.is-start,.is-end).kl-ac-pick > span{animation:kl-pop var(--kl-motion-count-pop) var(--kl-motion-spring-pop) both}
  .kl-slider::-webkit-slider-thumb{transition:scale var(--kl-motion-press) var(--kl-motion-ease-out),box-shadow var(--kl-motion-press) var(--kl-motion-ease-out)}
  .kl-slider:active:not(:disabled)::-webkit-slider-thumb,.kl-slider.is-pressed::-webkit-slider-thumb{scale:1.12}
  .kl-slider:active:not(:disabled)::-moz-range-thumb,.kl-slider.is-pressed::-moz-range-thumb{scale:1.12}
  /* Floating things arrive */
  .kl-menu{animation:kl-menu-in var(--kl-motion-press) var(--kl-motion-ease-out) both}
  .kl-menu.is-closing{pointer-events:none;animation:kl-menu-out var(--kl-motion-fade-out) var(--kl-motion-ease-in) forwards}
  .kl-tooltip{animation:kl-tip-in var(--kl-motion-press) var(--kl-motion-ease-out) both}
  .kl-toast{animation:kl-toast-in var(--kl-motion-hover) var(--kl-motion-ease-out) both}
  .kl-toast.is-leaving{transition:opacity var(--kl-motion-fade-out) var(--kl-motion-ease-in),translate var(--kl-motion-fade-out) var(--kl-motion-ease-in);translate:0 6px}
  .kl-toast__timer{animation:kl-countdown var(--kl-motion-toast) linear forwards}
  .kl-toast:hover .kl-toast__timer,.kl-toast:focus-within .kl-toast__timer{animation-play-state:paused}
  .kl-scrim{animation:kl-fade-in var(--kl-motion-hover) var(--kl-motion-ease-out) both}
  .kl-dialog{animation:kl-dialog-in var(--kl-motion-hover) var(--kl-motion-ease-out) both}
  .kl-field.is-shaking,.kl-search.is-shaking{animation:kl-shake var(--kl-motion-shake) var(--kl-motion-ease-out)}
  /* Status: a running dot sends out a soft ring */
  .kl-dot.is-pulsing::after{animation:kl-dot-ring var(--kl-dot-cadence) var(--kl-motion-ease-out) infinite}
  .kl-select::after{transition:background-color var(--kl-motion-press) var(--kl-motion-ease-out)}
}
@media (prefers-reduced-motion:reduce){
  .kl-menu,.kl-tooltip,.kl-toast,.kl-scrim,.kl-dialog{animation:kl-fade-in var(--kl-motion-press) linear both}
  .kl-check{animation:kl-check-fade var(--kl-motion-press) linear both}
  .kl-menu.is-closing{pointer-events:none;animation:kl-fade-out var(--kl-motion-fade-out) linear forwards}
  .kl-toast__timer{animation:kl-fade-timer var(--kl-motion-toast) linear forwards}
  .kl-switch__knob,.kl-tabs__pill,.kl-meter__fill{transition:none}
  .kl-ac-cal__day.kl-ac-pick > span{animation:kl-fade-in var(--kl-motion-fade) linear both}
}
/* The app's own switch: .kl-motion-reduce on any ancestor gives the same fades-only treatment as the OS setting */
.kl-motion-reduce :is(.kl-menu,.kl-tooltip,.kl-toast,.kl-scrim,.kl-dialog){animation:kl-fade-in var(--kl-motion-press) linear both}
.kl-motion-reduce .kl-check,.kl-motion-reduce.kl-check{animation:kl-check-fade var(--kl-motion-press) linear both}
.kl-motion-reduce .kl-menu.is-closing{pointer-events:none;animation:kl-fade-out var(--kl-motion-fade-out) linear forwards}
.kl-motion-reduce .kl-toast__timer{animation:kl-fade-timer var(--kl-motion-toast) linear forwards}
.kl-motion-reduce :is(.kl-switch__knob,.kl-tabs__pill,.kl-meter__fill){transition:none}
.kl-motion-reduce :is(.kl-field,.kl-search).is-shaking,.kl-motion-reduce .kl-dot.is-pulsing::after{animation:none}
.kl-motion-reduce :is(.kl-btn,.kl-iconbtn,.kl-chip,.kl-seg__item,.kl-stepper__btn,.kl-checkbox > span,.kl-radio > span){scale:none!important}
.kl-motion-reduce .kl-ac-cal__day.kl-ac-pick > span{animation:kl-fade-in var(--kl-motion-fade) linear both}
@keyframes kl-fade-in{from{opacity:0}}
@keyframes kl-fade-out{to{opacity:0}}
@keyframes kl-pop{from{opacity:0;scale:.6}to{opacity:1;scale:1}}
@keyframes kl-check-fade{from{opacity:0}to{opacity:1}}  /* explicit end, so fill-mode both holds the check visible */
@keyframes kl-menu-in{from{opacity:0;transform:translateY(-4px) scale(.96)}}
@keyframes kl-menu-out{to{opacity:0;transform:translateY(-2px) scale(.98)}}
@keyframes kl-tip-in{from{opacity:0;transform:translateY(2px)}}
@keyframes kl-toast-in{from{opacity:0;transform:translateY(12px)}}
@keyframes kl-dialog-in{from{opacity:0;transform:scale(.96)}}
@keyframes kl-countdown{from{transform:scaleX(1)}to{transform:scaleX(0)}}
@keyframes kl-fade-timer{from{opacity:1}to{opacity:.15}}
@keyframes kl-dot-ring{0%{opacity:.55;transform:scale(1)}80%,100%{opacity:0;transform:scale(2.6)}}
@keyframes kl-shake{0%,100%{translate:0}20%{translate:-4px 0}40%{translate:4px 0}60%{translate:-2px 0}80%{translate:2px 0}}

/* Forced colours: shadows vanish, so edges and the selection come back as system colours */
@media (forced-colors:active){
  .kl-btn,.kl-iconbtn,.kl-select,.kl-chip,.kl-seg,.kl-tabs,.kl-stepper,.kl-toast,.kl-dialog,.kl-menu,.kl-switch{border:1px solid ButtonText}
  .kl-selected::after{box-shadow:none;outline:2px solid Highlight;outline-offset:-2px}
  .kl-seg__item[aria-pressed="true"],.kl-tabs__tab[aria-selected="true"],.kl-switch[aria-checked="true"]{outline:2px solid Highlight}
  .kl-dot,.kl-meter__track,.kl-meter__mark{forced-color-adjust:none;outline:1px solid CanvasText}
  .kl-check,.kl-checkbox__box,.kl-radio__box{forced-color-adjust:none}
}

/* ===== controls/prompter.css ===== */
/* Klippan design system v2 — Controls: the prompter
   The one shared prompter that sits in the middle of the board. Compact (440 x 104 board units, step 10) with the
   draft, the destination, the model button and Send; expanded it grows upward to 720px into four tabs: Saved prompts,
   Templates, Model and Agent presets. The draft and Send stay in the bottom row while it grows.

   Uses the basic controls from controls.css (.kl-btn, .kl-iconbtn, .kl-tabs, .kl-search, .kl-meter, .kl-chip,
   .kl-badge, .kl-select, .kl-seg, .kl-stepper, .kl-selected, .kl-check, .kl-kbd) and never restyles their colours.
   Send is the only primary (blue) button in the prompter, in every state and on every tab.

   Root:   .kl-prompter                    compact, opaque (step 10 "G2": cards never show through)
           .kl-prompter--glass             frosted variant, for a prompter docked over a wallpaper
           .kl-prompter--anchored          absolute, bottom-anchored and centred, so it grows upward
   States on the root (static specimens) mirror real attributes:
           .is-expanded  .is-expanding  .is-collapsing     open / opening / closing
           .is-no-dest   .is-linked     .is-link-target    destination
           .is-focus     .is-typing     .is-sending   .is-delivered   .is-failed   .is-deploying
           .is-behind    something else is in front (the project switcher): fades back, sinks to .97, takes no clicks
           .is-answering answering a question card: asking project in the approval tone, "Answer Atlas", Cancel / Esc
   Motion: --kl-motion-expand / --kl-motion-collapse on --kl-motion-ease-out for the size change; content rises in with
           --kl-motion-reveal, --kl-motion-reveal-delay and --kl-motion-reveal-step (set --kl-i on each row); the model chevron,
           the check and the attach point use --kl-motion-spring-pop; the field shakes once on --kl-motion-shake.
           Reduced motion: no size glide, no shake, no lift; content fades only. */

/* ---------- Root ---------- */
.kl-prompter {
  /* Component sizes (board units). Step 10: 440 x 104 collapsed, 720 wide expanded. */
  --kl-prompter-w: 440px;
  --kl-prompter-w-open: var(--kl-size-prompter-expanded);
  --kl-prompter-pad: var(--kl-space-3);
  --kl-prompter-pad-open: var(--kl-space-4);
  --kl-prompter-field-h: 40px;
  --kl-prompter-field-h-open: 88px;
  --kl-prompter-bar-h: 32px;
  --kl-prompter-send: 32px;
  --kl-prompter-pane-h: var(--kl-size-prompter-pane);
  --kl-prompter-radius: var(--kl-radius-prompter);
  --kl-prompter-radius-open: var(--kl-radius-prompter-expanded, var(--kl-radius-prompter));
  --kl-prompter-radius-field: var(--kl-radius-draft, var(--kl-radius-groupbox));
  --kl-prompter-radius-tile: var(--kl-radius-tile, var(--kl-radius-groupbox));
  --kl-prompter-spin: calc(var(--kl-motion-expand) * 2);
  --kl-prompter-fly: var(--kl-motion-travel, var(--kl-motion-expand));

  position: relative;
  box-sizing: border-box;
  display: grid;
  grid-template-rows: auto auto;
  width: var(--kl-prompter-w);
  max-width: 100%;
  padding: var(--kl-prompter-pad);
  border-radius: var(--kl-prompter-radius);
  background: var(--kl-color-surface);
  box-shadow: 0 0 0 1px var(--kl-color-line), var(--kl-glass-shadow);
  color: var(--kl-color-text);
  font: var(--kl-font-body);
  font-family: var(--kl-font-sans);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  /* Collapsing: the closing values apply on the way back */
  transition:
    width var(--kl-motion-collapse) var(--kl-motion-ease-out),
    padding var(--kl-motion-collapse) var(--kl-motion-ease-out),
    border-radius var(--kl-motion-collapse) var(--kl-motion-ease-out),
    box-shadow var(--kl-motion-press) ease,
    opacity var(--kl-motion-hover) var(--kl-motion-ease-out),
    scale var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-prompter *, .kl-prompter *::before, .kl-prompter *::after { box-sizing: border-box; }
.kl-prompter svg { display: block; flex: none; }
.kl-prompter button { font-family: inherit; }

.kl-prompter--glass {
  background: var(--kl-glass-fill);
  -webkit-backdrop-filter: blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));
  backdrop-filter: blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));
  box-shadow: var(--kl-glass-shadow), var(--kl-glass-rim);
}

/* On the board: centred and anchored at its bottom edge, so expanding grows it upward and the draft row stays put */
.kl-prompter--anchored {
  position: absolute;
  left: 50%;
  bottom: var(--kl-prompter-bottom, var(--kl-space-6));
  translate: -50% 0;
  z-index: 40;
}

/* Behind: something else is in front of the prompter (the project switcher). It fades back and sinks a little
   toward its bottom edge, so an anchored prompter stays on its line; nothing in it can be clicked. Ease-out, no bounce. */
.kl-prompter.is-behind {
  opacity: .38;
  scale: .97;
  transform-origin: 50% 100%;
  pointer-events: none;
}

/* Visually hidden text (labels for the field, the Send label in compact) */
.kl-prompter__sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ---------- Expanded ---------- */
.kl-prompter.is-expanded,
.kl-prompter.is-expanding {
  width: var(--kl-prompter-w-open);
  padding: var(--kl-prompter-pad-open);
  border-radius: var(--kl-prompter-radius-open);
  transition-duration: var(--kl-motion-expand), var(--kl-motion-expand), var(--kl-motion-expand), var(--kl-motion-press), var(--kl-motion-hover), var(--kl-motion-hover);
}

/* The library (tabs + pane) lives in a drawer above the draft. 0fr when compact, 1fr when expanded. */
.kl-prompter__drawer {
  display: grid;
  grid-template-rows: 0fr;
  min-width: 0;
  transition: grid-template-rows var(--kl-motion-collapse) var(--kl-motion-ease-out);
}
.kl-prompter.is-expanded .kl-prompter__drawer,
.kl-prompter.is-expanding .kl-prompter__drawer {
  grid-template-rows: 1fr;
  transition-duration: var(--kl-motion-expand);
}
.kl-prompter__library {
  min-height: 0;
  min-width: 0;
  overflow: hidden;
  opacity: 0;
  visibility: hidden;
  /* Closing: content fades out first, then the drawer folds; visibility flips after the fold */
  transition:
    opacity var(--kl-motion-fade-out) ease,
    visibility 0s linear var(--kl-motion-collapse);
}
.kl-prompter.is-expanded .kl-prompter__library,
.kl-prompter.is-expanding .kl-prompter__library {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--kl-motion-reveal) var(--kl-motion-ease-out) var(--kl-motion-reveal-delay), visibility 0s;
}
.kl-prompter__library-in { padding-bottom: var(--kl-space-3); }

/* Library head: tabs, key hint, collapse chevron */
.kl-prompter__head {
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  min-width: 0;
}
.kl-prompter__head .kl-tabs { flex: 1 1 auto; min-width: 0; max-width: 560px; } /* equal tabs: set --kl-tabs-n: 4 and --kl-tab-i on .kl-tabs */
.kl-prompter__spacer { flex: 1 1 auto; }
.kl-prompter__keyhint {
  display: inline-flex;
  align-items: center;
  gap: var(--kl-space-1);
  color: var(--kl-color-text-secondary);
  font: var(--kl-font-caption);
  white-space: nowrap;
}
.kl-prompter__collapse svg { rotate: 0deg; }

/* The pane: one fixed-height well under the tabs; inner radius = prompter radius minus its padding */
.kl-prompter__pane {
  height: var(--kl-prompter-pane-h);
  margin-top: var(--kl-space-3);
  padding: var(--kl-space-2);
  border-radius: calc(var(--kl-prompter-radius-open) - var(--kl-prompter-pad-open));
  background: var(--kl-color-surface-sunken);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
  overflow: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: var(--kl-space-2);
}
.kl-prompter__pane[hidden] { display: none; }
.kl-prompter__pane:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }

/* ---------- Compose: the draft and the bar under it (always shown, never moves) ---------- */
.kl-prompter__compose {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  grid-template-rows: var(--kl-prompter-field-h) var(--kl-prompter-bar-h);
  column-gap: var(--kl-space-2);
  row-gap: var(--kl-space-2);
  align-items: center;
  min-width: 0;
  transition: grid-template-rows var(--kl-motion-collapse) var(--kl-motion-ease-out);
}
.kl-prompter.is-expanded .kl-prompter__compose,
.kl-prompter.is-expanding .kl-prompter__compose {
  grid-template-rows: var(--kl-prompter-field-h-open) var(--kl-prompter-bar-h);
  transition-duration: var(--kl-motion-expand);
}

/* Field */
.kl-prompter__field {
  grid-column: 1 / -1;
  grid-row: 1;
  align-self: stretch;
  width: 100%;
  min-width: 0;
  height: 100%;
  margin: 0;
  padding: var(--kl-space-2) var(--kl-space-3);
  border: 1px solid var(--kl-color-field-border);
  border-radius: var(--kl-prompter-radius-field);
  background: var(--kl-color-surface-sunken);
  color: var(--kl-color-text);
  font: var(--kl-font-body);
  font-family: var(--kl-font-sans);
  resize: none;
  overflow: hidden;
  outline: none;
  transition:
    border-color var(--kl-motion-press) ease,
    box-shadow var(--kl-motion-press) ease,
    color var(--kl-motion-press) ease;
}
/* Compact: one line, no wrap (the draft scrolls sideways); expanded: wraps over three lines */
.kl-prompter:not(.is-expanded):not(.is-expanding) .kl-prompter__field { white-space: nowrap; overflow-x: hidden; overflow-y: hidden; }
.kl-prompter.is-expanded .kl-prompter__field { overflow: auto; }
.kl-prompter__field::placeholder { color: var(--kl-color-text-secondary); opacity: 1; }
.kl-prompter__field:hover { border-color: var(--kl-color-line-strong); }
.kl-prompter__field:focus-visible,
.kl-prompter.is-focus .kl-prompter__field {
  border-color: var(--kl-color-focus);
  box-shadow: 0 0 0 3px var(--kl-color-selection-soft);
}
/* Sending: the field is locked (readonly) and dims until delivery finishes */
.kl-prompter.is-sending .kl-prompter__field,
.kl-prompter.is-deploying .kl-prompter__field,
.kl-prompter__field[readonly] {
  color: var(--kl-color-text-secondary);
  border-color: var(--kl-color-field-border);
  box-shadow: none;
  cursor: progress;
}
/* Failed: error ink edge; it shakes once (motion block below) */
.kl-prompter.is-failed .kl-prompter__field,
.kl-prompter__field[aria-invalid="true"] {
  border-color: var(--kl-color-status-stopped);
  box-shadow: 0 0 0 3px var(--kl-color-status-stopped-soft);
}

/* ---------- Destination ---------- */
.kl-prompter__dest {
  grid-column: 1;
  grid-row: 2;
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 180px;
  height: 28px;
  padding: 0 var(--kl-space-2) 0 10px;
  border: 1px dashed var(--kl-color-line-strong);
  border-radius: var(--kl-radius-pill);
  background: transparent;
  color: var(--kl-color-text-secondary);
  font: var(--kl-font-label);
  font-family: var(--kl-font-sans);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--kl-motion-press) ease, color var(--kl-motion-press) ease, border-color var(--kl-motion-press) ease;
}
.kl-prompter__dest:hover, .kl-prompter__dest.is-hover { color: var(--kl-color-text); border-color: var(--kl-color-text-tertiary); }
.kl-prompter__dest:focus-visible, .kl-prompter__dest.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-prompter__dest-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.kl-prompter__dest-chev { width: 12px; height: 12px; opacity: .8; }
/* Set (by the pop-up or by linking a card): blue soft fill and the project's mark */
.kl-prompter__dest.is-set,
.kl-prompter.is-linked .kl-prompter__dest {
  border-color: transparent;
  background: var(--kl-color-selection-soft);
  color: var(--kl-color-selection-ink);
}
.kl-prompter__dest.is-set:hover { border-color: transparent; color: var(--kl-color-selection-ink); box-shadow: inset 0 0 0 1px var(--kl-color-selection); }
.kl-prompter__mark {
  width: 8px;
  height: 8px;
  flex: none;
  border-radius: 2.5px;
  background: var(--kl-color-selection);
}

/* Attach point: where the link line from the linked card meets the prompter's edge.
   Place it with --kl-attach-x / --kl-attach-y (percent of the prompter box; the board computes the edge facing the card). */
.kl-prompter__attach {
  position: absolute;
  left: var(--kl-attach-x, 50%);
  top: var(--kl-attach-y, 0%);
  width: 12px;
  height: 12px;
  translate: -50% -50%;
  border-radius: 50%;
  background: var(--kl-color-selection);
  box-shadow: 0 0 0 2px var(--kl-color-surface), 0 0 0 5px var(--kl-color-selection-soft);
  pointer-events: none;
  opacity: 0;
  scale: .4;
  transition: opacity var(--kl-motion-press) ease, scale var(--kl-motion-press) var(--kl-motion-spring-pop);
}
.kl-prompter.is-linked .kl-prompter__attach,
.kl-prompter__attach.is-on { opacity: 1; scale: 1; }

/* Link target: a link is held from a card and the pointer is over the prompter */
.kl-prompter.is-link-target {
  box-shadow: 0 0 0 1px var(--kl-color-line), var(--kl-glass-shadow), 0 0 0 2px var(--kl-color-selection), 0 0 0 6px var(--kl-color-selection-soft);
}

/* ---------- Status (between destination and the model button) ---------- */
.kl-prompter__status {
  grid-column: 2;
  grid-row: 2;
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  max-width: 100%;
  color: var(--kl-color-text-secondary);
  font: var(--kl-font-meta);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.kl-prompter__status-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.kl-prompter__status svg { width: 14px; height: 14px; }
.kl-prompter__status--hint { color: var(--kl-color-selection-ink); font: var(--kl-font-label); }
.kl-prompter__status--ok { color: var(--kl-color-status-executing-ink); font: var(--kl-font-label); }
.kl-prompter__status--error { color: var(--kl-color-status-stopped-ink); font: var(--kl-font-label); }
.kl-prompter__status--busy { color: var(--kl-color-text-secondary); }
.kl-prompter__status .kl-badge { flex: none; }
/* In the expanded prompter the status starts left, next to the destination */
.kl-prompter.is-expanded .kl-prompter__status { justify-self: start; }

/* ---------- Model button: names the model and opens the expanded prompter ---------- */
.kl-prompter__model {
  grid-column: 3;
  grid-row: 2;
  display: inline-flex;
  align-items: center;
  gap: var(--kl-space-1);
  height: 28px;
  padding: 0 var(--kl-space-2) 0 var(--kl-space-3);
  border: 0;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-control-fill);
  color: var(--kl-color-text);
  font: var(--kl-font-label);
  font-family: var(--kl-font-sans);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--kl-motion-press) ease, color var(--kl-motion-press) ease, scale var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-prompter__model:hover, .kl-prompter__model.is-hover { background: var(--kl-color-button-secondary); }
.kl-prompter__model:active, .kl-prompter__model.is-pressed { background: var(--kl-color-control-fill-pressed); scale: .97; }
.kl-prompter__model:focus-visible, .kl-prompter__model.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-prompter__model svg {
  width: 12px;
  height: 12px;
  color: var(--kl-color-text-secondary);
  rotate: 180deg; /* chevron points up: the prompter opens upward */
  transition: rotate var(--kl-motion-expand) var(--kl-motion-spring-pop);
}
.kl-prompter__model[aria-expanded="true"],
.kl-prompter.is-expanded .kl-prompter__model {
  background: var(--kl-color-selection-soft);
  color: var(--kl-color-selection-ink);
}
.kl-prompter__model[aria-expanded="true"] svg,
.kl-prompter.is-expanded .kl-prompter__model svg { rotate: 0deg; color: currentColor; }

/* ---------- Send (the only primary button; .kl-btn.kl-btn--primary gives the colour) ---------- */
.kl-prompter__send {
  grid-column: 4;
  grid-row: 2;
  position: relative;
  width: var(--kl-prompter-send);
  min-width: var(--kl-prompter-send);
  height: var(--kl-prompter-send);
  min-height: var(--kl-prompter-send);
  padding: 0;
  border-radius: 50%;
  justify-content: center;
  gap: 6px;
  transition: width var(--kl-motion-collapse) var(--kl-motion-ease-out), padding var(--kl-motion-collapse) var(--kl-motion-ease-out), border-radius var(--kl-motion-collapse) var(--kl-motion-ease-out);
}
.kl-prompter__send svg { width: 16px; height: 16px; }
.kl-prompter__send-label {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
/* Expanded, and Retry in any size: a labelled pill */
.kl-prompter.is-expanded .kl-prompter__send,
.kl-prompter.is-expanding .kl-prompter__send,
.kl-prompter__send--retry {
  width: auto;
  padding: 0 var(--kl-space-3) 0 14px;
  border-radius: var(--kl-radius-pill);
  transition-duration: var(--kl-motion-expand);
}
.kl-prompter.is-expanded .kl-prompter__send-label,
.kl-prompter.is-expanding .kl-prompter__send-label,
.kl-prompter__send--retry .kl-prompter__send-label {
  position: static; width: auto; height: auto; overflow: visible; clip-path: none;
}
.kl-prompter__send--retry { padding: 0 14px 0 var(--kl-space-3); }
/* Sending: Send shows progress and cannot be pressed twice (aria-busy + aria-disabled keep the blue) */
.kl-prompter__send.is-busy,
.kl-prompter__send[aria-busy="true"] { cursor: progress; }
.kl-prompter__send.is-busy > svg,
.kl-prompter__send[aria-busy="true"] > svg { display: none; }
.kl-prompter__spinner { display: none; }
.kl-prompter__send.is-busy .kl-prompter__spinner,
.kl-prompter__send[aria-busy="true"] .kl-prompter__spinner,
.kl-prompter__status .kl-prompter__spinner {
  display: block;
  width: 14px;
  height: 14px;
  flex: none;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, currentColor 30%, transparent);
  border-top-color: currentColor;
}

/* Deploy / send progress: a thin line along the prompter's bottom edge (--kl-progress 0–100%) */
.kl-prompter__progress {
  position: absolute;
  left: var(--kl-prompter-radius);
  right: var(--kl-prompter-radius);
  bottom: 5px;
  height: 3px;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-control-fill);
  overflow: hidden;
  pointer-events: none;
}
.kl-prompter__progress-fill {
  display: block;
  width: var(--kl-progress, 0%);
  height: 100%;
  border-radius: inherit;
  background: var(--kl-color-selection);
  transition: width var(--kl-motion-hover) var(--kl-motion-ease-out);
}

/* ---------- Pane parts shared by the tabs ---------- */
.kl-prompter__bar {
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  min-height: 32px;
  flex: none;
}
.kl-prompter__bar .kl-search { flex: 0 1 280px; min-width: 0; }
.kl-prompter__note {
  color: var(--kl-color-text-secondary);
  font: var(--kl-font-caption);
  font-variant-numeric: tabular-nums;
}
.kl-prompter__note b { color: var(--kl-color-text); font-weight: 590; }
.kl-prompter__group {
  margin: var(--kl-space-1) 0 0;
  padding: 0 var(--kl-space-2);
  color: var(--kl-color-text-secondary);
  font: var(--kl-font-caption);
}
.kl-prompter__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.kl-prompter__box {
  border-radius: var(--kl-radius-groupbox);
  background: var(--kl-color-surface);
  box-shadow: 0 0 0 1px var(--kl-color-line);
  padding: 2px var(--kl-space-3);
}
.kl-prompter__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--kl-space-3);
  min-height: 40px;
  font: var(--kl-font-label);
}
.kl-prompter__row + .kl-prompter__row { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-prompter__row-label { display: grid; gap: 1px; min-width: 0; color: var(--kl-color-text); }
.kl-prompter__row-sub { color: var(--kl-color-text-secondary); font: var(--kl-font-caption); }
.kl-prompter__row-value { color: var(--kl-color-text); font: var(--kl-font-label); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ---------- Saved prompts ---------- */
.kl-prompter__saved {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--kl-space-1);
  border-radius: var(--kl-radius-groupbox);
  transition: background-color var(--kl-motion-press) ease;
}
.kl-prompter__saved:hover, .kl-prompter__saved.is-hover { background: var(--kl-color-surface); box-shadow: 0 0 0 1px var(--kl-color-line); }
.kl-prompter__saved-main {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: var(--kl-space-3);
  row-gap: 2px;
  min-width: 0;
  padding: 7px 0 7px var(--kl-space-3);
  border: 0;
  border-radius: var(--kl-radius-groupbox);
  background: transparent;
  color: var(--kl-color-text);
  text-align: left;
  cursor: pointer;
}
.kl-prompter__saved-main:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: -2px; }
.kl-prompter__saved-title { font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kl-prompter__saved-meta { display: inline-flex; align-items: center; gap: 6px; color: var(--kl-color-text-secondary); font: var(--kl-font-caption); white-space: nowrap; }
.kl-prompter__saved-text { grid-column: 1 / -1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--kl-color-text-secondary); font: var(--kl-font-meta); }
.kl-prompter__saved.is-inserted .kl-prompter__saved-title { color: var(--kl-color-selection-ink); }
/* Pin: a quiet round button; pinned fills the glyph in the accent */
.kl-prompter__pin {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin-right: var(--kl-space-1);
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--kl-color-text-tertiary);
  cursor: pointer;
  transition: color var(--kl-motion-press) ease, background-color var(--kl-motion-press) ease, scale var(--kl-motion-press) var(--kl-motion-spring-pop);
}
.kl-prompter__pin svg { width: 16px; height: 16px; }
.kl-prompter__pin:hover { background: var(--kl-color-control-fill); color: var(--kl-color-text-secondary); }
.kl-prompter__pin:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 0; }
.kl-prompter__pin[aria-pressed="true"] { color: var(--kl-color-selection); }
.kl-prompter__pin[aria-pressed="true"] svg { fill: currentColor; }
.kl-prompter__pin:active { scale: .9; }
.kl-prompter__empty { margin: var(--kl-space-6) auto; max-width: 320px; text-align: center; color: var(--kl-color-text-secondary); font: var(--kl-font-meta); }

/* ---------- Templates ---------- */
.kl-prompter__tiles {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--kl-space-2);
  flex: none;
}
.kl-prompter__tile {
  position: relative;
  display: grid;
  align-content: start;
  gap: var(--kl-space-1);
  min-width: 0;
  min-height: 112px;
  padding: 10px var(--kl-space-3);
  border: 0;
  border-radius: var(--kl-prompter-radius-tile);
  background: var(--kl-color-surface);
  box-shadow: var(--kl-shadow-card);
  color: var(--kl-color-text);
  text-align: left;
  cursor: pointer;
  transition: box-shadow var(--kl-motion-press) ease, scale var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-prompter__tile:hover, .kl-prompter__tile.is-hover { box-shadow: var(--kl-shadow-card-hover); }
.kl-prompter__tile:active { scale: .98; }
.kl-prompter__tile:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-prompter__tile-name { padding-right: var(--kl-space-5); font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-prompter__tile-about { color: var(--kl-color-text-secondary); font: var(--kl-font-caption); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.kl-prompter__tile-blanks { display: flex; flex-wrap: wrap; gap: var(--kl-space-1); align-self: end; margin-top: var(--kl-space-1); }
.kl-prompter__tile.kl-selected > .kl-check { position: absolute; top: var(--kl-space-2); right: var(--kl-space-2); box-shadow: none; }
.kl-prompter__tile--new {
  background: transparent;
  box-shadow: none;
  border: 1px dashed var(--kl-color-line-strong);
  color: var(--kl-color-text-secondary);
}
.kl-prompter__tile--new:hover { box-shadow: none; border-color: var(--kl-color-text-tertiary); color: var(--kl-color-text); }
.kl-prompter__tile--new .kl-prompter__tile-name { display: inline-flex; align-items: center; gap: 6px; }
.kl-prompter__tile--new svg { width: 14px; height: 14px; }
/* A blank as written in a template: [deadline] */
.kl-prompter__blank {
  display: inline-flex;
  align-items: center;
  height: 18px;
  padding: 0 6px;
  border-radius: var(--kl-radius-control);
  background: var(--kl-color-control-fill);
  color: var(--kl-color-text-secondary);
  font: var(--kl-font-caption);
  font-family: var(--kl-font-mono);
  white-space: nowrap;
}
/* The draft with its fill-in fields */
.kl-prompter__preview {
  display: grid;
  gap: var(--kl-space-1);
  padding: 10px var(--kl-space-3);
  border-radius: var(--kl-radius-groupbox);
  background: var(--kl-color-surface);
  box-shadow: 0 0 0 1px var(--kl-color-line);
  font: var(--kl-font-meta);
  color: var(--kl-color-text);
}
.kl-prompter__preview-label { display: flex; align-items: center; gap: var(--kl-space-2); color: var(--kl-color-text-secondary); font: var(--kl-font-caption); }
.kl-prompter__fill {
  padding: 0 3px;
  border-radius: 4px;
  background: var(--kl-color-selection-soft);
  color: var(--kl-color-selection-ink);
  font-weight: 590;
}
.kl-prompter__fill.is-current { box-shadow: 0 0 0 1.5px var(--kl-color-selection); }
.kl-prompter__fill.is-done { padding: 0; background: transparent; color: var(--kl-color-text); font-weight: inherit; box-shadow: inset 0 -1.5px 0 var(--kl-color-selection-soft); }

/* ---------- Model ---------- */
.kl-prompter__split {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: var(--kl-space-2);
  align-items: start;
}
.kl-prompter__col { display: grid; gap: var(--kl-space-2); min-width: 0; }
.kl-prompter__meterbox {
  display: grid;
  gap: var(--kl-space-2);
  padding: var(--kl-space-3);
  border-radius: var(--kl-radius-groupbox);
  background: var(--kl-color-surface);
  box-shadow: 0 0 0 1px var(--kl-color-line);
}
.kl-prompter__row .kl-seg { flex: none; }

/* Effort pips (low / medium / high) */
.kl-prompter__pips { display: inline-flex; align-items: flex-end; gap: 2px; height: 12px; flex: none; }
.kl-prompter__pip { width: 4px; border-radius: 1px; background: var(--kl-color-pip-off); }
.kl-prompter__pip:nth-child(1) { height: 6px; }
.kl-prompter__pip:nth-child(2) { height: 9px; }
.kl-prompter__pip:nth-child(3) { height: 12px; }
.kl-prompter__pip.is-on { background: currentColor; }
.kl-prompter__effort { display: inline-flex; align-items: center; gap: 6px; color: var(--kl-color-text-secondary); font: var(--kl-font-caption); white-space: nowrap; }
.kl-prompter__effort .kl-prompter__pip.is-on { background: var(--kl-color-text); }

/* ---------- Agent presets ---------- */
.kl-prompter__picks {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--kl-space-2);
  flex: none;
}
.kl-prompter__pick {
  position: relative;
  display: grid;
  gap: 2px;
  min-width: 0;
  padding: var(--kl-space-2) var(--kl-space-3);
  border: 0;
  border-radius: var(--kl-prompter-radius-tile);
  background: var(--kl-color-surface);
  box-shadow: var(--kl-shadow-card);
  color: var(--kl-color-text);
  text-align: left;
  cursor: pointer;
  transition: box-shadow var(--kl-motion-press) ease, scale var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-prompter__pick:hover { box-shadow: var(--kl-shadow-card-hover); }
.kl-prompter__pick:active { scale: .98; }
.kl-prompter__pick:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-prompter__pick-name { padding-right: var(--kl-space-5); font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kl-prompter__pick-meta { color: var(--kl-color-text-secondary); font: var(--kl-font-caption); font-variant-numeric: tabular-nums; }
.kl-prompter__pick.kl-selected > .kl-check { position: absolute; top: 7px; right: 7px; box-shadow: none; }

.kl-prompter__preset {
  display: grid;
  gap: var(--kl-space-2);
  padding: var(--kl-space-3);
  border-radius: var(--kl-radius-groupbox);
  background: var(--kl-color-surface);
  box-shadow: 0 0 0 1px var(--kl-color-line);
}
.kl-prompter__preset-head { display: flex; align-items: center; gap: var(--kl-space-2); min-width: 0; flex-wrap: wrap; }
.kl-prompter__preset-name { margin: 0; font: var(--kl-font-headline); letter-spacing: var(--kl-font-label-strong-tracking); }
/* Capacity against the project's maximum: one seat per agent. used = already running, adding = this preset, free = room left */
.kl-prompter__cap {
  margin: 0;
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  min-height: 24px;
  color: var(--kl-color-text-secondary);
  font: var(--kl-font-caption);
  font-variant-numeric: tabular-nums;
}
.kl-prompter__cap b { color: var(--kl-color-text); font-weight: 590; }
.kl-prompter__cap--full { color: var(--kl-color-status-stopped-ink); }
.kl-prompter__cap--capped { color: var(--kl-color-status-planning-ink); }
.kl-prompter__seats { display: inline-flex; gap: 3px; flex: none; }
.kl-prompter__seat { width: 10px; height: 10px; border-radius: 3px; box-shadow: inset 0 0 0 1.5px var(--kl-color-line-strong); }
.kl-prompter__seat.is-used { background: var(--kl-color-text-tertiary); box-shadow: none; }
.kl-prompter__seat.is-adding { background: var(--kl-color-selection); box-shadow: none; }
.kl-prompter__seat.is-full { background: var(--kl-color-status-stopped); box-shadow: none; }
.kl-prompter__agents { list-style: none; margin: 0; padding: 0; display: grid; }
.kl-prompter__agent {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr) minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--kl-space-2);
  min-height: 32px;
  font: var(--kl-font-label);
}
.kl-prompter__agent + .kl-prompter__agent { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-prompter__agent svg { width: 16px; height: 16px; color: var(--kl-color-text-secondary); }
.kl-prompter__agent-model { color: var(--kl-color-text-secondary); font: var(--kl-font-meta); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kl-prompter__agent.is-capped { opacity: .45; }
.kl-prompter__agent.is-capped .kl-prompter__agent-model::after { content: " · stops at the maximum"; }

/* ---------- A preset being deployed: agents travel along the link to the card ---------- */
.kl-prompter__flyer {
  position: absolute;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 10px 0 6px;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-surface);
  box-shadow: var(--kl-shadow-card);
  color: var(--kl-color-text);
  font: var(--kl-font-caption);
  white-space: nowrap;
  pointer-events: none;
  z-index: 2;
}
.kl-prompter__flyer::before {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--kl-color-selection);
  box-shadow: 0 0 0 3px var(--kl-color-selection-soft);
}

/* ---------- Answering a question card (.is-answering) ----------
   Alban answers an agent's question from the prompter (picked up from the question card, its link, or the pending pill).
   The destination is the asking project in the approval tone (magenta: waiting on Alban), the status says whose
   question it is, the draft is the answer ("Type your answer…"), and Send is labelled for answering ("Answer Atlas"),
   still the one primary button. A quiet Cancel (Esc; its tooltip says so) takes the model button's place: Cancel or Esc puts the
   question back on its card and brings Alban's own draft back. Compact only; the harness additions' mode and
   attachment chips hide while a question is open, so the row stays short. */
.kl-prompter.is-answering {
  box-shadow: 0 0 0 1px var(--kl-color-line), var(--kl-glass-shadow), 0 0 0 3px var(--kl-color-status-approval-soft);
}
.kl-prompter.is-answering .kl-prompter__dest,
.kl-prompter__dest.is-asking {
  border-color: transparent;
  background: var(--kl-color-status-approval-soft);
  color: var(--kl-color-status-approval-ink);
}
.kl-prompter.is-answering .kl-prompter__dest:hover,
.kl-prompter.is-answering .kl-prompter__dest.is-hover,
.kl-prompter__dest.is-asking:hover { border-color: transparent; color: var(--kl-color-status-approval-ink); box-shadow: inset 0 0 0 1px var(--kl-color-status-approval); }
.kl-prompter.is-answering .kl-prompter__mark,
.kl-prompter__dest.is-asking .kl-prompter__mark { background: var(--kl-color-status-approval); }
.kl-prompter__status--answering { color: var(--kl-color-status-approval-ink); font: var(--kl-font-label); }
/* Cancel: only while answering, in the model button's column */
.kl-prompter__cancel { grid-column: 3; grid-row: 2; display: none; gap: var(--kl-space-1); --kl-btn-px: 8px; }
.kl-prompter__cancel .kl-kbd { height: 16px; min-width: 16px; padding: 0 4px; }   /* optional Esc hint, where the row has room */
/* The destination is locked to the asker while answering: no chevron, no menu */
.kl-prompter.is-answering .kl-prompter__dest { padding-right: 10px; cursor: default; }
.kl-prompter.is-answering .kl-prompter__dest-chev { display: none; }
.kl-prompter.is-answering .kl-prompter__cancel { display: inline-flex; }
.kl-prompter.is-answering .kl-prompter__model,
.kl-prompter.is-answering .kl-prompter__mode,
.kl-prompter.is-answering .kl-prompter__chips { display: none; }
/* Send: a labelled pill, like Retry, so it says what it does */
.kl-prompter.is-answering .kl-prompter__send {
  width: auto;
  padding: 0 var(--kl-space-3) 0 14px;
  border-radius: var(--kl-radius-pill);
  transition-duration: var(--kl-motion-expand);
}
.kl-prompter.is-answering .kl-prompter__send-label { position: static; width: auto; height: auto; overflow: visible; clip-path: none; }

/* ---------- Motion ---------- */
@media (prefers-reduced-motion: no-preference) {
  /* Expanding: the drawer's rows rise in one after another (set --kl-i: 0, 1, 2 … on each) */
  .kl-prompter.is-expanded .kl-prompter__head,
  .kl-prompter.is-expanded .kl-prompter__pane:not([hidden]) > * {
    animation: kl-prompter-rise var(--kl-motion-reveal) var(--kl-motion-ease-out) both;
    animation-delay: calc(var(--kl-motion-reveal-delay) + var(--kl-i, 0) * var(--kl-motion-reveal-step));
  }
  /* Collapsing: contents go first, quicker than they came */
  .kl-prompter.is-collapsing .kl-prompter__library { opacity: 0; transition: opacity var(--kl-motion-fade-out) ease; }

  /* Failed: the field shakes once */
  .kl-prompter.is-failed .kl-prompter__field { animation: kl-prompter-shake var(--kl-motion-shake) var(--kl-motion-ease-out) 1; }
  /* Delivered: the check pops on the spring */
  .kl-prompter__status--ok svg { animation: kl-prompter-pop var(--kl-motion-hover) var(--kl-motion-spring-pop) both; }
  .kl-prompter__status--ok,
  .kl-prompter__status--error,
  .kl-prompter__status--answering { animation: kl-prompter-fade var(--kl-motion-press) var(--kl-motion-ease-out) both; }
  /* Sent: the draft lifts away before the field empties (add .is-leaving for one --kl-motion-press) */
  .kl-prompter__field.is-leaving { animation: kl-prompter-lift var(--kl-motion-press) var(--kl-motion-ease-in) forwards; }
  /* Destination landing (a link just arrived) */
  .kl-prompter__dest.is-landing { animation: kl-prompter-land var(--kl-motion-hover) var(--kl-motion-spring-pop); }
  .kl-prompter__spinner { animation: kl-prompter-spin var(--kl-prompter-spin) linear infinite; }
  /* Flyers: give each an inline offset-path (the link line) and --kl-i; they follow it 2 staggers apart */
  .kl-prompter__flyer.is-flying {
    offset-rotate: 0deg;
    animation: kl-prompter-fly var(--kl-prompter-fly) var(--kl-motion-ease-out) both;
    animation-delay: calc(var(--kl-i, 0) * var(--kl-motion-reveal-step) * 2);
  }
}
@media (prefers-reduced-motion: reduce) {
  .kl-prompter,
  .kl-prompter *,
  .kl-prompter__drawer,
  .kl-prompter__compose { transition-property: opacity, color, background-color, border-color, box-shadow !important; }
  .kl-prompter.is-expanded .kl-prompter__head,
  .kl-prompter.is-expanded .kl-prompter__pane:not([hidden]) > *,
  .kl-prompter__status--ok,
  .kl-prompter__status--error,
  .kl-prompter__status--answering { animation: kl-prompter-fade var(--kl-motion-fade-out) ease both; }
  .kl-prompter.is-failed .kl-prompter__field,
  .kl-prompter__field.is-leaving,
  .kl-prompter__dest.is-landing { animation: none; }
  .kl-prompter__spinner { animation: kl-prompter-breathe calc(var(--kl-prompter-spin) * 2) ease-in-out infinite; }
  .kl-prompter__flyer { display: none; }
  .kl-prompter.is-behind { scale: none; }
}
/* The app's own switch: .kl-motion-reduce on any ancestor gets the same fades-only treatment */
.kl-motion-reduce .kl-prompter,
.kl-motion-reduce .kl-prompter *,
.kl-motion-reduce .kl-prompter__drawer,
.kl-motion-reduce .kl-prompter__compose { transition-property: opacity, color, background-color, border-color, box-shadow !important; }
.kl-motion-reduce .kl-prompter.is-behind { scale: none; }
.kl-motion-reduce :is(.kl-prompter.is-expanded .kl-prompter__head, .kl-prompter.is-expanded .kl-prompter__pane:not([hidden]) > *, .kl-prompter__status--ok, .kl-prompter__status--error, .kl-prompter__status--answering) { animation: kl-prompter-fade var(--kl-motion-fade-out) ease both; }
.kl-motion-reduce :is(.kl-prompter.is-failed .kl-prompter__field, .kl-prompter__field.is-leaving, .kl-prompter__dest.is-landing, .kl-prompter__status--ok svg) { animation: none; }
.kl-motion-reduce .kl-prompter__spinner { animation: kl-prompter-breathe calc(var(--kl-prompter-spin) * 2) ease-in-out infinite; }
.kl-motion-reduce .kl-prompter__flyer { display: none; }

@keyframes kl-prompter-rise { from { opacity: 0; translate: 0 6px; } to { opacity: 1; translate: 0 0; } }
@keyframes kl-prompter-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes kl-prompter-shake { 0%, 100% { translate: 0 0; } 20% { translate: -3px 0; } 40% { translate: 3px 0; } 60% { translate: -2px 0; } 80% { translate: 1px 0; } }
@keyframes kl-prompter-pop { from { scale: .4; opacity: 0; } to { scale: 1; opacity: 1; } }
@keyframes kl-prompter-lift { to { translate: 0 -8px; opacity: 0; } }
@keyframes kl-prompter-land { 0% { scale: 1; } 35% { scale: 1.04; } 100% { scale: 1; } }
@keyframes kl-prompter-spin { to { rotate: 360deg; } }
@keyframes kl-prompter-breathe { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@keyframes kl-prompter-fly { 0% { offset-distance: 0%; opacity: 0; scale: .7; } 12% { opacity: 1; scale: 1; } 88% { opacity: 1; } 100% { offset-distance: 100%; opacity: 0; scale: .8; } }

@media (forced-colors: active) {
  .kl-prompter { border: 1px solid CanvasText; }
  .kl-prompter.is-link-target { outline: 3px solid Highlight; }
  .kl-prompter__field:focus-visible { outline: 2px solid Highlight; }
  .kl-prompter__attach { background: Highlight; }
}

/* ===== controls/windows.css ===== */
/* Klippan v2 · Controls · Floating windows, setting rows, Simulate menu, theme switch.
   Loaded after fallback-tokens.css, foundations, motion and controls.css. Uses the basic controls
   (.kl-btn, .kl-iconbtn, .kl-switch, .kl-select, .kl-seg, .kl-field, .kl-badge, .kl-dot, .kl-stepper,
   .kl-dialog, .kl-check) as they are and never restyles them. Every colour, shadow, radius, space, type
   and motion value is a --kl- token; pixel sizes that belong to one component are local properties.

   Source of truth: the step 10 board (Playground.dc.html + playground.css + floating.css). Windows are
   opaque like cards (glass stays for chrome), non-modal, open beside the card that opened them with a
   faint tether, drag by the title bar, snap to 8 px and minimise back into their card. */

/* Component-local spacing steps between the 4px scale's steps (EYEos uses 2, 6 and 10) */
.kl-win, .kl-setting-group, .kl-setting, .kl-simulate, .kl-theme {
  --kl-win-hair: 2px;
  --kl-win-tight: 6px;
  --kl-win-item-x: 10px;
}

/* =====================================================================================
   1. Window frame
   ===================================================================================== */
.kl-win {
  --kl-win-w: 440px;               /* settings 480, project 460, presets 440, alerts/requests/knowledge 400; wide 880 */
  --kl-win-max-h: 876px;
  --kl-win-bar-h: 44px;
  --kl-win-bar-pad-y: 6px;
  --kl-win-icon: 28px;
  --kl-win-from-x: 12px;           /* opens from its card's side: +12px card on the right, -12px on the left */
  --kl-win-origin: right center;   /* the side facing the card */
  --kl-win-to-x: 160px;            /* vector from the window to its card, for minimise and restore */
  --kl-win-to-y: 0px;
  position: relative;              /* on the board: position absolute, left/top/z-index set by the board */
  display: flex;
  flex-direction: column;
  width: var(--kl-win-w);
  max-width: 100%;
  max-height: var(--kl-win-max-h);
  background: var(--kl-color-surface);
  color: var(--kl-color-text);
  border-radius: var(--kl-radius-card);
  box-shadow: var(--kl-shadow-window);
  overflow: hidden;
  isolation: isolate;
  font: var(--kl-font-meta);
  font-family: var(--kl-font-sans);
  text-align: left;
  transform-origin: var(--kl-win-origin);
  transition: box-shadow var(--kl-motion-press) var(--kl-motion-ease-out);
  -webkit-font-smoothing: antialiased;
}
.kl-win *, .kl-win *::before, .kl-win *::after { box-sizing: border-box; }
.kl-win--settings { --kl-win-w: 480px; }
.kl-win--project  { --kl-win-w: 460px; }
.kl-win--presets  { --kl-win-w: 440px; }
.kl-win--alerts,
.kl-win--requests { --kl-win-w: 400px; }
.kl-win--inspector,
.kl-win--helper   { --kl-win-w: 380px; }
.kl-win--garbage  { --kl-win-w: 460px; }
.kl-win--knowledge { --kl-win-w: 400px; }
/* The one wide size, for windows that show a whole piece of work: agent workflows, a diff, the agent browser.
   Ordinary windows stay 380 to 480; there is no 720 or 780 any more. The browser and workflow classes resolve to it. */
.kl-win--wide,
.kl-win.kl-browser,
.kl-flow-win      { --kl-win-w: 880px; }
.kl-win--from-left { --kl-win-from-x: -12px; --kl-win-origin: left center; }

/* Stacking: the front window has the window shadow, the ones behind drop to the card shadow and a grey title */
.kl-win.is-front { box-shadow: var(--kl-shadow-window); }
.kl-win.is-back { box-shadow: var(--kl-shadow-card); }
.kl-win.is-back .kl-win__title { color: var(--kl-color-text-secondary); }
.kl-win.is-back .kl-win__icon { color: var(--kl-color-text-secondary); }
/* Dragging: lifted a little more; never scaled */
.kl-win.is-dragging { box-shadow: var(--kl-shadow-window-drag, 0 0 0 1px var(--kl-color-line-strong), var(--kl-shadow-window)); }
.kl-win.is-dragging .kl-win__bar { cursor: grabbing; }
.kl-win.is-minimized { display: none; }

/* Title bar: icon tile, title, scope tag, minimise and close */
.kl-win__bar {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  min-height: var(--kl-win-bar-h);
  padding: var(--kl-win-bar-pad-y) var(--kl-space-2) var(--kl-win-bar-pad-y) var(--kl-space-4);
  border-bottom: 1px solid var(--kl-color-line);
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
.kl-win__icon {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--kl-win-icon);
  height: var(--kl-win-icon);
  border-radius: var(--kl-radius-row);
  background: var(--kl-color-control-fill);
  color: var(--kl-color-text);
}
.kl-win__icon svg { width: 16px; height: 16px; }
.kl-win__icon--project { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
.kl-win__icon--researcher { background: color-mix(in srgb, var(--kl-color-helper-researcher) 18%, transparent); }
.kl-win__icon--builder { background: color-mix(in srgb, var(--kl-color-helper-builder) 18%, transparent); }
.kl-win__icon--cleanser { background: color-mix(in srgb, var(--kl-color-helper-cleanser) 18%, transparent); }
.kl-win__icon--researcher,
.kl-win__icon--builder,
.kl-win__icon--cleanser { border-radius: var(--kl-radius-pill); }
.kl-win__title {
  margin: 0;
  min-width: 0;
  font: var(--kl-font-headline);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kl-win__scope {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: var(--kl-win-tight);
  padding: var(--kl-win-hair) var(--kl-space-2);
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-neutral-soft);
  color: var(--kl-color-neutral-ink);
  font: var(--kl-font-badge);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.kl-win__scope--project { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
.kl-win__ctl { display: flex; align-items: center; gap: var(--kl-win-hair); margin-left: auto; flex: none; }

/* Body and footer */
.kl-win__body {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--kl-space-4);
  padding: var(--kl-space-4);
  overflow: auto;
  overscroll-behavior: contain;
}
.kl-win__body--tight { gap: var(--kl-space-2); }
.kl-win__foot {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--kl-space-2);
  padding: var(--kl-space-3) var(--kl-space-4);
  border-top: 1px solid var(--kl-color-line);
  background: var(--kl-color-surface-sunken);
}
.kl-win__note {
  flex: 1 1 160px;
  min-width: 0;
  margin: 0 auto 0 0;
  font: var(--kl-font-meta);
  color: var(--kl-color-text-secondary);
}

/* A confirm inside one window (Garbage's Empty trash): a veil over that window only, the board stays live */
.kl-win__veil {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--kl-space-4);
  border-radius: inherit;
  background: var(--kl-color-overlay);
  animation: kl-win-fade-in var(--kl-motion-press) var(--kl-motion-ease-out) both;
}

/* Keyboard focus inside a window */
.kl-win :where(button, [role="radio"], [role="option"]):focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }

/* -------- Motion: open from the card's side, minimise into the card, restore, close. No bounce on size. -------- */
@keyframes kl-win-open    { from { opacity: 0; transform: translateX(var(--kl-win-from-x)) scale(.94); } to { opacity: 1; transform: none; } }
@keyframes kl-win-restore { from { opacity: 0; transform: translate(var(--kl-win-to-x), var(--kl-win-to-y)) scale(.2); } to { opacity: 1; transform: none; } }
@keyframes kl-win-min     { 70% { opacity: .9; } to { opacity: 0; transform: translate(var(--kl-win-to-x), var(--kl-win-to-y)) scale(.2); } }
@keyframes kl-win-close   { to { opacity: 0; transform: scale(.97); } }
@keyframes kl-win-fade-in  { from { opacity: 0; } to { opacity: 1; } }
@keyframes kl-win-fade-out { to { opacity: 0; } }
.kl-win.is-opening    { animation: kl-win-open var(--kl-motion-expand) var(--kl-motion-ease-out) backwards; }
.kl-win.is-restoring  { animation: kl-win-restore var(--kl-motion-expand) var(--kl-motion-ease-out) backwards; }
.kl-win.is-minimizing { animation: kl-win-min var(--kl-motion-collapse) var(--kl-motion-ease-out) forwards; pointer-events: none; }
.kl-win.is-closing    { animation: kl-win-close var(--kl-motion-collapse) var(--kl-motion-ease-out) forwards; pointer-events: none; }
/* The body swaps (account to project, one helper to another) with a short fade */
.kl-win.is-swapping .kl-win__body { animation: kl-win-fade-in var(--kl-motion-reveal) var(--kl-motion-ease-out) both; }

/* Tether: a faint dotted line from a window back to the card that opened it, with a ring where it meets the card */
.kl-win-tether { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; z-index: 0; }
.kl-win-tether path { fill: none; stroke: var(--kl-color-line-strong); stroke-width: 1.5; stroke-dasharray: 3 4; stroke-linecap: round; }
.kl-win-tether circle { fill: var(--kl-color-surface); stroke: var(--kl-color-line-strong); stroke-width: 1.5; }
.kl-win-tether.is-back { opacity: .6; }

/* Snap guide: where the dragged window lands on the 8 px grid */
.kl-win-snap {
  position: absolute;
  pointer-events: none;
  border: 1px dashed var(--kl-color-selection);
  border-radius: var(--kl-radius-card);
  opacity: .6;
}

/* =====================================================================================
   2. Setting rows and groups (Settings, project settings, Alerts)
   ===================================================================================== */
.kl-setting-group { display: flex; flex-direction: column; gap: var(--kl-space-2); min-width: 0; }
.kl-setting-group__label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--kl-space-2);
  padding: 0 var(--kl-space-1);
  margin: 0;
  font: var(--kl-font-label-strong);
  letter-spacing: var(--kl-font-label-strong-tracking);
  color: var(--kl-color-text);
}
.kl-setting-group__box {
  display: flex;
  flex-direction: column;
  padding: 0 var(--kl-space-3);
  border-radius: var(--kl-radius-groupbox);
  background: var(--kl-color-surface);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
}
.kl-setting-group__note { margin: 0; padding: 0 var(--kl-space-1); font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }

.kl-setting {
  --kl-setting-min-h: 44px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--kl-space-3);
  min-height: var(--kl-setting-min-h);
  padding: var(--kl-space-2) 0;
  font: var(--kl-font-meta);
  color: var(--kl-color-text);
}
.kl-setting + .kl-setting { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-setting__text { display: flex; flex-direction: column; gap: var(--kl-win-hair); min-width: 96px; flex: 1 1 96px; }
.kl-setting__label { font: var(--kl-font-meta); color: var(--kl-color-text); }
.kl-setting__hint { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-setting__control { --kl-select-w: 88px; display: inline-flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--kl-space-1) var(--kl-space-2); flex: 0 1 auto; min-width: 0; }
.kl-setting__control .kl-field { width: var(--kl-setting-field-w, 180px); }
.kl-setting__value { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Where the value comes from, in a project's window: the account, or changed for this project */
.kl-setting__tag {
  display: inline-flex;
  align-items: center;
  padding: var(--kl-win-hair) var(--kl-space-2);
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-neutral-soft);
  color: var(--kl-color-neutral-ink);
  font: var(--kl-font-badge);
  white-space: nowrap;
}
.kl-setting__tag--changed { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
.kl-setting.is-disabled .kl-setting__label,
.kl-setting.is-disabled .kl-setting__value { color: var(--kl-color-text-tertiary); }
.kl-setting.is-disabled .kl-setting__control { opacity: .5; pointer-events: none; }
/* A row that is itself a button (open a sub-window, pick a preset) */
button.kl-setting { width: 100%; border: 0; background: transparent; font: var(--kl-font-meta); text-align: left; cursor: pointer; }
button.kl-setting:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: -2px; border-radius: var(--kl-radius-row); }

/* =====================================================================================
   3. Window contents
   ===================================================================================== */
/* Section heading inside a body: label on the left, a badge or quiet action on the right */
.kl-win-heading { display: flex; align-items: center; justify-content: space-between; gap: var(--kl-space-2); padding: 0 var(--kl-space-1); }
.kl-win-heading__label { margin: 0; font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); color: var(--kl-color-text); }

/* A rounded list box of rows (the same box as a setting group) */
.kl-win-list {
  display: flex;
  flex-direction: column;
  padding: 0 var(--kl-space-3);
  border-radius: var(--kl-radius-groupbox);
  background: var(--kl-color-surface);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
}
.kl-win-empty { margin: 0; padding: var(--kl-space-3) 0; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }

/* Marks: project square, helper discs */
.kl-win-mark { flex: none; display: inline-block; width: 10px; height: 10px; border-radius: 3px; background: var(--kl-color-primary); }
.kl-win-mark--lg { width: 14px; height: 14px; border-radius: 4px; }
.kl-win-mark--researcher { background: var(--kl-color-helper-researcher); border-radius: var(--kl-radius-pill); }
.kl-win-mark--builder { background: var(--kl-color-helper-builder); border-radius: var(--kl-radius-pill); }
.kl-win-mark--cleanser { background: var(--kl-color-helper-cleanser); border-radius: var(--kl-radius-pill); }

/* Account header in Settings */
.kl-win-account { display: flex; align-items: center; gap: var(--kl-space-3); min-width: 0; }
.kl-win-account__avatar {
  --kl-win-avatar: 44px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--kl-win-avatar);
  height: var(--kl-win-avatar);
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-primary);
  color: var(--kl-color-text-on-fill);
  font: var(--kl-font-title);
}
.kl-win-account__text { display: flex; flex-direction: column; min-width: 0; }
.kl-win-account__name { font: var(--kl-font-headline); }
.kl-win-account__meta { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }

/* Generic two-column item: text on the left, actions or a state on the right (files, findings, checks) */
.kl-win-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--kl-space-1) var(--kl-space-3);
  padding: var(--kl-space-3) 0;
  font: var(--kl-font-meta);
}
.kl-win-item + .kl-win-item { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-win-item__text { display: flex; flex-direction: column; gap: var(--kl-win-hair); min-width: 0; }
.kl-win-item__title { font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); color: var(--kl-color-text); }
.kl-win-item__path { font: var(--kl-font-meta); font-family: var(--kl-font-mono); color: var(--kl-color-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kl-win-item__sub { color: var(--kl-color-text-secondary); }
.kl-win-item__actions { display: inline-flex; align-items: center; gap: var(--kl-win-tight); flex-wrap: nowrap; }
.kl-win-item__state { display: inline-flex; align-items: center; gap: var(--kl-space-1); font: var(--kl-font-badge); white-space: nowrap; }
.kl-win-item__state svg { width: 14px; height: 14px; }
.kl-win-item__state--done { color: var(--kl-color-status-executing-ink); }
.kl-win-item__state--kept { color: var(--kl-color-text-secondary); }
.kl-win-item__state--waiting { color: var(--kl-color-status-planning-ink); }
.kl-win-item.is-settled .kl-win-item__path,
.kl-win-item.is-settled .kl-win-item__title { color: var(--kl-color-text-secondary); }

/* Inline notice with an Undo (given back, moved to archive) */
.kl-win-notice {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--kl-space-2);
  min-height: 36px;
  padding: var(--kl-space-1) var(--kl-space-1) var(--kl-space-1) var(--kl-space-3);
  border-radius: var(--kl-radius-menu);
  background: var(--kl-color-neutral-soft);
  color: var(--kl-color-text);
  font: var(--kl-font-meta);
}
.kl-win-notice--info { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
.kl-win-notice--ok { background: var(--kl-color-status-executing-soft); color: var(--kl-color-status-executing-ink); }
.kl-win-notice--stopped { background: var(--kl-color-status-stopped-soft); color: var(--kl-color-status-stopped-ink); }
.kl-win-notice .kl-btn--plain { color: inherit; }

/* ---- Presets: a radio list of presets, then the chosen preset's agents ---- */
.kl-win-preset {
  display: flex;
  align-items: center;
  gap: var(--kl-space-3);
  width: 100%;
  min-height: 44px;
  padding: var(--kl-space-2) 0;
  border: 0;
  background: transparent;
  color: var(--kl-color-text);
  font: var(--kl-font-meta);
  text-align: left;
  cursor: pointer;
}
.kl-win-preset + .kl-win-preset { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-win-preset__text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--kl-win-hair); }
.kl-win-preset__name { font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-win-preset__meta { color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-win-preset__aside { flex: none; color: var(--kl-color-text-secondary); white-space: nowrap; }
.kl-win-preset__check { display: none; align-items: center; gap: var(--kl-win-tight); flex: none; color: var(--kl-color-selection-ink); font: var(--kl-font-badge); }
.kl-win-preset__check svg { width: 14px; height: 14px; }
.kl-win-preset[aria-checked="true"] .kl-win-preset__check { display: inline-flex; }
.kl-win-preset[aria-checked="true"] .kl-win-preset__aside { display: none; }
.kl-win-preset[aria-checked="true"] .kl-win-preset__name { color: var(--kl-color-selection-ink); }
.kl-win-preset:hover .kl-win-preset__name,
.kl-win-preset.is-hover .kl-win-preset__name { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--kl-color-line-strong); }
.kl-win-preset:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: -2px; border-radius: var(--kl-radius-row); }

.kl-win-agents { display: flex; flex-direction: column; border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface-sunken); padding: var(--kl-space-1) var(--kl-space-3); }
.kl-win-agent {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  align-items: center;
  gap: var(--kl-space-2);
  min-height: 36px;
  font: var(--kl-font-meta);
}
.kl-win-agent + .kl-win-agent { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-win-agent__role { font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kl-win-agent__model { color: var(--kl-color-text-secondary); white-space: nowrap; }
.kl-win-agent__via {
  padding: 0 var(--kl-win-tight);
  border-radius: var(--kl-radius-control);
  box-shadow: inset 0 0 0 1px var(--kl-color-line-strong);
  color: var(--kl-color-text-secondary);
  font: var(--kl-font-caption);
}
.kl-win-agent__effort { color: var(--kl-color-text-secondary); font: var(--kl-font-badge); white-space: nowrap; }

/* ---- Alerts: stopped projects waiting for an acknowledgement ---- */
.kl-win-alert {
  display: grid;
  grid-template-columns: 10px minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--kl-win-hair) var(--kl-space-3);
  padding: var(--kl-space-3) 0;
  font: var(--kl-font-meta);
}
.kl-win-alert + .kl-win-alert { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-win-alert > .kl-dot { margin-top: var(--kl-space-1); }
.kl-win-alert__head { display: flex; align-items: baseline; gap: var(--kl-space-2); min-width: 0; }
.kl-win-alert__name { font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-win-alert__time { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.kl-win-alert__reason { grid-column: 2; color: var(--kl-color-text); }
.kl-win-alert__action { grid-column: 3; grid-row: 1 / span 2; align-self: center; }
.kl-win-alert__done { display: inline-flex; align-items: center; gap: var(--kl-space-1); color: var(--kl-color-text-secondary); font: var(--kl-font-badge); white-space: nowrap; }
.kl-win-alert__done svg { width: 14px; height: 14px; }
.kl-win-alert.is-acknowledged .kl-win-alert__reason { color: var(--kl-color-text-secondary); }

/* ---- Alerts: questions waiting on Alban, above the stopped projects ----
   Heading "Waiting on you" with a count in the approval tone (magenta: waiting on Alban, never stopped red).
   .kl-win-list.kl-win-questions holds one .kl-win-question per open ask: dot, project mark and name, how long it has
   waited, the question in one line, and a secondary Answer that opens the question card on the board.
   States: waiting (default) · answering now (.is-answering or aria-current="true": its card is open, .kl-card.is-asking
   on the board) · answered (.is-answered: grey, check, "Answered") · empty (.kl-win-empty in the list). */
.kl-win-questions__head .kl-win-heading__label { display: inline-flex; align-items: center; gap: var(--kl-space-2); }
.kl-win-questions__count.kl-badge--count { background: var(--kl-color-status-approval); color: var(--kl-color-text-on-fill); box-shadow: none; }
.kl-win-mark--p1 { background: var(--kl-color-project-1); }
.kl-win-mark--p2 { background: var(--kl-color-project-2); }
.kl-win-mark--p3 { background: var(--kl-color-project-3); }
.kl-win-mark--p4 { background: var(--kl-color-project-4); }
.kl-win-mark--p5 { background: var(--kl-color-project-5); }
.kl-win-mark--p6 { background: var(--kl-color-project-6); }
.kl-win-mark--p7 { background: var(--kl-color-project-7); }
.kl-win-mark--p8 { background: var(--kl-color-project-8); }
.kl-win-question {
  position: relative;
  display: grid;
  grid-template-columns: 10px minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--kl-win-hair) var(--kl-space-3);
  padding: var(--kl-space-3) 0;
  font: var(--kl-font-meta);
  transition: background-color var(--kl-motion-press) var(--kl-motion-ease-out), color var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-win-question + .kl-win-question { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-win-question > .kl-dot { --kl-dot: var(--kl-color-status-approval); margin-top: var(--kl-space-1); }
.kl-win-question__head { display: flex; align-items: center; gap: var(--kl-win-tight); min-width: 0; }
.kl-win-question__head .kl-win-mark { width: 8px; height: 8px; border-radius: 2.5px; }
.kl-win-question__project { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-win-question__time { flex: none; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.kl-win-question__ask { grid-column: 2; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--kl-color-text); }
.kl-win-question__action { grid-column: 3; grid-row: 1 / span 2; align-self: center; display: inline-flex; align-items: center; }
.kl-win-question__now,
.kl-win-question__done { display: inline-flex; align-items: center; gap: var(--kl-space-1); font: var(--kl-font-badge); white-space: nowrap; }
.kl-win-question__now { color: var(--kl-color-status-approval-ink); }
.kl-win-question__done { color: var(--kl-color-text-secondary); }
.kl-win-question__done svg { width: 14px; height: 14px; }
/* Answering now: its card is open on the board. A soft approval wash across the row (to the list's edges), no edge,
   no pulse; the action reads "Answering" in the approval ink. */
.kl-win-question.is-answering,
.kl-win-question[aria-current="true"] {
  margin: 0 calc(-1 * var(--kl-space-3));
  padding-inline: var(--kl-space-3);
  background: color-mix(in srgb, var(--kl-color-status-approval-soft) 70%, transparent);
}
.kl-win-question:first-child:is(.is-answering, [aria-current="true"]) { border-top-left-radius: var(--kl-radius-groupbox); border-top-right-radius: var(--kl-radius-groupbox); }
.kl-win-question:last-child:is(.is-answering, [aria-current="true"]) { border-bottom-left-radius: var(--kl-radius-groupbox); border-bottom-right-radius: var(--kl-radius-groupbox); }
.kl-win-question:is(.is-answering, [aria-current="true"]) .kl-win-question__project { color: var(--kl-color-status-approval-ink); }
/* Answered: grey, the dot goes idle, the check and "Answered" replace the button */
.kl-win-question.is-answered > .kl-dot { --kl-dot: var(--kl-color-status-idle); }
.kl-win-question.is-answered :is(.kl-win-question__project, .kl-win-question__ask) { color: var(--kl-color-text-secondary); }
.kl-win-question.is-answered .kl-win-mark { opacity: .5; }

/* ---- Requests: every request across projects; one is chosen and drawn on the board ---- */
.kl-win-request {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 20px;
  align-items: center;
  gap: var(--kl-win-hair) var(--kl-space-2);
  width: 100%;
  padding: var(--kl-space-2) var(--kl-space-3);
  border: 0;
  border-radius: var(--kl-radius-menu);
  background: var(--kl-color-surface);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
  color: var(--kl-color-text);
  font: var(--kl-font-meta);
  text-align: left;
  cursor: pointer;
  transition: box-shadow var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-win-request:hover, .kl-win-request.is-hover { box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
.kl-win-request__dir { display: flex; align-items: center; gap: var(--kl-win-tight); min-width: 0; font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-win-request__end { display: inline-flex; align-items: center; gap: var(--kl-space-1); min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kl-win-request__arrow { flex: none; width: 16px; height: 16px; color: var(--kl-color-text-secondary); }
.kl-win-request__note { grid-column: 1; color: var(--kl-color-text-secondary); }
.kl-win-request__check { grid-column: 2; grid-row: 1 / span 2; display: none; color: var(--kl-color-selection); }
.kl-win-request__check svg { width: 18px; height: 18px; }
/* Chosen: the selection edge, never a fill (same rule as .kl-selected) */
.kl-win-request[aria-pressed="true"], .kl-win-request.is-selected { box-shadow: inset 0 0 0 2px var(--kl-color-selection); }
.kl-win-request[aria-pressed="true"] .kl-win-request__arrow, .kl-win-request.is-selected .kl-win-request__arrow { color: var(--kl-color-selection-ink); }
.kl-win-request[aria-pressed="true"] .kl-win-request__check, .kl-win-request.is-selected .kl-win-request__check { display: inline-flex; }
.kl-win-request:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-win-requests { display: flex; flex-direction: column; gap: var(--kl-win-tight); }

/* ---- Request inspector ---- */
.kl-win-flow { display: grid; grid-template-columns: minmax(0, 1fr) 72px minmax(0, 1fr); align-items: center; gap: var(--kl-space-2); padding: var(--kl-space-3); border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface-sunken); }
.kl-win-flow__end { display: flex; flex-direction: column; align-items: center; gap: var(--kl-win-tight); min-width: 0; text-align: center; font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-win-flow__end small { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-win-flow__arrow { width: 72px; height: 28px; color: var(--kl-color-selection); overflow: visible; }
.kl-win-flow__arrow path { fill: none; stroke: currentColor; stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.kl-win-dl { display: grid; grid-template-columns: 88px minmax(0, 1fr); gap: var(--kl-space-2) var(--kl-space-3); margin: 0; font: var(--kl-font-meta); }
.kl-win-dl dt { font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); color: var(--kl-color-text); }
.kl-win-dl dd { margin: 0; color: var(--kl-color-text-secondary); min-width: 0; }

/* ---- Helper detail: Researcher, Agent Builder, File Cleanser ---- */
.kl-win-status { display: flex; flex-wrap: wrap; align-items: center; gap: var(--kl-win-tight); }
.kl-win-now { display: flex; flex-direction: column; gap: var(--kl-space-1); padding: var(--kl-space-3); border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface-sunken); }
.kl-win-now__label { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-win-now__text { font: var(--kl-font-meta); color: var(--kl-color-text); }
.kl-win-now__bar { position: relative; height: 3px; margin-top: var(--kl-space-1); border-radius: var(--kl-radius-pill); background: var(--kl-color-line); overflow: hidden; }
.kl-win-now__bar::after { content: ""; position: absolute; inset: 0 auto 0 0; width: var(--kl-win-now, 40%); border-radius: inherit; background: var(--kl-color-helper-researcher); }
.kl-win-blurb { margin: 0; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }

/* ---- Knowledge (.kl-win--knowledge, 400): search, filter chips, then entries. A skill entry has a Try it field. ---- */
.kl-win-kn { display: flex; flex-direction: column; gap: var(--kl-space-3); min-width: 0; }
.kl-win-kn__filters { display: flex; flex-wrap: wrap; gap: var(--kl-win-tight); }
.kl-win-kn__entry {
  display: flex;
  flex-direction: column;
  gap: var(--kl-win-item-x);
  padding: var(--kl-space-3);
  border-radius: var(--kl-radius-groupbox);
  background: var(--kl-color-surface);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
}
.kl-win-kn__head { display: flex; align-items: center; gap: var(--kl-win-item-x); min-width: 0; }
.kl-win-kn__mono {
  --kl-win-kn-mono: 36px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--kl-win-kn-mono);
  height: var(--kl-win-kn-mono);
  border-radius: var(--kl-radius-tile);
  background: var(--kl-color-teach-soft);
  color: var(--kl-color-teach-ink);
  font: var(--kl-font-headline);
}
.kl-win-kn__title { display: flex; flex-direction: column; min-width: 0; }
.kl-win-kn__kind { font: var(--kl-font-badge); font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-teach-ink); text-transform: uppercase; letter-spacing: .04em; }
.kl-win-kn__name { font: var(--kl-font-headline); color: var(--kl-color-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kl-win-kn__entry .kl-win-dl dt { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-win-kn__entry .kl-win-dl dd { color: var(--kl-color-text); overflow-wrap: anywhere; }
.kl-win-kn__entry .kl-win-dl { gap: var(--kl-space-1) var(--kl-win-item-x); }
.kl-win-kn__try { display: flex; align-items: center; gap: var(--kl-win-tight); min-width: 0; }
.kl-win-kn__try .kl-field { flex: 1 1 auto; min-width: 0; }
.kl-win-kn__result { display: flex; align-items: center; gap: var(--kl-space-2); margin: 0; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-win-kn__result svg { flex: none; width: 16px; height: 16px; color: var(--kl-color-teach-ink); }
.kl-win-kn__entry.is-trying .kl-win-kn__result { color: var(--kl-color-text); }

/* =====================================================================================
   4. Simulate: a card on the board that opens a menu of scripted moments
   ===================================================================================== */
.kl-simulate {
  --kl-simulate-w: 212px;
  --kl-simulate-menu-w: 320px;
  --kl-simulate-tile: 36px;
  position: relative;
  display: inline-block;
  font-family: var(--kl-font-sans);
}
.kl-simulate__card {
  position: relative;
  display: grid;
  grid-template-columns: var(--kl-simulate-tile) minmax(0, 1fr);
  align-items: center;
  gap: var(--kl-win-hair) var(--kl-space-3);
  width: var(--kl-simulate-w);
  min-height: 72px;
  padding: var(--kl-space-3) var(--kl-space-4) var(--kl-space-3) var(--kl-space-3);
  border: 0;
  border-radius: var(--kl-radius-panel);
  background: var(--kl-color-surface);
  box-shadow: var(--kl-shadow-card);
  color: var(--kl-color-text);
  font: var(--kl-font-meta);
  text-align: left;
  cursor: pointer;
  transition: box-shadow var(--kl-motion-press) var(--kl-motion-ease-out), scale var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-simulate__card:hover, .kl-simulate__card.is-hover { box-shadow: var(--kl-shadow-card-hover); }
.kl-simulate__card:active, .kl-simulate__card.is-pressed { scale: .98; }
.kl-simulate__card:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 3px; }
.kl-simulate__tile {
  grid-row: 1 / span 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--kl-simulate-tile);
  height: var(--kl-simulate-tile);
  border-radius: var(--kl-radius-row);
  background: var(--kl-color-control-fill);
  color: var(--kl-color-text);
}
.kl-simulate__tile svg { width: 18px; height: 18px; }
.kl-simulate__name { font: var(--kl-font-headline); }
.kl-simulate__meta { display: flex; align-items: center; gap: var(--kl-win-tight); min-width: 0; color: var(--kl-color-text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Open: the card wears the selection edge while its menu is up */
.kl-simulate__card[aria-expanded="true"], .kl-simulate.is-open .kl-simulate__card { box-shadow: 0 0 0 2px var(--kl-color-selection), var(--kl-shadow-card); }
.kl-simulate__card[aria-expanded="true"] .kl-simulate__tile, .kl-simulate.is-open .kl-simulate__tile { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
/* Running: a story is playing; the meta names it, a blue dot breathes, the menu offers Stop */
.kl-simulate.is-running .kl-simulate__tile { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
.kl-simulate.is-running .kl-simulate__meta { color: var(--kl-color-selection-ink); }
.kl-simulate__dot { flex: none; width: 8px; height: 8px; border-radius: var(--kl-radius-pill); background: var(--kl-color-selection); animation: kl-simulate-breathe calc(var(--kl-motion-expand) * 5) ease-in-out infinite; }
@keyframes kl-simulate-breathe { 50% { opacity: .35; } }

/* The menu opens to the card's left (to its bottom when there is no room). Opaque, so cards never show through. */
.kl-simulate__menu {
  position: absolute;
  top: 0;
  right: calc(100% + var(--kl-space-3));
  z-index: 80;
  display: flex;
  flex-direction: column;
  gap: var(--kl-win-hair);
  width: var(--kl-simulate-menu-w);
  padding: var(--kl-win-tight);
  border-radius: var(--kl-radius-menu);
  background: var(--kl-color-surface);
  box-shadow: var(--kl-shadow-menu);
  color: var(--kl-color-text);
  transform-origin: top right;
  animation: kl-simulate-in var(--kl-motion-press) var(--kl-motion-ease-out) both;
}
.kl-simulate__menu--below { top: calc(100% + var(--kl-space-2)); right: 0; }
.kl-simulate__menu.is-closing { pointer-events: none; animation: kl-simulate-out var(--kl-motion-fade-out) var(--kl-motion-ease-in) forwards; }
.kl-simulate__menu.is-static { position: relative; top: auto; right: auto; animation: none; }
@keyframes kl-simulate-in  { from { opacity: 0; transform: translateY(-4px) scale(.96); } to { opacity: 1; transform: none; } }
@keyframes kl-simulate-out { to { opacity: 0; transform: translateY(-2px) scale(.98); } }
.kl-simulate__head { padding: var(--kl-win-tight) var(--kl-win-item-x) var(--kl-space-1); font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-simulate__item {
  display: flex;
  align-items: flex-start;
  gap: var(--kl-win-item-x);
  width: 100%;
  min-height: 36px;
  padding: var(--kl-space-2) var(--kl-win-item-x);
  border: 0;
  border-radius: var(--kl-radius-row);
  background: transparent;
  color: var(--kl-color-text);
  font: var(--kl-font-meta);
  text-align: left;
  cursor: pointer;
}
.kl-simulate__item > svg { flex: none; width: 16px; height: 16px; margin-top: var(--kl-win-hair); }
.kl-simulate__body { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.kl-simulate__title { font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-simulate__sub { color: var(--kl-color-text-secondary); }
.kl-simulate__item:hover, .kl-simulate__item.is-hover, .kl-simulate__item:focus-visible { background: var(--kl-color-selection); color: var(--kl-color-text-on-fill); outline: 0; }
.kl-simulate__item:hover .kl-simulate__sub, .kl-simulate__item.is-hover .kl-simulate__sub, .kl-simulate__item:focus-visible .kl-simulate__sub { color: var(--kl-color-text-on-fill); opacity: .85; }
.kl-simulate__item:disabled, .kl-simulate__item.is-disabled { color: var(--kl-color-text-tertiary); cursor: default; background: transparent; }
.kl-simulate__item:disabled .kl-simulate__sub, .kl-simulate__item.is-disabled .kl-simulate__sub { color: var(--kl-color-text-tertiary); opacity: 1; }
.kl-simulate__item.is-running .kl-simulate__title { color: var(--kl-color-selection-ink); }
.kl-simulate__item.is-running:hover .kl-simulate__title, .kl-simulate__item.is-running.is-hover .kl-simulate__title { color: var(--kl-color-text-on-fill); }
.kl-simulate__badge { flex: none; align-self: center; display: inline-flex; align-items: center; gap: var(--kl-space-1); font: var(--kl-font-badge); color: var(--kl-color-selection-ink); }
.kl-simulate__item:hover .kl-simulate__badge, .kl-simulate__item.is-hover .kl-simulate__badge { color: var(--kl-color-text-on-fill); }
.kl-simulate__sep { height: 1px; margin: var(--kl-space-1) var(--kl-win-tight); background: var(--kl-color-line); }

/* =====================================================================================
   5. Theme switch: two options on the Klippan card, a knob slides across, the active icon turns a little
   ===================================================================================== */
.kl-theme {
  --kl-theme-icon: 14px;
  --kl-theme-pad: 2px;
  position: relative;
  isolation: isolate;
  display: inline-flex;
  padding: var(--kl-theme-pad);
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-control-fill);
}
.kl-theme::before {
  content: "";
  position: absolute;
  z-index: 0;
  top: var(--kl-theme-pad);
  bottom: var(--kl-theme-pad);
  left: var(--kl-theme-pad);
  width: calc(50% - var(--kl-theme-pad));
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-surface);
  box-shadow: var(--kl-shadow-knob);
  transition: translate var(--kl-motion-expand) var(--kl-motion-spring-pop);
}
.kl-theme:has(> .kl-theme__opt:last-child[aria-checked="true"])::before,
.kl-theme.is-dark::before { translate: 100% 0; }
.kl-theme__opt {
  position: relative;
  z-index: 1;
  flex: 1 1 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  height: calc(var(--kl-size-button) - 2 * var(--kl-theme-pad));
  padding: 0 var(--kl-space-2);
  border: 0;
  border-radius: var(--kl-radius-pill);
  background: transparent;
  color: var(--kl-color-text-secondary);
  cursor: pointer;
  transition: color var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-theme__opt svg { width: var(--kl-theme-icon); height: var(--kl-theme-icon); transition: rotate var(--kl-motion-hover) var(--kl-motion-spring-pop); }
.kl-theme__opt:hover, .kl-theme__opt.is-hover { color: var(--kl-color-text); }
.kl-theme__opt[aria-checked="true"] { color: var(--kl-color-text); }
.kl-theme__opt[aria-checked="true"] svg { rotate: -20deg; }
.kl-theme__opt:active svg, .kl-theme__opt.is-pressed svg { rotate: -35deg; }
.kl-theme__opt:focus-visible, .kl-theme__opt.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 1px; }

/* =====================================================================================
   Reduced motion: fades only. High contrast: real edges.
   ===================================================================================== */
@media (prefers-reduced-motion: reduce) {
  .kl-win.is-opening, .kl-win.is-restoring { animation: kl-win-fade-in var(--kl-motion-press) ease backwards; }
  .kl-win.is-closing, .kl-win.is-minimizing { animation: kl-win-fade-out var(--kl-motion-fade-out) ease forwards; }
  .kl-win, .kl-win-request, .kl-win-question, .kl-simulate__card { transition: none; }
  .kl-simulate__card:active, .kl-simulate__card.is-pressed { scale: none; }
  .kl-simulate__menu { animation: kl-win-fade-in var(--kl-motion-press) ease both; }
  .kl-simulate__menu.is-closing { animation: kl-win-fade-out var(--kl-motion-fade-out) ease forwards; }
  .kl-simulate__dot { animation: none; }
  .kl-theme::before, .kl-theme__opt svg { transition: none; }
}
/* The app's own switch: .kl-motion-reduce on any ancestor gets the same treatment as the OS setting.
   Windows keep their fades and lose every scale and slide. */
.kl-motion-reduce .kl-win.is-opening, .kl-motion-reduce .kl-win.is-restoring { animation: kl-win-fade-in var(--kl-motion-press) ease backwards; }
.kl-motion-reduce .kl-win.is-closing, .kl-motion-reduce .kl-win.is-minimizing { animation: kl-win-fade-out var(--kl-motion-fade-out) ease forwards; }
.kl-motion-reduce :is(.kl-win, .kl-win-request, .kl-win-question, .kl-simulate__card) { transition: none; }
.kl-motion-reduce :is(.kl-simulate__card:active, .kl-simulate__card.is-pressed) { scale: none; }
.kl-motion-reduce .kl-simulate__menu:not(.is-static) { animation: kl-win-fade-in var(--kl-motion-press) ease both; }
.kl-motion-reduce .kl-simulate__menu.is-closing { animation: kl-win-fade-out var(--kl-motion-fade-out) ease forwards; }
.kl-motion-reduce .kl-simulate__dot { animation: none; }
.kl-motion-reduce .kl-theme::before, .kl-motion-reduce .kl-theme__opt svg { transition: none; }
@media (prefers-contrast: more) {
  .kl-win, .kl-simulate__card, .kl-simulate__menu { box-shadow: 0 0 0 1px var(--kl-color-text-secondary), var(--kl-shadow-window); }
  .kl-setting-group__box, .kl-win-list, .kl-win-request { box-shadow: inset 0 0 0 1px var(--kl-color-text-secondary); }
}
@media (forced-colors: active) {
  .kl-win, .kl-simulate__card, .kl-simulate__menu, .kl-win-request, .kl-setting-group__box, .kl-win-list { border: 1px solid CanvasText; }
  .kl-win.is-front { outline: 2px solid Highlight; }
  .kl-win-question:is(.is-answering, [aria-current="true"]) { outline: 2px solid Highlight; outline-offset: -2px; }
  .kl-win-questions__count { border: 1px solid CanvasText; }
  .kl-win-request[aria-pressed="true"], .kl-win-request.is-selected { outline: 3px solid Highlight; }
  .kl-theme::before { border: 1px solid Highlight; }
}

/* ===== harness/prompter/prompter-additions.css ===== */
/* build.py: 59 rules this file shares word for word with question-card are kept once, in question-card's section below. */
/* Klippan master design system, harness part 9: prompter additions
   Five things a harness needs in the prompter, built on v2's prompter (klippan-v2/controls/prompter.css) without
   editing it: the permission-mode control, attachment chips (and the drop-target state), the / menu, Stop, and the
   queued-notes chip. Load after klippan-v2/combined/klippan.css.

   Scope: everything that changes v2's prompter layout sits under .kl-prompter--harness, so the v2 prompter still looks
   exactly as before. When the assembly merges this into v2, .kl-prompter--harness becomes the default.

   Root additions:  .kl-prompter--harness             the bar becomes: + · destination · status · mode · model · (stop) · send
                    .is-running                        the destination's agents are working: model hides, Stop shows
                    .is-drop-target                    a file or card is held over the prompter
                    .has-queue                         notes are queued (the model button steps aside)
   New pieces:      .kl-prompter__plus                 add a file, link or card
                    .kl-prompter__mode (--always --risky --plan --free, --quiet)   permission mode, opens a .kl-menu
                    .kl-prompter__chips > .kl-attach (--file --link --image --card --command --skill)
                    .kl-prompter__drop                 the drop-target overlay
                    .kl-slash                          the / menu (commands, skills, saved prompts in one list)
                    .kl-prompter__stop (--side)        Stop while running
                    .kl-qchip, .kl-queue               queued notes: the chip in the status slot and its list
                    .kl-badge--mode (--free)           mode badge for a run row (the Runs part places it)
                    .is-answering, .kl-ask-strip, .kl-ask-chip, .kl-ask-pending   open questions (the question card's markup)

   Rules: Send (or Queue while running) is the only blue button. Run freely is the only mode drawn in red, and
   choosing it opens a confirm with Cancel first. Removing a chip or a queued note ends on v2's Undo toast.
   Motion: chips arrive on a small pop that scales with the dial (--kl-motion-k); the queued count bumps when it
   changes; nothing here moves on its own. Reduced motion (the media query, or .kl-motion-reduce on any ancestor):
   fades only. */

/* ---------- Bar layout ---------- */
.kl-prompter--harness {
  --kl-prompter-chip-h: 28px;
  --kl-prompter-stop: var(--kl-prompter-send, 32px);
  grid-template-rows: auto auto auto;
}
/* The bar under the draft becomes a wrapping flex row: the draft takes the first line, the controls the second. */
.kl-prompter--harness .kl-prompter__compose {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: var(--kl-space-2);
  row-gap: var(--kl-space-2);
}
.kl-prompter--harness .kl-prompter__field {
  flex: 1 0 100%;
  height: var(--kl-prompter-field-h);
  transition:
    height var(--kl-motion-collapse) var(--kl-motion-ease-out),
    border-color var(--kl-motion-press) ease,
    box-shadow var(--kl-motion-press) ease,
    color var(--kl-motion-press) ease;
}
.kl-prompter--harness.is-expanded .kl-prompter__field { height: var(--kl-prompter-field-h-open); transition-duration: var(--kl-motion-expand); }
.kl-prompter--harness .kl-prompter__dest { flex: 0 1 auto; min-width: 0; max-width: 140px; }
.kl-prompter--harness .kl-prompter__status { flex: 1 1 0; min-width: 0; justify-content: flex-end; }
.kl-prompter--harness.is-expanded .kl-prompter__status { justify-content: flex-start; }
.kl-prompter--harness .kl-prompter__model,
.kl-prompter--harness .kl-prompter__send { flex: none; }
/* While running the model can't change mid-run, so its button steps aside for Stop; it also steps aside while notes
   are queued after a stop, so the queued chip has room */
.kl-prompter--harness.is-running .kl-prompter__model,
.kl-prompter--harness.has-queue .kl-prompter__model { display: none; }

/* ---------- + (add a file, a link or a card) ---------- */
.kl-prompter__plus {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--kl-color-control-fill);
  color: var(--kl-color-text-secondary);
  cursor: pointer;
  transition: background-color var(--kl-motion-press) ease, color var(--kl-motion-press) ease, scale var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-prompter__plus::before { content: ""; position: absolute; inset: -8px; border-radius: 50%; } /* 44px hit area */
.kl-prompter__plus svg { width: 16px; height: 16px; transition: rotate var(--kl-motion-hover) var(--kl-motion-spring-pop); }
.kl-prompter__plus:hover, .kl-prompter__plus.is-hover { background: var(--kl-color-button-secondary); color: var(--kl-color-text); }
.kl-prompter__plus:active, .kl-prompter__plus.is-pressed { background: var(--kl-color-control-fill-pressed); scale: .94; }
.kl-prompter__plus:focus-visible, .kl-prompter__plus.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-prompter__plus[aria-expanded="true"] { background: var(--kl-color-control-fill-pressed); color: var(--kl-color-text); }
.kl-prompter__plus[aria-expanded="true"] svg { rotate: 45deg; }

/* ---------- Permission mode ---------- */
/* How much the destination's agents may do without asking. A 28px pill beside the model button, so the two "how it
   runs" settings sit together next to Send. Four modes, ordered from most asking to least:

     --always  Ask always    hand        asks before every edit and every command
     --risky   Ask if risky  auto        the default: edits and safe commands on its own, asks before risky steps
     --plan    Plan first    plan        changes nothing until you OK its plan, then works as Ask if risky
     --free    Run freely    warning     never asks. The one red mode, and it always confirms first

   At a glance: the default reads quiet (secondary ink), any other mode reads in full ink, and Run freely is red.
   The pill always shows the icon and the name; --quiet folds it to the icon for a narrow prompter (name in the
   tooltip and for screen readers). Old names stay as aliases until the assembly updates: --auto = --risky,
   --full = --free. */
.kl-prompter__mode {
  --kl-mode-bg: var(--kl-color-control-fill);
  --kl-mode-ink: var(--kl-color-text);
  --kl-mode-icon: var(--kl-color-text);
  flex: none;
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 28px;
  padding: 0 var(--kl-space-3) 0 var(--kl-space-2);
  border: 0;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-mode-bg);
  color: var(--kl-mode-ink);
  font: var(--kl-font-label);
  font-family: var(--kl-font-sans);
  white-space: nowrap;
  cursor: pointer;
  overflow: clip;
  overflow-clip-margin: 8px;
  interpolate-size: allow-keywords; /* the width glides when the pill folds to its icon or opens out again */
  transition:
    background-color var(--kl-motion-press) ease,
    color var(--kl-motion-press) ease,
    box-shadow var(--kl-motion-press) ease,
    width var(--kl-motion-hover) var(--kl-motion-spring),
    scale var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-prompter__mode::before { content: ""; position: absolute; inset: -8px 0; } /* 44px hit area */
.kl-prompter__mode svg { flex: none; width: 15px; height: 15px; color: var(--kl-mode-icon); }
.kl-prompter__mode-label { display: inline-block; }
.kl-prompter__mode:hover, .kl-prompter__mode.is-hover { --kl-mode-bg: var(--kl-color-button-secondary); }
.kl-prompter__mode:active, .kl-prompter__mode.is-pressed { --kl-mode-bg: var(--kl-color-control-fill-pressed); scale: .97; }
.kl-prompter__mode:focus-visible, .kl-prompter__mode.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-prompter__mode[aria-expanded="true"], .kl-prompter__mode.is-open { --kl-mode-bg: var(--kl-color-control-fill-pressed); }
/* The default reads quiet, so a pill in full ink always means "not the usual" */
.kl-prompter__mode--risky, .kl-prompter__mode--auto { --kl-mode-ink: var(--kl-color-text-secondary); --kl-mode-icon: var(--kl-color-text-secondary); }
.kl-prompter__mode--risky:hover, .kl-prompter__mode--auto:hover { --kl-mode-ink: var(--kl-color-text); }
/* Run freely: stopped soft fill, stopped ink and a faint red edge, so it can never be missed */
.kl-prompter__mode--free, .kl-prompter__mode--full {
  --kl-mode-bg: var(--kl-color-status-stopped-soft);
  --kl-mode-ink: var(--kl-color-status-stopped-ink);
  --kl-mode-icon: var(--kl-color-status-stopped-ink);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--kl-color-status-stopped) 40%, transparent);
}
:is(.kl-prompter__mode--free, .kl-prompter__mode--full):is(:hover, .is-hover, [aria-expanded="true"], .is-open) { --kl-mode-bg: color-mix(in srgb, var(--kl-color-status-stopped) 22%, var(--kl-color-surface)); }
/* Quiet: icon only, for a narrow prompter. The name stays in the tooltip and for screen readers. */
.kl-prompter__mode--quiet { width: 28px; padding: 0; justify-content: center; }
.kl-prompter__mode--quiet .kl-prompter__mode-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* Switching: the menu closes, the new icon turns in and the new name rolls up into the pill, then the pill lands once. Amplitudes scale with the dial; at 0 it is a plain fade. */
.kl-prompter__mode.is-changed { animation: kl-pa-bump var(--kl-motion-count-bump) var(--kl-motion-ease-out); }
.kl-prompter__mode.is-changed .kl-prompter__mode-label { animation: kl-pm-roll var(--kl-motion-hover) var(--kl-motion-spring) both; }
.kl-prompter__mode.is-changed svg { animation: kl-pm-turn var(--kl-motion-hover) var(--kl-motion-spring-pop) both; }

/* The mode menu: v2's .kl-menu, opening upward from the pill */
.kl-modemenu { --kl-menu-w: 300px; --kl-menu-origin: bottom right; max-width: 300px; }
.kl-modemenu:focus { outline: none; }
.kl-modemenu .kl-menu__item { min-height: 48px; align-items: center; gap: 10px; padding-top: 6px; padding-bottom: 6px; }
.kl-modemenu .kl-menu__item > svg { width: 16px; height: 16px; }
.kl-modemenu .kl-menu__text { flex: 1 1 auto; min-width: 0; }
.kl-modemenu .kl-menu__desc { display: block; white-space: normal; }
.kl-modemenu .kl-menu__shortcut { align-self: center; }
/* "Default" beside the mode new projects start on */
.kl-modemenu__name { display: flex; align-items: baseline; }
.kl-modemenu__tag { margin-left: 6px; color: var(--kl-color-text-secondary); font: var(--kl-font-caption); font-weight: 400; }
.kl-menu__item:is(:hover, :focus-visible, .is-active) .kl-modemenu__tag { color: var(--kl-color-text-on-fill); }
.kl-modemenu__foot {
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  padding: 6px 10px 4px;
  border-top: 1px solid var(--kl-color-line);
  margin-top: 4px;
  color: var(--kl-color-text-secondary);
  font: var(--kl-font-caption);
}

/* Mode badge for a run row (the Runs part places it). Outline for every mode but Run freely. */
.kl-badge--mode { background: transparent; color: var(--kl-color-text-secondary); box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
.kl-badge--mode svg { width: 12px; height: 12px; }
.kl-badge--mode:is(.kl-badge--free, .kl-badge--full) { background: var(--kl-color-status-stopped-soft); color: var(--kl-color-status-stopped-ink); box-shadow: none; }

/* ---------- Attachment chips ---------- */
/* A row above the draft, inside the prompter. Wraps to a second line; the prompter grows upward. */
.kl-prompter__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  min-width: 0;
  margin: 0 0 var(--kl-space-2);
  padding: 0;
  list-style: none;
}
.kl-prompter__chips:empty { display: none; }
.kl-prompter__chips > li { display: contents; }

.kl-attach {
  --kl-attach-bg: var(--kl-color-surface-sunken);
  --kl-attach-ring: var(--kl-color-line);
  --kl-attach-thumb: var(--kl-color-control-fill);
  --kl-attach-thumb-ink: var(--kl-color-text-secondary);
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 220px;
  height: var(--kl-prompter-chip-h, 28px);
  padding: 0 3px 0 4px;
  border-radius: var(--kl-radius-groupbox);
  background: var(--kl-attach-bg);
  box-shadow: inset 0 0 0 1px var(--kl-attach-ring);
  color: var(--kl-color-text);
  font: var(--kl-font-label);
  white-space: nowrap;
  overflow: hidden;
  transition: box-shadow var(--kl-motion-press) ease, background-color var(--kl-motion-press) ease, opacity var(--kl-motion-fade-out) ease;
}
.kl-attach:hover, .kl-attach.is-hover { --kl-attach-ring: var(--kl-color-line-strong); }
.kl-attach:focus-within, .kl-attach.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 1px; }
.kl-attach__thumb {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 5px;
  background: var(--kl-attach-thumb);
  color: var(--kl-attach-thumb-ink);
}
.kl-attach__thumb svg { width: 14px; height: 14px; }
.kl-attach__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.kl-attach__meta { flex: none; color: var(--kl-color-text-secondary); font: var(--kl-font-caption); font-variant-numeric: tabular-nums; }
.kl-attach__remove {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 20px;
  height: 20px;
  margin-left: -1px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--kl-color-text-secondary);
  cursor: pointer;
  transition: background-color var(--kl-motion-press) ease, color var(--kl-motion-press) ease;
}
.kl-attach__remove::before { content: ""; position: absolute; inset: -8px -4px; border-radius: 50%; }
.kl-attach__remove svg { width: 12px; height: 12px; --kl-icon-stroke: 2; }
.kl-attach__remove:hover, .kl-attach__remove.is-hover { background: var(--kl-color-control-fill-pressed); color: var(--kl-color-text); }
.kl-attach__remove:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 0; }

/* Kinds */
.kl-attach--link .kl-attach__thumb { --kl-attach-thumb: var(--kl-color-selection-soft); --kl-attach-thumb-ink: var(--kl-color-selection-ink); }
/* Image: a tiny preview. The specimen shows the image icon on the hue; the app puts the picture in __thumb as an <img>. */
.kl-attach--image .kl-attach__thumb { --kl-attach-thumb: var(--kl-color-project-3-soft); --kl-attach-thumb-ink: var(--kl-color-project-3-ink); }
.kl-attach__thumb img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
/* Card: tinted with the card's own glass and its project mark, so it reads as that card */
.kl-attach--card {
  --kl-attach-bg: var(--kl-attach-card-glass, var(--kl-glass-card-project-1));
  -webkit-backdrop-filter: var(--kl-glass-card-filter);
  backdrop-filter: var(--kl-glass-card-filter);
}
.kl-attach--card .kl-attach__thumb { --kl-attach-thumb: transparent; }
.kl-attach__mark { width: 9px; height: 9px; border-radius: 2.5px; background: var(--kl-attach-mark, var(--kl-color-project-1)); }
/* The card's project: --p1 to --p8 (default p1) */
.kl-attach--p1 { --kl-attach-card-glass: var(--kl-glass-card-project-1); --kl-attach-mark: var(--kl-color-project-1); }
.kl-attach--p2 { --kl-attach-card-glass: var(--kl-glass-card-project-2); --kl-attach-mark: var(--kl-color-project-2); }
.kl-attach--p3 { --kl-attach-card-glass: var(--kl-glass-card-project-3); --kl-attach-mark: var(--kl-color-project-3); }
.kl-attach--p4 { --kl-attach-card-glass: var(--kl-glass-card-project-4); --kl-attach-mark: var(--kl-color-project-4); }
.kl-attach--p5 { --kl-attach-card-glass: var(--kl-glass-card-project-5); --kl-attach-mark: var(--kl-color-project-5); }
.kl-attach--p6 { --kl-attach-card-glass: var(--kl-glass-card-project-6); --kl-attach-mark: var(--kl-color-project-6); }
.kl-attach--p7 { --kl-attach-card-glass: var(--kl-glass-card-project-7); --kl-attach-mark: var(--kl-color-project-7); }
.kl-attach--p8 { --kl-attach-card-glass: var(--kl-glass-card-project-8); --kl-attach-mark: var(--kl-color-project-8); }
/* Command and skill: they change what the agent does, so they read as settings rather than files */
.kl-attach--command, .kl-attach--skill {
  --kl-attach-bg: var(--kl-color-selection-soft);
  --kl-attach-ring: transparent;
  color: var(--kl-color-selection-ink);
}
.kl-attach--command .kl-attach__thumb, .kl-attach--skill .kl-attach__thumb { --kl-attach-thumb: transparent; --kl-attach-thumb-ink: var(--kl-color-selection-ink); }
.kl-attach--command .kl-attach__name { font-family: var(--kl-font-mono); font-weight: var(--kl-font-weight-medium); }
.kl-attach--command .kl-attach__meta, .kl-attach--skill .kl-attach__meta { color: var(--kl-color-selection-ink); opacity: .8; }
.kl-attach--command .kl-attach__remove, .kl-attach--skill .kl-attach__remove { color: var(--kl-color-selection-ink); }

/* States */
/* Reading: the file is being read into the draft. A thin line fills along the chip's bottom (--kl-attach-progress). */
.kl-attach.is-reading .kl-attach__name { color: var(--kl-color-text-secondary); }
.kl-attach__progress {
  position: absolute;
  left: 6px;
  right: 6px;
  bottom: 2px;
  height: 2px;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-control-fill);
  overflow: hidden;
  pointer-events: none;
}
.kl-attach__progress::after {
  content: "";
  display: block;
  width: var(--kl-attach-progress, 30%);
  height: 100%;
  border-radius: inherit;
  background: var(--kl-color-selection);
  transition: width var(--kl-motion-hover) var(--kl-motion-ease-out);
}
/* Failed: red edge, the reason in the meta, Retry beside remove */
.kl-attach.is-failed { max-width: 300px; --kl-attach-bg: var(--kl-color-status-stopped-soft); --kl-attach-ring: color-mix(in srgb, var(--kl-color-status-stopped) 45%, transparent); }
.kl-attach.is-failed .kl-attach__thumb { --kl-attach-thumb: transparent; --kl-attach-thumb-ink: var(--kl-color-status-stopped-ink); }
.kl-attach.is-failed .kl-attach__meta { color: var(--kl-color-status-stopped-ink); }
.kl-attach__retry {
  flex: none;
  height: 20px;
  padding: 0 6px;
  border: 0;
  border-radius: var(--kl-radius-pill);
  background: transparent;
  color: var(--kl-color-status-stopped-ink);
  font: var(--kl-font-label);
  font-family: var(--kl-font-sans);
  cursor: pointer;
}
.kl-attach__retry:hover { background: color-mix(in srgb, var(--kl-color-status-stopped) 14%, transparent); }
.kl-attach__retry:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 0; }

/* ---------- Drop target ---------- */
/* A file or a card is held over the prompter: the same ring as a link target, and the draft shows where it lands */
.kl-prompter.is-drop-target { box-shadow: 0 0 0 1px var(--kl-color-line), var(--kl-glass-shadow), var(--kl-shadow-ring-target); }
.kl-prompter__drop {
  position: absolute;
  inset: var(--kl-prompter-pad, 12px);
  z-index: 3;
  display: none;
  align-items: center;
  justify-content: center;
  gap: var(--kl-space-2);
  border: 1.5px dashed var(--kl-color-selection);
  border-radius: var(--kl-prompter-radius-field, var(--kl-radius-groupbox));
  background: color-mix(in srgb, var(--kl-color-selection) 12%, var(--kl-color-surface));
  color: var(--kl-color-selection-ink);
  font: var(--kl-font-label);
  pointer-events: none;
}
.kl-prompter__drop svg { width: 16px; height: 16px; }
.kl-prompter.is-drop-target .kl-prompter__drop { display: flex; animation: kl-pa-fade var(--kl-motion-press) var(--kl-motion-ease-out) both; }

/* ---------- The / menu ---------- */
/* Opens above the prompter when the draft starts with "/". One list: commands, skills, saved prompts. Glass like
   every v2 menu. Rows are 36px; the active row is the menu's blue fill. Return picks, Esc closes. */
.kl-slash {
  --kl-slash-row: 36px;
  display: flex;
  flex-direction: column;
  width: var(--kl-slash-w, 100%);
  max-height: var(--kl-slash-max-h, 312px);
  margin: 0;
  padding: 6px;
  border-radius: var(--kl-radius-menu);
  background: var(--kl-glass-fill-menu);
  -webkit-backdrop-filter: blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));
  backdrop-filter: blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));
  box-shadow: var(--kl-shadow-menu), var(--kl-glass-rim);
  color: var(--kl-color-text);
  font: var(--kl-font-label);
  font-family: var(--kl-font-sans);
  transform-origin: bottom center;
  isolation: isolate;
}
.kl-slash *, .kl-slash *::before, .kl-slash *::after { box-sizing: border-box; }
.kl-slash__list { flex: 1 1 auto; min-height: 0; overflow: auto; overscroll-behavior: contain; margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 1px; }
.kl-slash__group { padding: 8px 10px 4px; color: var(--kl-color-text-secondary); font: var(--kl-font-caption); }
.kl-slash__group:first-child { padding-top: 2px; }
.kl-slash__item {
  display: grid;
  grid-template-columns: 16px minmax(auto, max-content) minmax(0, 1fr) auto;
  align-items: center;
  column-gap: 10px;
  width: 100%;
  min-height: var(--kl-slash-row);
  padding: 0 10px;
  border: 0;
  border-radius: calc(var(--kl-radius-menu) - 6px);
  background: transparent;
  color: var(--kl-color-text);
  font: var(--kl-font-label);
  font-family: var(--kl-font-sans);
  text-align: left;
  cursor: pointer;
}
.kl-slash__item > svg { width: 16px; height: 16px; color: var(--kl-color-text-secondary); }
.kl-slash__name { white-space: nowrap; }
.kl-slash__name--cmd { font-family: var(--kl-font-mono); font-weight: var(--kl-font-weight-medium); }
.kl-slash__desc { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--kl-color-text-secondary); font: var(--kl-font-meta); }
.kl-slash__hint { visibility: hidden; display: inline-flex; align-items: center; gap: 4px; font: var(--kl-font-caption); }
.kl-slash__match { font-weight: var(--kl-font-weight-bold); }
.kl-slash__item:hover, .kl-slash__item.is-active, .kl-slash__item[aria-selected="true"] { background: var(--kl-color-selection); color: var(--kl-color-text-on-fill); }
.kl-slash__item:hover :is(svg, .kl-slash__desc, .kl-slash__hint),
.kl-slash__item.is-active :is(svg, .kl-slash__desc, .kl-slash__hint),
.kl-slash__item[aria-selected="true"] :is(svg, .kl-slash__desc, .kl-slash__hint) { color: var(--kl-color-text-on-fill); }
.kl-slash__item.is-active .kl-slash__hint, .kl-slash__item[aria-selected="true"] .kl-slash__hint { visibility: visible; }
.kl-slash__item:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: -2px; }
.kl-slash__empty { margin: 0; padding: 14px 10px; color: var(--kl-color-text-secondary); font: var(--kl-font-meta); text-align: center; }
.kl-slash__foot {
  display: flex;
  align-items: center;
  gap: var(--kl-space-3);
  margin-top: 4px;
  padding: 6px 10px 2px;
  border-top: 1px solid var(--kl-color-line);
  color: var(--kl-color-text-secondary);
  font: var(--kl-font-caption);
}
.kl-slash__foot span { display: inline-flex; align-items: center; gap: 4px; }
.kl-slash__foot .kl-kbd { height: 16px; min-width: 16px; font-size: 10.5px; }

/* ---------- Running: Stop ---------- */
/* Running with an empty draft: Stop takes Send's place, round and ink (never blue, never red: stopping is safe).
   Running with a draft: Send becomes Queue (still the one blue button) and Stop moves beside it as a smaller --side. */
.kl-prompter__stop {
  flex: none;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--kl-prompter-stop);
  height: var(--kl-prompter-stop);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--kl-color-text);
  color: var(--kl-color-surface);
  cursor: pointer;
  transition: background-color var(--kl-motion-press) ease, scale var(--kl-motion-press) var(--kl-motion-ease-out), width var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-prompter__stop::before { content: ""; position: absolute; inset: -6px; border-radius: 50%; }
.kl-prompter__stop svg { width: 16px; height: 16px; }
.kl-prompter__stop:hover, .kl-prompter__stop.is-hover { background: color-mix(in srgb, var(--kl-color-text) 82%, var(--kl-color-surface)); }
.kl-prompter__stop:active, .kl-prompter__stop.is-pressed { scale: .94; }
.kl-prompter__stop:focus-visible, .kl-prompter__stop.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-prompter__stop--side {
  width: 28px;
  height: 28px;
  background: var(--kl-color-control-fill);
  color: var(--kl-color-text);
}
.kl-prompter__stop--side svg { width: 14px; height: 14px; }
.kl-prompter__stop--side:hover, .kl-prompter__stop--side.is-hover { background: var(--kl-color-button-secondary); }
/* Queue: Send's slot while running with a draft, labelled by its tooltip ("Queue for Atlas's next step") */
.kl-prompter__send--queue svg { width: 16px; height: 16px; }

/* Running status: the destination's executing dot (a signal, so it may pulse) and a short line */
.kl-prompter__running { display: inline-flex; align-items: center; gap: 6px; min-width: 0; color: var(--kl-color-text-secondary); font: var(--kl-font-meta); }
.kl-prompter__running .kl-dot { flex: none; }
.kl-prompter__running-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kl-prompter__status--stopped { color: var(--kl-color-text-secondary); font: var(--kl-font-label); }

/* ---------- Queued notes ---------- */
/* The chip in the status slot: "2 queued". Notes wait there until the agent's next step reads them. */
.kl-qchip {
  flex: none;
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 24px;
  padding: 0 8px 0 7px;
  border: 0;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-control-fill);
  color: var(--kl-color-text);
  font: var(--kl-font-label);
  font-family: var(--kl-font-sans);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--kl-motion-press) ease;
}
.kl-qchip::before { content: ""; position: absolute; inset: -10px 0; }
.kl-qchip svg { width: 14px; height: 14px; color: var(--kl-color-text-secondary); }
.kl-qchip:hover, .kl-qchip.is-hover { background: var(--kl-color-button-secondary); }
.kl-qchip[aria-expanded="true"], .kl-qchip.is-open { background: var(--kl-color-control-fill-pressed); }
.kl-qchip:focus-visible, .kl-qchip.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-qchip__n { display: inline-block; min-width: 1ch; text-align: right; }
.kl-qchip.is-bumped .kl-qchip__n { animation: kl-count-bump var(--kl-motion-count-bump) var(--kl-motion-ease-out); }

/* The list of queued notes: glass like a menu, opens upward from the chip */
.kl-queue {
  display: flex;
  flex-direction: column;
  gap: var(--kl-space-1);
  width: var(--kl-queue-w, 320px);
  max-width: 100%;
  padding: 10px 6px 6px;
  border-radius: var(--kl-radius-menu);
  background: var(--kl-glass-fill-menu);
  -webkit-backdrop-filter: blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));
  backdrop-filter: blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));
  box-shadow: var(--kl-shadow-menu), var(--kl-glass-rim);
  color: var(--kl-color-text);
  font: var(--kl-font-label);
  font-family: var(--kl-font-sans);
  transform-origin: bottom right;
}
.kl-queue *, .kl-queue *::before, .kl-queue *::after { box-sizing: border-box; }
.kl-queue__head { display: grid; gap: 2px; padding: 0 8px 4px; }
.kl-queue__title { margin: 0; font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-queue__sub { margin: 0; color: var(--kl-color-text-secondary); font: var(--kl-font-caption); }
.kl-queue__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.kl-queue__note {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--kl-space-2);
  padding: 7px 4px 7px 8px;
  border-radius: calc(var(--kl-radius-menu) - 6px);
  background: var(--kl-color-surface);
  box-shadow: 0 0 0 1px var(--kl-color-line);
}
.kl-queue__num { padding-top: 1px; color: var(--kl-color-text-secondary); font: var(--kl-font-caption); font-variant-numeric: tabular-nums; }
.kl-queue__text { margin: 0; font: var(--kl-font-meta); color: var(--kl-color-text); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.kl-queue__note .kl-attach__remove { margin-top: -1px; }
.kl-queue__foot { display: flex; align-items: center; justify-content: space-between; gap: var(--kl-space-2); padding: 4px 4px 0 8px; color: var(--kl-color-text-secondary); font: var(--kl-font-caption); }

/* ---------- Open questions: the pill and the strip ---------- */
/* Taken in from the question card part (question-card/question-card.css, sections 11, 13 and 14) so open questions
   show on the harness prompter with the card's own markup. The class names are the card's; v2 Controls is adding
   .is-answering to the v2 prompter under the same name.
     .kl-ask-pending             "3 questions" on the prompter's top edge, in the approval magenta (a question waits
                                 on Alban, like an approval). Pressing it picks up the oldest blocking question.
     .kl-prompter.is-answering   the strip is open; add .kl-ask-hue--pN on the root for the asking project's ink
     .kl-ask-strip > __in        head (mark, "Planner · Atlas", Draft kept, 1 of 3, previous, next, Not now), __q,
                                 __opts of .kl-ask-chip, __why
   While a question is open the harness additions step aside so the strip stays short: the mode, the + and the
   attachment chips hide, and come back with the draft when the strip folds away. */

/* Hue helpers: the strip and the status speak in the asking project's voice */









/* The project's mark: the 8 px rounded square v2 uses for a project in windows and the prompter, in its hue */






/* A hairline between the question and the draft; padding keeps the chips' focus ring inside the clip */













/* Choices as chips: a key number, the answer, a dot in the project's ink on the recommended one. Chosen uses v2's
   selection: the soft blue fill, a 2 px edge and the check in place of the number. */

















/* The recommended answer in the status slot while nothing is chosen, in the project's ink like on the card */


/* The pending pill: open questions wait on the prompter's top edge, in the approval magenta that marks everything
   waiting on Alban. Pressing it opens the strip with the oldest blocking question. It pops in (kl-m-count-pop)
   through the quiet gate, so never while Alban types, drags or links, and it hides while the strip is open. */







/* In the harness prompter: the additions step aside while a question is open */
.kl-prompter--harness.is-answering :is(.kl-prompter__mode, .kl-prompter__plus, .kl-prompter__chips) { display: none; }

/* Increased contrast, forced colours and reduced motion for the strip, chips and pill */





/* Reduced motion: no unfolding, the strip and the row body only fade */




/* ---------- Floating layer (specimen and app): menus sit above the prompter, centred or at their opener ---------- */
.kl-prompter__float {
  position: absolute;
  left: var(--kl-float-x, 0);
  right: var(--kl-float-r, auto);
  bottom: calc(100% + var(--kl-space-2));
  z-index: 45;
}
.kl-prompter__float--full { left: 0; right: 0; }
.kl-prompter__float--end { left: auto; right: 0; }

/* ---------- Motion ---------- */
@media (prefers-reduced-motion: no-preference) {
  .kl-attach.is-arriving { animation: kl-pa-in var(--kl-motion-hover) var(--kl-motion-spring-pop) both; }
  .kl-attach.is-leaving { opacity: 0; }
  .kl-slash, .kl-queue, .kl-modemenu { animation: kl-pa-menu var(--kl-motion-menu-in, var(--kl-motion-press)) var(--kl-motion-ease-out) both; }
  .kl-qchip.is-arriving, .kl-prompter__stop.is-arriving, .kl-prompter__send.is-arriving { animation: kl-pa-in var(--kl-motion-hover) var(--kl-motion-spring-pop) both; }
}
@media (prefers-reduced-motion: reduce) {
  .kl-attach, .kl-qchip, .kl-qchip__n, .kl-prompter__mode, .kl-prompter__mode svg, .kl-prompter__mode-label, .kl-prompter__stop, .kl-prompter__plus svg { animation-name: kl-pa-fade !important; transition-property: opacity, color, background-color, box-shadow !important; }
  .kl-slash, .kl-queue, .kl-modemenu { animation: kl-pa-fade var(--kl-motion-fade-out) ease both; }
}
/* The specimen's (and app setting's) reduced-motion switch: v2 Motion's .kl-motion-reduce class on any ancestor */
.kl-motion-reduce :is(.kl-attach, .kl-qchip .kl-qchip__n, .kl-qchip, .kl-prompter__mode, .kl-prompter__mode svg, .kl-prompter__mode-label, .kl-prompter__stop, .kl-prompter__send) { animation-name: kl-pa-fade !important; }
.kl-motion-reduce .kl-prompter__mode { transition-property: background-color, color, box-shadow !important; }
.kl-motion-reduce :is(.kl-slash, .kl-queue, .kl-modemenu, .kl-prompter__drop) { animation: kl-pa-fade var(--kl-motion-fade-out) ease both !important; }
.kl-motion-reduce :is(.kl-prompter__plus svg, .kl-prompter__field) { transition-property: opacity, color, border-color, box-shadow !important; }
.kl-motion-reduce .kl-prompter.is-failed .kl-prompter__field { animation: none !important; }

/* Amplitudes scale with the dial: at 0 a chip just fades in, at 1 it pops from 40% with a small overshoot */
@keyframes kl-pa-in {
  0% { opacity: 0; scale: calc(1 - .6 * var(--kl-motion-k, .35)); translate: 0 calc(6px * var(--kl-motion-k, .35)); }
  60% { opacity: 1; }
  100% { opacity: 1; scale: 1; translate: 0 0; }
}
@keyframes kl-pa-bump { 0% { scale: 1; } 35% { scale: calc(1 + .08 * var(--kl-motion-k, .35)); } 100% { scale: 1; } }
@keyframes kl-pa-menu { from { opacity: 0; translate: 0 4px; scale: .98; } }
@keyframes kl-pa-fade { from { opacity: 0; } }
@keyframes kl-pm-roll { from { opacity: 0; translate: 0 calc(8px * var(--kl-motion-k, .35)); } }
@keyframes kl-pm-turn { from { opacity: 0; scale: calc(1 - .5 * var(--kl-motion-k, .35)); rotate: calc(-30deg * var(--kl-motion-k, .35)); } }

@media (forced-colors: active) {
  :is(.kl-prompter__mode--free, .kl-prompter__mode--full) { outline: 2px solid Mark; }
  .kl-attach, .kl-qchip, .kl-prompter__plus, .kl-prompter__mode { border: 1px solid CanvasText; }
  .kl-prompter__stop { background: CanvasText; color: Canvas; }
  .kl-slash__item.is-active { outline: 2px solid Highlight; }
  .kl-prompter__drop { border-color: Highlight; }
}

/* ===== stacks/stacks.css ===== */
/* =====================================================================================================
   Klippan master design system, first draft: card stacks and groups.
   Load after ../../klippan-v2/combined/klippan.css (tokens, kl-m-* motion, board pieces).

   A stack is two or more stackable cards held in one frame. Unnamed, the frame is only a hairline round the
   cards ("these belong together"). Named, it gets a tab on its top edge and a faint tray. Collapsed, the cards
   pile up behind the first one.

   Stacking is a drag thing, linking is a click thing:
     linking  = click a card, light follows the pointer (selection blue), no line, click the target
     stacking = press and drag a card, hold it over another stackable card, a slot opens in the target's hue,
                let go and a frame forms round them
   Nothing here uses selection blue or the link glow, and nothing here draws a line.

   Every size is a board unit (the board draws at --kl-board-scale x zoom). Colours, padding, gap and radius are
   Foundations' stack tokens (--kl-color-stack-*, --kl-space-stack-*, --kl-radius-stack); timings are Motion's
   --kl-motion-stack-*. The board keeps the tilt, z-order, pile-line and zoomed-out rules (v2 board.css, 10b).
   ===================================================================================================== */

.kl-stack,
.kl-board,
.kl-card {
  /* This part's own sizes (the rest are Foundations' --kl-space-stack-*, --kl-radius-stack) */
  --kl-stack-tab-h: 28px;
  --kl-stack-peek: 10px;                                        /* how far each card shows under the top card when collapsed */
}

/* The stack's hue: the card it was dropped on decides it. --p1 to --p8 = Foundations' project hues.
   Setting --kl-color-stack makes Foundations recompute rim, wash, slot and slot-edge on the frame */
.kl-stack { --kl-stack-ink: var(--kl-color-project-1-ink); --kl-stack-glass: var(--kl-glass-card-project-1); }
.kl-stack--p1 { --kl-color-stack: var(--kl-color-project-1); --kl-stack-ink: var(--kl-color-project-1-ink); --kl-stack-glass: var(--kl-glass-card-project-1); }
.kl-stack--p2 { --kl-color-stack: var(--kl-color-project-2); --kl-stack-ink: var(--kl-color-project-2-ink); --kl-stack-glass: var(--kl-glass-card-project-2); }
.kl-stack--p3 { --kl-color-stack: var(--kl-color-project-3); --kl-stack-ink: var(--kl-color-project-3-ink); --kl-stack-glass: var(--kl-glass-card-project-3); }
.kl-stack--p4 { --kl-color-stack: var(--kl-color-project-4); --kl-stack-ink: var(--kl-color-project-4-ink); --kl-stack-glass: var(--kl-glass-card-project-4); }
.kl-stack--p5 { --kl-color-stack: var(--kl-color-project-5); --kl-stack-ink: var(--kl-color-project-5-ink); --kl-stack-glass: var(--kl-glass-card-project-5); }
.kl-stack--p6 { --kl-color-stack: var(--kl-color-project-6); --kl-stack-ink: var(--kl-color-project-6-ink); --kl-stack-glass: var(--kl-glass-card-project-6); }
.kl-stack--p7 { --kl-color-stack: var(--kl-color-project-7); --kl-stack-ink: var(--kl-color-project-7-ink); --kl-stack-glass: var(--kl-glass-card-project-7); }
.kl-stack--p8 { --kl-color-stack: var(--kl-color-project-8); --kl-stack-ink: var(--kl-color-project-8-ink); --kl-stack-glass: var(--kl-glass-card-project-8); }

/* =====================================================================================================
   1. The frame. Two layouts, one look:
      .kl-stack            the cards are its children, laid out in a column (specimens, static boards)
      .kl-stack.is-free    the board places the frame and the cards itself (left/top/width/height inline);
                           cards stay siblings on the board, so moving one in or out never re-parents it
   ===================================================================================================== */
.kl-stack {
  position: relative;
  display: inline-flex; flex-direction: column; align-items: flex-start;
  gap: var(--kl-space-stack-gap);
  padding: var(--kl-space-stack-pad);
  border-radius: var(--kl-radius-stack);
  /* Unnamed: only a hairline in the stack's hue and the faintest wash, so it reads as "grouped", not as a panel */
  background: var(--kl-color-stack-wash);
  box-shadow: inset 0 0 0 1.5px var(--kl-color-stack-rim);
  z-index: var(--kl-z-under, 1);               /* with the light pools and resting lines, under every card (Board) */
  transition:
    background-color var(--kl-motion-stack-slot) var(--kl-motion-ease-out),
    box-shadow var(--kl-motion-stack-slot) var(--kl-motion-ease-out),
    opacity var(--kl-motion-stack-dissolve) var(--kl-motion-ease-out),
    scale var(--kl-motion-stack-dissolve) var(--kl-motion-ease-out);
}
.kl-stack.is-free { position: absolute; display: block; padding: 0; }

/* Named: a tray (tint over a little more wash) and the tab. Room above the first card for the tab's lower half */
.kl-stack--named {
  padding-top: calc(var(--kl-space-stack-pad) + var(--kl-stack-tab-h) / 2);
  background: var(--kl-color-stack-wash-named);
}
.kl-stack--named.is-free { padding: 0; }

/* Cards inside a stack stand straight (Board's .kl-tilt.is-stacked rule): the stack is the one tidy thing on an untidy board */

/* =====================================================================================================
   2. The tab (named stacks) and the quiet "Name" button (unnamed ones)
   ===================================================================================================== */
.kl-stack__tab {
  position: absolute; left: calc(var(--kl-space-stack-pad) + 6px); top: 0; translate: 0 -50%;
  z-index: 3;
  display: inline-flex; align-items: center; gap: 6px;
  height: var(--kl-stack-tab-h); max-width: calc(100% - 2 * var(--kl-space-stack-pad));
  padding: 0 4px 0 10px;
  border: 0; border-radius: var(--kl-radius-pill);
  background: var(--kl-stack-glass);
  -webkit-backdrop-filter: var(--kl-glass-card-filter); backdrop-filter: var(--kl-glass-card-filter);
  box-shadow: inset 0 0 0 1px var(--kl-color-stack-rim), var(--kl-glass-card-shadow);
  color: var(--kl-color-text);
  font: var(--kl-font-label-strong); font-family: var(--kl-font-sans);
  white-space: nowrap; cursor: grab;
}
.kl-stack__tab:active { cursor: grabbing; }
.kl-stack__glyph { flex: none; width: 14px; height: 14px; color: var(--kl-stack-ink); }
.kl-stack__name { min-width: 0; max-width: 180px; overflow: hidden; text-overflow: ellipsis; }
.kl-stack__count { flex: none; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-stack__tab .kl-iconbtn { --kl-iconbtn: 22px; flex: none; }
.kl-stack__tab .kl-iconbtn .kl-icon { --kl-icon-size: 14px; transition: rotate var(--kl-motion-expand) var(--kl-motion-spring); }
.kl-stack.is-collapsed .kl-stack__tab .kl-iconbtn .kl-icon { rotate: -90deg; }

/* Renaming: the name turns into a field inside the tab; Enter keeps it, Esc puts the old one back, empty = unnamed */
.kl-stack__field {
  min-width: 96px; width: calc(var(--kl-stack-field-ch, 10) * 1ch + 8px); max-width: 220px;
  height: 20px; margin: 0; padding: 0 4px;
  border: 0; border-radius: 6px; outline: 0;
  background: color-mix(in srgb, var(--kl-color-surface) 70%, transparent);
  box-shadow: 0 0 0 2px var(--kl-color-focus);
  color: var(--kl-color-text); font: inherit; font-family: inherit;
}
.kl-stack__field::placeholder { color: var(--kl-color-text-tertiary); font-weight: var(--kl-font-weight-regular); }
.kl-stack__tab.is-editing { cursor: text; padding-right: 10px; }

/* Unnamed: "Name" waits, half on the top edge, until you hover or focus the frame */
.kl-stack__nameit {
  position: absolute; left: calc(var(--kl-space-stack-pad) + 6px); top: 0; translate: 0 -50%;
  z-index: 3;
  display: inline-flex; align-items: center; gap: 4px;
  height: 22px; padding: 0 9px 0 7px;
  border: 0; border-radius: var(--kl-radius-pill);
  background: var(--kl-color-board);
  box-shadow: inset 0 0 0 1px var(--kl-color-stack-rim);
  color: var(--kl-color-text-secondary);
  font: var(--kl-font-caption); font-family: var(--kl-font-sans);
  cursor: pointer;
  opacity: 0; transition: opacity var(--kl-motion-hover) ease;
}
.kl-stack__nameit .kl-icon { --kl-icon-size: 12px; }
.kl-stack:hover > .kl-stack__nameit, .kl-stack.is-hover > .kl-stack__nameit, .kl-stack__nameit:focus-visible { opacity: 1; }
.kl-stack__nameit:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 1px; }
.kl-board.is-dragging .kl-stack__nameit { opacity: 0; }   /* never pops up while a card is being dragged across */

/* Count on an unnamed stack that is collapsed (a named one shows it in its tab) */
.kl-stack__badge {
  position: absolute; right: 10px; top: 0; translate: 0 -50%; z-index: 3;
  min-width: 22px; height: 22px; padding: 0 7px; box-sizing: border-box;
  display: inline-grid; place-items: center;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-stack-glass);
  box-shadow: inset 0 0 0 1px var(--kl-color-stack-rim), var(--kl-glass-card-shadow);
  color: var(--kl-color-text); font: var(--kl-font-badge); font-family: var(--kl-font-sans);
}

/* The collapse chevron on an unnamed stack sits where the badge sits on the right */
.kl-stack__fold { position: absolute; right: 8px; top: 0; translate: 0 -50%; z-index: 3;
  --kl-iconbtn: 22px; background: var(--kl-color-board); box-shadow: inset 0 0 0 1px var(--kl-color-stack-rim);
  opacity: 0; transition: opacity var(--kl-motion-hover) ease; }
.kl-stack__fold .kl-icon { --kl-icon-size: 14px; }
.kl-stack:hover > .kl-stack__fold, .kl-stack.is-hover > .kl-stack__fold, .kl-stack__fold:focus-visible { opacity: 1; }
.kl-stack.is-collapsed > .kl-stack__fold { opacity: 0; pointer-events: none; }

/* =====================================================================================================
   3. While a stackable card is being dragged
      .kl-board.is-stacking          a stackable card is held: other stackable cards show their shelf
      .kl-card[data-stackable]       can be stacked (set from the card's gear: "Can stack")
      i.kl-stack-shelf               an empty <i> inside every stackable card, before the face: two card edges
                                     peeking out under it, so you see where a stack could start
      .kl-card.kl-stack-target       the held card has been over this one for --kl-motion-stack-dwell: it settles, the
                                     shelf opens fully, and a .kl-stack__slot shows where the held card will go
      .kl-card.is-over-stack         the held card, while a slot is open for it
   Only stackable cards ever react. Nothing on the board moves on its own meanwhile: all of this is the drag's feedback.
   ===================================================================================================== */
.kl-stack-shelf {
  position: absolute; inset: 0; z-index: -1;            /* Board makes it ignore the pointer */
  border-radius: inherit;
  opacity: 0; transition: opacity var(--kl-motion-hover) ease;
}
.kl-stack-shelf::before, .kl-stack-shelf::after {
  content: ""; position: absolute; height: 18px; bottom: 0;
  border-radius: 0 0 calc(var(--kl-radius-card) - 8px) calc(var(--kl-radius-card) - 8px);
  background: var(--kl-card-glass, var(--kl-glass-card));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--kl-color-text) 16%, transparent), 0 2px 4px rgba(0, 0, 0, .08);
  transition: translate var(--kl-motion-stack-slot) var(--kl-motion-spring), opacity var(--kl-motion-stack-slot) ease;
}
.kl-stack-shelf::before { left: 10px; right: 10px; translate: 0 6px; opacity: .95; }
.kl-stack-shelf::after  { left: 22px; right: 22px; translate: 0 11px; opacity: .7; }
.kl-board.is-stacking .kl-card[data-stackable]:not(.is-dragging):not(.is-stacked) > .kl-stack-shelf,
.kl-card.is-can-stack > .kl-stack-shelf { opacity: 1; }

/* The target settles a touch (the dial scales it: .986 at 35, .96 at 100, none at 0) and its shelf opens */
.kl-card.kl-stack-target > .kl-card__face { scale: calc(1 - .04 * var(--kl-motion-k)); transition: scale var(--kl-motion-stack-slot) var(--kl-motion-spring); }
.kl-card.kl-stack-target > .kl-stack-shelf { opacity: 1; }
.kl-card.kl-stack-target > .kl-stack-shelf::before { translate: 0 9px; }
.kl-card.kl-stack-target > .kl-stack-shelf::after  { translate: 0 16px; }
/* The held card leans in: a little smaller, its shadow closer, as if it is about to sit down */
.kl-card.is-over-stack > .kl-card__face { scale: calc(1 - .03 * var(--kl-motion-k)); box-shadow: var(--kl-glass-card-shadow); transition: scale var(--kl-motion-stack-slot) var(--kl-motion-spring); }
.kl-card.is-dragging > .kl-card__face { box-shadow: var(--kl-shadow-card-lifted, var(--kl-glass-card-shadow-hover)); }

/* The slot: a ghost of the held card, dashed in the stack's hue, where it will land */
.kl-stack__slot {
  position: relative; flex: none; box-sizing: border-box;
  width: var(--kl-slot-w, var(--kl-card-compact-w)); height: var(--kl-slot-h, var(--kl-card-compact-h));
  border-radius: var(--kl-radius-card);
  border: 1.5px dashed var(--kl-color-stack-slot-edge);
  background: var(--kl-color-stack-slot);
  pointer-events: none;
  animation: kl-stack-slot-in var(--kl-motion-stack-slot) var(--kl-motion-spring) both;
}
.kl-stack.is-free > .kl-stack__slot, .kl-board > .kl-stack__slot { position: absolute; }
.kl-stack__slot.is-closing { animation: kl-stack-slot-out var(--kl-motion-fade-out) var(--kl-motion-ease-out) both; }
@keyframes kl-stack-slot-in { from { opacity: 0; scale: calc(1 - .12 * var(--kl-motion-k)) calc(1 - .2 * var(--kl-motion-k)); } to { opacity: 1; scale: 1; } }
@keyframes kl-stack-slot-out { to { opacity: 0; } }

/* The preview frame round target and slot: dashed, no tab, a little wash. It becomes the real frame on drop */
.kl-stack.is-preview {
  background: var(--kl-color-stack-wash);
  box-shadow: none;
  outline: 1.5px dashed var(--kl-color-stack-rim); outline-offset: -1.5px;
  animation: kl-stack-preview-in var(--kl-motion-stack-slot) var(--kl-motion-ease-out) both;
}
@keyframes kl-stack-preview-in { from { opacity: 0; } to { opacity: 1; } }
/* Dropped: the dashes go solid and the frame breathes in once (scale x dial) */
.kl-stack.is-forming { animation: kl-stack-form var(--kl-motion-stack-form) var(--kl-motion-spring) both; }
@keyframes kl-stack-form { from { scale: calc(1 + .02 * var(--kl-motion-k)); box-shadow: inset 0 0 0 1.5px var(--kl-color-stack-rim-strong); } to { scale: 1; } }

/* Dragging over a card already in a stack, or over its frame: the frame lights up and a slot opens in the column */
.kl-stack.is-joining {
  background: var(--kl-color-stack-wash-joining);
  box-shadow: inset 0 0 0 1.5px var(--kl-color-stack-rim-strong);
}

/* =====================================================================================================
   4. Pulling a card out. The frame holds on for a moment (it stretches toward the card, up to 40 x dial units),
      then lets go once the card is clear of it by KlMotion.STACK.letGo (KlMotion.stackStretch); the cards left behind close up on the room
      spring. A stack with one card left dissolves: the frame fades and that card stays where it is.
   ===================================================================================================== */
.kl-stack.is-stretching { box-shadow: inset 0 0 0 1.5px var(--kl-color-stack-rim-strong); }
.kl-stack.is-letting-go { animation: kl-stack-letgo var(--kl-motion-stack-form) var(--kl-motion-spring) both; }
@keyframes kl-stack-letgo { 0% { scale: 1; } 40% { scale: calc(1 - .012 * var(--kl-motion-k)); } 100% { scale: 1; } }
.kl-stack.is-dissolving { opacity: 0; scale: calc(1 + .02 * var(--kl-motion-k)); pointer-events: none; }
.kl-stack.is-dissolving > :is(.kl-stack__tab, .kl-stack__nameit, .kl-stack__badge, .kl-stack__fold) { opacity: 0; transition: opacity var(--kl-motion-stack-dissolve) ease; }

/* =====================================================================================================
   5. Collapsed: the cards pile up behind the first one. Up to two edges peek out under it, the rest hide.
      In .kl-stack (children) layout CSS does the pile; in .is-free layout the board sets each card's spot and
      adds .kl-stack-pile-1 / -2 / -hidden so the same look applies.
   ===================================================================================================== */
.kl-stack.is-collapsed:not(.is-free) { display: inline-grid; gap: 0; padding-bottom: calc(var(--kl-space-stack-pad) + 2 * var(--kl-stack-peek)); }
.kl-stack.is-collapsed:not(.is-free) > :is(.kl-card, .kl-stack__slot) { grid-area: 1 / 1; }
.kl-stack > .kl-card, .kl-card.is-stacked { transform-origin: 50% 100%; }
.kl-stack > .kl-card { transition: translate var(--kl-motion-expand) var(--kl-motion-spring), scale var(--kl-motion-expand) var(--kl-motion-spring), opacity var(--kl-motion-fade) ease; transition-delay: calc(var(--kl-i, 0) * var(--kl-motion-stack-stagger)); }
.kl-stack.is-collapsed:not(.is-free) > .kl-card:nth-of-type(1), .kl-card.kl-stack-pile-0 { z-index: 3; }
.kl-stack.is-collapsed:not(.is-free) > .kl-card:nth-of-type(2), .kl-card.kl-stack-pile-1 { z-index: 2; translate: 0 var(--kl-stack-peek); scale: .95; }
.kl-stack.is-collapsed:not(.is-free) > .kl-card:nth-of-type(3), .kl-card.kl-stack-pile-2 { z-index: 1; translate: 0 calc(2 * var(--kl-stack-peek)); scale: .9; }
.kl-stack.is-collapsed:not(.is-free) > .kl-card:nth-of-type(n+4), .kl-card.kl-stack-pile-hidden { opacity: 0; pointer-events: none; }
/* Cards under the top one show only their edge: their content fades so the pile reads as one thing */
.kl-stack.is-collapsed:not(.is-free) > .kl-card:nth-of-type(n+2) > .kl-card__face > *,
.kl-stack.is-collapsed:not(.is-free) > .kl-card:nth-of-type(n+2) > :is(.kl-card__ctl, .kl-card__grip),
.kl-card:is(.kl-stack-pile-1, .kl-stack-pile-2) > .kl-card__face > *,
.kl-card:is(.kl-stack-pile-1, .kl-stack-pile-2) > :is(.kl-card__ctl, .kl-card__grip) { opacity: 0; transition: opacity var(--kl-motion-fade) ease; }
.kl-stack.is-collapsed:not(.is-free) > .kl-card:nth-of-type(n+2) { pointer-events: none; }

/* =====================================================================================================
   5b. Stacking with the keyboard. A stackable card and a stack's tab take focus (Tab), with the keyboard ring.
       S picks the focused card up for stacking (Shift+S, or S on a tab, picks up its whole stack). It lifts
       where it is and the nearest place it can go opens at once, with the same slot and frames as a drag:
       a key is deliberate, so there is no dwell. Left and Right choose another place (nearest first), Up and
       Down move the slot inside a stack, Enter or S puts it there, Esc puts it back. U takes the focused card
       out of its stack. Up and Down move focus through the cards of an open stack.
       .kl-card.is-kbd-held      the card picked up by the keyboard (lifted, stays where it is, no lean)
       .kl-stack.is-kbd-held     a whole stack picked up by the keyboard (to merge it into another)
       .kl-stack-keys            the key hint under what is held: where it goes, and the keys
   ===================================================================================================== */
/* The keyboard ring is never blue. A card's ring is v2 Board's .kl-card:focus-visible (its hue ink, 3 px out);
   .is-focus draws the same ring in static specimens. The tab's ring is the stack's ink */
.kl-card.is-focus { outline: 2px solid var(--kl-card-hue-ink); outline-offset: 3px; }
.kl-stack__tab:focus { outline: 0; }
.kl-stack__tab:focus-visible, .kl-stack__tab.is-focus { outline: 2px solid var(--kl-stack-ink); outline-offset: 2px; }

/* Held by the keyboard: lifted where it is, above the other cards. Its focus ring stays on */
.kl-card.is-kbd-held { z-index: var(--kl-z-drag, 44); }
.kl-card.is-kbd-held > .kl-card__face { box-shadow: var(--kl-shadow-card-lifted, var(--kl-glass-card-shadow-hover)); }
.kl-stack.is-kbd-held { z-index: calc(var(--kl-z-drag, 44) - 1); box-shadow: inset 0 0 0 1.5px var(--kl-color-stack-rim-strong); }
.kl-card.is-dragging-with { z-index: var(--kl-z-drag, 44); }

/* The key hint: a glass tooltip under what is held. Line 1 says where it will go, line 2 the keys */
.kl-stack-keys.kl-tooltip {
  position: absolute; z-index: calc(var(--kl-z-drag, 44) + 1);
  display: grid; gap: 4px; width: max-content; max-width: none; padding: 7px 12px 8px; border-radius: 14px;
  white-space: nowrap; font: var(--kl-font-caption); font-family: var(--kl-font-sans);
  animation: kl-stack-keys-in var(--kl-motion-stack-slot) var(--kl-motion-ease-out) both;
}
.kl-stack-keys__to { display: flex; align-items: center; gap: 6px; font: var(--kl-font-label-strong); font-family: var(--kl-font-sans); }
.kl-stack-keys__to .kl-icon { --kl-icon-size: 14px; color: var(--kl-stack-keys-ink, var(--kl-color-text-secondary)); }
.kl-stack-keys__of { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-stack-keys__keys { display: flex; align-items: center; gap: 4px 10px; color: var(--kl-color-text-secondary); }
.kl-stack-keys__keys > span { display: inline-flex; align-items: center; gap: 3px; white-space: nowrap; }
.kl-stack-keys .kl-kbd { height: 18px; min-width: 18px; padding: 0 4px; opacity: 1; background: var(--kl-color-surface); color: var(--kl-color-text); box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
@keyframes kl-stack-keys-in { from { opacity: 0; translate: 0 calc(-4px * var(--kl-motion-k)); } to { opacity: 1; translate: 0 0; } }

/* =====================================================================================================
   5c. Merging two stacks. Drag a stack (its tab, its frame or its pile) over another stack and hold it there
       for the same 280 ms. The target lights as when a card joins it, a slot the size of every incoming card
       opens where the pointer is, and a pill on its bottom edge says what the merge does to the names. Let go
       and the cards slide in, the dragged frame fades into the target, and the target breathes in once.
       Names: the target's name stays. If only the dragged stack has a name, the merged stack takes it.
       The hue and the open or collapsed state are always the target's.
       .kl-stack.is-over-stack   the dragged stack while a merge slot is open for it (it leans in, as a card does)
       .kl-stack__merge          the pill on the target's bottom edge
   ===================================================================================================== */
.kl-stack.is-dragging-whole { z-index: calc(var(--kl-z-drag, 44) - 1); }
.kl-stack.is-over-stack { scale: calc(1 - .03 * var(--kl-motion-k)); transition: scale var(--kl-motion-stack-slot) var(--kl-motion-spring); }
.kl-stack__merge {
  position: absolute; left: calc(var(--kl-space-stack-pad) + 6px); bottom: 0; translate: 0 50%; z-index: 3;
  display: inline-flex; align-items: center; gap: 6px; max-width: calc(100% - 2 * var(--kl-space-stack-pad));
  height: 24px; padding: 0 11px 0 9px; box-sizing: border-box;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-stack-glass);
  -webkit-backdrop-filter: var(--kl-glass-card-filter); backdrop-filter: var(--kl-glass-card-filter);
  box-shadow: inset 0 0 0 1px var(--kl-color-stack-rim-strong), var(--kl-glass-card-shadow);
  color: var(--kl-color-text); font: var(--kl-font-caption); font-family: var(--kl-font-sans);
  white-space: nowrap; pointer-events: none;
  animation: kl-stack-merge-in var(--kl-motion-stack-slot) var(--kl-motion-spring) both;
}
.kl-stack__merge > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.kl-stack__merge b { font-weight: var(--kl-font-weight-semibold); }
.kl-stack__merge .kl-icon { --kl-icon-size: 14px; flex: none; color: var(--kl-stack-ink); }
@keyframes kl-stack-merge-in { from { opacity: 0; translate: 0 calc(50% + 4px * var(--kl-motion-k)); } to { opacity: 1; translate: 0 50%; } }

/* =====================================================================================================
   6. Increased contrast and reduced motion
   ===================================================================================================== */
@media (prefers-contrast: more) {
  .kl-stack { background: transparent; box-shadow: inset 0 0 0 2px var(--kl-color-line-strong); }
  .kl-stack--named { background: var(--kl-color-surface-sunken); }
  .kl-stack.is-joining { box-shadow: inset 0 0 0 3px var(--kl-color-text); }
  .kl-stack.is-preview, .kl-stack__slot { outline-color: var(--kl-color-text); border-color: var(--kl-color-text); }
  .kl-stack__tab, .kl-stack__badge { box-shadow: inset 0 0 0 1.5px var(--kl-color-line-strong); }
  .kl-stack__merge { background: var(--kl-color-surface); box-shadow: inset 0 0 0 2px var(--kl-color-text); }
  .kl-stack.is-kbd-held { box-shadow: inset 0 0 0 3px var(--kl-color-text); }
  .kl-stack__tab:focus-visible, .kl-stack__tab.is-focus { outline-color: var(--kl-color-text); }
}
[data-contrast="more"] .kl-stack, .kl-stack[data-contrast="more"] { background: transparent; box-shadow: inset 0 0 0 2px var(--kl-color-line-strong); }
[data-contrast="more"] .kl-stack--named { background: var(--kl-color-surface-sunken); }
[data-contrast="more"] .kl-stack.is-joining { box-shadow: inset 0 0 0 3px var(--kl-color-text); }
[data-contrast="more"] .kl-stack.is-preview { outline-color: var(--kl-color-text); }
[data-contrast="more"] .kl-stack__slot { border-color: var(--kl-color-text); }
[data-contrast="more"] :is(.kl-stack__tab, .kl-stack__badge) { box-shadow: inset 0 0 0 1.5px var(--kl-color-line-strong); }
[data-contrast="more"] .kl-stack__merge { background: var(--kl-color-surface); box-shadow: inset 0 0 0 2px var(--kl-color-text); }
[data-contrast="more"] .kl-stack.is-kbd-held { box-shadow: inset 0 0 0 3px var(--kl-color-text); }
[data-contrast="more"] :is(.kl-stack__tab:focus-visible, .kl-stack__tab.is-focus) { outline-color: var(--kl-color-text); }

/* Reduced motion: no settle, squash, stretch or breath; slots, frames and piles fade or jump into place */
@media (prefers-reduced-motion: reduce) {
  .kl-stack, .kl-stack > .kl-card, .kl-stack-shelf::before, .kl-stack-shelf::after { transition-duration: 0ms, 0ms, var(--kl-motion-fade), 0ms; }
  .kl-stack__slot, .kl-stack.is-preview { animation: kl-stack-preview-in var(--kl-motion-fade) linear both; }
  .kl-stack.is-forming, .kl-stack.is-letting-go { animation: none; }
  .kl-card.kl-stack-target > .kl-card__face, .kl-card.is-over-stack > .kl-card__face, .kl-stack.is-over-stack { scale: 1; }
  .kl-stack__merge, .kl-stack-keys.kl-tooltip { animation: kl-stack-preview-in var(--kl-motion-fade) linear both; translate: 0 50%; }
  .kl-stack-keys.kl-tooltip { translate: none; }
}
.kl-motion-reduce :is(.kl-stack, .kl-stack > .kl-card) { transition-duration: 0ms !important; }
.kl-motion-reduce .kl-stack__slot, .kl-motion-reduce .kl-stack.is-preview { animation: kl-stack-preview-in var(--kl-motion-fade) linear both; }
.kl-motion-reduce :is(.kl-stack.is-forming, .kl-stack.is-letting-go) { animation: none; }
.kl-motion-reduce .kl-card:is(.kl-stack-target, .is-over-stack) > .kl-card__face, .kl-motion-reduce .kl-stack.is-over-stack { scale: 1; }
.kl-motion-reduce :is(.kl-stack__merge, .kl-stack-keys.kl-tooltip) { animation: kl-stack-preview-in var(--kl-motion-fade) linear both; }

/* ===== question-card/question-card.css ===== */
/* =====================================================================================================
   Klippan master DS · Question card (.kl-ask)
   An agent asks Alban something and offers answers inside the card, like Claude's AskUserQuestion tool:
   a short question, two to four options each with a one-line consequence, one marked Recommended,
   a "Something else" answer, choose-any when the question allows it, and several questions in one card.

   Builds on v2: load ../../klippan-v2/combined/klippan.css first, then this file. Everything here is --kl- tokens
   and v2 classes (.kl-card, .kl-dot, .kl-radio, .kl-checkbox, .kl-btn, .kl-kbd, .kl-toast, kl-m-*). Tokens and icons
   this part would like from Foundations, Icons and Motion are read through a fallback and listed in NEEDS.md.

   Markup:
   <div class="kl-card kl-card--p<N> kl-card--question kl-ask" data-stage="0..3" data-ask="<state>" [data-blocking="false"]>
     [<span class="kl-card__rays kl-m-rays"></span>]   waiting and blocking only
     <div class="kl-card__face"> head · status line · .kl-card__more (the answering body) </div>
     <div class="kl-card__ctl"> chevron </div>
     <i class="kl-m-link-edge"></i>
   </div>
   States (data-ask): waiting · answered · expired · withdrawn · failed
   ===================================================================================================== */

/* ---- 1. The card: the asking project's hue; size from v2's .kl-card--question ------------------------------ */
.kl-ask {
  --kl-ask-ink: var(--kl-color-selection-ink);
  --kl-ask-soft: var(--kl-color-selection-soft);
}
/* The card is tinted with the hue of the project whose agent asked (.kl-card--p1..p8 sets the glass). Its ink and
   soft tint carry the agent's voice: who asked, and the Recommended tag. */
.kl-ask.kl-card--p1 { --kl-ask-ink: var(--kl-color-project-1-ink); --kl-ask-soft: var(--kl-color-project-1-soft); }
.kl-ask.kl-card--p2 { --kl-ask-ink: var(--kl-color-project-2-ink); --kl-ask-soft: var(--kl-color-project-2-soft); }
.kl-ask.kl-card--p3 { --kl-ask-ink: var(--kl-color-project-3-ink); --kl-ask-soft: var(--kl-color-project-3-soft); }
.kl-ask.kl-card--p4 { --kl-ask-ink: var(--kl-color-project-4-ink); --kl-ask-soft: var(--kl-color-project-4-soft); }
.kl-ask.kl-card--p5 { --kl-ask-ink: var(--kl-color-project-5-ink); --kl-ask-soft: var(--kl-color-project-5-soft); }
.kl-ask.kl-card--p6 { --kl-ask-ink: var(--kl-color-project-6-ink); --kl-ask-soft: var(--kl-color-project-6-soft); }
.kl-ask.kl-card--p7 { --kl-ask-ink: var(--kl-color-project-7-ink); --kl-ask-soft: var(--kl-color-project-7-soft); }
.kl-ask.kl-card--p8 { --kl-ask-ink: var(--kl-color-project-8-ink); --kl-ask-soft: var(--kl-color-project-8-soft); }

/* Name only: a short question plus 90, the most v2 allows (228 to 246) */
.kl-ask[data-stage="0"] { --kl-card-name-w: 228px; }
/* Compact: 24 wider than a project card's, so a short question fits beside the chevron */
.kl-ask[data-stage="1"] { width: calc(var(--kl-card-compact-w) + 24px); }
/* Expanded: v2's .kl-card--question (put it on the card) makes it 384 wide and as tall as its questions, up to 600,
   then it scrolls inside. */
.kl-ask[data-stage="3"] > .kl-card__face { padding-bottom: 14px; }
.kl-ask[data-stage="3"] .kl-card__more { gap: 12px; overflow: visible; }

/* The name is the question's short title, three words or about 16 characters ("Release date?"). A question card
   has no gear, only the chevron, so the head gives the title the gear's room. */
.kl-ask .kl-card__name-text { min-width: 0; }
.kl-ask .kl-card__head { padding-right: calc(28px + 8px * var(--kl-oc)); }
/* Expanded hides the recommended line: the Recommended tag on the option says it */
.kl-ask[data-stage="3"] .kl-ask__rec-line { display: none; }
/* v2 lifts the face above the rays; keep the chevron and the grip above both */
.kl-ask > .kl-card__ctl, .kl-ask > .kl-card__grip { z-index: 2; }

/* Who asked, in the agent-count slot: agent icon, role, project. In the asking project's ink. */
.kl-ask__from { color: var(--kl-ask-ink); max-width: 100%; }
.kl-ask__from > span:last-child { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-ask__from .kl-ask__count { color: var(--kl-color-text-secondary); font-weight: var(--kl-font-weight-medium); }

/* Full stage status line: the recommended answer, so a glance is often enough */
.kl-ask__rec-line b { color: var(--kl-ask-ink); font-weight: var(--kl-font-weight-semibold); }

/* Answered: the check takes the agent icon's place in the count slot, "Sent to Planner" (kl-m-count-pop on arrival) */
.kl-ask__stamp {
  display: inline-grid; place-items: center; flex: none; width: 16px; height: 16px; border-radius: var(--kl-radius-round);
  background: var(--kl-color-control); color: var(--kl-color-text-on-fill);
}
.kl-ask__stamp .kl-icon { --kl-icon-size: 11px; --kl-icon-stroke: 2.2; }

/* ---- 2. Several questions: a step strip, one pill per question --------------------------------------- */
.kl-ask__steps {
  display: flex; gap: 2px; padding: 2px; border-radius: var(--kl-radius-pill);
  background: var(--kl-color-control-fill); align-self: flex-start; max-width: 100%;
}
.kl-ask__step {
  display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 10px; border: 0; border-radius: var(--kl-radius-pill);
  background: transparent; color: var(--kl-color-text-secondary); font: var(--kl-font-label); cursor: pointer; white-space: nowrap;
  transition: background-color var(--kl-motion-press) var(--kl-motion-ease-out), color var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-ask__step:hover { color: var(--kl-color-text); }
.kl-ask__step[aria-current="step"], .kl-ask__step.is-current {
  background: var(--kl-color-surface-raised, var(--kl-color-surface)); color: var(--kl-color-text);
  box-shadow: var(--kl-shadow-knob);
}
.kl-ask__step:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 1px; }
.kl-ask__step .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2.2; color: var(--kl-color-control); }
.kl-ask__step-n { font-variant-numeric: tabular-nums; }

/* ---- 3. The question and its hint -------------------------------------------------------------------- */
.kl-ask__q {
  margin: 0; font: var(--kl-font-body); font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text);
  text-wrap: pretty;
}
.kl-ask__hint {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin: -6px 0 0;
  font: var(--kl-font-caption); color: var(--kl-color-text-secondary);
}

/* ---- 4. Options: a radio (choose one) or checkbox (choose any) row with a consequence line ------------- */
.kl-ask__opts { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; border: 0; min-width: 0; }
.kl-ask__opts-scroll { overflow: auto; margin: 0 -4px; padding: 0 4px; }

/* Uses v2's .kl-radio / .kl-checkbox for the box, the input and its states; this only lays out the row. */
.kl-ask__opt.kl-radio, .kl-ask__opt.kl-checkbox {
  display: grid; grid-template-columns: 16px minmax(0, 1fr) auto; align-items: start; column-gap: 10px;
  min-height: var(--kl-size-target); padding: 9px 10px 9px 12px; border-radius: var(--kl-radius-row);
  background: var(--kl-ask-row, color-mix(in srgb, var(--kl-color-surface) 62%, transparent));
  box-shadow: inset 0 0 0 1px var(--kl-ask-row-ring, var(--kl-color-line));
  transition: background-color var(--kl-motion-hover) ease, box-shadow var(--kl-motion-hover) ease;
}
.kl-ask__opt > input { left: 12px; top: 19px; }
.kl-ask__opt > .kl-radio__box, .kl-ask__opt > .kl-checkbox__box { margin-top: 2px; }
.kl-ask__opt:hover:not(.is-disabled, :has(input:disabled)), .kl-ask__opt.is-hover {
  --kl-ask-row: var(--kl-color-surface); --kl-ask-row-ring: var(--kl-color-line-strong);
}
/* Chosen: v2's selection style for chosen rows, an inset edge (Controls chose edge plus check) */
.kl-ask__opt:has(> input:checked), .kl-ask__opt.is-checked {
  --kl-ask-row: var(--kl-color-surface); --kl-ask-row-ring: var(--kl-color-selection);
  box-shadow: inset 0 0 0 2px var(--kl-color-selection);
}
.kl-ask__opt:has(> input:focus-visible), .kl-ask__opt.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-ask__opt:has(> input:focus-visible) > span, .kl-ask__opt.is-focus > span { outline: 0; }
.kl-ask__opt.is-disabled, .kl-ask__opt:has(> input:disabled) { --kl-ask-row: transparent; cursor: default; }

.kl-ask__opt-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.kl-ask__opt-title { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font: var(--kl-font-label-strong); color: var(--kl-color-text); }
.kl-ask__opt-why { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-ask__opt .kl-kbd { margin-top: 1px; color: var(--kl-color-text-secondary); }
.kl-ask__opt:has(> input:checked) .kl-kbd, .kl-ask__opt.is-checked .kl-kbd { color: var(--kl-color-text); }

/* Recommended: a small tag in the asking project's colour. Never selection blue (blue means chosen) and never a status
   colour: it is the agent's suggestion, in its project's voice. */
.kl-ask__rec {
  display: inline-flex; align-items: center; height: 18px; padding: 0 7px; border-radius: var(--kl-radius-pill);
  background: var(--kl-ask-soft); color: var(--kl-ask-ink);
  font: var(--kl-font-badge); font-weight: var(--kl-font-weight-semibold); letter-spacing: var(--kl-font-badge-tracking);
}

/* "Something else": the last row holds a field. Typing in it chooses it. */
.kl-ask__opt--other { grid-template-columns: 16px minmax(0, 1fr); align-items: center; padding-top: 6px; padding-bottom: 6px; }
.kl-ask__opt--other > input { top: 50%; }
.kl-ask__opt--other > .kl-radio__box, .kl-ask__opt--other > .kl-checkbox__box { margin-top: 0; }
.kl-ask__opt > .kl-ask__other {
  position: static; opacity: 1; pointer-events: auto;
  width: 100%; min-width: 0; height: 30px; margin: 0; padding: 0 2px; border: 0; outline: 0; background: transparent;
  color: var(--kl-color-text); font: var(--kl-font-label);
}
.kl-ask__other::placeholder { color: var(--kl-color-text-secondary); opacity: 1; }
.kl-ask__opt--other:has(.kl-ask__other:focus-visible) { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }

/* ---- 5. Footer: what happens if Alban waits, and the buttons (one primary) ----------------------------- */
.kl-ask__foot { display: flex; align-items: center; gap: 8px; padding-top: 2px; }
.kl-ask__note {
  flex: 1 1 auto; min-width: 0; margin: 0; display: flex; align-items: center; gap: 6px;
  font: var(--kl-font-caption); color: var(--kl-color-text-secondary);
}
.kl-ask__note .kl-icon { --kl-icon-size: 14px; flex: none; }
.kl-ask__note b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }
.kl-ask__foot .kl-btn { flex: none; }

/* ---- 6. States -------------------------------------------------------------------------------------- */
/* Waiting and blocking: the agent waits on Alban. v2's asking colour (--kl-card-approval) on the still dot
   (.kl-dot--approval) and the breathing rays, as on the asker (.is-asking) and on approvals. No edge on the
   question card itself: the asker carries it. */
.kl-ask[data-ask="waiting"] .kl-card__rays { border-color: var(--kl-card-approval); }

/* Waiting, not blocking: the agent carries on with the recommended answer meanwhile. Amber planning dot, no rays. */

/* Answered: collapses to compact with the chosen answer as its line; folds into the asker shortly after. */
.kl-ask[data-ask="answered"] .kl-card__status { color: var(--kl-color-text); }
.kl-ask__answer { display: inline; color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }
.kl-ask__answers { display: flex; flex-direction: column; gap: 4px; margin: 0; padding: 0; list-style: none; font: var(--kl-font-meta); }
.kl-ask__answers li { display: flex; gap: 6px; min-width: 0; color: var(--kl-color-text-secondary); }
.kl-ask__answers li b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Expired, withdrawn: no longer needed. Grey still dot, quieter title, options greyed but readable. */
.kl-ask:is([data-ask="expired"], [data-ask="withdrawn"]) .kl-card__name-text { color: var(--kl-color-text-secondary); }
.kl-ask:is([data-ask="expired"], [data-ask="withdrawn"]) .kl-ask__opt-title,
.kl-ask:is([data-ask="expired"], [data-ask="withdrawn"]) .kl-ask__q { color: var(--kl-color-text-secondary); }
.kl-ask:is([data-ask="expired"], [data-ask="withdrawn"]) .kl-ask__opts { opacity: .72; }
.kl-ask__gone {
  margin: 0; padding: 8px 10px; border-radius: var(--kl-radius-row);
  background: var(--kl-color-neutral-soft); color: var(--kl-color-neutral-ink); font: var(--kl-font-meta);
}
.kl-ask__gone b { font-weight: var(--kl-font-weight-semibold); }

/* Failed to reach the agent: the answer is kept, Send becomes Retry, one shake (kl-m-shake on the face). */
.kl-ask__err {
  display: flex; align-items: center; gap: 6px; margin: 0;
  font: var(--kl-font-caption); color: var(--kl-color-status-stopped-ink);
}
.kl-ask__err .kl-icon { --kl-icon-size: 14px; flex: none; }

/* ---- 7. On the asking card: an open-question count, and the line it writes -------------------------- */
/* The open-question count is v2 Board's .kl-countbadge.kl-countbadge--approval on the asking card's top edge (the
   approval magenta, as on .is-asking: a question waits on Alban). Pops in with kl-m-count-pop. No local badge. */

/* ---- 8. Docked beside the asker: the tie -------------------------------------------------------------- */
/* The question card docks 28 units from the side of the asking card with the most room (right first, then left,
   below), top edges aligned, tilted the other way. The tie is v2's project tie: svg.kl-link.kl-link--tie.kl-link--p<N>
   (the project's ink, a dot at each end, no arrowhead). Nothing to style here. */

/* ---- 9. Motion -------------------------------------------------------------------------------------- */
/* Everything reuses Motion: arrival kl-m-say-in on the card (it is the agent speaking) with kl-m-hop on the asker,
   stage changes on the stage spring, the chosen box on v2's spring-pop, the answered check kl-m-count-pop, the
   asker's line kl-m-write, a failed send kl-m-shake. Folding into the asker after an answer is v2's kl-m-fold
   (--kl-motion-ask-fold), started --kl-motion-ask-fold-after the answer through KlMotion.whenQuiet. */

/* ---- 10. Increased contrast and forced colours -------------------------------------------------------- */
/* The glass becomes v2's solid face by itself. Rows get the strong line so they read as buttons. */
[data-contrast="more"] .kl-ask__opt { --kl-ask-row: var(--kl-color-surface); --kl-ask-row-ring: var(--kl-color-line-strong); }
[data-contrast="more"] .kl-ask__rec { box-shadow: inset 0 0 0 1px currentColor; }
@media (prefers-contrast: more) {
  .kl-ask__opt { --kl-ask-row: var(--kl-color-surface); --kl-ask-row-ring: var(--kl-color-line-strong); }
  .kl-ask__rec { box-shadow: inset 0 0 0 1px currentColor; }
}
@media (forced-colors: active) {
  .kl-ask__opt { border: 1px solid CanvasText; }
  .kl-ask__opt:has(> input:checked) { border: 2px solid Highlight; }
  .kl-ask__rec { border: 1px solid CanvasText; }
}

/* =====================================================================================================
   Answering from elsewhere (2026-10-13): the Alerts window lists every open question, and the prompter can
   answer one. The question card stays the source of truth: a choice made in one place shows in the other two,
   and Send in any of them answers the same question once.
   ===================================================================================================== */

/* ---- 11. Hue helpers for surfaces that are not the card ---------------------------------------------- */
/* Rows in the Alerts window and the prompter's question strip speak in the asking project's voice too. Put
   .kl-ask-hue--p<N> on the row, or on the prompter root so the strip and the status line both get it; the card
   itself keeps using .kl-card--p<N>. Without a hue they fall back to the selection blue. */
.kl-ask-hue--p1 { --kl-ask-ink: var(--kl-color-project-1-ink); --kl-ask-soft: var(--kl-color-project-1-soft); --kl-ask-mark: var(--kl-color-project-1); }
.kl-ask-hue--p2 { --kl-ask-ink: var(--kl-color-project-2-ink); --kl-ask-soft: var(--kl-color-project-2-soft); --kl-ask-mark: var(--kl-color-project-2); }
.kl-ask-hue--p3 { --kl-ask-ink: var(--kl-color-project-3-ink); --kl-ask-soft: var(--kl-color-project-3-soft); --kl-ask-mark: var(--kl-color-project-3); }
.kl-ask-hue--p4 { --kl-ask-ink: var(--kl-color-project-4-ink); --kl-ask-soft: var(--kl-color-project-4-soft); --kl-ask-mark: var(--kl-color-project-4); }
.kl-ask-hue--p5 { --kl-ask-ink: var(--kl-color-project-5-ink); --kl-ask-soft: var(--kl-color-project-5-soft); --kl-ask-mark: var(--kl-color-project-5); }
.kl-ask-hue--p6 { --kl-ask-ink: var(--kl-color-project-6-ink); --kl-ask-soft: var(--kl-color-project-6-soft); --kl-ask-mark: var(--kl-color-project-6); }
.kl-ask-hue--p7 { --kl-ask-ink: var(--kl-color-project-7-ink); --kl-ask-soft: var(--kl-color-project-7-soft); --kl-ask-mark: var(--kl-color-project-7); }
.kl-ask-hue--p8 { --kl-ask-ink: var(--kl-color-project-8-ink); --kl-ask-soft: var(--kl-color-project-8-soft); --kl-ask-mark: var(--kl-color-project-8); }

/* The project's mark: the 8 px rounded square v2 uses for a project in windows and the prompter, in its hue */
.kl-ask-mark { flex: none; display: inline-block; width: 8px; height: 8px; border-radius: 2.5px; background: var(--kl-ask-mark, var(--kl-color-primary)); }

/* ---- 12. In the Alerts window: open questions above stopped projects ---------------------------------- */
/* Markup, inside v2's .kl-win.kl-win--alerts > .kl-win__body:
   <div class="kl-win-heading"><h4 class="kl-win-heading__label">Questions · 3</h4> [Use all recommended] </div>
   <div class="kl-win-list kl-ask-list">
     <article class="kl-ask-row kl-ask-hue--p<N> [is-open | is-answered | is-gone]">
       <div class="kl-ask-row__sum"> dot · __head (__title, __time) · __from (mark, agent · project) · __line </div>
       <span class="kl-ask-row__act"> Answer / collapse chevron / Undo </span>
       <div class="kl-ask-row__body"><div class="kl-ask-row__in"> steps · question · .kl-ask__opts · __foot </div></div>
     </article>
   </div>
   One row is open at a time. The options are the card's own .kl-ask__opt rows, so the choice looks and behaves
   the same in both places. */
.kl-ask-list { padding: 0 var(--kl-space-3); }
.kl-ask-row {
  display: grid;
  grid-template-columns: 10px minmax(0, 1fr) auto;
  column-gap: var(--kl-space-3);
  padding: var(--kl-space-3) 0;
  font: var(--kl-font-meta);
}
.kl-ask-row + .kl-ask-row { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-ask-row__sum {
  grid-column: 1 / 3; grid-row: 1;
  display: grid; grid-template-columns: 10px minmax(0, 1fr); column-gap: var(--kl-space-3); row-gap: 2px;
  min-width: 0; cursor: pointer; border-radius: var(--kl-radius-row);
}
.kl-ask-row__sum > .kl-dot { grid-row: 1; margin-top: 4px; }
.kl-ask-row__sum:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 4px; }
.kl-ask-row__head { display: flex; align-items: baseline; gap: var(--kl-space-2); min-width: 0; }
.kl-ask-row__title {
  min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); color: var(--kl-color-text);
}
.kl-ask-row__time { flex: none; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.kl-ask-row__from {
  grid-column: 2; display: flex; align-items: center; gap: 6px; min-width: 0;
  font: var(--kl-font-caption); font-weight: var(--kl-font-weight-semibold); color: var(--kl-ask-ink, var(--kl-color-selection-ink));
}
.kl-ask-row__from > span:last-child { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-ask-row__line { grid-column: 2; min-width: 0; color: var(--kl-color-text-secondary); }
.kl-ask-row__line b { color: var(--kl-ask-ink, var(--kl-color-selection-ink)); font-weight: var(--kl-font-weight-semibold); }
.kl-ask-row__act { grid-column: 3; grid-row: 1; align-self: start; display: flex; align-items: center; gap: var(--kl-space-1); }
.kl-ask-row__act .kl-iconbtn--chev svg { rotate: 180deg; }

/* Open: the body unfolds under the summary on the expand timing (0fr to 1fr, like the prompter's drawer). The
   recommended line hides; the Recommended tag on the option says it. */
.kl-ask-row__body {
  grid-column: 2 / 4; grid-row: 2;
  display: grid; grid-template-rows: 0fr; min-width: 0;
  transition: grid-template-rows var(--kl-motion-collapse) var(--kl-motion-ease-out);
}
.kl-ask-row__in {
  min-height: 0; overflow: hidden;
  display: flex; flex-direction: column; gap: 10px;
  opacity: 0; visibility: hidden;
  transition: opacity var(--kl-motion-fade-out) ease, visibility 0s linear var(--kl-motion-collapse);
}
.kl-ask-row.is-open .kl-ask-row__body { grid-template-rows: 1fr; transition-duration: var(--kl-motion-expand); }
.kl-ask-row.is-open .kl-ask-row__in {
  opacity: 1; visibility: visible;
  transition: opacity var(--kl-motion-reveal) var(--kl-motion-ease-out) var(--kl-motion-reveal-delay), visibility 0s;
}
.kl-ask-row.is-open .kl-ask-row__line { display: none; }
.kl-ask-row__in > :first-child { margin-top: var(--kl-space-3); }
/* Room for the option rows' focus ring inside the clipped body */
.kl-ask-row__in { padding: 0 3px 3px; margin: 0 -3px -3px; }
.kl-ask-row .kl-ask__q { font: var(--kl-font-label-strong); }
.kl-ask-row .kl-ask__opt.kl-radio, .kl-ask-row .kl-ask__opt.kl-checkbox { --kl-ask-row: var(--kl-color-surface-sunken); }
.kl-ask-row .kl-ask__opt:hover:not(.is-disabled, :has(input:disabled)), .kl-ask-row .kl-ask__opt.is-hover { --kl-ask-row: var(--kl-color-surface); }
.kl-ask-row__foot { display: flex; align-items: center; gap: var(--kl-space-2); }
.kl-ask-row__foot .kl-ask__note { flex: 1 1 auto; }
.kl-ask-row__foot .kl-btn { flex: none; }

/* Answered: green dot while the agent acts on it, "Sent to Planner: 14 Nov" and Undo. The row stays, quieter,
   until the window closes, like an acknowledged alert. */
.kl-ask-row.is-answered .kl-ask-row__title,
.kl-ask-row.is-gone .kl-ask-row__title { color: var(--kl-color-text-secondary); }
.kl-ask-row__sent { display: flex; align-items: center; gap: 6px; min-width: 0; color: var(--kl-color-text); }
.kl-ask-row__sent-to { flex: none; white-space: nowrap; color: var(--kl-color-text-secondary); }
.kl-ask-row__sent .kl-ask__stamp { width: 14px; height: 14px; }
.kl-ask-row__sent .kl-ask__stamp .kl-icon { --kl-icon-size: 10px; }
.kl-ask-row__sent b { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-weight: var(--kl-font-weight-semibold); }
.kl-ask-row.is-gone .kl-ask-row__line { color: var(--kl-color-text-secondary); }

/* The Alerts card on the board carries the same count as the asking cards: Board's .kl-section--alerts.is-asking
   with .kl-countbadge--approval (Board PR #42, 84155bf). Nothing local. */

/* ---- 13. In the prompter: answer the question you picked up --------------------------------------------- */
/* Markup, inside v2's .kl-prompter (add .is-answering and the hue on the root):
   <section class="kl-prompter kl-prompter--anchored is-answering kl-ask-hue--p<N>">
     <div class="kl-ask-strip"><div class="kl-ask-strip__in">
       <div class="kl-ask-strip__head"> mark · __from "Planner · Atlas asks" · [__kept] · __count "1 of 3" · prev · next · Not now </div>
       <p class="kl-ask-strip__q">the full question</p>
       [.kl-ask__steps]
       <div class="kl-ask-strip__opts" role="radiogroup|group"> .kl-ask-chip × 2–4 </div>
       <p class="kl-ask-strip__why">the consequence of the chosen or hovered choice</p>
     </div></div>
     <div class="kl-prompter__compose"> v2's draft, destination, status, model, Send ("Answer Planner") </div>
   </section>
   The strip opens only when Alban asks for it: the pending pill on the prompter's top edge, or linking a question
   card to the prompter. Typing in the draft answers as Something else. */
.kl-ask-strip {
  display: grid; grid-template-rows: 0fr; min-width: 0;
  transition: grid-template-rows var(--kl-motion-collapse) var(--kl-motion-ease-out);
}
.kl-ask-strip__in {
  min-height: 0; overflow: hidden;
  display: flex; flex-direction: column; gap: 8px;
  opacity: 0; visibility: hidden;
  transition: opacity var(--kl-motion-fade-out) ease, visibility 0s linear var(--kl-motion-collapse);
}
.kl-prompter.is-answering .kl-ask-strip { grid-template-rows: 1fr; transition-duration: var(--kl-motion-expand); }
.kl-prompter.is-answering .kl-ask-strip__in {
  opacity: 1; visibility: visible;
  transition: opacity var(--kl-motion-reveal) var(--kl-motion-ease-out) var(--kl-motion-reveal-delay), visibility 0s;
}
/* A hairline between the question and the draft; padding keeps the chips' focus ring inside the clip */
.kl-ask-strip__in { padding: 3px 3px 0; margin: -3px -3px 0; }
.kl-prompter.is-answering .kl-ask-strip__in { padding-bottom: var(--kl-space-3); margin-bottom: var(--kl-space-3); box-shadow: 0 1px 0 var(--kl-color-line); }

.kl-ask-strip__head { display: flex; align-items: center; gap: 6px; min-width: 0; height: 24px; }
.kl-ask-strip__from {
  min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  font: var(--kl-font-caption); font-weight: var(--kl-font-weight-semibold); color: var(--kl-ask-ink, var(--kl-color-selection-ink));
}
.kl-ask-strip__kept {
  display: inline-flex; align-items: center; gap: 4px; flex: none; margin-left: var(--kl-space-1);
  font: var(--kl-font-caption); color: var(--kl-color-text-secondary); white-space: nowrap;
}
.kl-ask-strip__kept .kl-icon { --kl-icon-size: 12px; }
.kl-ask-strip__count { margin-left: auto; flex: none; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.kl-ask-strip__head .kl-iconbtn { flex: none; width: 24px; height: 24px; min-width: 24px; }
.kl-ask-strip__head .kl-iconbtn .kl-icon { --kl-icon-size: 14px; }
.kl-ask-strip__q { margin: 0; font: var(--kl-font-label-strong); color: var(--kl-color-text); text-wrap: pretty; }
.kl-ask-strip .kl-ask__steps .kl-ask__step { height: 22px; padding: 0 8px; font: var(--kl-font-caption); font-weight: var(--kl-font-weight-medium); }

/* Choices as chips: a key number, the answer, a dot in the project's ink on the recommended one. Chosen uses v2's
   selection: the soft blue fill, a 2 px edge and the check in place of the number. */
.kl-ask-strip__opts { display: flex; flex-wrap: wrap; gap: 6px; }
.kl-ask-chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  height: 28px; padding: 0 10px 0 5px; border: 0; border-radius: var(--kl-radius-pill);
  background: var(--kl-color-control-fill); color: var(--kl-color-text);
  font: var(--kl-font-label); font-family: var(--kl-font-sans); white-space: nowrap; cursor: pointer;
  transition: background-color var(--kl-motion-press) ease, box-shadow var(--kl-motion-press) ease, scale var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-ask-chip__text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.kl-ask-chip .kl-kbd { flex: none; min-width: 18px; height: 18px; border-radius: var(--kl-radius-pill); color: var(--kl-color-text-secondary); }
.kl-ask-chip__check {
  display: none; place-items: center; flex: none; width: 18px; height: 18px; border-radius: var(--kl-radius-round);
  background: var(--kl-color-selection); color: var(--kl-color-text-on-fill);
}
.kl-ask-chip__check .kl-icon { --kl-icon-size: 11px; --kl-icon-stroke: 2.2; }
.kl-ask-chip__rec { flex: none; width: 6px; height: 6px; border-radius: var(--kl-radius-round); background: var(--kl-ask-ink, var(--kl-color-selection-ink)); }
.kl-ask-chip:hover, .kl-ask-chip.is-hover { background: var(--kl-color-button-secondary); }
.kl-ask-chip:active, .kl-ask-chip.is-pressed { background: var(--kl-color-control-fill-pressed); scale: .97; }
.kl-ask-chip:focus-visible, .kl-ask-chip.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-ask-chip[aria-checked="true"], .kl-ask-chip.is-checked {
  background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink);
  box-shadow: inset 0 0 0 2px var(--kl-color-selection);
}
.kl-ask-chip[aria-checked="true"] .kl-kbd, .kl-ask-chip.is-checked .kl-kbd { display: none; }
.kl-ask-chip[aria-checked="true"] .kl-ask-chip__check, .kl-ask-chip.is-checked .kl-ask-chip__check { display: inline-grid; }
.kl-ask-chip:disabled { opacity: .5; cursor: default; }
.kl-ask-strip__why { margin: 0; min-height: 18px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-ask-strip__why b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }

/* The recommended answer in the status slot while nothing is chosen, in the project's ink like on the card */
.kl-prompter__status .kl-ask-strip__rec b { color: var(--kl-ask-ink, var(--kl-color-selection-ink)); font-weight: var(--kl-font-weight-semibold); }

/* The pending pill: open questions wait on the prompter's top edge. Waiting on Alban, so v2's approval magenta
   (--kl-card-approval, from --kl-color-status-approval) like the card badge and .is-asking. It is a
   button: pressing it opens the strip with the oldest blocking question. It pops in (kl-m-count-pop) through the
   quiet gate, so never while Alban types, drags or links, and it hides while the strip is open. */
.kl-ask-pending {
  position: absolute; left: 50%; top: 0; translate: -50% -50%; z-index: 2;
  display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 10px 0 8px; border: 0;
  border-radius: var(--kl-radius-pill); background: var(--kl-card-approval); color: var(--kl-color-text-on-fill);
  box-shadow: 0 0 0 3px var(--kl-color-surface);
  font: var(--kl-font-badge); font-family: var(--kl-font-sans); font-weight: var(--kl-font-weight-semibold);
  font-variant-numeric: tabular-nums; white-space: nowrap; cursor: pointer;
  transition: scale var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-ask-pending .kl-icon { --kl-icon-size: 13px; --kl-icon-stroke: 2; }
.kl-ask-pending:hover { scale: 1.04; }
.kl-ask-pending:active { scale: .97; }
.kl-ask-pending:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 3px; }
.kl-prompter.is-answering .kl-ask-pending { display: none; }

/* ---- 14. Increased contrast, forced colours and reduced motion for 11 to 13 ------------------------------ */
[data-contrast="more"] .kl-ask-chip { box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
[data-contrast="more"] .kl-ask-chip[aria-checked="true"] { box-shadow: inset 0 0 0 2px var(--kl-color-selection); }
[data-contrast="more"] .kl-ask-chip__rec { box-shadow: 0 0 0 1px var(--kl-color-surface), 0 0 0 2px currentColor; }
@media (prefers-contrast: more) {
  .kl-ask-chip { box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
  .kl-ask-chip[aria-checked="true"] { box-shadow: inset 0 0 0 2px var(--kl-color-selection); }
}
@media (forced-colors: active) {
  .kl-ask-chip { border: 1px solid CanvasText; }
  .kl-ask-chip[aria-checked="true"] { border: 2px solid Highlight; }
  .kl-ask-pending { border: 1px solid CanvasText; }
}
/* Reduced motion: no unfolding, the strip and the row body only fade */
@media (prefers-reduced-motion: reduce) {
  .kl-ask-row__body, .kl-ask-strip { transition: none; }
  .kl-ask-chip, .kl-ask-pending { transition: none; scale: 1; }
}
.kl-motion-reduce :is(.kl-ask-row__body, .kl-ask-strip) { transition: none; }
.kl-motion-reduce :is(.kl-ask-chip, .kl-ask-pending) { transition: none; scale: 1; }

/* ===== teach-card/teach-card.css ===== */
/* =====================================================================================================
   Klippan master DS · Teach card (.kl-teach)
   "Teach an agent to do something": paste a link, the agent opens it, explores the site read-only and writes down
   what it can do there. The learned skill then ties to project cards and lives in Knowledge.

   Builds on v2: load ../../klippan-v2/combined/klippan.css first, then this file. Everything here is --kl- tokens and
   v2 classes (.kl-card, .kl-card--teach, .kl-dot, .kl-btn, .kl-field, .kl-run, .kl-cardmeter, .kl-win--knowledge,
   .kl-link--teach, .kl-say--teach, kl-m-*) and v2's teach tokens (--kl-color-teach*, --kl-glass-card-teach, lime).

   Markup: <div class="kl-card kl-card--teach kl-teach" data-stage="0..3" data-teach="<state>"> ... <i class="kl-m-link-edge"></i></div>
   (.kl-card--teach is v2 Board's size class: compact 264, expanded 380.)
   States (data-teach): empty · reading · learning · paused · signin · check · failed · learned · stale
   ===================================================================================================== */

.kl-teach {
  /* The teach kind's hue (v2 Foundations: lime) */
  --kl-teach: var(--kl-color-teach);
  --kl-teach-soft: var(--kl-color-teach-soft);
  --kl-teach-ink: var(--kl-color-teach-ink);
  --kl-card-glass: var(--kl-glass-card-teach);
}
.kl-teach .kl-card__more { gap: 10px; overflow: hidden; }
.kl-teach .kl-card__status, .kl-teach .kl-card__more > :not(.kl-teach__scroll) { flex: none; }
/* Long lists scroll inside the card; the footer under them stays put */
.kl-teach__scroll { display: flex; flex-direction: column; gap: 10px; flex: 1 1 auto; min-height: 0; overflow: auto; margin: 0 -4px; padding: 0 4px; }

/* Name: an empty card's name is a prompt, so it reads quieter */
.kl-teach[data-teach="empty"] .kl-card__name-text { color: var(--kl-color-text-secondary); }
/* The count slot: agents while it learns, a check and the number of actions once learned */
.kl-teach .kl-card__agents.is-skill { color: var(--kl-teach-ink); }

/* The learned check that lands beside the name (kl-m-count-pop when it arrives) */
.kl-teach__stamp {
  display: inline-grid; place-items: center; flex: none; width: 18px; height: 18px; border-radius: var(--kl-radius-round);
  background: var(--kl-teach); color: var(--kl-color-text-on-fill);
}
.kl-teach__stamp .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2.2; }

/* ---- Site row: monogram tile, host, when ------------------------------------------------------------- */
.kl-teach__site { display: flex; align-items: center; gap: 10px; min-width: 0; }
.kl-teach__mono {
  display: grid; place-items: center; flex: none; width: 28px; height: 28px; border-radius: var(--kl-radius-control);
  background: var(--kl-teach-soft); color: var(--kl-teach-ink);
  font: var(--kl-font-label-strong); text-transform: lowercase;
}
.kl-teach__mono--lg { width: 36px; height: 36px; border-radius: var(--kl-radius-tile); font: var(--kl-font-headline); }
.kl-teach__mono .kl-icon { --kl-icon-size: 16px; }
.kl-teach__host { display: flex; flex-direction: column; min-width: 0; }
.kl-teach__host > b { font: var(--kl-font-label-strong); color: var(--kl-color-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kl-teach__host > span { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---- Empty: the link field, the optional goal, how it learns ----------------------------------------- */
.kl-teach__url {
  --kl-field-ring: var(--kl-color-field-border); --kl-field-halo: 0 0 0 0 transparent;
  display: flex; align-items: center; gap: 8px; height: var(--kl-size-button-large, 36px); padding: 0 6px 0 10px;
  border-radius: var(--kl-radius-control); background: var(--kl-color-surface); color: var(--kl-color-text-secondary);
  box-shadow: inset 0 0 0 1px var(--kl-field-ring), var(--kl-field-halo);
  transition: box-shadow var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-teach__url:hover { --kl-field-ring: var(--kl-color-line-strong); }
.kl-teach__url:focus-within, .kl-teach__url.is-focus { --kl-field-ring: var(--kl-color-focus); --kl-field-halo: 0 0 0 3px var(--kl-color-selection-soft); }
.kl-teach__url.is-error { --kl-field-ring: var(--kl-color-status-stopped); --kl-field-halo: 0 0 0 3px var(--kl-color-status-stopped-soft); }
.kl-teach__url .kl-icon { --kl-icon-size: 16px; }
.kl-teach__input {
  flex: 1 1 auto; min-width: 0; height: 100%; margin: 0; padding: 0; border: 0; outline: 0; background: transparent;
  color: var(--kl-color-text); font: var(--kl-font-body);
}
.kl-teach__input::placeholder { color: var(--kl-color-text-secondary); opacity: 1; }
.kl-teach__go { flex: none; }
.kl-teach__label { display: block; margin: 0 0 6px; font: var(--kl-font-label); color: var(--kl-color-text); }
.kl-teach__label > span { color: var(--kl-color-text-secondary); font-weight: var(--kl-font-weight-regular); }
.kl-teach__how { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-teach__how .kl-icon { --kl-icon-size: 14px; color: var(--kl-teach-ink); }
.kl-teach__safe { display: inline-flex; align-items: center; gap: 5px; }
.kl-teach__ideas { display: flex; flex-wrap: wrap; gap: 6px; }

/* Drop a link or a bookmark on the card: its whole edge lights (Motion's kl-m-target) and the face says so */
.kl-teach__drop {
  position: absolute; inset: 6px; z-index: 2; display: none; place-items: center; border-radius: calc(var(--kl-card-r) - 6px);
  background: color-mix(in srgb, var(--kl-teach-soft) 82%, transparent);
  font: var(--kl-font-label-strong); color: var(--kl-teach-ink); text-align: center;
}
.kl-teach.is-dropping .kl-teach__drop { display: grid; }
.kl-teach.is-dropping .kl-card__face > * { opacity: 0; }

/* ---- Learning: counts, the page map, the trail ------------------------------------------------------- */
.kl-teach__stats { display: flex; align-items: flex-end; gap: 18px; }
.kl-teach__stat { display: flex; flex-direction: column; gap: 0; }
.kl-teach__stat > b { font: var(--kl-font-title); color: var(--kl-color-text); font-variant-numeric: tabular-nums; }
.kl-teach__stat > span { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-teach__stats .kl-teach__map { margin-left: auto; }

/* One square per page it has seen, filling left to right, top to bottom. The page it is on breathes (kl-m-dot). */
.kl-teach__map { display: grid; grid-template-columns: repeat(10, 9px); grid-auto-rows: 9px; gap: 4px; }
.kl-teach__pg { width: 9px; height: 9px; border-radius: 3px; background: transparent; box-shadow: inset 0 0 0 1.5px var(--kl-color-line-strong); color: var(--kl-teach); }
.kl-teach__pg.is-seen { background: var(--kl-teach); box-shadow: none; }
.kl-teach__pg.is-now { background: var(--kl-teach); box-shadow: none; border-radius: var(--kl-radius-round); }
.kl-teach__pg.is-locked { box-shadow: inset 0 0 0 1.5px var(--kl-color-status-approval); background: var(--kl-color-status-approval-soft); }   /* behind a sign-in: waits on Alban */
.kl-teach__pg.is-skipped { background: var(--kl-color-switch-off); box-shadow: none; }
.kl-teach__pg.is-failed { background: var(--kl-color-status-stopped); box-shadow: none; }

.kl-teach__trail {
  display: flex; align-items: center; gap: 4px; min-width: 0; overflow: hidden; white-space: nowrap;
  font: var(--kl-font-caption); font-family: var(--kl-font-mono); color: var(--kl-color-text-secondary);
}
.kl-teach__trail > span { overflow: hidden; text-overflow: ellipsis; }
.kl-teach__trail > span:last-of-type { color: var(--kl-color-text); }
.kl-teach__trail > i { font-style: normal; opacity: .6; }

/* ---- The action list: what it found, and how sure it is ----------------------------------------------- */
.kl-teach__head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 2px 0 -4px;
  font: var(--kl-font-caption); font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text-secondary);
}
.kl-teach__acts { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0; list-style: none; }
.kl-teach__act {
  display: grid; grid-template-columns: 18px minmax(0, 1fr) auto; align-items: center; gap: 8px;
  min-height: 26px; padding: 0 8px 0 6px; border-radius: var(--kl-radius-row);
  font: var(--kl-font-meta); color: var(--kl-color-text);
}
.kl-teach__act .kl-icon { --kl-icon-size: 16px; color: var(--kl-color-text-secondary); }
.kl-teach__verb { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kl-teach__verb small { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-teach__tag { font: var(--kl-font-badge); font-weight: var(--kl-font-weight-medium); color: var(--kl-color-text-secondary); white-space: nowrap; }
/* Tried and it worked */
.kl-teach__act--tried .kl-icon { color: var(--kl-teach-ink); }
/* Seen on the page but never pressed: things that change something (save, book, post, pay) are never tried while learning */
.kl-teach__act--asks { background: var(--kl-color-status-planning-soft); }
.kl-teach__act--asks .kl-icon, .kl-teach__act--asks .kl-teach__tag { color: var(--kl-color-status-planning-ink); }
/* Behind a sign-in it did not get past */
.kl-teach__act--locked { color: var(--kl-color-text-secondary); }
.kl-teach__act--locked .kl-icon { color: var(--kl-color-status-approval-ink); }
/* Broke on the last run (out of date) */
.kl-teach__act--broken .kl-icon, .kl-teach__act--broken .kl-teach__tag { color: var(--kl-color-status-stopped-ink); }
.kl-teach__act--broken .kl-teach__verb { text-decoration: line-through; text-decoration-color: var(--kl-color-status-stopped); }
/* The row just found: lit for a moment (kl-m-reveal brings it in) */
.kl-teach__act.is-new { background: var(--kl-teach-soft); }

/* ---- Needs you: sign-in or a check wait on Alban (magenta, --asking, on a .kl-card.is-asking card); a failure is stopped (red) */
.kl-teach__ask {
  display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: 4px 10px; padding: 12px;
  border-radius: var(--kl-radius-menu); background: var(--kl-color-surface);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
}
.kl-teach__ask-tile {
  grid-row: span 2; display: grid; place-items: center; width: 32px; height: 32px; border-radius: var(--kl-radius-control);
  background: var(--kl-color-status-stopped-soft); color: var(--kl-color-status-stopped-ink);
}
.kl-teach__ask-tile .kl-icon { --kl-icon-size: 18px; }
.kl-teach__ask b { font: var(--kl-font-label-strong); color: var(--kl-color-text); }
.kl-teach__ask p { margin: 0; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-teach__ask-acts { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.kl-teach__ask--asking .kl-teach__ask-tile { background: var(--kl-color-status-approval-soft); color: var(--kl-color-status-approval-ink); }
.kl-teach__ask--stale .kl-teach__ask-tile { background: var(--kl-color-status-planning-soft); color: var(--kl-color-status-planning-ink); }
.kl-teach__ask--paused .kl-teach__ask-tile { background: var(--kl-color-control-fill); color: var(--kl-color-text-secondary); }
.kl-teach__ask--wait .kl-teach__ask-tile { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }

/* ---- Footer: buttons, "used by" -------------------------------------------------------------------------- */
.kl-teach__foot { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: auto; padding-top: 2px; }
.kl-teach__foot .kl-teach__push { margin-left: auto; }
.kl-teach .kl-teach__foot:last-child { padding-right: 18px; }   /* clear of the corner grip */
.kl-teach__used { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-teach__proj {
  display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 8px; border-radius: var(--kl-radius-pill);
  background: var(--kl-color-surface); box-shadow: inset 0 0 0 1px var(--kl-color-line);
  font: var(--kl-font-badge); font-weight: var(--kl-font-weight-medium); color: var(--kl-color-text);
}
.kl-teach__proj::before { content: ""; width: 7px; height: 7px; border-radius: var(--kl-radius-round); background: var(--kl-proj, var(--kl-color-project-1)); }

/* ---- Small forms --------------------------------------------------------------------------------------------- */
/* Compact and full keep the project card's anatomy: dot, name, count, one status line. Nothing extra. */
.kl-teach[data-stage="0"] .kl-teach__stamp { display: none; }

/* ===== adaptive-card/adaptive-card.css ===== */
/* Klippan master design system, first draft: the adaptive card.
   A project card whose input section shapes itself to what you give it: a sentence, a link or a file.
   "Search Airbnb listings for me" grows Where, Dates, Guests and Budget; a thesis PDF grows File, Style and Due.
   Each field can carry a suggestion read from your connected sources (Mail, Messages, Calendar, past searches),
   always with where it came from.

   Builds on Klippan v2. Load ../../klippan-v2/combined/klippan.css first (tokens, motion, icons, board, controls),
   then this file. Every value is a --kl- token or a component-local --kl-ac-* size. Classes are kl-ac-*.
   The card itself is v2's .kl-card + .kl-card__face, so glass, hue, dot, stages, linking glow and contrast all carry over. */

/* ===== 1. The card at expanded: grows with its input section =====
   Markup: <article class="kl-card kl-ac kl-card--grow kl-card--wide">. v2 Board's .kl-card--grow makes the expanded card
   as tall as its face with overflow visible (so the calendar and the "why" popover reach past the edge); .kl-card--wide
   sets the 420 width (--kl-card-expanded-w-wide). This file only adds the narrower blank card and the face spacing. */
.kl-card.kl-ac {
  --kl-ac-w-blank: 360px;    /* a new card, before it knows what it is for */
  --kl-ac-gap: 14px;
  transition: width var(--kl-motion-expand) var(--kl-motion-ease-out);
}
.kl-card.kl-ac[data-stage="3"].is-blank { --kl-card-w: var(--kl-ac-w-blank); }
.kl-card.kl-ac[data-stage="3"] > .kl-card__face { gap: var(--kl-ac-gap); padding: 16px 20px 18px; }
/* The name row keeps v2's layout; a blank card's name is a quiet placeholder */
.kl-ac .kl-card__name-text.is-placeholder { color: var(--kl-color-text-secondary); font-weight: var(--kl-font-weight-semibold); }
.kl-ac .kl-card__status { -webkit-line-clamp: 2; }

/* Icons in adaptive parts are 16 px, inside a card or shown on their own */
:is(.kl-ac-brief, .kl-ac-given, .kl-ac-shape, .kl-ac-field, .kl-ac-sugg-wrap, .kl-ac-results, .kl-ac-sources, .kl-ac-foot) .kl-icon { --kl-icon-size: 16px; }

/* Sections inside the face */
.kl-ac__section { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.kl-ac__title {
  display: flex; align-items: center; gap: 8px; margin: 0;
  font: var(--kl-font-label-strong); color: var(--kl-color-text-secondary);
}
.kl-ac__title > .kl-ac__aside { margin-left: auto; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-ac__rule { height: 1px; margin: 0 -20px; background: var(--kl-color-line); border: 0; }

/* Fields open one after another with v2 Motion's kl-m-grow (+ .is-in). An open menu or popover sits over the blocks after it. */
.kl-ac .kl-m-grow:has(.kl-menu, .kl-ac-why, .kl-ac-cal) { position: relative; z-index: 4; }
.kl-card.kl-ac .kl-menu { background: var(--kl-color-surface-raised); }   /* opaque over the card, like the why popover */

/* ===== 2. The brief: what a new card is for ===== */
.kl-ac-brief {
  position: relative; display: flex; flex-direction: column; gap: 8px; padding: 10px;
  border-radius: var(--kl-radius-draft); background: var(--kl-color-surface);
  box-shadow: inset 0 0 0 1px var(--kl-color-field-border);
  transition: box-shadow var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-ac-brief:focus-within, .kl-ac-brief.is-focus { box-shadow: inset 0 0 0 1px var(--kl-color-focus), 0 0 0 3px var(--kl-color-selection-soft); }
.kl-ac-brief__input {
  display: block; width: 100%; min-height: 60px; margin: 0; padding: 2px 2px 0; border: 0; outline: 0; resize: none;
  background: transparent; color: var(--kl-color-text); font: var(--kl-font-body);
}
.kl-ac-brief__input::placeholder { color: var(--kl-color-text-secondary); opacity: 1; }
.kl-ac-brief__given { display: flex; flex-wrap: wrap; gap: 6px; }
.kl-ac-brief__bar { display: flex; align-items: center; gap: 4px; }
.kl-ac-brief__hint { margin-left: auto; margin-right: 6px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
/* Something dragged over the brief: a dashed selection edge and one plain line */
.kl-ac-brief.is-drop { box-shadow: none; outline: 1.5px dashed var(--kl-color-selection); outline-offset: -1.5px; background: var(--kl-color-selection-soft); }
.kl-ac-brief__drop { position: absolute; inset: 0; display: none; place-items: center; border-radius: inherit;
  font: var(--kl-font-label); color: var(--kl-color-selection-ink); }
.kl-ac-brief.is-drop .kl-ac-brief__drop { display: grid; }
.kl-ac-brief.is-drop > :not(.kl-ac-brief__drop) { visibility: hidden; }
/* Try lines under a blank brief */
.kl-ac-tries { display: flex; flex-wrap: wrap; gap: 6px; }

/* Once made, the brief folds into one quoted line you can edit */
.kl-ac-given { display: flex; align-items: flex-start; gap: 8px; min-width: 0; }
.kl-ac-given__text { flex: 1 1 auto; min-width: 0; margin: 0; font: var(--kl-font-meta); color: var(--kl-color-text); }
.kl-ac-given__text q { quotes: "\201C" "\201D"; }
.kl-ac-given__srcs { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }

/* ===== 3. Source chip: a link or file the card was given ===== */
.kl-ac-src {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%; height: 26px; padding: 0 10px 0 4px;
  border-radius: var(--kl-radius-pill); background: var(--kl-color-surface); box-shadow: inset 0 0 0 1px var(--kl-color-line);
  font: var(--kl-font-label); color: var(--kl-color-text); white-space: nowrap;
}
.kl-ac-src__tile { display: inline-grid; place-items: center; flex: none; width: 18px; height: 18px; border-radius: var(--kl-radius-round);
  background: var(--kl-color-hue-pink-soft); color: var(--kl-color-hue-pink-ink); font: var(--kl-font-caption); font-weight: var(--kl-font-weight-bold); }
.kl-ac-src__tile .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
.kl-ac-src--file .kl-ac-src__tile { border-radius: 5px; background: var(--kl-color-hue-indigo-soft); color: var(--kl-color-hue-indigo-ink); }
.kl-ac-src__name { overflow: hidden; text-overflow: ellipsis; }
.kl-ac-src__kind { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-ac-src__x { display: grid; place-items: center; width: 18px; height: 18px; margin-right: -6px; padding: 0; border: 0; border-radius: 50%;
  background: transparent; color: var(--kl-color-text-secondary); cursor: pointer; }
.kl-ac-src__x:hover { background: var(--kl-color-control-fill); }
.kl-ac-src__x .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }

/* ===== 4. Reading: what the card is doing before it shapes itself ===== */
.kl-ac-steps { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0; list-style: none; }
.kl-ac-step { display: flex; align-items: center; gap: 10px; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-ac-step__mark { display: grid; place-items: center; flex: none; width: 18px; height: 18px; border-radius: 50%;
  color: var(--kl-color-text-on-fill); background: var(--kl-color-status-executing); }
.kl-ac-step__mark .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2.2; }
.kl-ac-step.is-now { color: var(--kl-color-text); }
.kl-ac-step.is-now .kl-ac-step__mark { background: transparent; }
.kl-ac-step.is-now .kl-dot { --kl-dot-c: var(--kl-color-status-planning); }

/* "Shaped as a stay search · Change · Undo" */
.kl-ac-shape { display: flex; align-items: center; gap: 6px; min-width: 0; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-ac-shape b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }
.kl-ac-shape .kl-btn { margin-left: 2px; }
.kl-ac-shape__end { margin-left: auto; display: flex; gap: 4px; }

/* ===== 5. Fields: the parts the input section can grow ===== */
.kl-ac-fields { display: flex; flex-direction: column; gap: 8px; }
.kl-ac-field {
  position: relative; display: flex; flex-direction: column; gap: 8px; padding: 10px 12px 12px;
  border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface-sunken);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
}
.kl-ac-field__head { display: flex; align-items: center; gap: 6px; min-width: 0; font: var(--kl-font-label); color: var(--kl-color-text); }
.kl-ac-field__head .kl-icon { --kl-icon-size: 14px; color: var(--kl-color-text-secondary); }
.kl-ac-field__learned { margin-left: auto; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-ac-field__row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.kl-ac-field__row > .kl-ac-value { flex: 1 1 auto; }

/* Values are v2 Controls' .kl-ac-value (date picker section). The card adds the text slot and an inline input. */
.kl-ac-value__main { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-ac-value input { flex: 1 1 auto; min-width: 0; height: 100%; margin: 0; padding: 0; border: 0; outline: 0; background: transparent; color: inherit; font: inherit; }
.kl-ac-value input::placeholder { color: var(--kl-color-text-secondary); opacity: 1; }
/* Just filled from a suggestion: add v2 Motion's kl-m-filled to the value (the selection tint fades back).
   Date boxes, calendar and the range with history are v2 Controls' date picker (.kl-ac-dates, .kl-ac-cal, .kl-ac-usual). */

/* A file the card works on */
.kl-ac-file { display: flex; align-items: center; gap: 10px; min-width: 0; padding: 8px 10px; border-radius: var(--kl-radius-row);
  background: var(--kl-color-surface); box-shadow: inset 0 0 0 1px var(--kl-color-field-border); }
.kl-ac-file__tile { display: grid; place-items: center; flex: none; width: 32px; height: 40px; border-radius: 6px;
  background: var(--kl-color-hue-indigo-soft); color: var(--kl-color-hue-indigo-ink); font: var(--kl-font-caption); font-weight: var(--kl-font-weight-bold); }
.kl-ac-file__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.kl-ac-file__name { font: var(--kl-font-label-strong); color: var(--kl-color-text); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-ac-file__meta { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }

/* Choice chips (which checks to run, what a stay must have) wrap */
.kl-ac-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.kl-ac-chips .kl-chip { height: 28px; }

/* ===== 6. Suggestions and where they came from ===== */
.kl-ac-sugg {
  position: relative; display: flex; align-items: center; gap: 10px; width: 100%; min-width: 0; margin: 0; padding: 8px 8px 8px 10px;
  border: 1px dashed var(--kl-color-selection); border-radius: var(--kl-radius-row);
  background: var(--kl-color-surface); color: var(--kl-color-text); text-align: left; cursor: pointer;
  transition: background-color var(--kl-motion-press) var(--kl-motion-ease-out), border-color var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-ac-sugg:hover, .kl-ac-sugg.is-hover { background: var(--kl-color-selection-soft); }
.kl-ac-sugg:focus-visible { outline: 0; box-shadow: 0 0 0 3px var(--kl-color-selection-soft); border-style: solid; }
.kl-ac-sugg__icon { display: grid; place-items: center; flex: none; width: 28px; height: 28px; border-radius: var(--kl-radius-tile);
  background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
.kl-ac-sugg__icon .kl-icon { --kl-icon-size: 16px; }
.kl-ac-sugg__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.kl-ac-sugg__value { font: var(--kl-font-label-strong); color: var(--kl-color-text); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-ac-sugg__from { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-ac-sugg__use { flex: none; padding: 0 4px; font: var(--kl-font-label); color: var(--kl-color-selection-ink); }
.kl-ac-sugg-wrap { position: relative; display: flex; align-items: center; gap: 4px; }
.kl-ac-sugg-wrap > .kl-ac-sugg { flex: 1 1 auto; }
/* Suggestions, tags and the calendar arrive with v2 Motion's kl-m-pop (scaled by the dial), never while you type */
.kl-ac-sugg.is-leaving { animation: kl-ac-out var(--kl-motion-fade-out) ease both; pointer-events: none; }
@keyframes kl-ac-out { to { opacity: 0; transform: scale(.97); } }
/* Two sources disagree: a small count above the choices */
.kl-ac-sugg-count { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
/* Held while you type: one quiet line instead of a pop */
.kl-ac-waiting { display: inline-flex; align-items: center; gap: 6px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-ac-waiting::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--kl-color-selection); }

/* After you take a suggestion, the field keeps a tag saying where it came from */
.kl-ac-from {
  display: inline-flex; align-items: center; gap: 4px; flex: none; height: 22px; margin: 0; padding: 0 8px 0 6px; border: 0;
  border-radius: var(--kl-radius-pill); background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink);
  font: var(--kl-font-caption); white-space: nowrap; cursor: pointer;
}
.kl-ac-from .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
.kl-ac-from:hover { box-shadow: inset 0 0 0 1px var(--kl-color-selection); }
.kl-ac-from:focus-visible { outline: 0; box-shadow: 0 0 0 2px var(--kl-color-focus); }
.kl-ac-from--learned { background: var(--kl-color-control-fill); color: var(--kl-color-text-secondary); }

/* "Why this?": the source, quoted, and a way to stop using it */
.kl-ac-why {
  position: absolute; z-index: 60; width: var(--kl-ac-why-w, 288px); display: flex; flex-direction: column; gap: 10px; padding: 12px;
  border-radius: var(--kl-radius-menu); background: var(--kl-color-surface-raised);   /* opaque: you read it over the card */
  box-shadow: var(--kl-shadow-menu), inset 0 0 0 1px var(--kl-color-line); color: var(--kl-color-text);
}
.kl-ac-why--static { position: relative; z-index: auto; }   /* in flow, for specimens */
.kl-ac-why__title { margin: 0; font: var(--kl-font-label-strong); }
.kl-ac-why__src { display: flex; align-items: center; gap: 8px; }
.kl-ac-why__src .kl-ac-sugg__icon { width: 24px; height: 24px; }
.kl-ac-why__src-main { display: flex; flex-direction: column; min-width: 0; }
.kl-ac-why__src-name { font: var(--kl-font-label); }
.kl-ac-why__src-meta { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-ac-why__quote { margin: 0; padding: 8px 10px; border-radius: var(--kl-radius-row); background: var(--kl-color-surface-sunken);
  font: var(--kl-font-meta); font-family: var(--kl-font-mono); font-size: 12px; color: var(--kl-color-text); white-space: pre-line; }
.kl-ac-why__quote mark { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); border-radius: 3px; padding: 0 2px; }
.kl-ac-why__actions { display: flex; gap: 6px; justify-content: flex-end; }

/* Sources the card may read, each with its own switch */
.kl-ac-sources { display: flex; flex-direction: column; }
.kl-ac-source { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-top: 1px solid var(--kl-color-line); }
.kl-ac-source:first-child { border-top: 0; }
.kl-ac-source__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.kl-ac-source__name { font: var(--kl-font-label); color: var(--kl-color-text); }
.kl-ac-source__meta { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-ac-source.is-off .kl-ac-sugg__icon { background: var(--kl-color-control-fill); color: var(--kl-color-text-secondary); }

/* ===== 7. Results: what the card found ===== */
.kl-ac-results { display: flex; flex-direction: column; gap: 8px; }
.kl-ac-results__head { display: flex; align-items: center; gap: 8px; }
.kl-ac-results__head .kl-ac__title { flex: 1 1 auto; }
.kl-ac-lean { display: flex; align-items: center; gap: 8px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-ac-rows { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; list-style: none; }
.kl-ac-row {
  position: relative; display: flex; align-items: center; gap: 10px; min-width: 0; padding: 6px 10px 6px 6px;
  border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
}
.kl-ac-row__thumb { position: relative; display: grid; place-items: center; flex: none; width: 64px; height: 52px; border-radius: var(--kl-radius-row);
  background: var(--kl-color-hue-pink-soft); color: var(--kl-color-hue-pink-ink); overflow: hidden; }
.kl-ac-row__thumb .kl-icon { --kl-icon-size: 22px; }
.kl-ac-row__thumb--b { background: var(--kl-color-hue-cerulean-soft); color: var(--kl-color-hue-cerulean-ink); }
.kl-ac-row__thumb--c { background: var(--kl-color-hue-green-soft); color: var(--kl-color-hue-green-ink); }
.kl-ac-row__thumb--d { background: var(--kl-color-hue-orange-soft); color: var(--kl-color-hue-orange-ink); }
.kl-ac-row__tile { display: grid; place-items: center; flex: none; width: 28px; height: 28px; margin-left: 2px; border-radius: var(--kl-radius-tile);
  background: var(--kl-color-status-planning-soft); color: var(--kl-color-status-planning-ink); }
.kl-ac-row__tile .kl-icon { --kl-icon-size: 16px; }
.kl-ac-row__tile--stop { background: var(--kl-color-status-stopped-soft); color: var(--kl-color-status-stopped-ink); }
.kl-ac-row__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.kl-ac-row__name { font: var(--kl-font-label-strong); color: var(--kl-color-text); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-ac-row__meta { display: flex; align-items: center; gap: 4px; min-width: 0; overflow: hidden; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); white-space: nowrap; }
.kl-ac-row__meta > span { overflow: hidden; text-overflow: ellipsis; }
.kl-ac-row__meta .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
.kl-ac-row__aside { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 3px; }
.kl-ac-price { font: var(--kl-font-label-strong); color: var(--kl-color-text); font-variant-numeric: tabular-nums; }
.kl-ac-price small { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-ac-fit { display: inline-flex; align-items: center; height: 18px; padding: 0 6px; border-radius: var(--kl-radius-pill);
  font: var(--kl-font-caption); background: var(--kl-color-status-executing-soft); color: var(--kl-color-status-executing-ink); }
.kl-ac-fit--above { background: transparent; color: var(--kl-color-text-secondary); box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
/* New since you last looked: a small blue dot at the row's left edge */
.kl-ac-row.is-new::before { content: ""; position: absolute; left: -4px; top: 50%; width: 7px; height: 7px; margin-top: -3.5px;
  border-radius: 50%; background: var(--kl-color-primary); box-shadow: 0 0 0 2px var(--kl-color-surface); }
.kl-ac-more { align-self: flex-start; }

/* Footer: how often it runs, and the one action */
.kl-ac-foot { display: flex; align-items: center; gap: 8px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-ac-foot .kl-icon { --kl-icon-size: 14px; }
.kl-ac-foot__end { margin-left: auto; display: flex; gap: 6px; }

/* ===== 8. Small stages: the card on the board reads as its summary ===== */
.kl-ac-sum { display: flex; flex-wrap: wrap; gap: 4px; }
.kl-ac-sum .kl-ac-from { height: 20px; }

/* ===== 9. Reduced motion: fades only ===== */
/* kl-m-grow, kl-m-pop, kl-m-filled and the picked day carry their own reduced versions in v2. Only the width glide is ours. */
@media (prefers-reduced-motion: reduce) { .kl-card.kl-ac { transition-duration: 0s; } }
.kl-motion-reduce .kl-card.kl-ac { transition-duration: 0s; }

/* ===== agent-browser/agent-browser.css ===== */
/* =====================================================================================================
   Klippan master · Agent browser
   Watch what an agent is doing on the web: the live page, the agent's pointer with its click, type
   and read marks, the address, a short step log, and Pause / Take over / Hand back.

   Three sizes, all opened from the card the agent works for:
     .kl-card__web       on the card: v2 Board's web chip with the site the agent is on (states here as .kl-webchip.is-*)
     .kl-browser-peek    small, 288 wide: a live thumbnail tethered to the card
     .kl-win.kl-browser  large, 880 wide: the full window (a v2 .kl-win, the .kl-win--wide size)
   And inside an agent's session view (the transcript window):
     .kl-browser-dock    a 44 px strip under the session's status line: site, what it does now, step count, open

   Load after klippan-v2/combined/klippan.css. Every value is a --kl-* token; the only literals are this
   part's component sizes, kept as local custom properties (--kl-ab-*). Overlays (pointer, marks) are
   placed in page units (the simulated page is 960 × 640) through --x, --y, --w, --h and scaled by
   --kl-ab-zoom, so their text never shrinks with the page.
   ===================================================================================================== */

.kl-browser, .kl-browser-peek, .kl-browser-dock {
  /* The agent's colour is its project's hue. Alban's own pointer and edge stay selection blue. */
  --kl-ab-hue: var(--kl-color-project-1);
  --kl-ab-hue-soft: var(--kl-color-project-1-soft);
  --kl-ab-hue-ink: var(--kl-color-project-1-ink);
  --kl-ab-you: var(--kl-color-selection);
}
:is(.kl-browser, .kl-browser-peek, .kl-browser-dock).kl-ab--p2 { --kl-ab-hue: var(--kl-color-project-2); --kl-ab-hue-soft: var(--kl-color-project-2-soft); --kl-ab-hue-ink: var(--kl-color-project-2-ink); }
:is(.kl-browser, .kl-browser-peek, .kl-browser-dock).kl-ab--p3 { --kl-ab-hue: var(--kl-color-project-3); --kl-ab-hue-soft: var(--kl-color-project-3-soft); --kl-ab-hue-ink: var(--kl-color-project-3-ink); }
:is(.kl-browser, .kl-browser-peek, .kl-browser-dock).kl-ab--p4 { --kl-ab-hue: var(--kl-color-project-4); --kl-ab-hue-soft: var(--kl-color-project-4-soft); --kl-ab-hue-ink: var(--kl-color-project-4-ink); }
:is(.kl-browser, .kl-browser-peek, .kl-browser-dock).kl-ab--p5 { --kl-ab-hue: var(--kl-color-project-5); --kl-ab-hue-soft: var(--kl-color-project-5-soft); --kl-ab-hue-ink: var(--kl-color-project-5-ink); }
:is(.kl-browser, .kl-browser-peek, .kl-browser-dock).kl-ab--p6 { --kl-ab-hue: var(--kl-color-project-6); --kl-ab-hue-soft: var(--kl-color-project-6-soft); --kl-ab-hue-ink: var(--kl-color-project-6-ink); }
:is(.kl-browser, .kl-browser-peek, .kl-browser-dock).kl-ab--p7 { --kl-ab-hue: var(--kl-color-project-7); --kl-ab-hue-soft: var(--kl-color-project-7-soft); --kl-ab-hue-ink: var(--kl-color-project-7-ink); }
:is(.kl-browser, .kl-browser-peek, .kl-browser-dock).kl-ab--p8 { --kl-ab-hue: var(--kl-color-project-8); --kl-ab-hue-soft: var(--kl-color-project-8-soft); --kl-ab-hue-ink: var(--kl-color-project-8-ink); }

/* =====================================================================================================
   1. Web chip on the card
   The chip itself is v2 Board's button.kl-card__web (-host, -dot, --icon at compact; its hue is the card's
   --kl-card-hue). The agent browser adds its states as .kl-webchip.is-* on the same button.
   ===================================================================================================== */
.kl-webchip.is-live .kl-card__web-dot { animation: kl-ab-breathe 1.8s var(--kl-motion-ease-out) infinite; }
.kl-webchip.is-paused .kl-card__web-dot { background: var(--kl-color-status-idle); }
.kl-webchip.is-driving .kl-card__web-dot { background: var(--kl-color-selection); }
/* Needs Alban (a sign-in or an asks first): approval magenta, as .kl-card.is-asking. .is-needs and .is-asking are the same state */
.kl-webchip:is(.is-needs, .is-asking) { box-shadow: inset 0 0 0 1px var(--kl-color-status-approval); color: var(--kl-color-status-approval-ink); }
.kl-webchip:is(.is-needs, .is-asking) .kl-icon { color: var(--kl-color-status-approval-ink); }
.kl-webchip:is(.is-needs, .is-asking) .kl-card__web-dot { background: var(--kl-color-status-approval); animation: kl-ab-breathe 1.2s var(--kl-motion-ease-out) infinite; }
/* The page failed to load: an error, so stopped red */
.kl-webchip.is-failed { box-shadow: inset 0 0 0 1px var(--kl-color-status-stopped); color: var(--kl-color-status-stopped-ink); }
.kl-webchip.is-failed .kl-card__web-dot { background: var(--kl-color-status-stopped); }
.kl-webchip.is-done .kl-card__web-dot { background: var(--kl-color-status-executing); }
/* Waiting on Alban (a sign-in, or an "asks first" before it sends, buys or posts): v2's approval colours, as .kl-card.is-asking */
.kl-webchip.is-asking { box-shadow: inset 0 0 0 1px var(--kl-color-status-approval); color: var(--kl-color-status-approval-ink); }
.kl-webchip.is-asking .kl-icon { color: var(--kl-color-status-approval-ink); }
.kl-webchip.is-asking .kl-card__web-dot { background: var(--kl-color-status-approval); animation: kl-ab-breathe 1.2s var(--kl-motion-ease-out) infinite; }
.kl-webchip.is-open { box-shadow: inset 0 0 0 2px var(--kl-color-selection); }
.kl-webchip:active { animation: kl-press var(--kl-motion-press) var(--kl-motion-spring-pop); }
/* A window minimised into the chip lands there once */
.kl-webchip.is-landing { animation: kl-land var(--kl-motion-land) var(--kl-motion-spring); }

/* =====================================================================================================
   2. The simulated page (shared by peek and window)
   The page keeps the site's own light look in both themes, like a real browser; in Klippan's dark theme
   it is dimmed a little so it doesn't glare. Natural size 960 × 640, scaled by --kl-ab-zoom.
   ===================================================================================================== */
.kl-browser__stage {
  --kl-ab-zoom: .658333;            /* window: a 632px stage */
  --kl-ab-page-w: 960px;
  --kl-ab-page-h: 640px;
  position: relative;
  width: calc(var(--kl-ab-page-w) * var(--kl-ab-zoom));
  height: calc(var(--kl-ab-page-h) * var(--kl-ab-zoom));
  overflow: hidden;
  isolation: isolate;
  background: var(--kl-color-surface-sunken);
}
.kl-browser__page {
  position: absolute; left: 0; top: 0;
  width: var(--kl-ab-page-w); height: var(--kl-ab-page-h);
  transform: scale(var(--kl-ab-zoom));
  transform-origin: 0 0;
  transition: opacity var(--kl-motion-fade) var(--kl-motion-ease-out), filter var(--kl-motion-expand) var(--kl-motion-ease-out);
}
[data-theme="dark"] .kl-browser__page { filter: brightness(.92); }
.kl-browser__page.is-swapping { opacity: 0; }

.kl-site {
  --kl-site-brand: var(--kl-color-hue-teal);
  --kl-site-brand-ink: var(--kl-color-hue-teal-ink);
  --kl-site-brand-soft: var(--kl-color-hue-teal-soft);
  width: 100%; height: 100%;
  display: grid; grid-template-rows: 56px 1fr;
  background: var(--kl-color-surface);
  color: var(--kl-color-text);
  font: var(--kl-font-body);
  font-family: var(--kl-font-sans);
  color-scheme: light;
  overflow: hidden;
}
.kl-site *, .kl-site *::before, .kl-site *::after { box-sizing: border-box; }
.kl-site__head { display: flex; align-items: center; gap: 24px; padding: 0 28px; border-bottom: 1px solid var(--kl-color-line); }
.kl-site__logo { display: inline-flex; align-items: center; gap: 10px; font: var(--kl-font-headline); }
.kl-site__logo i { width: 26px; height: 26px; border-radius: 8px; background: var(--kl-site-brand); }
.kl-site__nav { display: flex; gap: 20px; font: var(--kl-font-label); color: var(--kl-color-text-secondary); }
.kl-site__nav .is-on { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }
.kl-site__search { position: relative; margin-left: auto; width: 260px; height: 34px; display: flex; align-items: center; gap: 8px; padding: 0 12px; border-radius: 8px; box-shadow: inset 0 0 0 1px var(--kl-color-field-border); color: var(--kl-color-text-tertiary); font: var(--kl-font-label); }
.kl-site__search b { font-weight: inherit; color: var(--kl-color-text); }
.kl-site__search .kl-icon { width: 16px; height: 16px; }
.kl-site__btn { height: 34px; padding: 0 14px; display: inline-flex; align-items: center; border-radius: 8px; background: var(--kl-site-brand); color: var(--kl-color-text-on-fill); font: var(--kl-font-label-strong); }
.kl-site__btn--ghost { background: transparent; color: var(--kl-color-text); box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
.kl-site__results { position: absolute; left: 0; right: 0; top: 40px; z-index: 2; padding: 6px; border-radius: 10px; background: var(--kl-color-surface); box-shadow: var(--kl-shadow-menu); }
.kl-site__result { display: block; padding: 8px 10px; border-radius: 6px; color: var(--kl-color-text); font: var(--kl-font-label); }
.kl-site__result small { display: block; color: var(--kl-color-text-secondary); font: var(--kl-font-caption); }
.kl-site__result.is-on { background: var(--kl-site-brand-soft); }
.kl-site__body { display: grid; grid-template-columns: 200px 1fr; min-height: 0; }
.kl-site__side { padding: 24px 20px; border-right: 1px solid var(--kl-color-line); display: flex; flex-direction: column; gap: 10px; font: var(--kl-font-label); color: var(--kl-color-text-secondary); }
.kl-site__side b { font: var(--kl-font-caption); color: var(--kl-color-text-tertiary); margin-top: 8px; }
.kl-site__side .is-on { color: var(--kl-site-brand-ink); font-weight: var(--kl-font-weight-semibold); }
.kl-site__main { padding: 28px 40px; display: flex; flex-direction: column; gap: 14px; min-width: 0; overflow: hidden; }
.kl-site__main h1 { margin: 0; font: var(--kl-font-display); }
.kl-site__main > * { transition: translate var(--kl-motion-travel) var(--kl-motion-ease-out); }
.kl-site.is-scrolled .kl-site__main > * { translate: 0 -64px; }
.kl-site__main h2 { margin: 6px 0 0; font: var(--kl-font-title); }
.kl-site__main p { margin: 0; color: var(--kl-color-text-secondary); max-width: 620px; }
.kl-site__crumbs { font: var(--kl-font-caption); color: var(--kl-color-text-tertiary); }
.kl-site__table { width: 100%; max-width: 620px; border-collapse: collapse; font: var(--kl-font-label); font-variant-numeric: tabular-nums; }
.kl-site__table th { text-align: left; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); padding: 8px 10px; border-bottom: 1px solid var(--kl-color-line-strong); }
.kl-site__table td { padding: 10px; border-bottom: 1px solid var(--kl-color-line); }
.kl-site__hero { padding: 48px 48px 32px; display: flex; flex-direction: column; gap: 14px; }
.kl-site__hero h1 { margin: 0; font: var(--kl-font-display); font-size: 40px; line-height: 48px; }
.kl-site__hero p { margin: 0; color: var(--kl-color-text-secondary); max-width: 520px; }
.kl-site__tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; padding: 0 48px; }
.kl-site__tile { padding: 18px; border-radius: 12px; box-shadow: inset 0 0 0 1px var(--kl-color-line); display: flex; flex-direction: column; gap: 6px; }
.kl-site__tile strong { font: var(--kl-font-label-strong); }
.kl-site__tile span { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-site__log { display: flex; flex-direction: column; gap: 0; max-width: 620px; }
.kl-site__log div { display: grid; grid-template-columns: 110px 1fr; gap: 16px; padding: 12px 0; border-bottom: 1px solid var(--kl-color-line); font: var(--kl-font-label); }
.kl-site__log time { color: var(--kl-color-text-tertiary); font-variant-numeric: tabular-nums; }
.kl-site__form { display: flex; flex-direction: column; gap: 12px; max-width: 380px; }
.kl-site__form label { display: flex; flex-direction: column; gap: 6px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-site__form label > span { height: 36px; border-radius: 8px; box-shadow: inset 0 0 0 1px var(--kl-color-field-border); display: flex; align-items: center; padding: 0 12px; font: var(--kl-font-label); color: var(--kl-color-text); }
.kl-site__form label > span.is-tall { height: 76px; align-items: flex-start; padding-top: 10px; }
.kl-site__center { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; text-align: center; height: 100%; }
.kl-site__center .kl-site__form { width: 320px; text-align: left; }
.kl-site__caret { display: inline-block; width: 2px; height: 1.1em; margin-left: 1px; vertical-align: -.15em; background: var(--kl-ab-hue, var(--kl-color-text)); }   /* blinks with v2's kl-m-caret, added only while typing */
/* The browser's own "couldn't load" page, drawn by Klippan, not by a site */
.kl-site--error { display: flex; align-items: center; justify-content: center; background: var(--kl-color-surface); }
.kl-site--error .kl-site__center { max-width: 420px; }
.kl-site--error .kl-icon { width: 40px; height: 40px; color: var(--kl-color-status-stopped); }
.kl-site--error h1 { margin: 0; font: var(--kl-font-title); }
.kl-site--error p { margin: 0; color: var(--kl-color-text-secondary); }
/* Loading: grey bars where the page will be */
.kl-site__skel { display: block; height: 14px; border-radius: 7px; background: var(--kl-color-control-fill); }

/* =====================================================================================================
   3. Overlays on the stage: the agent's pointer, its marks, the veil
   ===================================================================================================== */
.kl-browser__layer { position: absolute; inset: 0; pointer-events: none; z-index: 2; }
.kl-browser__layer > * { position: absolute; left: 0; top: 0; }

/* The agent's pointer: an arrow in the project's hue with a small name tag. It glides on the spring,
   so the dial sets its overshoot. While Alban drags, links or types (.is-quiet) it glides on ease-out. */
.kl-browser__cursor {
  --x: 480; --y: 320;
  z-index: 4;
  display: flex; align-items: flex-start;
  transform: translate(calc(var(--x) * var(--kl-ab-zoom) * 1px), calc(var(--y) * var(--kl-ab-zoom) * 1px));
  transition: transform var(--kl-motion-cursor-glide) var(--kl-motion-spring), opacity var(--kl-motion-fade) var(--kl-motion-ease-out);
  will-change: transform;
}
.kl-browser__arrow { width: 20px; height: 20px; flex: none; margin: -3.5px 0 0 -5px; color: var(--kl-ab-hue); filter: drop-shadow(var(--kl-shadow-cursor)); transform-origin: 5px 3.5px; transition: scale var(--kl-motion-press) var(--kl-motion-spring-pop); }
.kl-browser__arrow path { fill: currentColor; stroke: var(--kl-color-knob); stroke-width: 1.4; stroke-linejoin: round; }
.kl-browser__tag {
  margin: 14px 0 0 -2px;
  padding: 2px 8px;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-ab-hue);
  color: var(--kl-color-text-on-fill);
  font: var(--kl-font-caption);
  font-family: var(--kl-font-sans);
  white-space: nowrap;
  box-shadow: var(--kl-shadow-card);
}
.kl-browser__cursor.is-pressing .kl-browser__arrow { scale: calc(1 - .18 * var(--kl-motion-k)); }
.kl-browser__cursor.is-speaking .kl-browser__tag { animation: kl-hop var(--kl-motion-hop) var(--kl-motion-spring-pop); }
/* Alban took over: the agent's pointer parks in the corner, grey and still */
.kl-browser__cursor.is-parked { opacity: .55; }
.kl-browser__cursor.is-parked .kl-browser__arrow { color: var(--kl-color-status-idle); }
.kl-browser__cursor.is-parked .kl-browser__tag { background: var(--kl-color-neutral-soft); color: var(--kl-color-neutral-ink); box-shadow: none; }
.kl-browser__cursor.is-hidden { opacity: 0; }

/* Alban's own pointer while he drives (only drawn in specimens; in the app it is his real cursor) */
.kl-browser__mine { --x: 600; --y: 360; z-index: 5; transform: translate(calc(var(--x) * var(--kl-ab-zoom) * 1px), calc(var(--y) * var(--kl-ab-zoom) * 1px)); }
.kl-browser__mine .kl-browser__arrow { color: var(--kl-ab-you); }

/* Click: one ring from the click point (v2's kl-m-click-ring, replayed per click). Its reach grows a little with the dial. */
.kl-browser__ripple {
  --x: 0; --y: 0;
  width: 36px; height: 36px; margin: -18px 0 0 -18px;
  border-radius: var(--kl-radius-round);
  box-shadow: 0 0 0 2px var(--kl-ab-hue), inset 0 0 0 999px color-mix(in srgb, var(--kl-ab-hue) 14%, transparent);
  transform: translate(calc(var(--x) * var(--kl-ab-zoom) * 1px), calc(var(--y) * var(--kl-ab-zoom) * 1px));
  opacity: 0;
  z-index: 3;
}
.kl-browser__ripple.is-static { opacity: .6; }
.kl-browser__ripple--you { box-shadow: 0 0 0 2px var(--kl-ab-you), inset 0 0 0 999px color-mix(in srgb, var(--kl-ab-you) 14%, transparent); }

/* The element the agent is about to act on: an edge in its hue with a small verb label.
   Sizes glide on ease-out and never bounce. */
.kl-browser__target {
  --x: 0; --y: 0; --w: 100; --h: 40;
  left: calc(var(--x) * var(--kl-ab-zoom) * 1px - 3px);
  top: calc(var(--y) * var(--kl-ab-zoom) * 1px - 3px);
  width: calc(var(--w) * var(--kl-ab-zoom) * 1px + 6px);
  height: calc(var(--h) * var(--kl-ab-zoom) * 1px + 6px);
  border-radius: var(--kl-radius-control);
  box-shadow: 0 0 0 2px var(--kl-ab-hue), 0 0 0 6px color-mix(in srgb, var(--kl-ab-hue) 16%, transparent);
  background: color-mix(in srgb, var(--kl-ab-hue) 8%, transparent);
  z-index: 2;
  transition: left var(--kl-motion-expand) var(--kl-motion-ease-out), top var(--kl-motion-expand) var(--kl-motion-ease-out),
              width var(--kl-motion-expand) var(--kl-motion-ease-out), height var(--kl-motion-expand) var(--kl-motion-ease-out),
              opacity var(--kl-motion-fade) var(--kl-motion-ease-out);
}
.kl-browser__target.is-in { animation: kl-ab-target-in var(--kl-motion-reveal) var(--kl-motion-ease-out) both; }
.kl-browser__target.is-hidden { opacity: 0; }
.kl-browser__label {
  position: absolute; left: -2px; bottom: calc(100% + 6px);
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 7px;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-ab-hue);
  color: var(--kl-color-text-on-fill);
  font: var(--kl-font-caption);
  font-family: var(--kl-font-sans);
  white-space: nowrap;
}
.kl-browser__label .kl-icon { width: 12px; height: 12px; }
.kl-browser__target.is-below .kl-browser__label { bottom: auto; top: calc(100% + 6px); }
/* Typing: the field's edge is solid and the caret takes the hue */
.kl-browser__target.is-typing { background: transparent; }

/* Reading: a soft band of the hue writes itself in under the text being read */
.kl-browser__read {
  --x: 0; --y: 0; --w: 300; --h: 20;
  left: calc(var(--x) * var(--kl-ab-zoom) * 1px);
  top: calc(var(--y) * var(--kl-ab-zoom) * 1px);
  width: calc(var(--w) * var(--kl-ab-zoom) * 1px);
  height: calc(var(--h) * var(--kl-ab-zoom) * 1px);
  border-radius: 3px;
  background: color-mix(in srgb, var(--kl-ab-hue) 22%, transparent);
  mix-blend-mode: multiply;
  z-index: 1;
}
.kl-browser__read.is-on { animation: kl-write var(--kl-motion-write) var(--kl-motion-ease-out) both; }   /* Motion's status-line write, reused */
.kl-browser__read.is-hidden { opacity: 0; transition: opacity var(--kl-motion-fade) var(--kl-motion-ease-out); }

/* Scrolling: a thin bar on the stage's right edge shows where on the page the agent is */
.kl-browser__scroll { left: auto !important; right: 3px; top: 6px !important; bottom: 6px; width: 4px; border-radius: 2px; background: color-mix(in srgb, var(--kl-color-text) 8%, transparent); }
.kl-browser__scroll i { position: absolute; left: 0; right: 0; top: var(--kl-ab-scroll, 0%); height: 34%; border-radius: 2px; background: color-mix(in srgb, var(--kl-ab-hue) 70%, transparent); transition: top var(--kl-motion-travel) var(--kl-motion-ease-out); }

/* Veil: over the page only, for paused, needs you, asks first, failed and done.
   The board and the rest of the window stay live. */
.kl-browser__veil {
  position: absolute; inset: 0; z-index: 6;
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
  background: color-mix(in srgb, var(--kl-color-surface) 52%, transparent);
  -webkit-backdrop-filter: blur(2px) saturate(.7);
  backdrop-filter: blur(2px) saturate(.7);
  animation: kl-fade-in var(--kl-motion-fade) var(--kl-motion-ease-out) both;
}
.kl-browser__veil--clear { background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; align-items: flex-end; }
/* Needs you and asks first keep the page readable: Alban must see what the agent filled in or hit */
.kl-browser__veil--side { background: color-mix(in srgb, var(--kl-color-surface) 14%, transparent); -webkit-backdrop-filter: none; backdrop-filter: none; align-items: flex-end; justify-content: flex-end; padding: 10px; }
.kl-browser__veil--side .kl-browser__notice { width: min(288px, 100%); }
.kl-browser__veil--top { align-items: flex-start; }
.kl-browser__notice {
  width: min(360px, 100%);
  display: flex; flex-direction: column; gap: 10px;
  padding: 16px;
  border-radius: var(--kl-radius-menu);
  background: var(--kl-glass-fill-menu, var(--kl-color-surface));
  -webkit-backdrop-filter: var(--kl-glass-filter);
  backdrop-filter: var(--kl-glass-filter);
  box-shadow: var(--kl-shadow-menu);
  color: var(--kl-color-text);
  font: var(--kl-font-meta);
  font-family: var(--kl-font-sans);
  pointer-events: auto;
  animation: kl-say-in var(--kl-motion-say-in) var(--kl-motion-spring) both;
}
.kl-browser__notice-head { display: flex; align-items: center; gap: 10px; }
.kl-browser__notice-head .kl-icon { width: 20px; height: 20px; flex: none; }
.kl-browser__notice h4 { margin: 0; font: var(--kl-font-label-strong); }
.kl-browser__notice p { margin: 0; color: var(--kl-color-text-secondary); }
.kl-browser__notice-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; margin-top: 2px; }
.kl-browser__notice--paused .kl-icon { color: var(--kl-color-text-secondary); }
.kl-browser__notice--needs { box-shadow: var(--kl-shadow-menu), inset 0 0 0 1.5px var(--kl-color-status-approval); }
.kl-browser__notice--ask { box-shadow: var(--kl-shadow-menu), inset 0 0 0 1px var(--kl-color-status-approval); }
:is(.kl-browser__notice--needs, .kl-browser__notice--ask) .kl-icon { color: var(--kl-color-status-approval-ink); }
.kl-browser__notice--failed .kl-icon { color: var(--kl-color-status-stopped); }
.kl-browser__notice--done .kl-icon { color: var(--kl-color-status-executing); }
.kl-browser__facts { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; font-variant-numeric: tabular-nums; }
.kl-browser__facts li { display: flex; gap: 8px; color: var(--kl-color-text); }
.kl-browser__facts li::before { content: ""; width: 6px; height: 6px; margin-top: 6px; flex: none; border-radius: var(--kl-radius-round); background: var(--kl-ab-hue); }

/* Alban drives: a selection-blue edge round the page and a tag in the corner */
.kl-browser__drive {
  position: absolute; inset: 0; z-index: 5; pointer-events: none;
  box-shadow: inset 0 0 0 2px var(--kl-ab-you);
  animation: kl-fade-in var(--kl-motion-fade) var(--kl-motion-ease-out) both;
}
.kl-browser__drive span {
  position: absolute; left: 8px; bottom: 8px;
  padding: 2px 8px; border-radius: var(--kl-radius-pill);
  background: var(--kl-ab-you); color: var(--kl-color-text-on-fill);
  font: var(--kl-font-caption); font-family: var(--kl-font-sans);
}

/* Looking back at an earlier step: a strip at the top of the page and a quieter page */
.kl-browser__replay {
  position: absolute; left: 8px; right: 8px; top: 8px; z-index: 6;
  display: flex; align-items: center; gap: 8px;
  padding: 4px 4px 4px 12px;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-glass-fill-menu, var(--kl-color-surface));
  -webkit-backdrop-filter: var(--kl-glass-filter);
  backdrop-filter: var(--kl-glass-filter);
  box-shadow: var(--kl-shadow-menu);
  font: var(--kl-font-meta); font-family: var(--kl-font-sans);
  color: var(--kl-color-text);
  pointer-events: auto;
  animation: kl-menu-in var(--kl-motion-menu-in) var(--kl-motion-spring) both;
}
.kl-browser__replay > .kl-icon { width: 16px; height: 16px; flex: none; color: var(--kl-color-text-secondary); }
.kl-browser__replay span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kl-browser.is-replay .kl-browser__page { filter: saturate(.55); }

/* =====================================================================================================
   4. The large window: a v2 .kl-win with a toolbar, the stage and the step log
   ===================================================================================================== */
.kl-win.kl-browser {
  --kl-ab-log-w: 248px;   /* the width is v2's .kl-win--wide (880) */
  --kl-win-max-h: 720px;
}
.kl-browser .kl-win__icon { background: var(--kl-ab-hue-soft); color: var(--kl-ab-hue-ink); }
.kl-browser .kl-win__title { flex: 0 1 auto; }

/* Status in the bar: dot and a word, never colour alone */
.kl-browser__state {
  flex: none;
  display: inline-flex; align-items: center; gap: 6px;
  height: 22px; padding: 0 9px 0 7px;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-status-executing-soft);
  color: var(--kl-color-status-executing-ink);
  font: var(--kl-font-badge);
  white-space: nowrap;
}
.kl-browser__state .kl-dot { width: 8px; height: 8px; }
.kl-browser__state .kl-icon { width: 14px; height: 14px; }
.kl-browser__state--paused  { background: var(--kl-color-neutral-soft); color: var(--kl-color-neutral-ink); }
.kl-browser__state--driving { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
.kl-browser__state--needs   { background: var(--kl-color-status-approval-soft); color: var(--kl-color-status-approval-ink); }
.kl-browser__state--ask     { background: var(--kl-color-status-approval-soft); color: var(--kl-color-status-approval-ink); }
.kl-browser__state--failed  { background: var(--kl-color-status-stopped-soft); color: var(--kl-color-status-stopped-ink); }
.kl-browser__state--done    { background: var(--kl-color-status-executing-soft); color: var(--kl-color-status-executing-ink); }
.kl-browser__state.is-changed { animation: kl-dot-pop var(--kl-motion-dot-pop) var(--kl-motion-spring-pop); }

/* Toolbar: back, forward, reload (greyed while the agent drives), the address, the tabs, the log toggle */
.kl-browser__tools {
  flex: none;
  display: flex; align-items: center; gap: 4px;
  height: 44px;
  padding: 0 var(--kl-space-3) 0 var(--kl-space-2);
  border-bottom: 1px solid var(--kl-color-line);
}
.kl-browser__tools .kl-iconbtn:disabled, .kl-browser__tools .kl-iconbtn.is-disabled { opacity: .38; }
.kl-browser__addr {
  position: relative;
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; gap: 6px;
  height: 30px; margin: 0 6px;
  padding: 0 12px 0 10px;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-control-fill);
  font: var(--kl-font-label);
  color: var(--kl-color-text-secondary);
  overflow: hidden;
  white-space: nowrap;
}
.kl-browser__addr .kl-icon { width: 14px; height: 14px; flex: none; color: var(--kl-color-text-secondary); }
.kl-browser__host { color: var(--kl-color-text); font-weight: var(--kl-font-weight-medium); }
.kl-browser__path { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.kl-browser__addr.is-typing { box-shadow: inset 0 0 0 2px var(--kl-ab-you); background: var(--kl-color-surface); }
/* Page load: a thin line in the agent's hue along the bottom of the address */
.kl-browser__load { position: absolute; left: 10px; right: 10px; bottom: 0; height: 2px; border-radius: 1px; overflow: hidden; }
.kl-browser__load i { display: block; height: 100%; width: 100%; background: var(--kl-ab-hue); transform-origin: 0 50%; transform: scaleX(var(--kl-ab-load, 0)); transition: transform var(--kl-motion-expand) var(--kl-motion-ease-out), opacity var(--kl-motion-fade) var(--kl-motion-ease-out) var(--kl-motion-expand); }
.kl-browser__addr.is-loading .kl-browser__load i { --kl-ab-load: .72; }
.kl-browser__addr.is-loaded .kl-browser__load i { --kl-ab-load: 1; opacity: 0; }
/* The site rule: a quiet "allowed" tag when the site is on the project's list */
.kl-browser__allowed { flex: none; margin-left: auto; padding: 0 0 0 8px; font: var(--kl-font-caption); color: var(--kl-color-text-tertiary); }

/* Tabs the agent has open: a count that opens a menu, never a tab strip */
.kl-browser__tabs { position: relative; flex: none; }
.kl-browser__tabs .kl-btn { gap: 6px; font-variant-numeric: tabular-nums; }
.kl-browser__tabs .kl-menu { position: absolute; right: 0; top: calc(100% + 6px); z-index: 20; width: 260px; }
.kl-browser__fav { width: 16px; height: 16px; flex: none; border-radius: 5px; background: var(--kl-color-hue-teal); }

.kl-browser__main {
  --kl-ab-stage-h: 421.33px;        /* 640 × the window's zoom: the steps scroll inside this height */
  flex: none;
  height: var(--kl-ab-stage-h);
  display: grid;
  grid-template-columns: auto var(--kl-ab-log-w);
}
.kl-browser.is-log-hidden .kl-browser__main { grid-template-columns: auto 0; }
.kl-browser.is-log-hidden .kl-browser__log { visibility: hidden; }
.kl-browser.is-log-hidden { --kl-win-w: 632px; }

/* Step log */
.kl-browser__log {
  display: flex; flex-direction: column;
  min-width: 0; min-height: 0;
  border-left: 1px solid var(--kl-color-line);
  background: var(--kl-color-surface);
}
.kl-browser__loghead { flex: none; display: flex; align-items: center; gap: 8px; padding: 12px 12px 8px 16px; }
.kl-browser__loghead h4 { margin: 0; font: var(--kl-font-label-strong); }
.kl-browser__loghead span { margin-left: auto; font: var(--kl-font-caption); color: var(--kl-color-text-tertiary); font-variant-numeric: tabular-nums; }
.kl-browser__steps { flex: 1 1 auto; min-height: 0; overflow: auto; overscroll-behavior: contain; margin: 0; padding: 0 8px 8px; list-style: none; display: flex; flex-direction: column; gap: 2px; }
.kl-step {
  position: relative;
  width: 100%;
  display: grid; grid-template-columns: 20px 1fr auto; align-items: start; gap: 8px;
  padding: 7px 8px;
  border: 0; border-radius: var(--kl-radius-row);
  background: transparent;
  color: var(--kl-color-text);
  font: var(--kl-font-meta); font-family: var(--kl-font-sans);
  text-align: left;
  cursor: pointer;
  transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-step:hover, .kl-step.is-hover { background: var(--kl-color-control-fill); }
.kl-step:focus-visible, .kl-step.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: -2px; }
.kl-step__n {
  width: 20px; height: 20px; margin-top: -1px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--kl-radius-round);
  background: var(--kl-color-control-fill);
  color: var(--kl-color-text-secondary);
  font: var(--kl-font-caption); font-variant-numeric: tabular-nums;
}
.kl-step__n .kl-icon { width: 12px; height: 12px; }
.kl-step__text { min-width: 0; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.kl-step__text b { font-weight: var(--kl-font-weight-semibold); }
.kl-step__time { font: var(--kl-font-caption); color: var(--kl-color-text-tertiary); font-variant-numeric: tabular-nums; padding-top: 2px; }
.kl-step.is-done .kl-step__text { color: var(--kl-color-text-secondary); }
.kl-step.is-current .kl-step__n { position: relative; background: var(--kl-ab-hue); color: var(--kl-color-text-on-fill); --kl-ring: var(--kl-ab-hue); }   /* rings with v2's kl-m-ring */
.kl-step.is-paused .kl-step__n { background: var(--kl-color-status-idle); }
.kl-step:is(.is-needs, .is-ask) .kl-step__n { background: var(--kl-color-status-approval); color: var(--kl-color-text-on-fill); }
.kl-step.is-failed .kl-step__n { background: var(--kl-color-status-stopped); color: var(--kl-color-text-on-fill); }
.kl-step.is-you .kl-step__n { background: var(--kl-ab-you); color: var(--kl-color-text-on-fill); }
.kl-step.is-next { opacity: .5; cursor: default; }
.kl-step.is-next:hover { background: transparent; }
/* Viewing an earlier step: the selection edge plus a check, like every chosen row */
.kl-step.is-viewing { box-shadow: inset 0 0 0 2px var(--kl-color-selection); }
.kl-step.is-arriving { animation: kl-reveal var(--kl-motion-reveal) var(--kl-motion-ease-out) both; }
.kl-browser__rules { flex: none; display: flex; flex-direction: column; gap: 6px; padding: 10px 16px 12px; border-top: 1px solid var(--kl-color-line); font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-browser__rules p { margin: 0; display: flex; align-items: center; gap: 6px; }
.kl-browser__rules .kl-icon { width: 12px; height: 12px; flex: none; }

/* Footer: a meta line and the controls (v2 .kl-win__foot) */
.kl-browser__meta { font-variant-numeric: tabular-nums; }
.kl-browser__handback { flex: 1 1 260px; display: flex; gap: 8px; align-items: center; min-width: 0; }
.kl-browser__handback .kl-field { flex: 1; min-width: 0; }

/* Window sizes: the large window can widen to the board's focus width */
.kl-win.kl-browser.is-wide { --kl-win-w: 1160px; }
.kl-win.kl-browser.is-wide .kl-browser__stage { --kl-ab-zoom: .95; }
.kl-win.kl-browser.is-wide .kl-browser__main { --kl-ab-stage-h: 608px; }

/* Growing from the peek: v2's kl-m-grow-from, with --kl-from-x/-y/-s set to the peek's spot and scale
   (kl-m-shrink-to plays it back). Ease-out, no bounce, like every change of size. */

/* Quiet while Alban drags, links or types: no ripples, no hops, plain glides */
.kl-browser.is-quiet .kl-browser__cursor, .kl-browser-peek.is-quiet .kl-browser__cursor { transition-timing-function: var(--kl-motion-ease-out); }
.kl-browser.is-quiet .kl-browser__ripple, .kl-browser-peek.is-quiet .kl-browser__ripple { animation: none; opacity: 0; }
.kl-browser.is-quiet .kl-browser__tag { animation: none; }
.kl-browser.is-quiet .kl-step.is-arriving { animation: none; }

/* =====================================================================================================
   5. Peek: the small size, a live thumbnail beside the card
   ===================================================================================================== */
.kl-browser-peek {
  --kl-ab-peek-w: 288px;
  position: relative;
  width: var(--kl-ab-peek-w);
  display: flex; flex-direction: column;
  border-radius: var(--kl-radius-panel);
  background: var(--kl-color-surface);
  box-shadow: var(--kl-shadow-card), 0 0 0 1px var(--kl-color-line);
  color: var(--kl-color-text);
  font: var(--kl-font-meta); font-family: var(--kl-font-sans);
  overflow: hidden;
  isolation: isolate;
  transform-origin: var(--kl-win-origin, left center);
  transition: box-shadow var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-browser-peek *, .kl-browser-peek *::before, .kl-browser-peek *::after { box-sizing: border-box; }
.kl-browser-peek:hover, .kl-browser-peek.is-hover { box-shadow: var(--kl-shadow-card-hover), 0 0 0 1px var(--kl-color-line); }
.kl-browser-peek.is-opening { animation: kl-win-open var(--kl-motion-win-open) var(--kl-motion-spring-soft) both; }
.kl-browser-peek.is-closing { animation: kl-win-close var(--kl-motion-win-close) var(--kl-motion-ease-out) both; }
.kl-browser-peek.is-dragging { box-shadow: var(--kl-shadow-window-drag); cursor: grabbing; }
.kl-browser-peek__bar { display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 4px 0 12px; cursor: grab; user-select: none; -webkit-user-select: none; }
.kl-browser-peek__bar .kl-dot { width: 8px; height: 8px; }
.kl-browser-peek__host { flex: 1; min-width: 0; font: var(--kl-font-label-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kl-browser-peek__who { font: var(--kl-font-caption); color: var(--kl-color-text-tertiary); white-space: nowrap; }
.kl-browser-peek .kl-browser__stage { --kl-ab-zoom: .3; border-top: 1px solid var(--kl-color-line); border-bottom: 1px solid var(--kl-color-line); cursor: zoom-in; }
.kl-browser-peek .kl-browser__arrow { width: 14px; height: 14px; margin: -2.45px 0 0 -3.5px; }
.kl-browser-peek .kl-browser__tag, .kl-browser-peek .kl-browser__label { display: none; }
.kl-browser-peek .kl-browser__ripple { width: 20px; height: 20px; margin: -10px 0 0 -10px; }
.kl-browser-peek .kl-browser__target { box-shadow: 0 0 0 1.5px var(--kl-ab-hue); }
.kl-browser-peek__line { display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 12px; }
.kl-browser-peek__line span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--kl-color-text-secondary); }
.kl-browser-peek__line span.kl-m-write { animation: kl-write var(--kl-motion-write) var(--kl-motion-ease-out) both; }
.kl-browser-peek__line small { font: var(--kl-font-caption); color: var(--kl-color-text-tertiary); font-variant-numeric: tabular-nums; }
/* Controls appear on hover or keyboard focus, over the thumbnail's bottom right */
.kl-browser-peek__ctl { position: absolute; right: 8px; bottom: 44px; z-index: 7; display: flex; gap: 6px; opacity: 0; translate: 0 4px; transition: opacity var(--kl-motion-hover) var(--kl-motion-ease-out), translate var(--kl-motion-hover) var(--kl-motion-ease-out); }
.kl-browser-peek:hover .kl-browser-peek__ctl, .kl-browser-peek:focus-within .kl-browser-peek__ctl, .kl-browser-peek.is-hover .kl-browser-peek__ctl { opacity: 1; translate: 0 0; }
.kl-browser-peek .kl-browser__veil { padding: 8px; align-items: center; justify-content: center; }
.kl-browser-peek .kl-browser__drive span, .kl-browser-peek .kl-browser__replay { display: none; }
.kl-browser-peek__badge { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: var(--kl-radius-pill); background: var(--kl-glass-fill-menu, var(--kl-color-surface)); box-shadow: var(--kl-shadow-menu); font: var(--kl-font-badge); color: var(--kl-color-text); animation: kl-say-in var(--kl-motion-say-in) var(--kl-motion-spring) both; }
.kl-browser-peek__badge .kl-icon { width: 14px; height: 14px; }
.kl-browser-peek:is(.is-needs, .is-ask) { box-shadow: var(--kl-shadow-card), 0 0 0 1.5px var(--kl-color-status-approval); }
.kl-browser-peek:is(.is-needs, .is-ask) .kl-browser-peek__badge { color: var(--kl-color-status-approval-ink); }
.kl-browser-peek.is-failed .kl-browser-peek__badge { color: var(--kl-color-status-stopped-ink); }
.kl-browser-peek.is-driving { box-shadow: var(--kl-shadow-card), 0 0 0 2px var(--kl-ab-you); }
.kl-browser-peek.is-done .kl-browser-peek__badge .kl-icon { color: var(--kl-color-status-executing); }

/* =====================================================================================================
   5b. Driving bar: one line any surface can show while an agent drives a browser (the harness's
   session view, a card's expanded stage, the top of a window). Glass, because it floats.
   ===================================================================================================== */
.kl-browser-bar {
  --kl-ab-hue: var(--kl-color-project-1);
  --kl-ab-you: var(--kl-color-selection);
  display: inline-flex; align-items: center; gap: 10px;
  max-width: 100%;
  height: 40px;
  padding: 0 4px 0 14px;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-glass-fill-menu, var(--kl-color-surface));
  -webkit-backdrop-filter: var(--kl-glass-filter);
  backdrop-filter: var(--kl-glass-filter);
  box-shadow: var(--kl-shadow-menu), inset 0 0 0 1.5px color-mix(in srgb, var(--kl-ab-hue) 55%, transparent);
  color: var(--kl-color-text);
  font: var(--kl-font-meta); font-family: var(--kl-font-sans);
  white-space: nowrap;
}
.kl-browser-bar .kl-dot { width: 8px; height: 8px; }
.kl-browser-bar__text { min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--kl-color-text-secondary); }
.kl-browser-bar__text b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }
.kl-browser-bar__ctl { display: inline-flex; align-items: center; gap: 4px; flex: none; }
.kl-browser-bar.is-you { box-shadow: var(--kl-shadow-menu), inset 0 0 0 2px var(--kl-ab-you); }
.kl-browser-bar.is-needs { box-shadow: var(--kl-shadow-menu), inset 0 0 0 1.5px var(--kl-color-status-approval); }
.kl-browser-bar.is-arriving { animation: kl-menu-in var(--kl-motion-menu-in) var(--kl-motion-spring) both; }
:is(.kl-browser-bar).kl-ab--p2 { --kl-ab-hue: var(--kl-color-project-2); }
:is(.kl-browser-bar).kl-ab--p3 { --kl-ab-hue: var(--kl-color-project-3); }
:is(.kl-browser-bar).kl-ab--p4 { --kl-ab-hue: var(--kl-color-project-4); }

/* =====================================================================================================
   5c. Session bar: the agent's browser inside its session view (the transcript window).
   A 44 px strip pinned under the session's status line while the agent has a browser open, so it stays
   in view while the transcript scrolls. Flat on the window surface (the session window is opaque and its
   rows are flat), tinted 6% with the project's hue. From left: v2's web chip (site, dot in the hue;
   click = the peek), what the agent does now, the step count, and open (= the window). A 2 px line on
   the bottom edge fills with the steps done.
   States: (live), .is-idle, .is-asking (waiting on Alban: sign-in or asks first), .is-driving, .is-done.
   ===================================================================================================== */
.kl-browser-dock {
  --kl-ab-dock-h: 44px;
  --kl-ab-dock-chip-max: 160px;
  --kl-ab-dock-progress: 0;                       /* steps done ÷ steps, set inline */
  --kl-ab-dock-edge: var(--kl-ab-hue);
  --kl-ab-dock-tint: var(--kl-ab-hue);
  --kl-card-hue: var(--kl-ab-hue); --kl-card-hue-ink: var(--kl-ab-hue-ink); --kl-ol: 1;   /* the web chip reads these on a card */
  position: relative; flex: none;
  display: flex; align-items: center; gap: var(--kl-space-2);
  height: var(--kl-ab-dock-h); box-sizing: border-box;
  padding: 0 var(--kl-space-2) 0 var(--kl-space-3);
  background: color-mix(in srgb, var(--kl-ab-dock-tint) 6%, var(--kl-color-surface));
  border-bottom: 1px solid var(--kl-color-line);
  color: var(--kl-color-text-secondary);
  font: var(--kl-font-meta); font-family: var(--kl-font-sans);
  white-space: nowrap;
  transition: background-color var(--kl-motion-hover) ease;
}
.kl-browser-dock > .kl-card__web { max-width: var(--kl-ab-dock-chip-max); }
.kl-browser-dock__now { flex: 1 1 auto; min-width: 0; margin: 0; overflow: hidden; text-overflow: ellipsis; }
.kl-browser-dock__now b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }
.kl-browser-dock__now .kl-icon { --kl-icon-size: 14px; vertical-align: -2px; margin-right: 4px; }
.kl-browser-dock__count { flex: none; font: var(--kl-font-caption); font-variant-numeric: tabular-nums; color: var(--kl-color-text-tertiary); }
.kl-browser-dock__count b { color: var(--kl-color-text-secondary); font-weight: var(--kl-font-weight-semibold); }
.kl-browser-dock__ctl { flex: none; display: inline-flex; align-items: center; gap: 2px; }
.kl-browser-dock__progress { position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; pointer-events: none; }
.kl-browser-dock__progress i {
  display: block; height: 100%; width: calc(var(--kl-ab-dock-progress) * 100%);
  border-radius: 0 2px 2px 0; background: var(--kl-ab-dock-edge);
  transition: width var(--kl-motion-expand) var(--kl-motion-ease-out), background-color var(--kl-motion-hover) ease;   /* a size: ease-out, never the spring */
}

/* Idle: the browser is still open but the agent is doing something else (writing, reading files) */
.kl-browser-dock.is-idle { --kl-ab-dock-tint: var(--kl-color-status-idle); --kl-ab-dock-edge: var(--kl-color-status-idle); background: var(--kl-color-surface); }
.kl-browser-dock.is-idle .kl-browser-dock__now { color: var(--kl-color-text-tertiary); }
.kl-browser-dock.is-idle .kl-browser-dock__now b { color: var(--kl-color-text-secondary); }

/* Waiting on Alban: the approval colour of .kl-card.is-asking, an edge round the strip, the action in words */
.kl-browser-dock.is-asking { --kl-ab-dock-tint: var(--kl-color-status-approval); --kl-ab-dock-edge: var(--kl-color-status-approval); box-shadow: inset 0 0 0 1px var(--kl-color-status-approval); background: color-mix(in srgb, var(--kl-color-status-approval) 9%, var(--kl-color-surface)); }
.kl-browser-dock.is-asking .kl-browser-dock__now b { color: var(--kl-color-status-approval-ink); }

/* Alban drives the browser: selection blue, as the window's driving state */
.kl-browser-dock.is-driving { --kl-ab-dock-tint: var(--kl-color-selection); --kl-ab-dock-edge: var(--kl-color-selection); }
.kl-browser-dock.is-driving .kl-browser-dock__now b { color: var(--kl-color-selection-ink); }

/* Done: green check, the line full; it stays as the session's last browser line until the agent browses again or Alban hides it */
.kl-browser-dock.is-done { --kl-ab-dock-edge: var(--kl-color-status-executing); --kl-ab-dock-progress: 1; }
.kl-browser-dock.is-done .kl-browser-dock__now .kl-icon { color: var(--kl-color-status-executing); }

/* Motion. Opening: the strip grows down from the status line (a size: ease-out, no bounce), then the chip pops
   in on the dial's spring. A new step: the line writes itself in (kl-m-write) and the count rolls (kl-m-roll).
   A change of state (asking, driving, done): the chip pops once (.is-changed). Breathing dots are state. */
.kl-browser-dock.is-arriving { animation: kl-ab-dock-in var(--kl-motion-expand) var(--kl-motion-ease-out) both; overflow: hidden; }
.kl-browser-dock.is-arriving > .kl-card__web { animation: kl-say-in var(--kl-motion-pop) var(--kl-motion-spring-pop) calc(var(--kl-motion-expand) * .5) both; }
.kl-browser-dock.is-changed > .kl-card__web { animation: kl-say-in var(--kl-motion-pop) var(--kl-motion-spring-pop); }
/* Quiet: while Alban types a reply, drags or links (and 1.5 s after), words and numbers simply change */
.kl-browser-dock.is-quiet :is(.kl-m-write, .kl-m-roll-new, .kl-m-roll-old),
.kl-browser-dock.is-quiet.is-changed > .kl-card__web { animation: none; }

/* =====================================================================================================
   6. Keyframes (new; their amounts follow the dial where they move)
   ===================================================================================================== */
@keyframes kl-ab-target-in { from { opacity: 0; scale: 1.06; } to { opacity: 1; scale: 1; } }
@keyframes kl-ab-breathe { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@keyframes kl-ab-dock-in { from { height: 0; opacity: 0; } to { height: var(--kl-ab-dock-h); opacity: 1; } }

/* =====================================================================================================
   7. Reduced motion: the pointer jumps, marks fade, no loops
   ===================================================================================================== */
@media (prefers-reduced-motion: reduce) {
  .kl-browser__cursor, .kl-browser__target, .kl-browser__scroll i, .kl-browser__load i { transition: opacity var(--kl-motion-fade) linear !important; }
  .kl-browser-bar.is-arriving, .kl-browser__read.is-on, .kl-browser__target.is-in, .kl-step.is-arriving, .kl-browser__notice, .kl-browser__replay, .kl-browser-peek__badge,
  .kl-browser-peek.is-opening { animation: kl-fade-in var(--kl-motion-fade) linear both; }
  .kl-webchip.is-live .kl-card__web-dot, .kl-webchip.is-needs .kl-card__web-dot, .kl-browser__cursor.is-speaking .kl-browser__tag { animation: none; }
  .kl-webchip.is-asking .kl-card__web-dot, .kl-browser-dock :is(.kl-m-write, .kl-card__web), .kl-browser-dock.is-arriving > .kl-card__web { animation: none; }
  .kl-browser-dock.is-arriving { animation: kl-fade-in var(--kl-motion-fade) linear both; }
  .kl-browser-dock__progress i { transition: none; }
}
.kl-motion-reduce :is(.kl-browser__cursor, .kl-browser__target, .kl-browser__scroll i, .kl-browser__load i) { transition: opacity var(--kl-motion-fade) linear !important; }
.kl-motion-reduce :is(.kl-browser-bar.is-arriving, .kl-browser__read.is-on, .kl-browser__target.is-in, .kl-step.is-arriving, .kl-browser__notice, .kl-browser__replay, .kl-browser-peek__badge, .kl-browser-peek.is-opening) { animation: kl-fade-in var(--kl-motion-fade) linear both; }
.kl-motion-reduce :is(.kl-webchip.is-live .kl-card__web-dot, .kl-webchip.is-needs .kl-card__web-dot, .kl-browser__cursor.is-speaking .kl-browser__tag) { animation: none; }
.kl-motion-reduce :is(.kl-webchip.is-asking .kl-card__web-dot, .kl-browser-dock .kl-m-write, .kl-browser-dock > .kl-card__web) { animation: none; }
.kl-motion-reduce .kl-browser-dock.is-arriving { animation: kl-fade-in var(--kl-motion-fade) linear both; }
.kl-motion-reduce .kl-browser-dock__progress i { transition: none; }

/* Increased contrast: marks get a solid edge, the veil turns opaque */
@media (prefers-contrast: more) {
  .kl-browser__target { box-shadow: 0 0 0 2px var(--kl-ab-hue), 0 0 0 4px var(--kl-color-surface); background: transparent; }
  .kl-browser__veil { background: color-mix(in srgb, var(--kl-color-surface) 86%, transparent); -webkit-backdrop-filter: none; backdrop-filter: none; }
  .kl-browser__notice, .kl-browser__replay, .kl-browser-peek__badge, .kl-browser-bar { background: var(--kl-color-surface); -webkit-backdrop-filter: none; backdrop-filter: none; box-shadow: var(--kl-shadow-menu), inset 0 0 0 1px var(--kl-color-line-strong); }
  .kl-browser-dock { background: var(--kl-color-surface); border-bottom-color: var(--kl-color-line-strong); }
  .kl-browser-dock.is-asking { box-shadow: inset 0 0 0 2px var(--kl-color-status-approval); }
  .kl-browser-dock__progress { height: 3px; }
}
[data-contrast="more"] .kl-browser__target { box-shadow: 0 0 0 2px var(--kl-ab-hue), 0 0 0 4px var(--kl-color-surface); background: transparent; }
[data-contrast="more"] .kl-browser__veil { background: color-mix(in srgb, var(--kl-color-surface) 86%, transparent); -webkit-backdrop-filter: none; backdrop-filter: none; }
[data-contrast="more"] :is(.kl-browser__notice, .kl-browser__replay, .kl-browser-peek__badge, .kl-browser-bar) { background: var(--kl-color-surface); -webkit-backdrop-filter: none; backdrop-filter: none; box-shadow: var(--kl-shadow-menu), inset 0 0 0 1px var(--kl-color-line-strong); }
[data-contrast="more"] .kl-browser-dock { background: var(--kl-color-surface); border-bottom-color: var(--kl-color-line-strong); }
[data-contrast="more"] .kl-browser-dock.is-asking { box-shadow: inset 0 0 0 2px var(--kl-color-status-approval); }
[data-contrast="more"] .kl-browser-dock__progress { height: 3px; }

/* ===== harness/extend/extend.css ===== */
/* Klippan master · Harness · Extend: connectors, skills, hooks and the agent definition form.
   Loaded after ../../../klippan-v2/combined/klippan.css. Builds on the v2 window (.kl-win), setting rows
   (.kl-setting), and the basic controls (.kl-btn, .kl-iconbtn, .kl-switch, .kl-select, .kl-seg, .kl-field,
   .kl-checkbox, .kl-chip, .kl-badge, .kl-dot, .kl-stepper, .kl-toast, .kl-check) and never restyles them.
   Every colour, shadow, radius, space, type and motion value is a --kl- token; pixel sizes that belong to
   one component are local custom properties. Icons: v2 sprite (kl-*) plus the harness sprite
   (klippan-master/harness/icons/sprite.svg: connector, skill, hook, terminal, permission …).

   Rules kept: windows are opaque; one blue action per view (Done, or Save in a form); Cancel, Off and
   Block come first; nothing is deleted (Disconnect and Remove end on the Undo toast, removed skills go to
   the Garbage); tokens only, never money. */

.kl-win--connectors,
.kl-win--skills,
.kl-win--hooks,
.kl-win--agentdef,
.kl-conn, .kl-skill, .kl-hook, .kl-hookedit, .kl-agentdef, .kl-toolpick, .kl-xtag, .kl-xmark, .kl-xempty, .kl-xout {
  --kl-x-hair: 2px;
  --kl-x-tight: 6px;
  --kl-x-tile: 32px;           /* the icon tile on a connector, skill or hook row */
  --kl-x-tile-sm: 24px;
}
.kl-win--connectors { --kl-win-w: 440px; }
.kl-win--skills     { --kl-win-w: 480px; }
.kl-win--hooks      { --kl-win-w: 460px; }
.kl-win--agentdef   { --kl-win-w: 480px; }

/* The harness icons arrive as their own sprite; they use .kl-icon like every v2 icon. */
.kl-x-ico { width: 16px; height: 16px; }

/* =====================================================================================
   0. Shared bits: a heading row with a tool on the right, the spinner, the empty state
   ===================================================================================== */
.kl-x-head { display: flex; align-items: center; gap: var(--kl-space-2); flex-wrap: wrap; }
.kl-x-head .kl-search { flex: 1 1 160px; }
.kl-x-head__count { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* A small ring for something connecting or running. Control blue: it is progress, not status.
   It turns with v2's kl-m-spin (--kl-motion-spin), so mark it up as class="kl-x-spin kl-m-spin". */
.kl-x-spin {
  flex: none; display: inline-block; width: 14px; height: 14px; border-radius: 50%;
  box-shadow: inset 0 0 0 2px var(--kl-color-control-fill-pressed);
  border: 2px solid transparent; border-top-color: var(--kl-color-control);
  box-sizing: border-box;
}

.kl-xempty {
  display: flex; flex-direction: column; align-items: center; gap: var(--kl-space-3); text-align: center;
  padding: var(--kl-space-8) var(--kl-space-6);
  border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface-sunken);
}
.kl-xempty__icon { display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: var(--kl-radius-tile); background: var(--kl-color-control-fill); color: var(--kl-color-text-secondary); }
.kl-xempty__icon .kl-icon { --kl-icon-size: 22px; }
.kl-xempty__title { margin: 0; font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); color: var(--kl-color-text); }
.kl-xempty__text { margin: 0; max-width: 300px; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }

/* Hue tiles for connectors and skills: the hue tells rows apart, it never means status. */
.kl-x-tile {
  display: inline-grid; place-items: center; flex: none;
  width: var(--kl-x-tile); height: var(--kl-x-tile); border-radius: var(--kl-radius-tile);
  background: var(--kl-x-soft, var(--kl-color-control-fill)); color: var(--kl-x-ink, var(--kl-color-text));
}
.kl-x-tile .kl-icon { --kl-icon-size: 18px; }
.kl-x-tile--sm { width: var(--kl-x-tile-sm); height: var(--kl-x-tile-sm); border-radius: var(--kl-radius-row); }
.kl-x-tile--sm .kl-icon { --kl-icon-size: 14px; }
.kl-x-hue--blue     { --kl-x-soft: var(--kl-color-hue-blue-soft);     --kl-x-ink: var(--kl-color-hue-blue-ink); }
.kl-x-hue--teal     { --kl-x-soft: var(--kl-color-hue-teal-soft);     --kl-x-ink: var(--kl-color-hue-teal-ink); }
.kl-x-hue--purple   { --kl-x-soft: var(--kl-color-hue-purple-soft);   --kl-x-ink: var(--kl-color-hue-purple-ink); }
.kl-x-hue--indigo   { --kl-x-soft: var(--kl-color-hue-indigo-soft);   --kl-x-ink: var(--kl-color-hue-indigo-ink); }
.kl-x-hue--orange   { --kl-x-soft: var(--kl-color-hue-orange-soft);   --kl-x-ink: var(--kl-color-hue-orange-ink); }
.kl-x-hue--pink     { --kl-x-soft: var(--kl-color-hue-pink-soft);     --kl-x-ink: var(--kl-color-hue-pink-ink); }
.kl-x-hue--cerulean { --kl-x-soft: var(--kl-color-hue-cerulean-soft); --kl-x-ink: var(--kl-color-hue-cerulean-ink); }
.kl-x-hue--graphite { --kl-x-soft: var(--kl-color-hue-graphite-soft); --kl-x-ink: var(--kl-color-hue-graphite-ink); }
.kl-x-hue--brown    { --kl-x-soft: var(--kl-color-hue-brown-soft);    --kl-x-ink: var(--kl-color-hue-brown-ink); }

/* =====================================================================================
   1. Connectors window: one row per service, its state, tool count and scope
   ===================================================================================== */
.kl-conn-list {
  display: flex; flex-direction: column;
  border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface-sunken);
  overflow: hidden;
}
.kl-conn { position: relative; display: flex; flex-direction: column; }
.kl-conn + .kl-conn { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-conn__row {
  display: flex; align-items: center; gap: var(--kl-space-3);
  min-height: 56px; padding: var(--kl-space-2) var(--kl-space-3);
}
.kl-conn__open {
  /* The whole text block is the button that opens the row; the switch stays its own control. */
  flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: var(--kl-space-3);
  margin: calc(var(--kl-space-1) * -1) 0; padding: var(--kl-space-1) var(--kl-space-1) var(--kl-space-1) 0;
  border: 0; border-radius: var(--kl-radius-row); background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer;
  transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-conn__open:hover, .kl-conn__open.is-hover { background: var(--kl-color-control-fill); }
.kl-conn__open:focus-visible, .kl-conn__open.is-focus { outline: none; box-shadow: var(--kl-shadow-ring-focus); }
.kl-conn__text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--kl-x-hair); }
.kl-conn__name { font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); color: var(--kl-color-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kl-conn__meta { display: flex; align-items: center; gap: var(--kl-x-tight); font: var(--kl-font-meta); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kl-conn__meta .kl-icon { --kl-icon-size: 14px; }
.kl-conn__chev { flex: none; color: var(--kl-color-text-secondary); transition: rotate var(--kl-motion-expand) var(--kl-motion-spring-pop); }
.kl-conn__chev .kl-icon { --kl-icon-size: 14px; }
.kl-conn.is-open .kl-conn__chev { rotate: 90deg; }
.kl-conn__side { flex: none; display: inline-flex; align-items: center; gap: var(--kl-space-2); }

/* States */
.kl-conn.is-off .kl-conn__name { color: var(--kl-color-text-secondary); }
.kl-conn.is-off .kl-x-tile { background: var(--kl-color-control-fill); color: var(--kl-color-text-tertiary); }
.kl-conn.is-signin .kl-conn__meta { color: var(--kl-color-text); }
.kl-conn.is-failed .kl-conn__meta { color: var(--kl-color-status-stopped-ink); }
.kl-conn.is-failed .kl-conn__meta .kl-icon { color: var(--kl-color-status-stopped); }
.kl-conn.is-connecting .kl-conn__meta { color: var(--kl-color-text); }
.kl-conn.is-selected { background: var(--kl-color-surface); }

/* The open row: its tools, each with Off · Ask · Allow (Off first), then scope and Disconnect */
.kl-conn__more {
  display: flex; flex-direction: column; gap: var(--kl-space-3);
  padding: 0 var(--kl-space-3) var(--kl-space-3) calc(var(--kl-space-3) * 2 + var(--kl-x-tile));
}
.kl-conn__tools { display: flex; flex-direction: column; border-radius: var(--kl-radius-row); background: var(--kl-color-surface); box-shadow: inset 0 0 0 1px var(--kl-color-line); }
.kl-conn__tool { display: flex; align-items: center; gap: var(--kl-space-2); min-height: 40px; padding: var(--kl-space-1) var(--kl-space-1) var(--kl-space-1) var(--kl-space-3); }
.kl-conn__tool + .kl-conn__tool { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-conn__toolname { flex: 1 1 auto; min-width: 0; font: var(--kl-font-meta); color: var(--kl-color-text); }
.kl-conn__toolname small { display: block; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-conn__tool .kl-seg { --kl-seg-h: 24px; }
.kl-conn__tool .kl-seg__item { min-width: 44px; font: var(--kl-font-caption); }
.kl-conn__foot { display: flex; align-items: center; gap: var(--kl-space-2); flex-wrap: wrap; }
.kl-conn__foot .kl-select { --kl-select-w: 168px; }
.kl-conn__foot > :last-child { margin-left: auto; }
.kl-conn__why { margin: 0; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }

/* Add a connector: a catalog inside the same window, behind a back button */
.kl-conn-cat { display: flex; flex-direction: column; gap: var(--kl-space-3); }
.kl-conn-cat__back { align-self: flex-start; }
.kl-conn-cat__list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--kl-space-2); }
.kl-conn-cat__item {
  display: flex; align-items: center; gap: var(--kl-space-2); min-height: 52px; padding: var(--kl-space-2) var(--kl-space-2) var(--kl-space-2) var(--kl-space-2);
  border: 0; border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface-sunken); color: var(--kl-color-text);
  font: inherit; text-align: left; cursor: pointer;
  transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-conn-cat__item:hover, .kl-conn-cat__item.is-hover { background: var(--kl-color-control-fill); }
.kl-conn-cat__item:focus-visible { outline: none; box-shadow: var(--kl-shadow-ring-focus); }
.kl-conn-cat__name { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; font: var(--kl-font-meta); font-weight: var(--kl-font-weight-medium); }
.kl-conn-cat__name small { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-weight: var(--kl-font-weight-regular); }
.kl-conn-cat__item[aria-disabled="true"] { cursor: default; }
.kl-conn-cat__item[aria-disabled="true"] .kl-conn-cat__name { color: var(--kl-color-text-secondary); }

/* =====================================================================================
   2. Skill tiles: on, off, in use; chosen with the edge and check; a detail panel below
   ===================================================================================== */
.kl-skill-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--kl-space-3); }
.kl-skill {
  position: relative; display: flex; flex-direction: column; gap: var(--kl-space-2);
  min-height: 132px; padding: var(--kl-space-3);
  border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface-raised);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
  transition: box-shadow var(--kl-motion-hover) var(--kl-motion-ease-out), background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-skill__open {
  /* Covers the tile so a click anywhere opens the detail; the switch sits above it */
  position: absolute; inset: 0; z-index: 0; border: 0; border-radius: inherit; background: transparent; cursor: pointer;
}
.kl-skill__open:focus-visible { outline: none; box-shadow: var(--kl-shadow-ring-focus); }
.kl-skill:hover, .kl-skill.is-hover { box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
.kl-skill__head { display: flex; align-items: flex-start; gap: var(--kl-space-2); pointer-events: none; }
.kl-skill__name { flex: 1 1 auto; min-width: 0; margin: 0; padding-top: var(--kl-space-1); font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); color: var(--kl-color-text); }
.kl-skill__what { margin: 0; flex: 1 1 auto; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); pointer-events: none;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.kl-skill__foot { position: relative; z-index: 1; display: flex; align-items: center; gap: var(--kl-space-2); min-height: 24px; pointer-events: none; }
.kl-skill__foot > * { pointer-events: auto; }
.kl-skill__from { flex: 1 1 auto; min-width: 0; display: inline-flex; align-items: center; gap: var(--kl-x-tight); font: var(--kl-font-caption); color: var(--kl-color-text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kl-skill__from .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
.kl-skill__use { display: inline-flex; align-items: center; gap: var(--kl-x-tight); font: var(--kl-font-caption); color: var(--kl-color-status-executing-ink); white-space: nowrap; }
.kl-skill__use .kl-dot { --kl-dot-size: 8px; }
.kl-skill .kl-check { z-index: 3; }

.kl-skill.is-off { background: var(--kl-color-surface-sunken); box-shadow: none; }
.kl-skill.is-off .kl-skill__name { color: var(--kl-color-text-secondary); }
.kl-skill.is-off .kl-x-tile { background: var(--kl-color-control-fill); color: var(--kl-color-text-tertiary); }
.kl-skill.is-inuse { background: var(--kl-color-surface-raised); }
.kl-skill.is-blocked .kl-skill__name, .kl-skill.is-blocked .kl-skill__what { color: var(--kl-color-text-secondary); }
.kl-skill.is-blocked .kl-x-tile { background: var(--kl-color-control-fill); color: var(--kl-color-text-tertiary); }

/* A skill switched on: its tile carries v2's kl-m-hop once (height scales with the dial, none under reduced motion) */

/* Detail of the chosen skill */
.kl-skill-detail { display: flex; flex-direction: column; gap: var(--kl-space-3); padding: var(--kl-space-4); border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface-sunken); }
.kl-skill-detail__head { display: flex; align-items: center; gap: var(--kl-space-3); }
.kl-skill-detail__title { flex: 1 1 auto; min-width: 0; margin: 0; font: var(--kl-font-title); color: var(--kl-color-text); }
.kl-skill-detail__text { margin: 0; font: var(--kl-font-body); color: var(--kl-color-text); }
.kl-skill-detail__dl { display: grid; grid-template-columns: 112px minmax(0, 1fr); gap: var(--kl-space-2) var(--kl-space-3); margin: 0; font: var(--kl-font-meta); }
.kl-skill-detail__dl dt { color: var(--kl-color-text-secondary); }
.kl-skill-detail__dl dd { margin: 0; color: var(--kl-color-text); display: flex; flex-wrap: wrap; gap: var(--kl-space-1); }
.kl-skill-detail__files { font-family: var(--kl-font-mono); font-size: var(--kl-font-caption-size); line-height: var(--kl-font-caption-line); color: var(--kl-color-text-secondary); }
.kl-skill-detail__actions { display: flex; align-items: center; gap: var(--kl-space-2); flex-wrap: wrap; }
.kl-skill-detail__actions > :last-child { margin-left: auto; }

/* =====================================================================================
   3. Hooks: a list of plain sentences, and the editor (when, which tools, command, if it fails)
   ===================================================================================== */
.kl-hook-list { display: flex; flex-direction: column; border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface-sunken); overflow: hidden; }
.kl-hook { position: relative; display: flex; align-items: center; gap: var(--kl-space-3); min-height: 64px; padding: var(--kl-space-2) var(--kl-space-3); }
.kl-hook + .kl-hook { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-hook__open {
  flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: var(--kl-space-3);
  margin: calc(var(--kl-space-1) * -1) 0; padding: var(--kl-space-1) var(--kl-space-1) var(--kl-space-1) 0;
  border: 0; border-radius: var(--kl-radius-row); background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer;
  transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-hook__open:hover, .kl-hook__open.is-hover { background: var(--kl-color-control-fill); }
.kl-hook__open:focus-visible { outline: none; box-shadow: var(--kl-shadow-ring-focus); }
.kl-hook__text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--kl-x-hair); }
.kl-hook__say { font: var(--kl-font-meta); color: var(--kl-color-text); }
.kl-hook__say code, .kl-hookedit code { font-family: var(--kl-font-mono); font-size: .94em; padding: 0 var(--kl-space-1); border-radius: var(--kl-radius-sheet); background: var(--kl-color-control-fill); }
.kl-hook__last { display: inline-flex; align-items: center; gap: var(--kl-x-tight); font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-hook__last .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
.kl-hook__last--blocked { color: var(--kl-color-status-stopped-ink); }
.kl-hook__last--blocked .kl-icon { color: var(--kl-color-status-stopped); }
.kl-hook__last--running { color: var(--kl-color-text); }
.kl-hook.is-off .kl-hook__say { color: var(--kl-color-text-secondary); }
.kl-hook.is-off .kl-x-tile { color: var(--kl-color-text-tertiary); }
.kl-hook.is-selected { background: var(--kl-color-surface); }

/* The editor. Lives in the hooks window body (replacing the list) with its own foot: Cancel, Save hook */
.kl-hookedit { display: flex; flex-direction: column; gap: var(--kl-space-4); }
.kl-hookedit__sentence {
  margin: 0; padding: var(--kl-space-3) var(--kl-space-4); border-radius: var(--kl-radius-groupbox);
  background: var(--kl-color-surface-sunken); font: var(--kl-font-body); color: var(--kl-color-text);
}
.kl-hookedit__field { display: flex; flex-direction: column; gap: var(--kl-space-1); }
.kl-hookedit__field > .kl-select { --kl-select-w: 100%; }
.kl-hookedit__chips { display: flex; flex-wrap: wrap; gap: var(--kl-space-2); }
.kl-hookedit__row { display: flex; gap: var(--kl-space-4); flex-wrap: wrap; }
.kl-hookedit__row > * { flex: 1 1 160px; min-width: 0; }
.kl-field--mono { font-family: var(--kl-font-mono); }

/* A chip that toggles: pressed reads as chosen (selection soft, never primary) */
.kl-x-toggle {
  display: inline-flex; align-items: center; gap: var(--kl-x-tight); height: 30px; padding: 0 var(--kl-space-3);
  border: 0; border-radius: var(--kl-radius-pill); background: var(--kl-color-control-fill); color: var(--kl-color-text);
  font: var(--kl-font-meta); cursor: pointer; position: relative;
  transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out), color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-x-toggle::before { content: ""; position: absolute; inset: -7px -2px; border-radius: var(--kl-radius-pill); }
.kl-x-toggle:hover { background: var(--kl-color-control-fill-pressed); }
.kl-x-toggle:focus-visible { outline: none; box-shadow: var(--kl-shadow-ring-focus); }
.kl-x-toggle[aria-pressed="true"], .kl-x-toggle.is-selected { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); box-shadow: inset 0 0 0 1.5px var(--kl-color-selection); }
.kl-x-toggle .kl-icon { --kl-icon-size: 14px; }
.kl-x-toggle__tick { display: none; }
.kl-x-toggle[aria-pressed="true"] .kl-x-toggle__tick, .kl-x-toggle.is-selected .kl-x-toggle__tick { display: inline-block; animation: kl-x-pop var(--kl-motion-dot-pop) var(--kl-motion-spring-pop); }
.kl-motion-reduce .kl-x-toggle__tick { animation: none !important; }

/* Output of "Try it now" (and of a hook that ran): mono, sunken, a status line on top */
.kl-xout { display: flex; flex-direction: column; border-radius: var(--kl-radius-row); background: var(--kl-color-surface-sunken); box-shadow: inset 0 0 0 1px var(--kl-color-line); overflow: hidden; }
.kl-xout__head { display: flex; align-items: center; gap: var(--kl-x-tight); padding: var(--kl-space-2) var(--kl-space-3); font: var(--kl-font-meta); color: var(--kl-color-text); border-bottom: 1px solid var(--kl-color-line); }
.kl-xout__head .kl-icon { --kl-icon-size: 14px; }
.kl-xout__head small { margin-left: auto; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-xout__body { margin: 0; padding: var(--kl-space-2) var(--kl-space-3); font-family: var(--kl-font-mono); font-size: var(--kl-font-caption-size); line-height: var(--kl-font-caption-line); color: var(--kl-color-text-secondary); white-space: pre-wrap; }
.kl-xout--blocked .kl-xout__head { color: var(--kl-color-status-stopped-ink); }
.kl-xout--blocked .kl-xout__head .kl-icon { color: var(--kl-color-status-stopped); }
.kl-xout--blocked { box-shadow: inset 0 0 0 1px var(--kl-color-status-stopped-soft); }

/* =====================================================================================
   4. Agent definition form: name, when to use it, instructions, model, effort, runs on, tools
   ===================================================================================== */
.kl-agentdef { display: flex; flex-direction: column; gap: var(--kl-space-4); }
.kl-agentdef__who { display: flex; align-items: flex-start; gap: var(--kl-space-3); }
.kl-agentdef__face {
  display: inline-grid; place-items: center; flex: none; width: 52px; height: 52px; border-radius: var(--kl-radius-groupbox);
  background: var(--kl-x-soft, var(--kl-color-control-fill)); color: var(--kl-x-ink, var(--kl-color-text));
}
.kl-agentdef__face .kl-icon { --kl-icon-size: 26px; }
.kl-agentdef__names { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--kl-space-3); }
.kl-agentdef__field { display: flex; flex-direction: column; gap: var(--kl-space-1); min-width: 0; }
.kl-agentdef__field .kl-field, .kl-agentdef__field .kl-textarea { width: 100%; }
.kl-agentdef__field .kl-textarea { min-height: 112px; resize: vertical; }
.kl-agentdef__count { margin-left: auto; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-agentdef__labelrow { display: flex; align-items: baseline; gap: var(--kl-space-2); }
.kl-agentdef__labelrow .kl-fieldlabel { margin: 0; }
.kl-agentdef__hues { display: flex; gap: var(--kl-space-2); flex-wrap: wrap; }
.kl-agentdef__hue {
  position: relative; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 50%; cursor: pointer;
  background: var(--kl-x-ink); box-shadow: inset 0 0 0 1px var(--kl-color-line);
}
.kl-agentdef__hue::before { content: ""; position: absolute; inset: -11px; border-radius: 50%; }
.kl-agentdef__hue:focus-visible { outline: none; box-shadow: var(--kl-shadow-ring-focus); }
.kl-agentdef__hue[aria-checked="true"] { box-shadow: 0 0 0 2px var(--kl-color-surface), 0 0 0 4px var(--kl-color-selection); }

/* Allowed tools: quick choice (Read only · Standard · Everything · Custom), then grouped checkbox rows */
.kl-toolpick { display: flex; flex-direction: column; gap: var(--kl-space-3); }
.kl-toolpick__head { display: flex; align-items: center; gap: var(--kl-space-2); flex-wrap: wrap; }
.kl-toolpick__head .kl-seg { flex: 1 1 auto; }
.kl-toolpick__groups { display: flex; flex-direction: column; border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface-sunken); padding: var(--kl-space-1) 0; }
.kl-toolpick__group + .kl-toolpick__group { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-toolpick__ghead { display: flex; align-items: center; gap: var(--kl-space-2); min-height: 40px; padding: var(--kl-space-1) var(--kl-space-3); }
.kl-toolpick__ghead .kl-checkbox { flex: 1 1 auto; font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-toolpick__gcount { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-toolpick__tools { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--kl-space-3); padding: 0 var(--kl-space-3) var(--kl-space-2) calc(var(--kl-space-3) + var(--kl-space-6)); }
.kl-toolpick__tool { display: flex; align-items: center; min-height: 32px; min-width: 0; }
.kl-toolpick__tool .kl-checkbox { min-width: 0; font: var(--kl-font-meta); }
.kl-toolpick__tool small { display: block; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-toolpick__tool .kl-icon { --kl-icon-size: 14px; color: var(--kl-color-text-secondary); }
.kl-toolpick__note { margin: 0; display: flex; align-items: flex-start; gap: var(--kl-x-tight); font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-toolpick__note .kl-icon { --kl-icon-size: 14px; flex: none; }
.kl-toolpick__note.is-error { color: var(--kl-color-status-stopped-ink); }

/* How the saved agent will read in Presets: the v2 preset agent row, on its own */
.kl-agentdef__preview { display: flex; flex-direction: column; gap: var(--kl-space-2); }
.kl-agentdef__preview .kl-win-agents { padding-block: var(--kl-space-1); }

/* Errors (name taken, nothing allowed): the v2 field error plus a hint; the field shakes once */
.kl-agentdef .kl-fieldhint.is-error { color: var(--kl-color-status-stopped-ink); }

/* =====================================================================================
   5. Tags and markers for the transcript (the Transcript part places them; they are drawn here)
   ===================================================================================== */
.kl-xtag {
  display: inline-flex; align-items: center; gap: var(--kl-x-tight); height: 24px; padding: 0 var(--kl-space-2) 0 var(--kl-x-tight);
  border-radius: var(--kl-radius-pill); background: var(--kl-color-control-fill); color: var(--kl-color-text);
  font: var(--kl-font-caption); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.kl-xtag .kl-icon { --kl-icon-size: 14px; color: var(--kl-color-text-secondary); }
.kl-xtag b { font-weight: var(--kl-font-weight-semibold); }
.kl-xtag__sub { color: var(--kl-color-text-secondary); }
.kl-xtag--blocked { background: var(--kl-color-status-stopped-soft); color: var(--kl-color-status-stopped-ink); }
.kl-xtag--blocked .kl-icon, .kl-xtag--blocked .kl-xtag__sub { color: var(--kl-color-status-stopped-ink); }
button.kl-xtag { border: 0; cursor: pointer; transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out); }
button.kl-xtag:hover { background: var(--kl-color-control-fill-pressed); }
button.kl-xtag:focus-visible { outline: none; box-shadow: var(--kl-shadow-ring-focus); }

/* A marker line between transcript turns: "Hook ran · npm test · passed in 4.2 s" */
.kl-xmark { display: flex; align-items: center; gap: var(--kl-space-2); font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-xmark::before, .kl-xmark::after { content: ""; flex: 1 1 24px; height: 1px; background: var(--kl-color-line); }
.kl-xmark .kl-icon { --kl-icon-size: 14px; }
.kl-xmark code { font-family: var(--kl-font-mono); color: var(--kl-color-text); }
.kl-xmark--blocked { color: var(--kl-color-status-stopped-ink); }
.kl-xmark--blocked::before, .kl-xmark--blocked::after { background: var(--kl-color-status-stopped-soft); }

/* =====================================================================================
   6. Where they open from: four rows in the v2 Settings window (account) and the project gear
   ===================================================================================== */
.kl-x-entry .kl-setting__value { display: inline-flex; align-items: center; gap: var(--kl-space-1); }
.kl-x-entry .kl-setting__value .kl-icon { --kl-icon-size: 14px; }
.kl-x-entry .kl-setting__text { flex-direction: row; align-items: center; gap: var(--kl-space-2); }

/* =====================================================================================
   Motion
   ===================================================================================== */
/* Pops from a dial-scaled size: at dial 0 it simply appears */
@keyframes kl-x-pop { from { scale: max(.2, calc(1 - 1.4 * var(--kl-motion-k, .35))); opacity: 0; } to { scale: 1; opacity: 1; } }

/* Rows that appear (a row opening, the output of a try) rise in with v2's reveal */
.kl-conn__more, .kl-xout, .kl-skill-detail { animation: kl-reveal var(--kl-motion-reveal) var(--kl-motion-ease-out) backwards; }
.kl-motion-reduce :is(.kl-conn__more, .kl-xout, .kl-skill-detail) { animation: kl-fade-in var(--kl-motion-fade) ease backwards !important; }
@media (prefers-reduced-motion: reduce) {
  :is(.kl-conn__more, .kl-xout, .kl-skill-detail) { animation: kl-fade-in var(--kl-motion-fade) ease backwards; }
}


/* ===== harness/transcript/transcript.css ===== */
/* Klippan master · Harness · Transcript window.
   Load after ../../../klippan-v2/combined/klippan.css. Uses the v2 window frame (.kl-win), buttons, badges, dots,
   fields, tooltips and the kl-m-* motion classes as they are, and never restyles them.
   Every colour, radius, space, type and motion value is a --kl- token. Literal sizes that belong to this piece
   only are local --kl-tx-* properties. Terminal colours, the bubble tail, the code style and the row-in motion are v2 tokens.

   Folding: a row is open when it has .is-open, or when its own head has aria-expanded="true". The row is a grid
   whose second track goes 0fr to 1fr; the fold region (the __body, a run's __items, a command row's .kl-tx-term)
   is the clip. Keep vertical padding off a fold region: its spacing comes from margins and spacers inside it. */

/* =====================================================================================
   0. Local sizes
   ===================================================================================== */
:where(.kl-win--transcript, .kl-tx__list, .kl-tx-msg, .kl-tx-tool, .kl-tx-term, .kl-tx-think, .kl-tx-mark,
  .kl-tx-tick, .kl-tx-tag, .kl-tx-jump, .kl-tx-caret, .kl-tx-file) {
  --kl-tx-pad: var(--kl-space-4);       /* list side padding */
  --kl-tx-gutter: 20px;                 /* left gutter for checkpoint ticks */
  --kl-tx-head-h: 36px;                 /* status strip under the bar */
  --kl-tx-row-h: 32px;                  /* tool-call row */
  --kl-tx-child-h: 28px;                /* a row inside an open run */
  --kl-tx-child-indent: 28px;           /* icon 16 + gap 8 + 4 past the count: child verbs line up under the run's verb */
  --kl-tx-head-px: var(--kl-space-2);   /* heads bleed this far out of the column so icons stay on it */
  --kl-tx-tight: 6px;                   /* dot or icon to its text, as v2 windows */
  --kl-tx-avatar: 20px;
  --kl-tx-bubble-max: 84%;
  --kl-tx-tick: 6px;
  --kl-tx-tick-x: -18px;                /* centres the tick under the head's status dot */
  --kl-tx-tick-y: 38px;                 /* meta 18 + gap 4 + half the bubble's first line */
  --kl-tx-caret-w: 2px;
  --kl-tx-caret-h: 14px;
  --kl-tx-tag-h: 24px;                  /* the extend part's tag height, for the hit area */
  --kl-tx-count: 16px;                  /* the run's count badge */
  --kl-tx-line: var(--kl-font-code-line); /* one code line */
  --kl-tx-lines: 8;                     /* result and terminal lines shown */
  --kl-tx-lines-ended: 3;               /* lines kept when a command ends */
  --kl-tx-pill-h: 28px;                 /* marker pill and jump pill */
  --kl-tx-jump-gap: 12px;
  --kl-tx-chip-h: 20px;
  --kl-tx-chev-open: 90deg;             /* chevron-right turns to point down */
}

/* Code for results, targets and terminals: the v2 code style (.kl-code) */
:where(.kl-tx-tool__target, .kl-tx-tool__body, .kl-tx-term__out, .kl-tx-term__cmd) {
  font: var(--kl-font-code);
  letter-spacing: var(--kl-font-code-tracking);
  font-variant-ligatures: none;
}

/* =====================================================================================
   1. Window
   ===================================================================================== */
.kl-win--transcript { --kl-win-w: 480px; }
.kl-win--transcript.kl-win--wide { --kl-win-w: 640px; }
.kl-win--transcript > .kl-win__bar .kl-win__icon {
  background: var(--kl-tx-proj-soft, var(--kl-color-project-1-soft));
  color: var(--kl-tx-proj-ink, var(--kl-color-project-1-ink));
}
.kl-win--transcript > .kl-win__bar .kl-win__icon .kl-icon { --kl-icon-size: 16px; }
.kl-win--transcript .kl-win__scope .kl-win-mark { background: var(--kl-tx-proj, var(--kl-color-project-1)); }
.kl-win--transcript .kl-win__ctl .kl-iconbtn { --kl-iconbtn-glyph: 14px; }

/* Status strip: the agent's dot, the line it writes, Unfold all */
.kl-tx__head {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  height: var(--kl-tx-head-h);
  padding: 0 var(--kl-space-2) 0 var(--kl-space-4);
  border-bottom: 1px solid var(--kl-color-line);
}
.kl-tx__head > .kl-dot { align-self: center; }
.kl-tx__status {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font: var(--kl-font-meta);
  color: var(--kl-color-text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kl-tx__head > .kl-btn { flex: none; margin-left: auto; }

/* The scrolling log */
.kl-tx__list {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--kl-space-2);
  margin: 0;
  padding: var(--kl-space-4) var(--kl-tx-pad) var(--kl-space-6) calc(var(--kl-tx-pad) + var(--kl-tx-gutter));
  overflow: auto;
  overscroll-behavior: contain;
  list-style: none;
  font: var(--kl-font-meta);
  color: var(--kl-color-text);
}
.kl-tx__list > * { flex: none; min-width: 0; }
/* A message starts a group: 16 from whatever came before */
.kl-tx__list > .kl-tx-msg:not(:first-child) { margin-top: var(--kl-space-2); }
/* Markers are full-width rows: they span the gutter too */
.kl-tx__list > .kl-tx-mark { margin-left: calc(-1 * var(--kl-tx-gutter)); margin-block: var(--kl-space-1); }
.kl-tx__list > .kl-tx-mark:first-child { margin-top: 0; }

/* Footer: the reply field, Stop, Send. The jump pill floats above it. */
.kl-tx__foot { position: relative; flex-wrap: nowrap; }
.kl-tx__reply { --kl-field-w: auto; flex: 1 1 0; min-width: 0; }
.kl-tx__foot > .kl-btn { flex: none; }

/* Jump pill: the only glass in the window */
.kl-tx-jump {
  position: absolute;
  left: 50%;
  bottom: calc(100% + var(--kl-tx-jump-gap));
  z-index: 3;
  translate: -50% 0;
  display: inline-flex;
  align-items: center;
  gap: var(--kl-space-1);
  height: var(--kl-tx-pill-h);
  padding: 0 var(--kl-space-2) 0 var(--kl-space-3);
  border: 0;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-glass-fill-menu);
  -webkit-backdrop-filter: var(--kl-glass-filter);
  backdrop-filter: var(--kl-glass-filter);
  box-shadow: var(--kl-shadow-menu), var(--kl-glass-rim);
  color: var(--kl-color-text);
  font: var(--kl-font-label);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  cursor: pointer;
}
.kl-tx-jump::before { content: ""; position: absolute; inset: calc((var(--kl-tx-pill-h) - var(--kl-size-target)) / 2) 0; }
.kl-tx-jump .kl-icon { --kl-icon-size: 14px; color: var(--kl-color-text-secondary); }
.kl-tx-jump:hover { box-shadow: var(--kl-shadow-menu), var(--kl-glass-rim), inset 0 0 0 100px var(--kl-color-control-fill); }
.kl-tx-jump:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
/* Outside a footer (a window built without one), it sits 12 above the window's bottom edge */
.kl-win--transcript > .kl-tx-jump { bottom: var(--kl-tx-jump-gap); }

/* =====================================================================================
   2. Messages
   ===================================================================================== */
.kl-tx-msg {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--kl-space-1);
  min-width: 0;
  margin: 0;
}
.kl-tx-msg__meta {
  display: flex;
  align-items: center;
  gap: var(--kl-tx-tight);
  min-height: 18px;
  font: var(--kl-font-meta);
  color: var(--kl-color-text-secondary);
  font-variant-numeric: tabular-nums;
}
.kl-tx-msg__meta .kl-icon { --kl-icon-size: 14px; }
.kl-tx-msg__body {
  min-width: 0;
  font: var(--kl-font-body);
  color: var(--kl-color-text);
  overflow-wrap: anywhere;
}
.kl-tx-msg__body > * { margin: 0; }
.kl-tx-msg__body > * + * { margin-top: var(--kl-space-2); }
.kl-tx-msg__body :is(ul, ol) { padding-left: var(--kl-space-5); }
.kl-tx-msg__body code {
  padding: 1px 5px;
  border-radius: var(--kl-radius-control);
  background: var(--kl-color-surface-sunken);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
  font-family: var(--kl-font-mono);
  font-size: .87em;
}
.kl-tx-msg__body a { color: var(--kl-color-selection-ink); text-decoration: underline; text-decoration-color: color-mix(in srgb, currentColor 35%, transparent); text-underline-offset: 2px; }
.kl-tx-msg__body a:hover { text-decoration-color: currentColor; }

/* A file reference: mono with the file icon */
.kl-tx-file {
  display: inline-flex;
  align-items: baseline;
  gap: var(--kl-space-1);
  font-family: var(--kl-font-mono);
  font-size: .87em;
  color: var(--kl-color-text);
  white-space: nowrap;
}
.kl-tx-file .kl-icon { --kl-icon-size: 14px; align-self: center; color: var(--kl-color-text-secondary); }
:is(a, button).kl-tx-file { padding: 0; border: 0; background: none; cursor: pointer; text-decoration: none; }
:is(a, button).kl-tx-file:hover { text-decoration: underline; text-underline-offset: 2px; }

/* Yours: a bubble on the right, tucked bottom-right corner */
.kl-tx-msg--you { align-items: flex-end; }
.kl-tx-msg--you > .kl-tx-msg__body {
  max-width: var(--kl-tx-bubble-max);
  padding: var(--kl-space-2) var(--kl-space-3);
  border-radius: var(--kl-radius-notice) var(--kl-radius-notice) var(--kl-radius-bubble-tail) var(--kl-radius-notice);
  background: var(--kl-color-surface-sunken);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
}

/* Queued: the same bubble, dashed, waiting its turn. Cancel takes it back into the draft. */
.kl-tx-msg--queued > .kl-tx-msg__body {
  background: transparent;
  box-shadow: none;
  border: 1px dashed var(--kl-color-line-strong);
  padding: calc(var(--kl-space-2) - 1px) calc(var(--kl-space-3) - 1px);
}
.kl-tx-msg--queued > .kl-btn { align-self: flex-end; margin-right: calc(-1 * var(--kl-space-2)); }

/* The agent's: flat, full width */
.kl-tx-msg__who { display: flex; align-items: center; gap: var(--kl-space-2); min-height: var(--kl-tx-avatar); }
.kl-tx-msg__avatar {
  --kl-icon-size: 14px;
  flex: none;
  display: inline-grid;
  place-items: center;
  width: var(--kl-tx-avatar);
  height: var(--kl-tx-avatar);
  border-radius: var(--kl-radius-control);
  background: var(--kl-tx-proj-soft, var(--kl-color-project-1-soft));
  color: var(--kl-tx-proj-ink, var(--kl-color-project-1-ink));
}
.kl-tx-msg__name { min-width: 0; font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); color: var(--kl-color-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kl-tx-msg__time { flex: none; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-tx-msg__tags { display: flex; flex-wrap: wrap; align-items: center; gap: var(--kl-space-1) var(--kl-tx-tight); margin-top: var(--kl-space-1); }

/* Still being written: the caret holds still; the text arriving is the motion */
.kl-tx-caret {
  display: inline-block;
  width: var(--kl-tx-caret-w);
  height: var(--kl-tx-caret-h);
  margin-left: var(--kl-space-half);
  vertical-align: -2px;
  border-radius: 1px;
  background: var(--kl-color-text-secondary);
}

/* Checkpoint tick: in the gutter beside each of your messages, under the head's status dot */
.kl-tx-tick {
  position: absolute;
  left: var(--kl-tx-tick-x);
  top: var(--kl-tx-tick-y);
  z-index: 1;
  width: var(--kl-tx-tick);
  height: var(--kl-tx-tick);
  padding: 0;
  border: 0;
  border-radius: var(--kl-radius-round);
  background: var(--kl-color-line-strong);
  cursor: pointer;
  transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-tx-tick::before { content: ""; position: absolute; inset: calc((var(--kl-tx-tick) - var(--kl-size-target)) / 2); border-radius: var(--kl-radius-round); }
.kl-tx-tick:hover, .kl-tx-tick:focus-visible, .kl-tx-tick.is-shown { background: var(--kl-color-text-secondary); }
.kl-tx-tick:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 3px; }
.kl-tx-tick > .kl-tooltip {
  position: absolute;
  left: calc(-1 * var(--kl-space-2));
  bottom: calc(100% + var(--kl-space-2));
  opacity: 0;
  transition: opacity var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-tx-tick:is(:hover, :focus-visible, .is-shown) > .kl-tooltip { opacity: 1; }

/* =====================================================================================
   3. Tool-call row
   ===================================================================================== */
.kl-tx-tool {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto 0fr;
  min-width: 0;
  transition: grid-template-rows var(--kl-motion-collapse) var(--kl-motion-ease-out);
}
.kl-tx-tool:is(.is-open, :has(> .kl-tx-tool__head[aria-expanded="true"])) {
  grid-template-rows: auto 1fr;
  transition-duration: var(--kl-motion-expand);
}

.kl-tx-tool__head {
  grid-column: 1;
  grid-row: 1;
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  min-width: 0;
  height: var(--kl-tx-row-h);
  margin: 0 calc(-1 * var(--kl-tx-head-px));
  padding: 0 var(--kl-tx-head-px);
  border: 0;
  border-radius: var(--kl-radius-tile);
  background: transparent;
  color: var(--kl-color-text);
  font: var(--kl-font-label);
  text-align: left;
  cursor: pointer;
  transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-tx-tool__head::before { content: ""; position: absolute; inset: calc((var(--kl-tx-row-h) - var(--kl-size-target)) / 2) 0; }
.kl-tx-tool__head:hover, .kl-tx-tool__head.is-hover { background: var(--kl-color-surface-sunken); }
/* With an action beside it (Open, Stop), the head stops at the action */
.kl-tx-tool:has(> .kl-btn) > .kl-tx-tool__head { margin-right: 0; }
.kl-tx-tool > .kl-btn { grid-column: 2; grid-row: 1; align-self: center; margin-left: var(--kl-space-1); }

.kl-tx-tool__icon {
  --kl-icon-size: 16px;
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 16px;
  height: 16px;
  color: var(--kl-color-text-secondary);
}
.kl-tx-tool__verb { flex: none; font: var(--kl-font-label); color: var(--kl-color-text); white-space: nowrap; }
.kl-tx-tool__target {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--kl-color-text-secondary);
}
.kl-tx-tool__meta {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: var(--kl-tx-tight);
  margin-left: auto;
  font: var(--kl-font-meta);
  color: var(--kl-color-text-secondary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.kl-tx-tool__meta .kl-dot,
.kl-tx-term__state .kl-dot { --kl-dot-size: 8px; }
.kl-tx-tool__chev {
  --kl-icon-size: 14px;
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 14px;
  height: 14px;
  margin-left: auto;
  color: var(--kl-color-text-secondary);
  transition: rotate var(--kl-motion-collapse) var(--kl-motion-spring-pop);
}
.kl-tx-tool__meta + .kl-tx-tool__chev { margin-left: 0; }
.kl-tx-tool:is(.is-open, :has(> .kl-tx-tool__head[aria-expanded="true"])) > .kl-tx-tool__head > .kl-tx-tool__chev {
  rotate: var(--kl-tx-chev-open);
  transition-duration: var(--kl-motion-expand);
}

/* The fold regions of a tool row, a run, a thinking row and a marker */
.kl-tx-tool > .kl-tx-tool__body,
.kl-tx-run > .kl-tx-run__items,
.kl-tx-tool--command > .kl-tx-term,
.kl-tx-think > .kl-tx-think__body,
.kl-tx-mark > .kl-tx-mark__body {
  grid-column: 1 / -1;
  grid-row: 2;
  min-height: 0;
  overflow: hidden;
  visibility: hidden;
  margin-top: 0;
  transition: visibility 0s linear var(--kl-motion-collapse), margin-top var(--kl-motion-collapse) var(--kl-motion-ease-out);
}
.kl-tx-tool:is(.is-open, :has(> .kl-tx-tool__head[aria-expanded="true"])) > :is(.kl-tx-tool__body, .kl-tx-run__items, .kl-tx-term),
.kl-tx-think:is(.is-open, :has(> .kl-tx-think__head[aria-expanded="true"])) > .kl-tx-think__body,
.kl-tx-mark:is(.is-open, :has(.kl-tx-mark__action[aria-expanded="true"])) > .kl-tx-mark__body {
  visibility: visible;
  transition: visibility 0s linear 0s, margin-top var(--kl-motion-expand) var(--kl-motion-ease-out);
}

/* The result: a sunken box, mono, at most 8 lines, then Show all */
.kl-tx-tool__body {
  border-radius: var(--kl-radius-groupbox);
  background: var(--kl-color-surface-sunken);
  color: var(--kl-color-text);
  padding-inline: var(--kl-space-3);
}
.kl-tx-tool__body::before,
.kl-tx-tool__body::after { content: ""; display: block; height: var(--kl-space-2); }
.kl-tx-tool:is(.is-open, :has(> .kl-tx-tool__head[aria-expanded="true"])) > .kl-tx-tool__body { margin-top: var(--kl-space-1); }
.kl-tx-tool__body > :not(.kl-tx-tool__more) { display: block; min-height: var(--kl-tx-line); margin: 0; white-space: pre; overflow: hidden; text-overflow: ellipsis; }
.kl-tx-tool__body > :not(.kl-tx-tool__more):nth-child(n + 9) { display: none; }
.kl-tx-tool__body.is-all > :not(.kl-tx-tool__more):nth-child(n) { display: block; }
.kl-tx-tool__body > .kl-tx-tool__more { margin: var(--kl-space-1) 0 calc(-1 * var(--kl-space-1)) calc(-1 * var(--kl-space-2)); font-family: var(--kl-font-sans); }

/* Kinds share one look; the icon and the verb tell them apart. Diff counts stay neutral. */
.kl-tx-tool--edit .kl-tx-tool__meta { color: var(--kl-color-text-secondary); }

/* States */
.kl-tx-tool.is-failed > .kl-tx-tool__head :is(.kl-tx-tool__icon, .kl-tx-tool__verb, .kl-tx-tool__meta) { color: var(--kl-color-status-stopped-ink); }
.kl-tx-tool.is-failed > .kl-tx-tool__body { color: var(--kl-color-status-stopped-ink); }
.kl-tx-tool.is-denied > .kl-tx-tool__head :is(.kl-tx-tool__verb, .kl-tx-tool__target) { color: var(--kl-color-text-secondary); }
.kl-tx-tool.is-denied > .kl-tx-tool__head .kl-tx-tool__icon { color: var(--kl-color-text-tertiary); }
.kl-tx-tool.is-waiting > .kl-tx-tool__head .kl-tx-tool__meta { color: var(--kl-color-text); }

/* A row inside an open run: no icon of its own, verb under the run's verb */
.kl-tx-tool--child > .kl-tx-tool__head { height: var(--kl-tx-child-h); padding-left: calc(var(--kl-tx-head-px) + var(--kl-tx-child-indent)); }
.kl-tx-tool--child > .kl-tx-tool__head::before { inset: calc((var(--kl-tx-child-h) - var(--kl-size-target)) / 2) 0; }
.kl-tx-tool--child > .kl-tx-tool__head > .kl-tx-tool__icon { display: none; }
.kl-tx-tool--child > .kl-tx-tool__head .kl-tx-tool__verb { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-tx-tool--child > .kl-tx-tool__head:focus-visible { outline-offset: -2px; }

/* =====================================================================================
   4. Folded run
   ===================================================================================== */
.kl-tx-run__icon { position: relative; overflow: visible; }
.kl-tx-run__count {
  position: absolute;
  top: -6px;
  right: -8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--kl-tx-count);
  height: var(--kl-tx-count);
  padding: 0 4px;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-text);
  color: var(--kl-color-surface);
  box-shadow: 0 0 0 2px var(--kl-color-surface);
  font: var(--kl-font-caption);
  font-weight: var(--kl-font-weight-semibold);
  line-height: var(--kl-tx-count);
  font-variant-numeric: tabular-nums;
}
.kl-tx-run > .kl-tx-tool__head .kl-tx-tool__verb { margin-left: var(--kl-space-1); }
/* Open: the child rows, bleeding out to the same edge as the run's head */
.kl-tx-run > .kl-tx-run__items {
  display: flex;
  flex-direction: column;
  margin-inline: calc(-1 * var(--kl-tx-head-px));
  padding-inline: var(--kl-tx-head-px);
}
.kl-tx-run > .kl-tx-run__items::before { content: ""; flex: none; height: var(--kl-space-half); }

/* =====================================================================================
   5. Terminal block
   ===================================================================================== */
.kl-tx-term { display: flex; flex-direction: column; gap: var(--kl-space-1); min-width: 0; }
.kl-tx-term__head { display: flex; align-items: center; gap: var(--kl-space-2); min-width: 0; min-height: var(--kl-tx-row-h); }
.kl-tx-term__head > .kl-icon,
.kl-tx-term__head > .kl-tx-tool__icon { --kl-icon-size: 16px; flex: none; color: var(--kl-color-text-secondary); }
.kl-tx-term__cmd { flex: 0 1 auto; min-width: 0; color: var(--kl-color-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: var(--kl-font-weight-medium); }
.kl-tx-term__cwd {
  flex: none;
  display: inline-flex;
  align-items: center;
  height: var(--kl-tx-chip-h);
  padding: 0 var(--kl-space-2);
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-neutral-soft);
  color: var(--kl-color-neutral-ink);
  font: var(--kl-font-weight-regular) var(--kl-font-caption-size)/var(--kl-tx-chip-h) var(--kl-font-mono);
  white-space: nowrap;
}
.kl-tx-term__state {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: var(--kl-tx-tight);
  margin-left: auto;
  font: var(--kl-font-meta);
  color: var(--kl-color-text-secondary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.kl-tx-term__head > .kl-btn { flex: none; }
.kl-tx-term__chip {
  display: inline-flex;
  align-items: center;
  height: var(--kl-tx-chip-h);
  padding: 0 var(--kl-space-2);
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-neutral-soft);
  color: var(--kl-color-neutral-ink);
  font: var(--kl-font-badge);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
:is(.kl-tx-term.is-ok .kl-tx-term__chip, .kl-tx-term__chip.is-ok) { background: var(--kl-color-status-executing-soft); color: var(--kl-color-status-executing-ink); }
:is(.kl-tx-term.is-error .kl-tx-term__chip, .kl-tx-term__chip.is-error) { background: var(--kl-color-status-stopped-soft); color: var(--kl-color-status-stopped-ink); }
:is(.kl-tx-term.is-stopped .kl-tx-term__chip, .kl-tx-term__chip.is-stopped) { background: var(--kl-color-neutral-soft); color: var(--kl-color-neutral-ink); }

.kl-tx-term__out {
  display: flex;
  flex-direction: column;
  max-height: calc(var(--kl-tx-lines) * var(--kl-tx-line) + 2 * var(--kl-space-2));
  margin: 0;
  padding: 0 var(--kl-space-3);
  box-sizing: border-box;
  border-block: var(--kl-space-2) solid transparent;   /* not padding: lines clip at the inner edge, never under it */
  border-radius: var(--kl-radius-groupbox);
  background: var(--kl-color-terminal);
  color: var(--kl-color-text);
  overflow-y: auto;
  overscroll-behavior: contain;
  scroll-behavior: auto;               /* the tail jumps to the last line, never glides */
}
.kl-tx-term__line { flex: none; display: block; min-height: var(--kl-tx-line); white-space: pre; overflow: hidden; text-overflow: ellipsis; }
.kl-tx-term__line--err { color: var(--kl-color-terminal-err); }
/* Ended: the head and the last three lines */
.kl-tx-term:is(.is-ok, .is-error, .is-stopped) .kl-tx-term__out {
  max-height: calc(var(--kl-tx-lines-ended) * var(--kl-tx-line) + 2 * var(--kl-space-2));
  justify-content: flex-end;
  overflow: hidden;
}
/* Show all: every line, still eight in view, scrolling from the top */
.kl-tx-term.is-all .kl-tx-term__out {
  max-height: calc(var(--kl-tx-lines) * var(--kl-tx-line) + 2 * var(--kl-space-2));
  overflow-y: auto;
  justify-content: flex-start;
}
.kl-tx-term__follow,
.kl-tx-term__foot {
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  min-height: var(--kl-size-control);
  padding-left: var(--kl-space-3);
  font: var(--kl-font-meta);
  color: var(--kl-color-text-secondary);
}
.kl-tx-term__follow .kl-icon { --kl-icon-size: 14px; }
.kl-tx-term__foot { padding-left: var(--kl-space-1); }
.kl-tx-term__follow > .kl-btn { margin-left: calc(-1 * var(--kl-space-1)); }

/* Inside a command row the row's head already names the command and shows its state while folded */
.kl-tx-tool--command > .kl-tx-term > .kl-tx-term__head > :is(.kl-icon, .kl-tx-tool__icon, .kl-tx-term__cmd) { display: none; }
.kl-tx-tool--command:is(.is-open, :has(> .kl-tx-tool__head[aria-expanded="true"])) > .kl-tx-tool__head > .kl-tx-tool__meta { display: none; }
.kl-tx-tool--command:is(.is-open, :has(> .kl-tx-tool__head[aria-expanded="true"])) > .kl-tx-tool__head > .kl-tx-tool__chev { margin-left: auto; }
.kl-tx-tool--command > .kl-tx-term { gap: var(--kl-space-1); }
.kl-tx-tool--command > .kl-tx-term > .kl-tx-term__head { min-height: var(--kl-size-button); }

/* =====================================================================================
   6. Folded thinking
   ===================================================================================== */
.kl-tx-think {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto 0fr;
  justify-items: start;
  min-width: 0;
  transition: grid-template-rows var(--kl-motion-collapse) var(--kl-motion-ease-out);
}
.kl-tx-think:is(.is-open, :has(> .kl-tx-think__head[aria-expanded="true"])) { grid-template-rows: auto 1fr; transition-duration: var(--kl-motion-expand); }
.kl-tx-think__head {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--kl-tx-tight);
  height: var(--kl-size-button);
  margin-left: calc(-1 * var(--kl-tx-head-px));
  padding: 0 var(--kl-tx-head-px);
  border: 0;
  border-radius: var(--kl-radius-tile);
  background: transparent;
  color: var(--kl-color-text-secondary);
  font: var(--kl-font-meta);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out), color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-tx-think__head::before { content: ""; position: absolute; inset: calc((var(--kl-size-button) - var(--kl-size-target)) / 2) 0; }
.kl-tx-think__head:hover, .kl-tx-think__head.is-hover { background: var(--kl-color-surface-sunken); color: var(--kl-color-text); }
.kl-tx-think__head .kl-dot { --kl-dot-size: 8px; }
.kl-tx-think__head > .kl-tx-think__icon { --kl-icon-size: 16px; flex: none; }
.kl-tx-think__head > svg:last-child {
  --kl-icon-size: 14px;
  flex: none;
  transition: rotate var(--kl-motion-collapse) var(--kl-motion-spring-pop);
}
.kl-tx-think:is(.is-open, :has(> .kl-tx-think__head[aria-expanded="true"])) > .kl-tx-think__head > svg:last-child { rotate: var(--kl-tx-chev-open); transition-duration: var(--kl-motion-expand); }
.kl-tx-think__body,
.kl-tx-mark__body {
  justify-self: stretch;
  padding-inline: var(--kl-space-3);
  border-radius: var(--kl-radius-groupbox);
  background: var(--kl-color-surface-sunken);
  font: var(--kl-font-meta);
  color: var(--kl-color-text-secondary);
}
.kl-tx-think__body::before, .kl-tx-think__body::after,
.kl-tx-mark__body::before, .kl-tx-mark__body::after { content: ""; display: block; height: var(--kl-space-2); }
.kl-tx-think__body > *, .kl-tx-mark__body > * { margin: 0; }
.kl-tx-think__body > * + *, .kl-tx-mark__body > * + * { margin-top: var(--kl-space-2); }
.kl-tx-think:is(.is-open, :has(> .kl-tx-think__head[aria-expanded="true"])) > .kl-tx-think__body { margin-top: var(--kl-space-1); }

/* =====================================================================================
   7. Markers
   ===================================================================================== */
.kl-tx-mark {
  display: grid;
  grid-template-columns: minmax(var(--kl-space-2), 1fr) minmax(0, auto) minmax(var(--kl-space-2), 1fr);
  grid-template-rows: auto 0fr;
  align-items: center;
  column-gap: var(--kl-space-2);
  min-width: 0;
  transition: grid-template-rows var(--kl-motion-collapse) var(--kl-motion-ease-out);
}
.kl-tx-mark:is(.is-open, :has(.kl-tx-mark__action[aria-expanded="true"])) { grid-template-rows: auto 1fr; transition-duration: var(--kl-motion-expand); }
.kl-tx-mark__line { grid-row: 1; height: 1px; background: var(--kl-color-line); }
.kl-tx-mark__pill {
  grid-row: 1;
  grid-column: 2;
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  column-gap: var(--kl-tx-tight);
  min-width: 0;
  min-height: var(--kl-tx-pill-h);
  padding: var(--kl-space-1) var(--kl-space-3) var(--kl-space-1) var(--kl-space-2);
  border-radius: var(--kl-radius-draft);
  background: var(--kl-color-surface);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
  font: var(--kl-font-weight-regular) var(--kl-font-badge-size)/var(--kl-tx-line) var(--kl-font-sans);
  color: var(--kl-color-text-secondary);
  font-variant-numeric: tabular-nums;
  text-align: center;
}
.kl-tx-mark__pill:has(> .kl-tx-mark__action) { padding-right: var(--kl-space-half); }
.kl-tx-mark__icon { --kl-icon-size: 16px; flex: none; color: var(--kl-color-text-secondary); }
.kl-tx-mark__text { min-width: 0; }
.kl-tx-mark__action { flex: none; }
.kl-tx-mark__action { font-size: var(--kl-font-badge-size); }
.kl-tx-mark__action.kl-btn--plain { --kl-btn-px: 6px; }
.kl-tx-mark__action.kl-btn--plain[aria-expanded="true"] { --kl-btn-overlay: transparent; }   /* a link-style toggle shows no pressed fill */
.kl-tx-mark__pill > .kl-tx-mark__text + .kl-tx-mark__action { margin-left: calc(-1 * var(--kl-space-half)); }
/* The summary under a compaction marker */
.kl-tx-mark:is(.is-open, :has(.kl-tx-mark__action[aria-expanded="true"])) > .kl-tx-mark__body { margin-top: var(--kl-space-2); }

/* Day: words between the hairlines, no pill */
.kl-tx-mark--day .kl-tx-mark__pill { min-height: 0; padding: 0; background: none; box-shadow: none; font: var(--kl-font-caption); }

/* Failed turn: the stopped soft pill, reason on one line, the retry and its actions on the next */
.kl-tx-mark--failed .kl-tx-mark__pill {
  row-gap: var(--kl-space-1);
  padding: var(--kl-space-2) var(--kl-space-2) var(--kl-space-2) var(--kl-space-3);
  border-radius: var(--kl-radius-notice);
  background: var(--kl-color-status-stopped-soft);
  box-shadow: none;
  color: var(--kl-color-status-stopped-ink);
}
.kl-tx-mark--failed .kl-tx-mark__icon { color: var(--kl-color-status-stopped-ink); }
.kl-tx-mark--failed .kl-tx-mark__pill > * { order: 1; }
.kl-tx-mark--failed .kl-tx-mark__pill::before { content: ""; order: 2; flex-basis: 100%; height: 0; }
.kl-tx-mark--failed .kl-tx-mark__pill > :is(.kl-tx-mark__text ~ .kl-tx-mark__text, .kl-tx-mark__action) { order: 3; }
.kl-tx-mark--failed .kl-tx-mark__text:first-of-type { font-weight: var(--kl-font-weight-medium); }
.kl-tx-mark--failed .kl-tx-mark__pill > .kl-tx-mark__text + .kl-tx-mark__action { margin-left: 0; }
.kl-tx-mark--failed .kl-tx-mark__text ~ .kl-tx-mark__text { margin-right: var(--kl-space-1); }
.kl-tx-mark--failed .kl-btn--quiet { --kl-btn-ink: var(--kl-color-status-stopped-ink); }

/* =====================================================================================
   8. Tags
   The extend part draws the transcript's tags (.kl-xtag). .kl-tx-tag is only a layout alias on the same element:
   it adds the 44 px hit area to a tag that is a button and lets a tag shrink inside a tool row. No second look.
   ===================================================================================== */
/* .kl-xtag itself comes from ../extend/extend.css, loaded before this file. */

/* Layout alias only */
.kl-tx-tag { flex: none; max-width: 100%; }
:is(button, a).kl-tx-tag { position: relative; }
:is(button, a).kl-tx-tag::before { content: ""; position: absolute; inset: calc((var(--kl-tx-tag-h) - var(--kl-size-target)) / 2) 0; }
.kl-tx-tool__head > .kl-tx-tag { flex: 0 1 auto; min-width: 0; overflow: hidden; }

/* =====================================================================================
   9. Motion
   A row that arrives while the list follows the tail and Alban is not typing gets .kl-tx-new (the script adds it
   only then; scrolled up or typing, rows simply appear). No ambient motion anywhere in the transcript.
   ===================================================================================== */
@media (prefers-reduced-motion: no-preference) {
  .kl-tx-new { animation: kl-row-in var(--kl-motion-row-in) var(--kl-motion-ease-out) backwards; }
  .kl-tx-mark--failed.kl-tx-new > .kl-tx-mark__pill { animation: kl-shake var(--kl-motion-shake) ease-out var(--kl-motion-row-in) 1 backwards; }
}

/* Reduced motion: fades only, nothing rises, turns or shakes */
@media (prefers-reduced-motion: reduce) {
  .kl-tx-new { animation: kl-fade-in var(--kl-motion-fade) ease backwards; }
  .kl-tx-tool, .kl-tx-think, .kl-tx-mark,
  .kl-tx-tool__chev, .kl-tx-think__head > svg:last-child { transition: none; }
  .kl-tx-tool > .kl-tx-tool__body, .kl-tx-run > .kl-tx-run__items, .kl-tx-tool--command > .kl-tx-term,
  .kl-tx-think > .kl-tx-think__body, .kl-tx-mark > .kl-tx-mark__body { transition: none; }
}
.kl-motion-reduce .kl-tx-new { animation: kl-fade-in var(--kl-motion-fade) ease backwards; }
.kl-motion-reduce .kl-tx-mark--failed.kl-tx-new > .kl-tx-mark__pill { animation: none; }
.kl-motion-reduce :is(.kl-tx-tool, .kl-tx-think, .kl-tx-mark, .kl-tx-tool__chev, .kl-tx-think__head > svg:last-child) { transition: none; }
.kl-motion-reduce :is(.kl-tx-tool > .kl-tx-tool__body, .kl-tx-run > .kl-tx-run__items, .kl-tx-tool--command > .kl-tx-term,
  .kl-tx-think > .kl-tx-think__body, .kl-tx-mark > .kl-tx-mark__body) { transition: none; }

/* Forced colours: keep the edges that carry meaning */
@media (forced-colors: active) {
  .kl-tx-msg--you > .kl-tx-msg__body, .kl-tx-mark__pill, .kl-tx-tag, .kl-tx-term__chip, .kl-tx-tool__body, .kl-tx-term__out { border: 1px solid CanvasText; }
  .kl-tx-tick { background: CanvasText; }
}

/* ===== harness/approvals/approvals.css ===== */
/* =====================================================================================================
   Klippan master DS · Harness approvals
   The three places Alban says yes or no to an agent:
     1. Permission card  .kl-permit    an agent asks to run a command, edit files, open a site, use a connector
     2. Plan card        .kl-plan   an agent shows its plan before it starts; approve, edit a step, or send it back
     3. Rules window     .kl-rules  standing allow, ask and deny rules, per project or for every project

   Builds on v2: load ../../../klippan-v2/combined/klippan.css first, then this file. Icons come from the v2 sprite
   (#kl-<name>) and the harness icons sprite (../icons/sprite.svg: terminal, permission, plan, connector, browser...).
   Everything is --kl- tokens and v2 classes (.kl-card, .kl-dot, .kl-btn, .kl-seg, .kl-field, .kl-win, .kl-setting,
   .kl-toast, kl-m-*). The approval colour (--kl-color-status-approval*), .kl-dot--approval, .kl-card.is-asking and
   .kl-card__status.is-asking come from v2 Foundations and Board; the leave and row-out motions are v2 kl-m-leave and
   kl-m-row-out, the rays tint kl-m-rays--approval. Nothing new is needed (NEEDS.md).

   House rules kept here: Deny and Cancel come first; one blue action per view (none when the only "yes" destroys
   something); Undo instead of delete; tokens, never money; windows opaque, cards tinted glass.
   ===================================================================================================== */

/* ---- Shared ------------------------------------------------------------------------------------------ */
/* Mono text at this part's size: commands, paths, patterns (v2 .kl-mono sets only the family) */
.kl-amono { font-family: var(--kl-font-mono); font-size: 12.5px; line-height: 18px; font-variant-ligatures: none; }

/* A small tag in the card or window (scope, where a rule comes from, "new", "changed") */
.kl-atag {
  display: inline-flex; align-items: center; gap: 4px; flex: none; height: 20px; padding: 0 8px;
  border-radius: var(--kl-radius-pill); background: var(--kl-color-neutral-soft); color: var(--kl-color-neutral-ink);
  font: var(--kl-font-badge); white-space: nowrap;
}
.kl-atag .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
.kl-atag--project { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
.kl-atag--caution { background: var(--kl-color-status-approval-soft); color: var(--kl-color-status-approval-ink); }   /* "will ask first" and "Asks you": waiting on Alban */
.kl-atag--risk { background: var(--kl-color-status-stopped-soft); color: var(--kl-color-status-stopped-ink); }

/* Who asks: the agent's icon and name, in the card's agents slot */
.kl-afrom { display: inline-flex; align-items: center; gap: 5px; min-width: 0; font: var(--kl-font-meta); font-weight: var(--kl-font-weight-semibold);
  color: var(--kl-color-text-secondary); opacity: var(--kl-on); translate: 0 calc(5px * (1 - var(--kl-on))); white-space: nowrap; }
.kl-afrom .kl-icon { --kl-icon-size: 14px; }

/* The stamp that lands beside the name when something is answered (kl-m-count-pop as it arrives) */
.kl-astamp {
  display: inline-grid; place-items: center; flex: none; width: 18px; height: 18px; border-radius: var(--kl-radius-round);
  background: var(--kl-color-status-executing); color: var(--kl-color-text-on-fill);
}
.kl-astamp .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2.2; }
.kl-astamp--deny { background: var(--kl-color-status-idle); }

/* Label above a block inside a card */
.kl-alabel { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 0 0 6px;
  font: var(--kl-font-caption); font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text-secondary); }

/* Foot of a card: secondary actions on the left, the answer on the right. Deny is always first in tab order. */
.kl-afoot { display: flex; align-items: center; gap: 8px; margin-top: auto; padding-top: 2px; }
.kl-afoot__spacer { flex: 1 1 auto; }
.kl-afoot .kl-btn { flex: none; }

/* A caution line inside a card: amber ink, warning icon. Never red unless something would be destroyed. */
.kl-anote { display: flex; align-items: flex-start; gap: 8px; padding: 8px 10px; border-radius: var(--kl-radius-row);
  background: var(--kl-color-status-planning-soft); color: var(--kl-color-status-planning-ink); font: var(--kl-font-meta); }
.kl-anote .kl-icon { --kl-icon-size: 14px; flex: none; margin-top: 2px; }
.kl-anote--risk { background: var(--kl-color-status-stopped-soft); color: var(--kl-color-status-stopped-ink); }
.kl-anote--info { background: var(--kl-color-neutral-soft); color: var(--kl-color-neutral-ink); }

/* =====================================================================================================
   1. Permission card .kl-permit
      Markup: <div class="kl-card kl-card--pN kl-permit kl-tilt" data-stage="0..3" data-permit="<state>" data-kind="<kind>">
      States (data-permit): waiting · note (deny with a note) · allowed · always · denied · gone (stopped asking)
      Kinds (data-kind): command · edit · web · connector · delete · outside
      Sizes: compact 252 × 80, full 288 × 148 (holds the quick answer row), expanded 360 wide.
   ===================================================================================================== */
/* A little wider than a project card at compact and full: the name says what it wants, and the gear and chevron sit beside it */
.kl-permit[data-stage="1"] { width: var(--kl-approval-compact-w, 252px); }
.kl-permit[data-stage="2"] { width: var(--kl-approval-full-w, 288px); height: var(--kl-approval-full-h, 148px); }
.kl-permit[data-stage="2"] .kl-card__status { display: none; }   /* full shows the command line and the quick answer instead */
.kl-permit[data-stage="3"] { --kl-card-w: var(--kl-approval-expanded-w, 360px); height: clamp(var(--kl-card-expanded-h-min), var(--kl-card-h, 420px), var(--kl-approval-expanded-h-max, 520px)); }
.kl-permit .kl-card__more { gap: 12px; overflow: visible; }
/* Below expanded only the chevron shows (the gear comes with the expanded card), so the name has room. Same on plan cards. */
:is(.kl-permit, .kl-plan) .kl-card__head { padding-right: calc(28px + 28px * var(--kl-oc)); }
:is(.kl-permit, .kl-plan):not([data-stage="3"]) .kl-card__ctl .kl-iconbtn:not(.kl-iconbtn--chev) { display: none; }
:is(.kl-permit, .kl-plan)[data-stage="3"] .kl-card__head { padding-right: calc(28px + 56px * var(--kl-oc)); }
:is(.kl-permit, .kl-plan) :is(.kl-card__head, .kl-card__status) { flex: none; }
.kl-plan__step.is-editing { margin: 0; }


/* Full stage: the one line that says what it wants, then Deny and Allow once */
.kl-permit__line {
  display: block; margin: 0; padding: 4px 8px; border-radius: var(--kl-radius-sheet);
  background: var(--kl-color-surface-sunken); color: var(--kl-color-text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  opacity: var(--kl-ol); translate: 0 calc(6px * (1 - var(--kl-ol)));
}
.kl-permit__quick { display: flex; gap: 8px; opacity: var(--kl-ol); }
.kl-permit__quick .kl-btn { flex: 1 1 0; }
.kl-permit[data-stage="0"] .kl-permit__line, .kl-permit[data-stage="1"] .kl-permit__line,
.kl-permit[data-stage="0"] .kl-permit__quick, .kl-permit[data-stage="1"] .kl-permit__quick,
.kl-permit[data-stage="3"] .kl-permit__line, .kl-permit[data-stage="3"] .kl-permit__quick { display: none; }
.kl-permit[data-stage="0"] .kl-afrom { display: none; }

/* What it wants: a tool tile, the kind, and the exact command, files, site or connector */
.kl-permit__what { display: flex; flex-direction: column; gap: 8px; }
.kl-permit__kind { display: flex; align-items: center; gap: 8px; font: var(--kl-font-label-strong); color: var(--kl-color-text); }
.kl-permit__tile { display: grid; place-items: center; flex: none; width: 28px; height: 28px; border-radius: var(--kl-radius-control);
  background: var(--kl-color-control-fill); color: var(--kl-color-text); }
.kl-permit__tile .kl-icon { --kl-icon-size: 16px; }
.kl-permit__code {
  margin: 0; padding: 8px 10px; border-radius: var(--kl-radius-row);
  background: var(--kl-color-surface); color: var(--kl-color-text); box-shadow: inset 0 0 0 1px var(--kl-color-line);
  white-space: pre-wrap; word-break: break-word; max-height: 92px; overflow: auto;
}
.kl-permit__code b { font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-status-stopped-ink); }   /* the destructive part of a command */

/* File list (edit and delete asks): name, then +added −removed lines */
.kl-permit__files { display: flex; flex-direction: column; margin: 0; padding: 4px 10px; list-style: none; border-radius: var(--kl-radius-row);
  background: var(--kl-color-surface); box-shadow: inset 0 0 0 1px var(--kl-color-line); }
.kl-permit__file { display: flex; align-items: center; gap: 8px; min-height: 28px; }
.kl-permit__file + .kl-permit__file { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-permit__file .kl-amono { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: var(--kl-color-text); }
.kl-permit__delta { flex: none; font: var(--kl-font-caption); font-variant-numeric: tabular-nums; color: var(--kl-color-text-secondary); }
.kl-permit__delta ins { text-decoration: none; color: var(--kl-color-status-executing-ink); }
.kl-permit__delta del { text-decoration: none; color: var(--kl-color-status-stopped-ink); }

/* Where and why: two quiet rows */
.kl-permit__facts { display: grid; grid-template-columns: auto 1fr; gap: 6px 10px; margin: 0; font: var(--kl-font-meta); }
.kl-permit__facts dt { color: var(--kl-color-text-secondary); }
.kl-permit__facts dd { margin: 0; min-width: 0; color: var(--kl-color-text); display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.kl-permit__facts dd .kl-amono { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; max-width: 100%; }

/* Scope: once, this run, always for this project. A seg with a line under it that says what the choice means. */
.kl-permit__scope .kl-seg { width: 100%; }
.kl-permit__scope .kl-seg__item { flex: 1 1 0; min-width: 0; padding-left: 6px; padding-right: 6px; }
.kl-permit__scope-hint { margin: 6px 0 0; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); min-height: 32px; }
.kl-permit__scope-hint .kl-amono { font-size: 11.5px; line-height: 16px; color: var(--kl-color-text); }

/* Deny with a note: the field slides open under the scope (kl-m-reveal), Deny becomes "Deny and send" */
.kl-permit__note { display: none; flex-direction: column; gap: 6px; }
.kl-permit[data-permit="note"] .kl-permit__note { display: flex; }
.kl-permit__note .kl-textarea, .kl-permit__note .kl-field { width: 100%; }

/* Queue: "2 more from Atlas" bottom left */
.kl-permit__queue { display: inline-flex; align-items: center; gap: 4px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-permit__queue .kl-icon { --kl-icon-size: 12px; }

/* Answered: the body folds to one result line. The card then leaves on its own after a beat (fade + 4px rise), except
   "always", which stays until the Undo toast is gone. */
.kl-permit__done { display: none; flex-wrap: wrap; margin: 0; align-items: baseline; gap: 0 4px; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-permit__done b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }
.kl-permit:is([data-permit="allowed"], [data-permit="always"], [data-permit="denied"], [data-permit="gone"]) .kl-permit__done { display: flex; }
.kl-permit:is([data-permit="allowed"], [data-permit="always"], [data-permit="denied"], [data-permit="gone"]) :is(.kl-permit__body, .kl-permit__quick, .kl-permit__line, .kl-card__rays) { display: none; }
.kl-permit:is([data-permit="allowed"], [data-permit="always"], [data-permit="denied"], [data-permit="gone"]):is([data-stage="2"], [data-stage="3"]) { width: var(--kl-approval-full-w, 288px); height: var(--kl-approval-done-h, 112px); }
.kl-permit:is([data-permit="allowed"], [data-permit="always"], [data-permit="denied"], [data-permit="gone"]) .kl-card__head { padding-right: 0; }
.kl-permit:is([data-permit="allowed"], [data-permit="always"], [data-permit="denied"], [data-permit="gone"]) :is(.kl-card__more, .kl-card__status, .kl-card__grip) { display: none; }
.kl-permit:is([data-permit="denied"], [data-permit="gone"]) .kl-card__name-text { color: var(--kl-color-text-secondary); }

.kl-permit__body { display: flex; flex-direction: column; gap: 12px; }

/* Risky kinds: delete outside the archive, anything outside the project folder. Always is not offered, Allow is red. */
.kl-permit[data-kind="delete"] .kl-permit__tile { background: var(--kl-color-status-stopped-soft); color: var(--kl-color-status-stopped-ink); }
.kl-permit[data-kind="outside"] .kl-permit__tile { background: var(--kl-color-status-planning-soft); color: var(--kl-color-status-planning-ink); }

/* =====================================================================================================
   2. Plan card .kl-plan
      Markup: <div class="kl-card kl-card--pN kl-plan kl-tilt" data-stage="0..3" data-plan="<state>">
      States (data-plan): drafting · ready · editing · sendback · revised · running · done
      Sizes: compact 252 × 80, full 288 × 140, expanded 400 wide and up to 600 high (steps need the room). The steps scroll;
   the answer row stays put.
   ===================================================================================================== */
.kl-plan[data-stage="1"] { width: var(--kl-approval-compact-w, 252px); }
.kl-plan[data-stage="2"] { width: var(--kl-approval-full-w, 288px); }
.kl-plan[data-stage="3"] { --kl-card-w: var(--kl-plan-expanded-w, 400px); height: clamp(var(--kl-card-expanded-h-min), var(--kl-card-h, 520px), var(--kl-plan-expanded-h-max, 600px)); }
.kl-plan .kl-card__more { gap: 12px; flex: 1 1 auto; overflow: hidden; }
/* Everything but the answer row scrolls, so Approve never leaves the card */
.kl-plan__scroll { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 12px; overflow: auto; overscroll-behavior: contain;
  margin: 0 -8px; padding: 0 8px; }

/* Header line inside: version and token estimate */
.kl-plan__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }

/* Steps: numbered rows. Each can be edited in place (pencil on hover or focus). */
.kl-plan__steps { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; counter-reset: kl-step; }
.kl-plan__step {
  position: relative; display: grid; grid-template-columns: 22px 1fr auto; align-items: start; gap: 2px 10px;
  padding: 8px 6px; margin: 0 -6px; border-radius: var(--kl-radius-row);
  font: var(--kl-font-meta); color: var(--kl-color-text);
}
.kl-plan__step + .kl-plan__step::before { content: ""; position: absolute; left: 6px; right: 6px; top: 0; height: 1px; background: var(--kl-color-line); }
.kl-plan__step:hover, .kl-plan__step:focus-within { background: var(--kl-color-control-fill); }
.kl-plan__step:hover::before, .kl-plan__step:hover + .kl-plan__step::before,
.kl-plan__step:focus-within::before, .kl-plan__step:focus-within + .kl-plan__step::before { opacity: 0; }
.kl-plan__num {
  display: grid; place-items: center; width: 22px; height: 22px; border-radius: var(--kl-radius-round);
  background: var(--kl-color-surface); box-shadow: inset 0 0 0 1px var(--kl-color-line-strong);
  font: var(--kl-font-caption); font-weight: var(--kl-font-weight-semibold); font-variant-numeric: tabular-nums; color: var(--kl-color-text-secondary);
}
.kl-plan__num .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2.2; }
.kl-plan__text { min-width: 0; padding-top: 2px; }
.kl-plan__sub { grid-column: 2 / 3; display: flex; flex-wrap: wrap; gap: 4px; }
.kl-plan__edit { opacity: 0; transition: opacity var(--kl-motion-hover) ease; }
.kl-plan__step:hover .kl-plan__edit, .kl-plan__step:focus-within .kl-plan__edit, .kl-plan__edit:focus-visible { opacity: 1; }
.kl-plan .kl-iconbtn { --kl-iconbtn: 28px; }

/* A step being edited: the text turns into a field with Cancel and Save under it */
.kl-plan__step.is-editing { background: var(--kl-color-surface); box-shadow: inset 0 0 0 1px var(--kl-color-focus), 0 0 0 3px var(--kl-color-selection-soft); }
.kl-plan__step.is-editing::before, .kl-plan__step.is-editing + .kl-plan__step::before { opacity: 0; }
.kl-plan__step .kl-textarea { width: 100%; min-height: 56px; resize: none; }
.kl-plan__editbar { grid-column: 2 / 4; display: flex; justify-content: flex-end; gap: 6px; padding-top: 6px; }

/* Changed since the last plan (revised): a selection-tinted number and a "changed" tag */
.kl-plan__step.is-changed .kl-plan__num { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); box-shadow: none; }
.kl-plan__step.is-new .kl-plan__num { background: var(--kl-color-selection); color: var(--kl-color-text-on-fill); box-shadow: none; }

/* Running: steps become progress. Done steps check off, the current one breathes green, later ones wait. */
.kl-plan__step.is-done .kl-plan__num { background: var(--kl-color-status-executing); color: var(--kl-color-text-on-fill); box-shadow: none; }
.kl-plan__step.is-done .kl-plan__text { color: var(--kl-color-text-secondary); }
.kl-plan__step.is-now .kl-plan__num { box-shadow: inset 0 0 0 2px var(--kl-color-status-executing); color: var(--kl-color-status-executing-ink); }
.kl-plan__step.is-now .kl-plan__text { font-weight: var(--kl-font-weight-semibold); }
.kl-plan__step.is-writing .kl-plan__text { color: var(--kl-color-text-secondary); }

/* Files it expects to touch */
.kl-plan__files { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.kl-plan__file { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; height: 24px; padding: 0 8px; border-radius: var(--kl-radius-sheet);
  background: var(--kl-color-surface); box-shadow: inset 0 0 0 1px var(--kl-color-line); color: var(--kl-color-text); }
.kl-plan__file .kl-amono { font-size: 12px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-plan__file i { font-style: normal; font: var(--kl-font-badge); color: var(--kl-color-text-secondary); }
.kl-plan__file.is-new i { color: var(--kl-color-selection-ink); }

/* Assumptions the agent made, one line each */
.kl-plan__assume { margin: 0; padding-left: 18px; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-plan__assume li + li { margin-top: 2px; }

/* Send back: the note field replaces the answer row */
.kl-plan__note { display: none; flex-direction: column; gap: 6px; }
.kl-plan[data-plan="sendback"] .kl-plan__note { display: flex; }
.kl-plan__note .kl-textarea { width: 100%; min-height: 64px; resize: none; }

/* Progress bar while running: the v2 meter */
.kl-plan__progress { display: flex; flex-direction: column; gap: 6px; }

/* =====================================================================================================
   3. Rules window .kl-rules (a v2 .kl-win, 480 wide)
      Groups in the order they win: Deny, then Ask, then Allow. Each row: kind tile, pattern, decision, scope, more.
   ===================================================================================================== */
.kl-win--rules { --kl-win-w: 480px; }
.kl-rules .kl-win__body { gap: var(--kl-space-4); }
.kl-rules__lede { margin: 0; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }

/* Try a command or path: the field and what would happen */
.kl-rules__try { display: flex; flex-direction: column; gap: 8px; padding: 12px; border-radius: var(--kl-radius-groupbox);
  background: var(--kl-color-surface-sunken); }
.kl-rules__try .kl-field { width: 100%; font-family: var(--kl-font-mono); font-size: 12.5px; }
.kl-rules__verdict { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); min-height: 20px; }
.kl-rules__verdict b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }

/* Rule row */
.kl-rule { display: grid; grid-template-columns: 28px minmax(0, 1fr) auto; align-items: center; gap: 4px 10px; min-height: 52px; padding: 8px 0; }
.kl-rule + .kl-rule { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-rule__tile { display: grid; place-items: center; width: 28px; height: 28px; border-radius: var(--kl-radius-control);
  background: var(--kl-color-control-fill); color: var(--kl-color-text); }
.kl-rule__tile .kl-icon { --kl-icon-size: 16px; }
.kl-rule__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.kl-rule__pattern { color: var(--kl-color-text); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-rule__from { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-rule__ctl { display: inline-flex; align-items: center; gap: 4px; }
.kl-rule .kl-seg__item { height: 24px; padding: 0 8px; font: var(--kl-font-caption); font-weight: var(--kl-font-weight-medium); }
.kl-rule .kl-iconbtn { --kl-iconbtn: 28px; }
/* Inherited from every project: quieter, with "Change for Atlas" instead of the decision seg */
.kl-rule.is-inherited .kl-rule__pattern { color: var(--kl-color-text-secondary); }
.kl-rule.is-inherited .kl-rule__tile { background: transparent; box-shadow: inset 0 0 0 1px var(--kl-color-line); color: var(--kl-color-text-secondary); }
/* Never used: a rule above always wins over it */
.kl-rule.is-shadowed .kl-rule__pattern { text-decoration: line-through; text-decoration-color: var(--kl-color-text-tertiary); }
.kl-rule__warn { grid-column: 2 / 4; display: flex; align-items: center; gap: 6px; font: var(--kl-font-caption); color: var(--kl-color-status-planning-ink); }
.kl-rule__warn .kl-icon { --kl-icon-size: 12px; }
/* The row that matched the try field */
.kl-rule.is-match { margin: 0 calc(-1 * var(--kl-space-3)); padding-left: var(--kl-space-3); padding-right: var(--kl-space-3);
  background: var(--kl-color-selection-soft); border-radius: var(--kl-radius-row); box-shadow: none; }
.kl-rule.is-match + .kl-rule { box-shadow: none; }
/* Just added: lands with kl-m-land; just removed: folds away, the Undo toast takes over */

/* Group heads: decision icon + name + count */
.kl-rules .kl-setting-group__label .kl-atag { font-weight: var(--kl-font-weight-medium); }
.kl-rules__gicon { display: inline-flex; align-items: center; gap: 6px; }
.kl-rules__gicon .kl-icon { --kl-icon-size: 14px; color: var(--kl-color-text-secondary); }

/* Add a rule: a composer box at the bottom of the list */
.kl-rules__add { display: flex; flex-direction: column; gap: 10px; padding: 12px; border-radius: var(--kl-radius-groupbox);
  background: var(--kl-color-surface); box-shadow: inset 0 0 0 1px var(--kl-color-focus), 0 0 0 3px var(--kl-color-selection-soft); }
.kl-rules__add-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.kl-rules__add .kl-field { flex: 1 1 200px; min-width: 0; font-family: var(--kl-font-mono); font-size: 12.5px; }
.kl-rules__add .kl-seg__item { height: 26px; padding: 0 10px; }
.kl-rules__add-foot { display: flex; align-items: center; gap: 8px; }
.kl-rules__add-foot .kl-fieldhint { margin: 0 auto 0 0; }
.kl-rules__kinds { display: flex; flex-wrap: wrap; gap: 6px; }

/* Empty */
.kl-rules__empty { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 28px 16px; text-align: center;
  font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-rules__empty .kl-icon { --kl-icon-size: 24px; color: var(--kl-color-text-tertiary); }
.kl-rules__empty b { font: var(--kl-font-label-strong); color: var(--kl-color-text); }

/* =====================================================================================================
   4. Increased contrast and reduced motion
   ===================================================================================================== */
:is([data-contrast="more"]) .kl-permit__line, :is([data-contrast="more"]) .kl-permit__code, :is([data-contrast="more"]) .kl-permit__files,
:is([data-contrast="more"]) .kl-plan__file { box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
:is([data-contrast="more"]) .kl-atag, :is([data-contrast="more"]) .kl-anote { box-shadow: inset 0 0 0 1px currentColor; }
@media (prefers-contrast: more) {
  .kl-permit__line, .kl-permit__code, .kl-permit__files, .kl-plan__file { box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
  .kl-atag, .kl-anote { box-shadow: inset 0 0 0 1px currentColor; }
}

/* ===== harness/diff/diff.css ===== */
/* Klippan master, harness: diff review and rewind.
   Builds on klippan-v2/combined/klippan.css (load that first). Only --kl-* tokens; the few literals are this
   part's own component sizes, kept as local custom properties. The diff colours, the code type and the hunk fold
   timings are v2's own (--kl-color-diff-*, --kl-font-code, --kl-motion-hunk-*); the window is v2's .kl-win--wide.

   1. Change count        .kl-diffstat, .kl-diffline
   2. Diff window         .kl-win--diff, .kl-diff__sum, .kl-diff__files, .kl-difffile, .kl-diff__pane
   3. File and hunks      .kl-diffhead, .kl-hunk, .kl-dline
   4. Inline comments     .kl-dnote
   5. Rewind dialog       .kl-rewind, .kl-rewind__point, .kl-rewind__opt
   6. Increased contrast */

/* ===== 1. Change count: "+124 −38 in 6 files" ===== */
.kl-diffstat {
  display: inline-flex;
  align-items: center;
  gap: var(--kl-space-2);
  min-width: 0;
  font: var(--kl-font-meta);
  font-family: var(--kl-font-sans);
  font-variant-numeric: tabular-nums;
  color: var(--kl-color-text-secondary);
  white-space: nowrap;
}
.kl-diffstat__add, .kl-diffstat__del { display: inline-block; font-weight: var(--kl-font-weight-semibold); }
.kl-diffstat__add { color: var(--kl-color-diff-add-ink); }
.kl-diffstat__del { color: var(--kl-color-diff-del-ink); }
.kl-diffstat__files { color: var(--kl-color-text-secondary); }
/* Five pips, GitHub style: green for the share added, red for the share removed, grey for the rest (a tiny file) */
.kl-diffstat__bar { display: inline-flex; gap: 2px; flex: none; }
.kl-diffstat__pip { width: 7px; height: 7px; border-radius: 2px; background: var(--kl-color-control-fill-pressed); }
.kl-diffstat__pip--add { background: var(--kl-color-diff-add-ink); }
.kl-diffstat__pip--del { background: var(--kl-color-diff-del-ink); }
.kl-diffstat--sm { gap: 6px; font: var(--kl-font-caption); font-variant-numeric: tabular-nums; }
.kl-diffstat--sm .kl-diffstat__pip { width: 6px; height: 6px; }
.kl-diffstat--lg { font: var(--kl-font-label-strong); font-variant-numeric: tabular-nums; }
.kl-diffstat--lg .kl-diffstat__files { font-weight: var(--kl-font-weight-regular); }
.kl-diffstat.is-empty { color: var(--kl-color-text-tertiary); }
.kl-diffstat.is-reverted :is(.kl-diffstat__add, .kl-diffstat__del) { color: var(--kl-color-text-tertiary); text-decoration: line-through; }

/* The line on an expanded card and a run row: a button that opens the diff window */
.kl-diffline {
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  width: 100%;
  min-height: 32px;
  margin: 0;
  padding: 4px 6px 4px 8px;
  border: 0;
  border-radius: var(--kl-radius-row);
  background: var(--kl-color-control-fill);
  color: var(--kl-color-text);
  font: var(--kl-font-meta);
  font-family: var(--kl-font-sans);
  text-align: left;
  cursor: pointer;
  transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-diffline > .kl-icon { --kl-icon-size: 16px; color: var(--kl-color-text-secondary); }
.kl-diffline__go { display: inline-flex; align-items: center; gap: 2px; margin-left: auto; color: var(--kl-color-text-secondary); }
.kl-diffline__go .kl-icon { --kl-icon-size: 14px; }
.kl-diffline:hover, .kl-diffline.is-hover { background: var(--kl-color-control-fill-pressed); }
.kl-diffline:focus-visible, .kl-diffline.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-diffline[aria-expanded="true"], .kl-diffline.is-open { box-shadow: inset 0 0 0 2px var(--kl-color-selection); }

/* ===== 2. Diff window ===== */
.kl-win--diff {
  --kl-win-max-h: 680px;
  --kl-diff-files-w: 236px;
  height: var(--kl-diff-h, 620px);
}
.kl-win--diff > .kl-win__body { flex-direction: row; gap: 0; padding: 0; overflow: hidden; }

/* The strip under the bar: the whole count, who made it, how much is reviewed, and Rewind */
.kl-diff__sum {
  flex: none;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--kl-space-2) var(--kl-space-3);
  padding: var(--kl-space-2) var(--kl-space-3) var(--kl-space-2) var(--kl-space-4);
  border-bottom: 1px solid var(--kl-color-line);
}
.kl-diff__who { display: inline-flex; align-items: center; gap: 6px; min-width: 0; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-diff__who .kl-icon { --kl-icon-size: 14px; }
.kl-diff__progress { margin-left: auto; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }

/* Changed-file list */
.kl-diff__files {
  flex: none;
  width: var(--kl-diff-files-w);
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0;
  padding: var(--kl-space-2);
  list-style: none;
  overflow: auto;
  border-right: 1px solid var(--kl-color-line);
  background: var(--kl-color-surface-sunken);
}
.kl-difffile {
  position: relative;
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr) auto;
  grid-template-rows: auto auto;
  column-gap: var(--kl-space-2);
  align-items: center;
  width: 100%;
  min-height: 44px;
  margin: 0;
  padding: 5px 8px;
  border: 0;
  border-radius: var(--kl-radius-row);
  background: transparent;
  color: var(--kl-color-text);
  font: var(--kl-font-meta);
  font-family: var(--kl-font-sans);
  text-align: left;
  cursor: pointer;
  transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-difffile__kind {
  grid-row: 1 / span 2;
  display: inline-grid;
  place-items: center;
  width: 18px;
  height: 18px;
  border-radius: 5px;
  background: var(--kl-color-neutral-soft);
  color: var(--kl-color-neutral-ink);
  font: var(--kl-font-badge);
}
.kl-difffile__kind--added { background: var(--kl-color-diff-add); color: var(--kl-color-diff-add-ink); }
.kl-difffile__kind--deleted { background: var(--kl-color-diff-del); color: var(--kl-color-diff-del-ink); }
.kl-difffile__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--kl-font-weight-medium); }
.kl-difffile__dir { grid-column: 2; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--kl-font-caption); color: var(--kl-color-text-tertiary); }
.kl-difffile__end { grid-column: 3; grid-row: 1 / span 2; display: inline-flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.kl-difffile__state { display: inline-flex; align-items: center; gap: 3px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-difffile__state .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
.kl-difffile:hover, .kl-difffile.is-hover { background: var(--kl-color-control-fill); }
.kl-difffile:focus-visible, .kl-difffile.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: -2px; }
/* The open file: v2 selection, an edge (never a fill) */
.kl-difffile[aria-current="true"], .kl-difffile.is-selected { background: var(--kl-color-surface); box-shadow: inset 0 0 0 2px var(--kl-color-selection); }
.kl-difffile.is-kept .kl-difffile__state { color: var(--kl-color-diff-add-ink); }
.kl-difffile.is-reverted .kl-difffile__name { color: var(--kl-color-text-secondary); text-decoration: line-through; text-decoration-color: var(--kl-color-text-tertiary); }
.kl-difffile.is-live .kl-difffile__state { color: var(--kl-color-status-executing-ink); }
.kl-difffile .kl-dot { width: 8px; height: 8px; }

/* The pane on the right */
.kl-diff__pane { position: relative; flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; overflow: auto; }
.kl-diff__pane > .kl-win-notice { margin: var(--kl-space-3) var(--kl-space-3) 0; }
.kl-diff__hunks { display: flex; flex-direction: column; gap: var(--kl-space-3); padding: var(--kl-space-3); }
.kl-diff__empty { margin: auto; padding: var(--kl-space-8) var(--kl-space-6); max-width: 320px; text-align: center; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-diff__empty > .kl-icon { --kl-icon-size: 32px; display: block; margin: 0 auto var(--kl-space-3); color: var(--kl-color-text-tertiary); }
.kl-diff__empty b { display: block; margin-bottom: 4px; font: var(--kl-font-label-strong); color: var(--kl-color-text); }
/* Loading: still bars, no shimmer (a shimmer is a loop) */
.kl-diff__skel { display: flex; flex-direction: column; gap: 8px; padding: var(--kl-space-4); }
.kl-diff__skel i { display: block; height: 10px; width: var(--w, 80%); border-radius: var(--kl-radius-pill); background: var(--kl-color-control-fill); }
/* A file with no lines to show: an image, a lock file, a very large file */
.kl-diff__other { display: flex; align-items: center; gap: var(--kl-space-3); margin: var(--kl-space-3); padding: var(--kl-space-3); border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface-sunken); font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-diff__other .kl-icon { color: var(--kl-color-text-tertiary); }

/* ===== 3. File header, hunks and lines ===== */
.kl-diffhead {
  position: sticky;
  top: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  min-height: 44px;
  padding: 6px var(--kl-space-3);
  border-bottom: 1px solid var(--kl-color-line);
  background: var(--kl-color-surface);
}
.kl-diffhead__path { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--kl-font-code); font-weight: var(--kl-font-weight-medium); }
.kl-diffhead__path span { color: var(--kl-color-text-tertiary); }
.kl-diffhead__acts { display: inline-flex; gap: var(--kl-space-1); margin-left: auto; flex: none; }

.kl-hunk {
  border-radius: var(--kl-radius-groupbox);
  background: var(--kl-color-surface);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
  overflow: hidden;
}
.kl-hunk__head {
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  min-height: 36px;
  padding: 4px 6px 4px var(--kl-space-3);
  background: var(--kl-color-surface-sunken);
  border-bottom: 1px solid var(--kl-color-line);
}
.kl-hunk__where { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-hunk__where b { font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text); }
.kl-hunk__where code { font: var(--kl-font-code); font-size: inherit; }
.kl-hunk__acts { display: inline-flex; align-items: center; gap: var(--kl-space-1); margin-left: auto; flex: none; }
.kl-hunk__tag { display: inline-flex; align-items: center; gap: 4px; padding: 0 6px; font: var(--kl-font-caption); color: var(--kl-color-diff-add-ink); }
.kl-hunk__tag .kl-icon { --kl-icon-size: 14px; }
/* The body is v2's kl-m-grow: it folds shut on revert (remove .is-in) and opens again on Undo, on the hunk timings */
.kl-hunk__body { --kl-m-grow-in: var(--kl-motion-hunk-unfold); --kl-m-grow-out: var(--kl-motion-hunk-fold); }
.kl-hunk.is-reverted .kl-hunk__head { border-bottom-color: transparent; }
.kl-hunk.is-reverted .kl-hunk__where { text-decoration: line-through; text-decoration-color: var(--kl-color-text-tertiary); }
.kl-hunk__back { display: flex; align-items: center; gap: var(--kl-space-2); padding: 6px 6px 6px var(--kl-space-3); font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-hunk__back > .kl-icon { --kl-icon-size: 16px; color: var(--kl-color-text-tertiary); }
.kl-hunk__back .kl-btn { margin-left: auto; }
.kl-hunk.is-kept { box-shadow: inset 0 0 0 1px var(--kl-color-line); }
.kl-hunk.is-kept .kl-dline__sign { opacity: .7; }
/* Can't be reverted on its own: something later changed the same lines */
.kl-hunk__clash { display: flex; align-items: center; gap: var(--kl-space-2); padding: 8px var(--kl-space-3); background: var(--kl-color-hue-amber-soft); color: var(--kl-color-hue-amber-ink); font: var(--kl-font-meta); }
.kl-hunk__clash .kl-icon { --kl-icon-size: 16px; }
.kl-hunk__clash .kl-btn { margin-left: auto; color: inherit; }

.kl-dline {
  position: relative;
  display: grid;
  grid-template-columns: 36px 36px 18px minmax(0, 1fr);
  align-items: start;
  min-height: 20px;
  font: var(--kl-font-code);
  color: var(--kl-color-text);
}
.kl-dline__no { padding-right: 6px; text-align: right; color: var(--kl-color-text-tertiary); font-variant-numeric: tabular-nums; user-select: none; }
.kl-dline__sign { text-align: center; user-select: none; }
.kl-dline__code { padding-right: var(--kl-space-3); white-space: pre-wrap; overflow-wrap: anywhere; tab-size: 2; }
.kl-dline--add { background: var(--kl-color-diff-add); }
.kl-dline--add .kl-dline__sign { color: var(--kl-color-diff-add-ink); }
.kl-dline--del { background: var(--kl-color-diff-del); }
.kl-dline--del .kl-dline__sign { color: var(--kl-color-diff-del-ink); }
.kl-dline--add mark, .kl-dline--del mark { border-radius: 3px; color: inherit; }
.kl-dline--add mark { background: var(--kl-color-diff-add-word); }
.kl-dline--del mark { background: var(--kl-color-diff-del-word); }
/* Long hunks fold their middle; the row opens it */
.kl-dline--fold { display: flex; align-items: center; justify-content: center; min-height: 28px; padding: 0; border: 0; width: 100%; background: var(--kl-color-control-fill); color: var(--kl-color-text-secondary); font: var(--kl-font-caption); font-family: var(--kl-font-sans); cursor: pointer; }
.kl-dline--fold:hover, .kl-dline--fold.is-hover { background: var(--kl-color-control-fill-pressed); color: var(--kl-color-text); }
.kl-dline--fold:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: -2px; }
/* Comment on a line: a small + in the gutter on hover or focus; it stays while the line has a comment */
.kl-dline__note {
  position: absolute;
  left: 70px;
  top: 1px;
  z-index: 2;
  display: inline-grid;
  place-items: center;
  width: 18px;
  height: 18px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: var(--kl-color-primary);
  color: var(--kl-color-text-on-fill);
  opacity: 0;
  pointer-events: none;
  cursor: pointer;
  transition: opacity var(--kl-motion-hover) var(--kl-motion-ease-out);
}
/* The hit area grows sideways only, so it never reaches into the next line's button */
.kl-dline__note::before { content: ""; position: absolute; inset: -1px -14px; }
.kl-dline__note .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2.2; }
.kl-dline:hover .kl-dline__note, .kl-dline.is-hover .kl-dline__note, .kl-dline__note:focus-visible { opacity: 1; pointer-events: auto; }
.kl-dline__note:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 1px; }
.kl-dline.has-note { box-shadow: inset 0 -1px 0 var(--kl-color-selection-soft); }
.kl-dline.has-note .kl-dline__no:first-child { color: var(--kl-color-selection-ink); font-weight: var(--kl-font-weight-semibold); }

/* ===== 4. Inline comments for the agent ===== */
.kl-dnote {
  margin: 6px var(--kl-space-3) 8px calc(72px + 18px);
  padding: 10px 12px;
  border-radius: var(--kl-radius-row);
  background: var(--kl-color-surface-raised, var(--kl-color-surface));
  box-shadow: var(--kl-shadow-card);
  font: var(--kl-font-meta);
  font-family: var(--kl-font-sans);
  color: var(--kl-color-text);
}
.kl-dnote__head { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-dnote__head b { font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text); }
.kl-dnote__head .kl-icon { --kl-icon-size: 14px; }
.kl-dnote__state { display: inline-flex; align-items: center; gap: 3px; margin-left: auto; }
.kl-dnote__state .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
.kl-dnote__body { margin: 0; white-space: pre-wrap; }
.kl-dnote__reply { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--kl-color-line); }
.kl-dnote__acts { display: flex; justify-content: flex-end; gap: var(--kl-space-2); margin-top: 8px; }
.kl-dnote .kl-textarea { width: 100%; min-height: 64px; }
.kl-dnote.is-compose { box-shadow: var(--kl-shadow-card), 0 0 0 2px var(--kl-color-selection-soft); }
.kl-dnote.is-sent .kl-dnote__state { color: var(--kl-color-selection-ink); }
.kl-dnote.is-answered .kl-dnote__state { color: var(--kl-color-diff-add-ink); }
.kl-dnote.is-outdated { box-shadow: inset 0 0 0 1px var(--kl-color-line); background: transparent; color: var(--kl-color-text-secondary); }

/* ===== 5. Rewind dialog ===== */
.kl-rewind { --kl-dialog-w: 456px; gap: 14px; }
.kl-rewind__title { display: flex; align-items: center; gap: var(--kl-space-2); }
.kl-rewind__title .kl-icon { --kl-icon-size: 20px; color: var(--kl-color-text-secondary); }
.kl-rewind__label { margin: 0 0 6px; font: var(--kl-font-label-strong); color: var(--kl-color-text); }
.kl-rewind__points, .kl-rewind__opts { display: flex; flex-direction: column; gap: 4px; margin: 0; padding: 0; border: 0; }
.kl-rewind__points { max-height: 188px; overflow: auto; padding: 2px; }
.kl-rewind__point, .kl-rewind__opt {
  position: relative;
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr) auto auto;
  column-gap: var(--kl-space-2);
  align-items: center;
  min-height: 44px;
  padding: 6px 10px;
  border-radius: var(--kl-radius-row);
  background: var(--kl-color-surface-sunken);
  cursor: pointer;
  transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-rewind__point > input, .kl-rewind__opt > input { position: absolute; opacity: 0; pointer-events: none; }
.kl-rewind__point > .kl-icon, .kl-rewind__opt > .kl-icon { --kl-icon-size: 18px; color: var(--kl-color-text-secondary); }
.kl-rewind__text { display: flex; flex-direction: column; min-width: 0; }
.kl-rewind__text b { font: var(--kl-font-label-strong); }
.kl-rewind__text span { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-rewind__time { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-rewind__point:hover, .kl-rewind__opt:hover, .kl-rewind__point.is-hover, .kl-rewind__opt.is-hover { background: var(--kl-color-control-fill); }
.kl-rewind__point:has(input:focus-visible), .kl-rewind__opt:has(input:focus-visible), .kl-rewind__point.is-focus, .kl-rewind__opt.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
/* Chosen: the v2 edge plus the inline check, never a fill */
.kl-rewind__point:has(input:checked), .kl-rewind__opt:has(input:checked), .kl-rewind__point.is-selected, .kl-rewind__opt.is-selected { background: var(--kl-color-surface); box-shadow: inset 0 0 0 2px var(--kl-color-selection); }
.kl-rewind__point .kl-check, .kl-rewind__opt .kl-check { visibility: hidden; }
.kl-rewind__point:has(input:checked) .kl-check, .kl-rewind__opt:has(input:checked) .kl-check, .kl-rewind__point.is-selected .kl-check, .kl-rewind__opt.is-selected .kl-check { visibility: visible; }
.kl-rewind__point.is-now { cursor: default; opacity: .6; }
.kl-rewind__sum { margin: 0; padding: 0 0 0 18px; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-rewind__sum li + li { margin-top: 2px; }
.kl-rewind__warn { display: flex; align-items: flex-start; gap: var(--kl-space-2); padding: 8px 10px; border-radius: var(--kl-radius-row); background: var(--kl-color-hue-amber-soft); color: var(--kl-color-hue-amber-ink); font: var(--kl-font-meta); }
.kl-rewind__warn .kl-icon { --kl-icon-size: 16px; margin-top: 1px; }

/* ===== 6. Increased contrast (reduced motion is v2's: the hunk fold is kl-m-grow) ===== */
/* More contrast: the line tints alone are not enough, so added and removed lines also get a solid edge, and
   reviewed states get an outline */
@media (prefers-contrast: more) {
  .kl-dline--add { box-shadow: inset 3px 0 0 var(--kl-color-diff-add-ink); }
  .kl-dline--del { box-shadow: inset 3px 0 0 var(--kl-color-diff-del-ink); }
  .kl-hunk, .kl-difffile.is-selected { box-shadow: inset 0 0 0 2px var(--kl-color-line-strong); }
  .kl-difffile.is-selected { box-shadow: inset 0 0 0 2px var(--kl-color-selection); }
}
[data-contrast="more"] .kl-dline--add { box-shadow: inset 3px 0 0 var(--kl-color-diff-add-ink); }
[data-contrast="more"] .kl-dline--del { box-shadow: inset 3px 0 0 var(--kl-color-diff-del-ink); }
[data-contrast="more"] .kl-hunk { box-shadow: inset 0 0 0 2px var(--kl-color-line-strong); }
[data-contrast="more"] :is(.kl-diffline, .kl-rewind__point, .kl-rewind__opt, .kl-dnote) { box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
[data-contrast="more"] :is(.kl-rewind__point, .kl-rewind__opt):is(.is-selected, :has(input:checked)) { box-shadow: inset 0 0 0 2px var(--kl-color-selection); }

/* ===== harness/runs/runs.css ===== */
/* Klippan master · harness · Runs and environments
   Run row, Runs window, the two new run states (needs approval, ready for review), retrying, the fallback-model note,
   environment chip, picker and panel, runner status, the background tray, the Runs section card and its peek,
   and the run tally for a project card whose runs disagree.
   Load after ../../../klippan-v2/combined/klippan.css. Only --kl-* tokens; literals are this part's own sizes.
   The run-state colours are Foundations' --kl-color-status-approval and --kl-color-status-review (with -ink and -soft);
   the approval dot, the asking card and its rays are Board's and Motion's (.kl-dot--approval, .kl-card.is-asking, kl-m-rays--approval). */

/* -------------------------------------------------------------------------------------------------
   1. Run states on the dot. Works with both v2 dots (board: --kl-dot-c, controls: --kl-dot).
      v2 has executing, planning, stopped, idle and approval (Board). Here: review, plus retrying, queued, done, failed.
   ------------------------------------------------------------------------------------------------- */
.kl-dot--review   { --kl-dot: var(--kl-color-status-review); --kl-dot-c: var(--kl-color-status-review); color: var(--kl-color-status-review); }
.kl-dot--retrying { --kl-dot: var(--kl-color-status-planning); --kl-dot-c: var(--kl-color-status-planning); color: var(--kl-color-status-planning); }
.kl-dot--failed   { --kl-dot: var(--kl-color-status-stopped); --kl-dot-c: var(--kl-color-status-stopped); color: var(--kl-color-status-stopped); }
.kl-dot--done     { --kl-dot: var(--kl-color-status-idle); --kl-dot-c: var(--kl-color-status-idle); color: var(--kl-color-status-idle); }
/* Queued and paused: a hollow ring, nothing is happening yet */
.kl-dot--queued, .kl-dot--paused { --kl-dot: transparent; --kl-dot-c: transparent; color: var(--kl-color-status-idle);
  background: transparent; box-shadow: inset 0 0 0 1.6px var(--kl-color-status-idle); }
/* Ready for review carries a small notch so it never relies on colour alone: a ring of the surface inside the dot */
.kl-dot--review { box-shadow: inset 0 0 0 2.5px var(--kl-dot), inset 0 0 0 5px color-mix(in srgb, var(--kl-dot) 55%, transparent); }

/* Needs your approval on a card is Board's asking card: .kl-card.is-asking, .kl-card__status.is-asking, and
   .kl-card__rays.kl-m-rays.kl-m-rays--approval. Ready for review adds a soft cyan edge, no rays. */
.kl-card.is-review .kl-card__face { border-color: color-mix(in srgb, var(--kl-color-status-review) 60%, transparent); }

/* The status-line word that pairs with the colour ("Needs you", "Ready for review") */
.kl-rn-word { font-weight: var(--kl-font-weight-semibold); }
.kl-rn-word--approval { color: var(--kl-color-status-approval-ink); }
.kl-rn-word--review   { color: var(--kl-color-status-review-ink); }
.kl-rn-word--stopped  { color: var(--kl-color-status-stopped-ink); }
.kl-rn-word--retrying { color: var(--kl-color-status-planning-ink); }

/* -------------------------------------------------------------------------------------------------
   2. Small pieces: environment chip, tray count, fallback note, project mark, change count
   ------------------------------------------------------------------------------------------------- */
.kl-envchip {
  --kl-envchip-h: 22px;
  position: relative; display: inline-flex; align-items: center; gap: 5px; flex: none; max-width: 100%;
  height: var(--kl-envchip-h); padding: 0 8px 0 6px; border: 0; border-radius: var(--kl-radius-pill);
  background: var(--kl-color-control-fill); color: var(--kl-color-text);
  font: var(--kl-font-caption); font-weight: var(--kl-font-weight-medium); white-space: nowrap; cursor: pointer;
  transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-envchip::before { content: ""; position: absolute; inset: -11px 0; }   /* 44 px hit area */
.kl-envchip .kl-icon, .kl-envchip > svg { width: 14px; height: 14px; flex: none; color: var(--kl-color-text-secondary); }
.kl-envchip__branch { min-width: 0; overflow: hidden; text-overflow: ellipsis; font-family: var(--kl-font-mono); font-weight: var(--kl-font-weight-regular); color: var(--kl-color-text-secondary); }
.kl-envchip__chev { width: 10px !important; height: 10px !important; margin-left: -1px; }
.kl-envchip:hover, .kl-envchip.is-hover { background: var(--kl-color-control-fill-pressed); }
.kl-envchip:focus-visible, .kl-envchip.is-focus { outline: 0; box-shadow: var(--kl-shadow-ring-focus); }
.kl-envchip[aria-expanded="true"], .kl-envchip.is-open { box-shadow: inset 0 0 0 1.5px var(--kl-color-selection); background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
.kl-envchip.is-unavailable { color: var(--kl-color-text-secondary); }
.kl-envchip.is-unavailable .kl-icon { opacity: .6; }
/* Static (on a card's full stage there is no menu): no chevron, no pointer */
.kl-envchip--static { cursor: default; }

.kl-traychip {
  position: relative; display: inline-flex; align-items: center; gap: 5px; flex: none; height: 22px; padding: 0 8px 0 6px;
  border: 0; border-radius: var(--kl-radius-pill); background: var(--kl-color-control-fill); color: var(--kl-color-text);
  font: var(--kl-font-caption); font-weight: var(--kl-font-weight-medium); font-variant-numeric: tabular-nums; white-space: nowrap; cursor: pointer;
  transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-traychip::before { content: ""; position: absolute; inset: -11px 0; }
.kl-traychip .kl-icon { width: 14px; height: 14px; color: var(--kl-color-text-secondary); }
.kl-traychip:hover, .kl-traychip.is-hover { background: var(--kl-color-control-fill-pressed); }
.kl-traychip:focus-visible { outline: 0; box-shadow: var(--kl-shadow-ring-focus); }
.kl-traychip[aria-expanded="true"], .kl-traychip.is-open { box-shadow: inset 0 0 0 1.5px var(--kl-color-selection); background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
/* A job in the tray is still going: one small green pip, no animation (the card's dot already breathes) */
.kl-traychip__pip { width: 6px; height: 6px; border-radius: 50%; background: var(--kl-color-status-executing); }
/* Compact stage: just the icon and the number, next to the agent count */
.kl-traychip--mini { height: 18px; padding: 0 5px 0 4px; gap: 3px; background: transparent; color: var(--kl-color-text-secondary); }
.kl-traychip--mini .kl-icon { width: 13px; height: 13px; }

.kl-fallback {
  display: flex; align-items: flex-start; gap: 6px; margin: 0; min-width: 0;
  font: var(--kl-font-caption); color: var(--kl-color-text-secondary);
}
.kl-fallback .kl-icon { width: 13px; height: 13px; flex: none; margin-top: 1.5px; }
.kl-fallback b { font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text); }

.kl-rn-mark { flex: none; display: inline-block; width: 8px; height: 8px; border-radius: 2.5px; background: var(--kl-rn-mark, var(--kl-color-project-1)); }
.kl-rn-mark--p1 { --kl-rn-mark: var(--kl-color-project-1); } .kl-rn-mark--p2 { --kl-rn-mark: var(--kl-color-project-2); }
.kl-rn-mark--p3 { --kl-rn-mark: var(--kl-color-project-3); } .kl-rn-mark--p4 { --kl-rn-mark: var(--kl-color-project-4); }
.kl-rn-mark--p5 { --kl-rn-mark: var(--kl-color-project-5); } .kl-rn-mark--p6 { --kl-rn-mark: var(--kl-color-project-6); }
.kl-rn-mark--p7 { --kl-rn-mark: var(--kl-color-project-7); } .kl-rn-mark--p8 { --kl-rn-mark: var(--kl-color-project-8); }

/* The change count is the Diff part's .kl-diffstat--sm (../diff/diff.css) */
.kl-runrow__status .kl-diffstat { vertical-align: baseline; }

.kl-rn-code { font-family: var(--kl-font-mono); font-size: .92em; padding: 0 4px; border-radius: 4px; background: var(--kl-color-control-fill); }

/* -------------------------------------------------------------------------------------------------
   3. Run row  .kl-runrow
      [dot] [project · title / status line / chips] [time + action]
      The dot is centred top to bottom, as on the cards. Only rows waiting on Alban ring; working rows stay still
      in a list (their card on the board already breathes).
   ------------------------------------------------------------------------------------------------- */
.kl-runrow {
  --kl-runrow-dot-col: 22px;
  position: relative; display: grid; grid-template-columns: var(--kl-runrow-dot-col) minmax(0, 1fr) auto; align-items: center; column-gap: 8px;
  padding: 10px 10px 10px 6px; border-radius: var(--kl-radius-row); color: var(--kl-color-text);
  font: var(--kl-font-meta); cursor: default; outline: 0;
  transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-runrow + .kl-runrow::before { content: ""; position: absolute; left: 36px; right: 10px; top: 0; height: 1px; background: var(--kl-color-line); }
.kl-runrow__dot { display: flex; align-items: center; justify-content: center; align-self: stretch; }
.kl-runrow__main { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.kl-runrow__head { display: flex; align-items: center; gap: 6px; min-width: 0; }
.kl-runrow__project { display: inline-flex; align-items: center; gap: 5px; flex: none; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-runrow__title { margin: 0; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-runrow__status { margin: 0; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: var(--kl-color-text-secondary); }
.kl-runrow__chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 3px; min-width: 0; }
.kl-runrow__side { display: flex; flex-direction: column; align-items: flex-end; justify-content: center; gap: 6px; align-self: stretch; }
.kl-runrow__time { font: var(--kl-font-caption); color: var(--kl-color-text-tertiary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.kl-runrow__acts { display: flex; gap: 6px; }
.kl-runrow__ask { grid-column: 2 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; padding: 8px 10px;
  border-radius: var(--kl-radius-row); background: var(--kl-color-status-approval-soft); color: var(--kl-color-text); }
.kl-runrow__ask p { flex: 1 1 160px; margin: 0; min-width: 0; font: var(--kl-font-caption); }
.kl-runrow__ask .kl-rn-code { background: var(--kl-color-surface); }

.kl-runrow:hover, .kl-runrow.is-hover { background: var(--kl-color-control-fill); }
.kl-runrow:focus-visible, .kl-runrow.is-focus { box-shadow: var(--kl-shadow-ring-focus); }
.kl-runrow.is-selected, .kl-runrow[aria-selected="true"] { background: transparent; box-shadow: inset 0 0 0 2px var(--kl-color-selection); }
.kl-runrow.is-selected::before, .kl-runrow.is-selected + .kl-runrow::before { opacity: 0; }
.kl-runrow__check { position: absolute; right: -6px; top: -6px; }

/* States: the row only changes its dot, its status word and its actions */
.kl-runrow.is-done .kl-runrow__title, .kl-runrow.is-queued .kl-runrow__title { color: var(--kl-color-text-secondary); }
.kl-runrow.is-paused .kl-runrow__status { color: var(--kl-color-text-secondary); }
.kl-runrow.is-retrying .kl-runrow__count { font-variant-numeric: tabular-nums; }

/* Compact form for a card's expanded stage: no side column, smaller padding */
.kl-runrow--card { grid-template-columns: 18px minmax(0, 1fr) auto; padding: 8px 4px; }
.kl-runrow--card + .kl-runrow--card::before { left: 26px; right: 4px; }

/* -------------------------------------------------------------------------------------------------
   4. Runs window  .kl-win--runs  (480 wide, opaque, opens beside the card or section that opened it)
   ------------------------------------------------------------------------------------------------- */
.kl-win--runs { --kl-win-w: 480px; }
.kl-runs__tools { display: flex; flex-direction: column; gap: 10px; padding: 4px 16px 10px; border-bottom: 1px solid var(--kl-color-line); }
.kl-runs__toolrow { display: flex; align-items: center; gap: 8px; min-width: 0; }
.kl-runs__toolrow .kl-search { flex: 1 1 auto; min-width: 0; --kl-search-w: 100%; }
.kl-runs__filter { display: flex; max-width: 100%; overflow-x: auto; scrollbar-width: none; }
.kl-runs__filter .kl-seg { flex: 1 1 auto; }
.kl-runs__filter .kl-seg__item { flex: 1 1 auto; gap: 0; padding: 0 8px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.kl-runs__filter .kl-seg__n { margin-left: 5px; color: var(--kl-color-text-secondary); }
.kl-runs__filter .kl-seg__n--you { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: var(--kl-radius-pill); background: var(--kl-color-status-approval); color: var(--kl-color-text-on-fill); font: var(--kl-font-badge); }
.kl-runs__runners { display: flex; flex-wrap: wrap; gap: 6px 14px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-runs__runner { display: inline-flex; align-items: center; gap: 6px; }
.kl-runs__runner .kl-dot { --kl-dot-size: 7px; width: 7px; height: 7px; }
.kl-runs__runner .kl-icon { width: 13px; height: 13px; }
.kl-runs__list { display: flex; flex-direction: column; gap: 4px; padding: 6px 10px 12px; }
.kl-runs__group { display: flex; flex-direction: column; }
.kl-runs__group + .kl-runs__group { margin-top: 8px; }
.kl-runs__grouphead { display: flex; align-items: baseline; gap: 6px; margin: 0; padding: 8px 6px 4px; font: var(--kl-font-caption); font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text-secondary); }
.kl-runs__grouphead span { font-weight: var(--kl-font-weight-regular); font-variant-numeric: tabular-nums; }
.kl-runs__empty { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 40px 24px 44px; text-align: center; color: var(--kl-color-text-secondary); }
.kl-runs__empty .kl-icon { width: 24px; height: 24px; color: var(--kl-color-text-tertiary); }
.kl-runs__empty b { font: var(--kl-font-label-strong); color: var(--kl-color-text); }

/* -------------------------------------------------------------------------------------------------
   5. Environment picker: a .kl-menu with one row per place. Opens from the env chip or the prompter.
   ------------------------------------------------------------------------------------------------- */
.kl-envpick { --kl-menu-w: 280px; }
.kl-envpick .kl-menu__item { align-items: flex-start; padding-top: 7px; padding-bottom: 7px; }
.kl-envpick .kl-menu__item > .kl-icon { width: 16px; height: 16px; flex: none; margin-top: 1px; color: var(--kl-color-text-secondary); }
.kl-envpick .kl-menu__check { margin-top: 3px; }
.kl-envpick .kl-menu__text { white-space: normal; }
.kl-envpick__why { display: block; margin-top: 2px; font: var(--kl-font-caption); color: var(--kl-color-status-stopped-ink); }
.kl-envpick .kl-menu__item:disabled .kl-envpick__why { opacity: 1; }

/* -------------------------------------------------------------------------------------------------
   6. Environment panel  .kl-win--env  (440 wide). Built from v2 setting groups.
   ------------------------------------------------------------------------------------------------- */
.kl-win--env { --kl-win-w: 440px; }
.kl-env__body { display: flex; flex-direction: column; gap: 18px; padding: 8px 16px 16px; }
.kl-env__mono { font-family: var(--kl-font-mono); font-size: var(--kl-font-caption-size); }
.kl-env__hosts { display: flex; flex-wrap: wrap; gap: 6px; padding: 10px 12px; }
.kl-env__hosts .kl-chip { font-family: var(--kl-font-mono); font-size: var(--kl-font-caption-size); height: 26px; }
.kl-env__add { display: flex; gap: 6px; padding: 0 12px 10px; }
.kl-env__add .kl-field { flex: 1 1 auto; min-width: 0; font-family: var(--kl-font-mono); }
.kl-env__secret { display: inline-flex; align-items: center; gap: 6px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-env__warn { color: var(--kl-color-status-stopped-ink) !important; }
.kl-env__sandbox-off .kl-setting__label { color: var(--kl-color-status-stopped-ink); }

/* -------------------------------------------------------------------------------------------------
   7. Runner status  .kl-runner  (a tool card, 248 × 64) and its popover
   ------------------------------------------------------------------------------------------------- */
.kl-runner { --kl-tool-tile: 36px; --kl-tool-glass: var(--kl-glass-card-graphite, var(--kl-glass-card)); width: 248px; min-height: 64px; }
.kl-runner .kl-tool__tile { position: relative; display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 10px;
  background: var(--kl-color-control-fill); color: var(--kl-color-text); }
.kl-runner .kl-tool__tile .kl-icon { width: 20px; height: 20px; }
.kl-runner__dot { position: absolute; right: -3px; bottom: -3px; box-shadow: 0 0 0 2px var(--kl-color-surface); }
.kl-runner.is-offline .kl-tool__name { color: var(--kl-color-text-secondary); }
.kl-runner.is-offline .kl-tool__tile { color: var(--kl-color-text-secondary); }
.kl-runner__slots { display: flex; gap: 3px; margin-left: auto; }
.kl-runner__slots i { width: 6px; height: 12px; border-radius: 2px; background: var(--kl-color-control-fill-pressed); }
.kl-runner__slots i.is-on { background: var(--kl-color-control); }

.kl-runner-pop { width: 320px; max-width: 100%; display: flex; flex-direction: column; overflow: hidden;
  border-radius: var(--kl-radius-menu); background: var(--kl-color-surface); color: var(--kl-color-text); box-shadow: var(--kl-shadow-menu); font: var(--kl-font-meta); }
.kl-runner-pop__head { display: flex; align-items: center; gap: 10px; padding: 12px 14px 10px; }
.kl-runner-pop__head .kl-icon { width: 20px; height: 20px; }
.kl-runner-pop__head b { font: var(--kl-font-label-strong); display: block; }
.kl-runner-pop__head span { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-runner-pop__meter { display: flex; align-items: center; gap: 10px; padding: 0 14px 12px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-runner-pop__meter .kl-runner__slots { margin-left: 0; }
.kl-runner-pop__meter b { margin-left: auto; font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text); }
.kl-runner-pop__list { display: flex; flex-direction: column; padding: 4px 8px 8px; border-top: 1px solid var(--kl-color-line); }
.kl-runner-pop__foot { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 10px 14px; border-top: 1px solid var(--kl-color-line); font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }

/* -------------------------------------------------------------------------------------------------
   8. Background tray  .kl-tray  (opaque popover from the tray chip, 340 wide)
   ------------------------------------------------------------------------------------------------- */
.kl-tray { width: 340px; max-width: 100%; display: flex; flex-direction: column; overflow: hidden;
  border-radius: var(--kl-radius-menu); background: var(--kl-color-surface); color: var(--kl-color-text); box-shadow: var(--kl-shadow-menu); font: var(--kl-font-meta); }
.kl-tray__head { display: flex; align-items: center; gap: 8px; padding: 12px 14px 8px; font: var(--kl-font-label-strong); }
.kl-tray__head span { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); margin-left: auto; }
.kl-tray__job { display: flex; flex-direction: column; gap: 6px; padding: 10px 14px 12px; border-top: 1px solid var(--kl-color-line); }
.kl-tray__top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.kl-tray__name { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.kl-tray__name b { font: var(--kl-font-label-strong); }
.kl-tray__cmd { font-family: var(--kl-font-mono); font-size: var(--kl-font-caption-size); color: var(--kl-color-text-secondary); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-tray__time { font: var(--kl-font-caption); color: var(--kl-color-text-tertiary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.kl-tray__tail { margin: 0; padding: 7px 9px; border-radius: 8px; background: var(--kl-color-surface-sunken); color: var(--kl-color-text-secondary);
  font: var(--kl-font-caption); font-family: var(--kl-font-mono); line-height: 16px; white-space: pre; overflow: hidden; text-overflow: ellipsis; }
.kl-tray__tail b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-regular); }
.kl-tray__acts { display: flex; align-items: center; gap: 6px; }
.kl-tray__acts .kl-tray__port { margin-right: auto; font: var(--kl-font-caption); font-family: var(--kl-font-mono); color: var(--kl-color-link); }
.kl-tray__job.is-stopped .kl-tray__name b { color: var(--kl-color-text-secondary); }
.kl-tray__job.is-stopped .kl-tray__tail { opacity: .7; }
.kl-tray__empty { padding: 4px 14px 16px; color: var(--kl-color-text-secondary); font: var(--kl-font-caption); }

/* -------------------------------------------------------------------------------------------------
   9. Runs section card .kl-section--runs: v2's section card shell (212 x 72, .kl-tool.kl-section) with the runs icon.
      The meta line is the quick summary. Runs waiting on Alban put a magenta count on it; clicking opens .kl-win--runs.
      Its glass is Foundations' --kl-glass-card-runs (graphite); the count is Board's .kl-countbadge--approval.
   ------------------------------------------------------------------------------------------------- */
.kl-section--runs { --kl-tool-glass: var(--kl-glass-card-runs); }
.kl-section--runs .kl-tool__meta b { font-weight: var(--kl-font-weight-semibold); }
.kl-section--runs .kl-rn-you { color: var(--kl-color-status-approval-ink); }
/* Something waits on Alban: a magenta edge and tile, like Board's asking card. Still: the asking project cards already carry the rays */
.kl-section--runs.is-asking:not(.is-open) { border-color: var(--kl-color-status-approval); box-shadow: 0 0 0 1px var(--kl-color-status-approval), var(--kl-glass-card-shadow); }
/* Like v2's Alerts, the meta may wrap to a second line while something waits on Alban */
.kl-section--runs.is-asking .kl-tool__meta { white-space: normal; }
.kl-section--runs .kl-tool__meta > :is(b, span) { white-space: nowrap; }   /* wrap between the parts, never inside one */
.kl-section--runs.is-asking:not(.is-open) .kl-tool__tile { background: var(--kl-color-status-approval-soft); color: var(--kl-color-status-approval-ink); }
/* The count of runs waiting on Alban (approvals, questions and stopped runs) is Board's .kl-countbadge--approval */
/* Scoped to one project (the card is linked to it): the project's mark leads the meta line */
.kl-section--runs .kl-rn-mark { margin-right: 6px; vertical-align: 0; }

/* The quick summary peek: hover the card (after a short wait) or focus it. Opaque, since you read it. Never opens
   while Alban drags, links or types, and not while the Runs window is open */
.kl-runs-peek { width: 288px; max-width: 100%; display: flex; flex-direction: column; overflow: hidden;
  border-radius: var(--kl-radius-menu); background: var(--kl-color-surface); color: var(--kl-color-text); box-shadow: var(--kl-shadow-menu); font: var(--kl-font-meta); }
.kl-runs-peek__head { display: flex; align-items: center; gap: 8px; padding: 12px 14px 6px; }
.kl-runs-peek__head .kl-icon { width: 16px; height: 16px; color: var(--kl-color-text-secondary); }
.kl-runs-peek__head b { font: var(--kl-font-label-strong); }
.kl-runs-peek__head span { margin-left: auto; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-runs-peek__groups { list-style: none; margin: 0; padding: 4px 14px 8px; display: grid; grid-template-columns: 1fr 1fr; gap: 4px 14px; }
.kl-runs-peek__groups li { display: flex; align-items: center; gap: 7px; min-width: 0; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-runs-peek__groups li b { margin-left: auto; font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text); font-variant-numeric: tabular-nums; }
.kl-runs-peek__groups .kl-dot { width: 8px; height: 8px; }
.kl-runs-peek__rows { display: flex; flex-direction: column; margin: 0 6px; padding-top: 2px; border-top: 1px solid var(--kl-color-line); }
.kl-runs-peek__foot { margin: 0; padding: 8px 14px 12px; font: var(--kl-font-caption); color: var(--kl-color-text-tertiary); }

/* -------------------------------------------------------------------------------------------------
   10. When a project's runs disagree. The card's dot shows the run that matters most (the order is in the README):
       waiting on you, stopped, retrying, working, planning, ready for review, paused, queued, done.
       A run tally .kl-runtally leads the status line at full and expanded stages when the runs are in more than one state:
       one small still pip per run in the same order, at most five, then "+n". Name-only and compact show the dot alone.
   ------------------------------------------------------------------------------------------------- */
.kl-runtally { display: inline-flex; align-items: center; gap: 3px; margin-right: 7px; vertical-align: 0; }
.kl-runtally .kl-dot { width: 6px; height: 6px; }
.kl-runtally .kl-dot--review { box-shadow: inset 0 0 0 1.5px var(--kl-dot), inset 0 0 0 3px color-mix(in srgb, var(--kl-dot) 55%, transparent); }
.kl-runtally .kl-dot--queued, .kl-runtally .kl-dot--paused { box-shadow: inset 0 0 0 1.2px var(--kl-color-status-idle); }
.kl-runtally__more { font: var(--kl-font-caption); font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-card__status .kl-runtally { margin-top: -1px; }
.kl-card[data-stage="0"] .kl-runtally, .kl-card[data-stage="1"] .kl-runtally { display: none; }
/* A project whose winning run is done: the dot is grey and the name stays, nothing moves */
.kl-card.is-done .kl-card__status { color: var(--kl-color-text-secondary); }

/* -------------------------------------------------------------------------------------------------
   11. Motion. Every timing is a --kl-motion-* token; springs scale with the dial (--kl-motion-k) through
      the v2 spring curves. Nothing here loops except the waiting-on-you dot ring, which is a signal.
   ------------------------------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  /* A row arriving in a new group: rises 6 px and fades in */
  .kl-runrow.kl-rn-arrive { animation: kl-rn-arrive var(--kl-motion-reveal) var(--kl-motion-ease-out) both; }
  /* The dot changing state: Motion's dot pop, plus a colour glide */
  .kl-runrow__dot .kl-dot, .kl-card__name .kl-dot, .kl-section--runs .kl-tool__tile { transition: background-color var(--kl-motion-dot-colour) var(--kl-motion-ease-out), box-shadow var(--kl-motion-dot-colour) var(--kl-motion-ease-out); }
  /* Popovers open like v2 menus */
  .kl-tray.kl-rn-open, .kl-runner-pop.kl-rn-open, .kl-envpick.kl-rn-open, .kl-runs-peek.kl-rn-open { animation: kl-menu-in var(--kl-motion-menu-in) var(--kl-motion-spring-pop) both; }
  /* Ask strip in an approval row: slides open on ease-out, no bounce (it is something you read) */
  .kl-runrow__ask.kl-rn-open { animation: kl-rn-arrive var(--kl-motion-reveal) var(--kl-motion-ease-out) both; }
}
@keyframes kl-rn-arrive { from { opacity: 0; transform: translateY(var(--kl-motion-reveal-shift, 6px)); } to { opacity: 1; transform: none; } }
.kl-motion-reduce .kl-runrow.kl-rn-arrive, .kl-motion-reduce .kl-rn-open { animation: kl-rn-fade var(--kl-motion-fade) linear both !important; }
@keyframes kl-rn-fade { from { opacity: 0; } to { opacity: 1; } }

/* ===== harness/agents/agents.css ===== */
/* =====================================================================================================
   Klippan master · harness/agents: task checklist, subagent rows and fan-out, workflow view, agent message tag.
   Builds on klippan-v2/combined/klippan.css (load it first) and never restyles a v2 class's colours.
   Only --kl-* tokens; the literals below are this part's own sizes, kept as local custom properties on each block.
   Every duration and curve is a --kl-motion-* token; every overshoot comes from the dial-written springs or the
   dial-scaled v2 keyframes (kl-land, kl-dot-pop, kl-count-bump, kl-fly). Reduced motion: instant, or a fade of 120 ms or less.
   Uses v2's shared pieces: .kl-m-fly / .kl-m-fly--land and KlMotion.fly (travel), .kl-link-group / .kl-link-rider
   (a tag riding a line), .kl-win--wide (the 880 window) and the --kl-z-* stacking scale.
   ===================================================================================================== */

/* Shared: tabular figures for every count and token number in this part */
.kl-tasks, .kl-card__progress, .kl-sub-list, .kl-fanout, .kl-flow, .kl-flow-mini, .kl-msgtag { font-variant-numeric: tabular-nums; }
/* A state change made while Alban is busy (KlMotion.userBusy()): put .kl-agents-still on the changed block for one
   frame and it lands with no motion (status dots keep breathing; they are signals) */
.kl-agents-still :is(.kl-tasks__mark, .kl-tasks__text, .kl-tasks__bar > i, .kl-sub__kind, .kl-sub__task, .kl-sub__tile,
  .kl-fanout__dots > i, .kl-flow-mini__dots > i, .kl-flow__node) { transition: none !important; }

/* =====================================================================================================
   1. Task checklist .kl-tasks: the agent's own to-do list. In an expanded card's .kl-card__more (above the agent
      list) or as the opaque .kl-tasks--block in the transcript. Items take data-state done|doing|todo|blocked|skipped.
   ===================================================================================================== */
.kl-tasks {
  --kl-tasks-mark: 16px;         /* the round mark */
  --kl-tasks-mark-y: 1px;        /* sits on the first line of a 13/18 row */
  --kl-tasks-row: 26px;          /* one-line row */
  --kl-tasks-pad: 4px;
  --kl-tasks-ring: 1.5px;
  --kl-tasks-core: 6px;          /* the breathing centre of the doing mark */
  --kl-tasks-bar: 4px;           /* progress track */
  --kl-tasks-fold-h: 24px;
  --kl-tasks-done: 0%;           /* progress fill, set per list */
  display: flex; flex-direction: column; gap: var(--kl-space-1);
  min-width: 0; margin: 0;
  font: var(--kl-font-meta); color: var(--kl-color-text);
}
.kl-tasks [hidden], .kl-fanout[hidden], .kl-msgtag[hidden], .kl-flow__results[hidden], .kl-flow__note[hidden], .kl-flow-win [hidden] { display: none !important; }
.kl-tasks__head {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center;
  column-gap: var(--kl-space-2); row-gap: var(--kl-space-2); padding-bottom: var(--kl-space-half);
}
.kl-tasks__head > .kl-icon { --kl-icon-size: 14px; color: var(--kl-color-text-secondary); }
.kl-tasks__label { font: var(--kl-font-meta); font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text); }
.kl-tasks__count { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); white-space: nowrap; }
.kl-tasks__count .kl-m-roll { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }
.kl-tasks__bar {
  grid-column: 1 / -1; height: var(--kl-tasks-bar, 4px); min-width: 0;
  border-radius: var(--kl-radius-pill); background: var(--kl-color-switch-off); overflow: hidden;
}
.kl-tasks__bar > i { display: block; height: 100%; width: var(--kl-tasks-done, 0%); border-radius: inherit; background: var(--kl-color-control); }

.kl-tasks__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.kl-tasks__item {
  display: grid; grid-template-columns: var(--kl-tasks-mark) minmax(0, 1fr) auto; align-items: start;
  column-gap: var(--kl-space-2); min-height: var(--kl-tasks-row); padding: var(--kl-tasks-pad) 0; box-sizing: border-box;
}
.kl-tasks__mark {
  position: relative; display: grid; place-items: center; box-sizing: border-box;
  width: var(--kl-tasks-mark); height: var(--kl-tasks-mark); margin-top: var(--kl-tasks-mark-y);
  border-radius: var(--kl-radius-round); color: var(--kl-color-text-on-fill);
  box-shadow: inset 0 0 0 var(--kl-tasks-ring) var(--kl-color-line-strong);   /* todo: a hollow grey ring */
}
.kl-tasks__mark .kl-icon { --kl-icon-size: 10px; --kl-icon-stroke: 2.4; }
.kl-tasks__core { width: var(--kl-tasks-core); height: var(--kl-tasks-core); border-radius: var(--kl-radius-round); background: currentColor; color: var(--kl-color-status-executing); }
.kl-tasks__text { min-width: 0; color: var(--kl-color-text); overflow-wrap: anywhere; }
.kl-tasks__why { display: block; font: var(--kl-font-caption); font-weight: var(--kl-font-weight-semibold); color: var(--kl-card-approval-ink); margin-top: var(--kl-space-half); }
.kl-tasks__who { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); white-space: nowrap; margin-top: var(--kl-tasks-mark-y); line-height: var(--kl-tasks-mark); }

/* done: control-blue filled circle with a white check; text secondary, never struck through */
.kl-tasks__item[data-state="done"] .kl-tasks__mark { background: var(--kl-color-control); box-shadow: none; }
.kl-tasks__item[data-state="done"] .kl-tasks__text { color: var(--kl-color-text-secondary); }
/* doing: executing-green ring with a breathing centre (kl-m-dot kl-m-dot--executing on .kl-tasks__core); text semibold */
.kl-tasks__item[data-state="doing"] .kl-tasks__mark { box-shadow: inset 0 0 0 var(--kl-tasks-ring) var(--kl-color-status-executing); }
.kl-tasks__item[data-state="doing"] .kl-tasks__text { font-weight: var(--kl-font-weight-semibold); }
/* blocked on Alban: the approval (magenta) mark and a "Needs you" reason, as v2's .is-asking; red stays for stopped and failed */
.kl-tasks__item[data-state="blocked"] .kl-tasks__mark { background: var(--kl-card-approval); box-shadow: none; }
/* skipped: a grey dash, text secondary */
.kl-tasks__item[data-state="skipped"] .kl-tasks__mark { box-shadow: none; color: var(--kl-color-text-secondary); }
.kl-tasks__item[data-state="skipped"] .kl-tasks__mark .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
.kl-tasks__item[data-state="skipped"] .kl-tasks__text { color: var(--kl-color-text-secondary); }

/* Fold rows: "4 done" before the doing item, "+3 more" after the next two todo items. Max 6 rows in a card. */
.kl-tasks__fold {
  position: relative; display: grid; grid-template-columns: var(--kl-tasks-mark) auto; align-items: center; column-gap: var(--kl-space-2);
  width: fit-content; min-height: var(--kl-tasks-fold-h); margin: 0; padding: 0 var(--kl-space-2) 0 0; border: 0;
  border-radius: var(--kl-radius-row); background: transparent; cursor: pointer;
  font: var(--kl-font-caption); font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text-secondary);
}
.kl-tasks__fold::before { content: ""; position: absolute; inset: calc((var(--kl-tasks-fold-h) - var(--kl-size-target)) / 2) 0; }
.kl-tasks__fold:hover, .kl-tasks__fold.is-hover { color: var(--kl-color-text); background: var(--kl-color-control-fill); }
.kl-tasks__fold:focus-visible, .kl-tasks__fold.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 1px; }
.kl-tasks__fold .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; justify-self: center; }
.kl-tasks__fold[aria-expanded="true"] .kl-icon { rotate: 90deg; }

/* Transcript: the same list as an opaque block */
.kl-tasks--block {
  --kl-tasks-block-w: 360px;
  width: var(--kl-tasks-block-w); max-width: 100%; box-sizing: border-box;
  padding: var(--kl-space-3) var(--kl-space-4);
  border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface);
  box-shadow: 0 0 0 1px var(--kl-color-line);
}

/* Full stage (data-stage 2) shows the progress only, under the status line; name only, compact and expanded do not */
.kl-card__progress {
  --kl-tasks-bar: 4px;
  display: flex; align-items: center; gap: var(--kl-space-2); min-width: 0;
  font: var(--kl-font-caption); color: var(--kl-color-text-secondary); white-space: nowrap;
  opacity: var(--kl-ol); padding-right: var(--kl-space-6);
}
.kl-card__progress .kl-tasks__bar { flex: 1 1 auto; }
.kl-card__progress { flex: none; }
.kl-card__status:has(+ .kl-card__progress) { -webkit-line-clamp: 1; }   /* the progress takes the second status line's room */
.kl-card[data-stage="0"] .kl-card__progress, .kl-card[data-stage="1"] .kl-card__progress, .kl-card[data-stage="3"] .kl-card__progress { display: none; }

/* =====================================================================================================
   2. Subagents. Short-lived agents an agent starts with their own context; they live and die inside their parent's
      row. .kl-sub-list hangs off a parent .kl-agent-row on a hairline tree rail; .kl-sub rows take
      data-state running|done|failed|stopped|queued. .kl-fanout is the count pill on the parent row.
   ===================================================================================================== */
.kl-sub-list, .kl-sub-list__rows {
  --kl-sub-h: 28px;          /* row height (28 to 32) */
  --kl-sub-indent: 18px;     /* rows sit this far in from the parent row */
  --kl-sub-rail: 7px;        /* the rail's x inside the indent */
  --kl-sub-tick: 6px;        /* gap between the tick and the tile */
  --kl-sub-tile: 20px;
  --kl-sub-state: 16px;
  --kl-sub-dot: 8px;
  list-style: none; margin: 0; padding: 0 0 var(--kl-space-1) var(--kl-sub-indent);
}
.kl-agent-list > .kl-sub-list { border-bottom: 1px solid var(--kl-color-line); padding-bottom: var(--kl-space-half); }
.kl-agent-row:has(+ .kl-sub-list) { border-bottom-color: transparent; padding-bottom: var(--kl-space-1); }
.kl-sub-list.is-folded { display: none; }
.kl-sub {
  position: relative; display: grid; align-items: center; column-gap: var(--kl-space-2);
  grid-template-columns: var(--kl-sub-tile) auto minmax(0, 1fr) auto var(--kl-sub-state);
  height: var(--kl-sub-h); font: var(--kl-font-caption); color: var(--kl-color-text);
}
/* The tree rail: one segment per row, a tick to each tile; the last row's segment stops at its tick */
.kl-sub::before, .kl-sub::after { content: ""; position: absolute; left: calc(var(--kl-sub-rail) - var(--kl-sub-indent)); pointer-events: none; }
.kl-sub::after { top: 0; bottom: 0; border-left: 1px solid var(--kl-color-line-strong); }
.kl-sub:first-child::after { top: calc(-1 * var(--kl-space-1)); }
.kl-sub:last-child::after { bottom: 50%; }
.kl-sub::before { top: 50%; width: calc(var(--kl-sub-indent) - var(--kl-sub-rail) - var(--kl-sub-tick)); border-top: 1px solid var(--kl-color-line-strong); }
.kl-sub__tile {
  display: grid; place-items: center; width: var(--kl-sub-tile); height: var(--kl-sub-tile);
  border-radius: var(--kl-radius-control); background: var(--kl-color-neutral-soft); color: var(--kl-color-neutral-ink);
}
.kl-sub__tile .kl-icon { --kl-icon-size: 14px; }
.kl-sub__kind { font-weight: var(--kl-font-weight-semibold); white-space: nowrap; }
.kl-sub__task { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: var(--kl-color-text-secondary); }
.kl-sub__tok { white-space: nowrap; color: var(--kl-color-text-secondary); }
.kl-sub__state { display: grid; place-items: center; width: var(--kl-sub-state); height: var(--kl-sub-state); }
.kl-sub__state .kl-icon { --kl-icon-size: 14px; --kl-icon-stroke: 2; }
.kl-sub__dot { width: var(--kl-sub-dot); height: var(--kl-sub-dot); border-radius: var(--kl-radius-round); background: currentColor; color: var(--kl-color-status-executing); }
.kl-sub__retry { margin-right: calc(-1 * var(--kl-space-1)); }
/* running: green breathing dot (kl-m-dot kl-m-dot--executing on .kl-sub__dot) */
/* done: control check; the task cell holds the one-line result */
.kl-sub[data-state="done"] .kl-sub__state { color: var(--kl-color-control); }
.kl-sub[data-state="done"] .kl-sub__task { color: var(--kl-color-text); }
/* failed: red failed icon, the reason, a quiet Retry */
.kl-sub[data-state="failed"] .kl-sub__state { color: var(--kl-color-status-stopped); }
.kl-sub[data-state="failed"] .kl-sub__task { color: var(--kl-color-status-stopped-ink); }
/* stopped: a still red dot */
.kl-sub[data-state="stopped"] .kl-sub__dot { color: var(--kl-color-status-stopped); }
/* queued: the queue icon in grey, not started */
.kl-sub[data-state="queued"] .kl-sub__state { color: var(--kl-color-text-secondary); }
.kl-sub[data-state="queued"] .kl-sub__kind { color: var(--kl-color-text-secondary); }
/* Back: its result has landed on the parent; the row goes quiet */
.kl-sub.is-back .kl-sub__kind, .kl-sub.is-back .kl-sub__task { color: var(--kl-color-text-secondary); }
.kl-sub.is-back .kl-sub__tile { background: transparent; color: var(--kl-color-text-secondary); box-shadow: inset 0 0 0 1px var(--kl-color-line); }

/* The result landing back on the parent: a chip in the parent row's activity line */
.kl-sub__result {
  --kl-sub-result-h: 20px;
  display: inline-flex; align-items: center; gap: var(--kl-space-1); vertical-align: middle;
  height: var(--kl-sub-result-h); max-width: 100%; box-sizing: border-box; margin-right: var(--kl-space-1);
  padding: 0 var(--kl-space-2) 0 var(--kl-space-1); border-radius: var(--kl-radius-pill);
  background: var(--kl-color-surface); box-shadow: 0 0 0 1px var(--kl-color-line);
  font: var(--kl-font-caption); font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text);
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
/* While a result lands (v2 .kl-m-fly.kl-m-fly--land, played by KlMotion.fly), the activity line lets it fly in from below */
.kl-agent-row__act:has(.kl-sub__result.kl-m-fly) { overflow: visible; }
.kl-sub__result .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; color: var(--kl-color-control); flex: none; }
.kl-sub__result small { font: inherit; font-weight: var(--kl-font-weight-medium); color: var(--kl-color-text-secondary); }

/* Fan-out count on the parent row: fork + number + one dot per subagent (up to 8, then +n). Folds the sub-list. */
.kl-fanout {
  --kl-fanout-h: 22px;
  --kl-fanout-dot: 6px;
  --kl-fanout-gap: 3px;
  position: relative; display: inline-flex; align-items: center; gap: var(--kl-space-1);
  height: var(--kl-fanout-h); margin: 0; padding: 0 var(--kl-space-2) 0 var(--kl-space-1); border: 0;
  border-radius: var(--kl-radius-pill); background: var(--kl-color-control-fill); color: var(--kl-color-text);
  font: var(--kl-font-badge); cursor: pointer;
}
.kl-fanout::before { content: ""; position: absolute; inset: calc((var(--kl-fanout-h) - var(--kl-size-target)) / 2) 0; }
.kl-fanout:hover, .kl-fanout.is-hover { background: var(--kl-color-control-fill-pressed); }
.kl-fanout:focus-visible, .kl-fanout.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-fanout > .kl-icon { --kl-icon-size: 14px; color: var(--kl-color-text-secondary); }
.kl-fanout__n { display: inline-block; min-width: 1ch; text-align: center; }
.kl-fanout__dots { display: inline-flex; align-items: center; gap: var(--kl-fanout-gap); margin-left: var(--kl-space-half); }
.kl-fanout__dots > i { width: var(--kl-fanout-dot); height: var(--kl-fanout-dot); border-radius: var(--kl-radius-round); background: var(--kl-color-status-executing); }
.kl-fanout__dots > i[data-state="done"] { background: var(--kl-color-control); }
.kl-fanout__dots > i[data-state="failed"], .kl-fanout__dots > i[data-state="stopped"] { background: var(--kl-color-status-stopped); }
.kl-fanout__dots > i[data-state="queued"] { background: transparent; box-shadow: inset 0 0 0 1px var(--kl-color-text-secondary); }
.kl-fanout__more { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); margin-left: var(--kl-space-half); }
.kl-fanout__chev { --kl-icon-size: 10px !important; --kl-icon-stroke: 2.2; color: var(--kl-color-text-secondary); }
.kl-fanout[aria-expanded="true"] .kl-fanout__chev { rotate: 180deg; }
.kl-agent-row__meta .kl-fanout { margin-right: var(--kl-space-half); }

/* Transcript: the sub-list as an opaque block with its own head */
.kl-sub-list--block {
  --kl-sub-block-w: 400px;
  width: var(--kl-sub-block-w); max-width: 100%; box-sizing: border-box; padding: var(--kl-space-3) var(--kl-space-4) var(--kl-space-2);
  border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface); box-shadow: 0 0 0 1px var(--kl-color-line);
}
.kl-sub-list__head { display: flex; align-items: center; gap: var(--kl-space-2); padding-bottom: var(--kl-space-1); font: var(--kl-font-meta); }
.kl-sub-list__head > .kl-icon { --kl-icon-size: 16px; color: var(--kl-color-text-secondary); }
.kl-sub-list__head b { font-weight: var(--kl-font-weight-semibold); }
.kl-sub-list__head span { color: var(--kl-color-text-secondary); }
.kl-sub-list__head .kl-sub-list__sum { margin-left: auto; font: var(--kl-font-caption); white-space: nowrap; }

/* =====================================================================================================
   3. Workflow view. One job run as phases by many agents, with a check (gate) between phases.
      Window: .kl-win.kl-win--wide.kl-flow-win (opaque, v2's one wide size, 880). Body: .kl-flow > .kl-flow__phase + .kl-flow__gate, repeated.
      Phases take data-state done|running|waiting; gates waiting|passing|passed|failed; chips running|done|failed.
      On the card: .kl-flow-mini, one row of phase segments.
   ===================================================================================================== */
.kl-flow-win .kl-win__body { padding: var(--kl-space-3); }
.kl-flow {
  --kl-flow-gate: 28px;        /* the gap a gate sits in */
  --kl-flow-node: 16px;        /* the gate's round node */
  --kl-flow-head: 24px;        /* phase head height */
  --kl-flow-chip: 30px;        /* chip height */
  --kl-flow-ring: 1.5px;
  --kl-flow-min-h: 200px;
  --kl-flow-why-w: 196px;
  --kl-flow-dot: 8px;          /* running dot in a phase head */
  --kl-flow-hollow: 10px;      /* waiting ring in a phase head */
  --kl-flow-state: 14px;       /* chip and result state column */
  --kl-flow-chip-dot: 7px;
  --kl-flow-fill-inset: 3px;   /* the passing gate's green fill */
  --kl-flow-result-h: 26px;
  --kl-flow-menu-w: 176px;
  display: flex; align-items: stretch; min-height: var(--kl-flow-min-h);
}
.kl-flow__phase {
  flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: var(--kl-space-1);
  padding: var(--kl-space-2); border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface-sunken);
  box-shadow: inset 0 0 0 1px var(--kl-color-line); container-type: inline-size;
}
.kl-flow__head { display: flex; align-items: center; gap: var(--kl-space-2); height: var(--kl-flow-head); padding: 0 var(--kl-space-1); }
.kl-flow__mark { display: grid; place-items: center; flex: none; width: var(--kl-tasks-mark, 16px); height: var(--kl-tasks-mark, 16px); }
.kl-flow__mark .kl-icon { --kl-icon-size: 14px; --kl-icon-stroke: 2; }
.kl-flow__mark i { width: var(--kl-flow-dot); height: var(--kl-flow-dot); border-radius: var(--kl-radius-round); background: currentColor; }
.kl-flow__phase[data-state="done"] .kl-flow__mark { color: var(--kl-color-control); }
.kl-flow__phase[data-state="running"] .kl-flow__mark { color: var(--kl-color-status-executing); }
.kl-flow__phase[data-state="waiting"] .kl-flow__mark i { background: transparent; box-shadow: inset 0 0 0 var(--kl-flow-ring) var(--kl-color-line-strong); width: var(--kl-flow-hollow); height: var(--kl-flow-hollow); }
.kl-flow__phase[data-state="failed"] .kl-flow__mark { color: var(--kl-color-status-stopped); }
.kl-flow__name { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font: var(--kl-font-label-strong); color: var(--kl-color-text); }
.kl-flow__phase[data-state="waiting"] .kl-flow__name { color: var(--kl-color-text-secondary); }
.kl-flow__count { flex: none; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); white-space: nowrap; }
.kl-flow__note { margin: 0; padding: 0 var(--kl-space-1); font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-flow__chips { display: flex; flex-direction: column; gap: var(--kl-space-1); min-width: 0; }
.kl-flow__chips:not(:has(> .kl-flow__chip))::before {
  content: attr(data-empty); display: grid; place-items: center; height: var(--kl-flow-chip); border-radius: var(--kl-radius-row);
  box-shadow: inset 0 0 0 1px var(--kl-color-line); font: var(--kl-font-caption); color: var(--kl-color-text-secondary);
}
.kl-flow__chips[data-empty=""]::before { display: none; }

/* Chips: one per agent. Agent icon, a short label, tokens (hidden when the column is narrow), a state */
.kl-flow__chip {
  position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto; align-items: center; column-gap: var(--kl-space-2);
  width: 100%; height: var(--kl-flow-chip); margin: 0; padding: 0 var(--kl-space-2); box-sizing: border-box; border: 0;
  border-radius: var(--kl-radius-row); background: var(--kl-color-surface); box-shadow: 0 0 0 1px var(--kl-color-line);
  font: var(--kl-font-caption); color: var(--kl-color-text); text-align: left;
}
button.kl-flow__chip { cursor: pointer; }
button.kl-flow__chip:hover { box-shadow: 0 0 0 1px var(--kl-color-line-strong); }
button.kl-flow__chip:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-flow__chip > .kl-icon { --kl-icon-size: 14px; color: var(--kl-color-text-secondary); }
.kl-flow__label { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-weight: var(--kl-font-weight-semibold); }
.kl-flow__tok { color: var(--kl-color-text-secondary); white-space: nowrap; }
.kl-flow__state { display: grid; place-items: center; width: var(--kl-flow-state); height: var(--kl-flow-state); }
.kl-flow__state .kl-icon { --kl-icon-size: 14px; --kl-icon-stroke: 2; }
.kl-flow__state i { width: var(--kl-flow-chip-dot); height: var(--kl-flow-chip-dot); border-radius: var(--kl-radius-round); background: currentColor; }
.kl-flow__chip[data-state="running"] .kl-flow__state { color: var(--kl-color-status-executing); }
.kl-flow__chip[data-state="done"] .kl-flow__state { color: var(--kl-color-control); }
.kl-flow__chip[data-state="failed"] { box-shadow: 0 0 0 1px var(--kl-color-status-stopped); }
.kl-flow__chip[data-state="failed"] .kl-flow__state { color: var(--kl-color-status-stopped); }
.kl-flow__chip[data-state="failed"] .kl-flow__tok { color: var(--kl-color-status-stopped-ink); }
.kl-flow__chip[aria-expanded="true"] { box-shadow: 0 0 0 1px var(--kl-color-status-stopped), 0 0 0 4px var(--kl-color-status-stopped-soft); }
/* Four phases in 880 leave each column about 190 wide: icon, label, tokens and state all fit. Narrower columns
   (five or six phases) drop the agent icon first, then the tokens */
@container (max-width: 150px) { .kl-flow__chip { column-gap: var(--kl-space-1); grid-template-columns: minmax(0, 1fr) auto auto; } .kl-flow__chip > .kl-icon { display: none; } }
@container (max-width: 116px) { .kl-flow__tok { display: none; } }
/* A failed chip sits in a slot with its menu (v2 .kl-menu) under it */
.kl-flow__slot { position: relative; }
.kl-flow__menu { position: absolute; left: 0; top: calc(100% + var(--kl-space-1)); z-index: var(--kl-z-menu); --kl-menu-w: var(--kl-flow-menu-w); }

/* Gate between two phases: a round node on a hairline, level with the phase heads */
.kl-flow__gate { position: relative; flex: none; width: var(--kl-flow-gate); }
.kl-flow__gate::before {
  content: ""; position: absolute; left: 0; right: 0; top: calc(var(--kl-space-2) + var(--kl-flow-head) / 2);
  border-top: 1px solid var(--kl-color-line-strong);
}
.kl-flow__node {
  position: absolute; left: 50%; top: calc(var(--kl-space-2) + var(--kl-flow-head) / 2); translate: -50% -50%;
  display: grid; place-items: center; width: var(--kl-flow-node); height: var(--kl-flow-node); margin: 0; padding: 0; border: 0;
  border-radius: var(--kl-radius-round); background: var(--kl-color-surface); color: var(--kl-color-text-on-fill);
  box-shadow: inset 0 0 0 var(--kl-flow-ring) var(--kl-color-line-strong); cursor: default;
}
.kl-flow__node::after { content: ""; position: absolute; inset: calc((var(--kl-flow-node) - var(--kl-size-target)) / 2); border-radius: 50%; }
.kl-flow__node:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-flow__node .kl-icon { --kl-icon-size: 10px; --kl-icon-stroke: 2.4; position: relative; }
.kl-flow__node::before { content: ""; position: absolute; inset: var(--kl-flow-fill-inset); border-radius: 50%; background: var(--kl-color-status-executing); scale: 0; }
.kl-flow__gate[data-state="passing"] .kl-flow__node { box-shadow: inset 0 0 0 var(--kl-flow-ring) var(--kl-color-status-executing); }
.kl-flow__gate[data-state="passing"] .kl-flow__node::before { scale: 1; }
.kl-flow__gate[data-state="passed"] .kl-flow__node { background: var(--kl-color-control); box-shadow: none; }
.kl-flow__gate[data-state="failed"] .kl-flow__node { background: var(--kl-color-status-stopped); box-shadow: none; cursor: help; }
.kl-flow__gate[data-state="passed"] .kl-flow__node::before, .kl-flow__gate[data-state="failed"] .kl-flow__node::before { display: none; }
/* The reason, on hover or keyboard focus of a failed gate (or .is-open) */
.kl-flow__why {
  position: absolute; left: calc(50% - var(--kl-flow-node)); top: calc(var(--kl-space-2) + var(--kl-flow-head) / 2 + var(--kl-flow-node)); z-index: var(--kl-z-bubble);
  width: var(--kl-flow-why-w); box-sizing: border-box; padding: var(--kl-space-2) var(--kl-space-3); margin: 0;
  border-radius: var(--kl-radius-menu); background: var(--kl-color-surface); box-shadow: var(--kl-shadow-menu), 0 0 0 1px var(--kl-color-notice-edge-alert);
  font: var(--kl-font-caption); color: var(--kl-color-text); pointer-events: none; opacity: 0; visibility: hidden;
}
.kl-flow__why b { display: block; color: var(--kl-color-status-stopped-ink); font-weight: var(--kl-font-weight-semibold); margin-bottom: var(--kl-space-half); }
.kl-flow__gate:hover .kl-flow__why, .kl-flow__gate:focus-within .kl-flow__why, .kl-flow__gate.is-open .kl-flow__why { opacity: 1; visibility: visible; }

/* Results in the Verify column: confirmed and rejected findings, each a row you can open */
.kl-flow__results { display: flex; flex-direction: column; margin-top: var(--kl-space-1); padding-top: var(--kl-space-1); border-top: 1px solid var(--kl-color-line); }
.kl-flow__sum { padding: var(--kl-space-1); font: var(--kl-font-caption); color: var(--kl-color-text-secondary); white-space: nowrap; }
.kl-flow__sum b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }
.kl-flow__result {
  position: relative; display: grid; grid-template-columns: var(--kl-flow-state) minmax(0, 1fr); align-items: center; column-gap: var(--kl-space-2);
  width: 100%; height: var(--kl-flow-result-h); margin: 0; padding: 0 var(--kl-space-1); border: 0; border-radius: var(--kl-radius-control);
  background: transparent; font: var(--kl-font-caption); color: var(--kl-color-text); text-align: left; cursor: pointer;
}
.kl-flow__result:hover { background: var(--kl-color-control-fill); }
.kl-flow__result:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 1px; }
.kl-flow__result .kl-icon { --kl-icon-size: 14px; --kl-icon-stroke: 2; }
.kl-flow__result span { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-flow__result[data-result="confirmed"] .kl-icon { color: var(--kl-color-control); }
.kl-flow__result[data-result="rejected"] { color: var(--kl-color-text-secondary); }
.kl-flow-win .kl-win__foot .kl-btn--primary { min-width: 72px; }

/* On the card: one row of phase segments, the current phase raised; clicking opens the window */
.kl-flow-mini {
  --kl-flow-mini-h: 30px;
  --kl-flow-mini-pad: 3px;
  --kl-flow-mini-dot: 5px;
  position: relative; display: flex; align-items: center; gap: var(--kl-space-half); width: 100%; box-sizing: border-box;
  height: var(--kl-flow-mini-h); margin: 0; padding: var(--kl-flow-mini-pad); border: 0; flex: none;
  border-radius: var(--kl-radius-row); background: var(--kl-color-control-fill); color: var(--kl-color-text-secondary);
  font: var(--kl-font-caption); cursor: pointer;
}
.kl-flow-mini:hover { background: var(--kl-color-control-fill-pressed); }
.kl-flow-mini:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-flow-mini > .kl-icon { --kl-icon-size: 14px; margin: 0 var(--kl-space-1); color: var(--kl-color-text-secondary); }
.kl-flow-mini__seg {
  flex: 1 1 0; min-width: 0; height: 100%; display: flex; align-items: center; justify-content: center; gap: var(--kl-space-1);
  padding: 0 var(--kl-space-1); border-radius: var(--kl-radius-control);
}
.kl-flow-mini__seg.is-current { background: var(--kl-color-surface); color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); box-shadow: var(--kl-shadow-knob); }
.kl-flow-mini__seg.is-done { color: var(--kl-color-text); }
.kl-flow-mini__name { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-flow-mini__dots { display: inline-flex; gap: var(--kl-space-half); flex: none; }
.kl-flow-mini__dots > i { width: var(--kl-flow-mini-dot); height: var(--kl-flow-mini-dot); border-radius: var(--kl-radius-round); background: var(--kl-color-status-executing); }
.kl-flow-mini__dots > i[data-state="done"] { background: var(--kl-color-control); }
.kl-flow-mini__dots > i[data-state="failed"] { background: var(--kl-color-status-stopped); }
.kl-flow-mini__seg > .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; color: var(--kl-color-control); flex: none; }

/* =====================================================================================================
   4. Agent message tag .kl-msgtag: a small opaque pill riding a resting request or tie line between two cards.
      On the board the wrapper is also v2's .kl-link-rider, inside the line's .kl-link-group: it rides
      offset-path: var(--kl-link-path) and parks at --kl-link-at (80% for a tag, near the receiver; v2's default is 50%).
      v2 drops riders and tags to z 39 while a card is open. .kl-msgtag__tag is the real <button>;
      .kl-msgtag__peek opens on hover, keyboard focus or .is-open (pinned).
   ===================================================================================================== */
.kl-msgtag {
  --kl-msgtag-h: 24px;
  --kl-msgtag-dot: 7px;
  --kl-msgtag-count: 16px;
  --kl-msgtag-peek-w: 264px;
  --kl-msgtag-gap: 10px;       /* between the tag and its peek */
  --kl-msgtag-ring: 1.5px;     /* the tag's edge */
  --kl-msgtag-mark: 10px;      /* mini project mark in the peek */
  --kl-msgtag-mark-r: 3px;
  --kl-msgtag-tail: 10px;
  --kl-msgtag-edge: var(--kl-color-line-strong);
  --kl-msgtag-ink: var(--kl-color-text-secondary);
  --kl-link-at: 80%;
}
.kl-msgtag--inline { position: relative; display: inline-block; }
.kl-msgtag__tag {
  position: relative; display: inline-flex; align-items: center; gap: var(--kl-space-1);
  height: var(--kl-msgtag-h); margin: 0; padding: 0 var(--kl-space-3) 0 var(--kl-space-2); border: 0;
  border-radius: var(--kl-radius-pill); background: var(--kl-color-surface); color: var(--kl-color-text);
  box-shadow: 0 0 0 var(--kl-msgtag-ring) var(--kl-msgtag-edge), var(--kl-shadow-card);
  font: var(--kl-font-badge); white-space: nowrap; cursor: pointer;
}
.kl-msgtag__tag::before { content: ""; position: absolute; inset: calc((var(--kl-msgtag-h) - var(--kl-size-target)) / 2) 0; }
.kl-msgtag__tag:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 3px; }
.kl-msgtag__tag > .kl-icon { --kl-icon-size: 14px; color: var(--kl-msgtag-ink); }
.kl-msgtag__unread { width: var(--kl-msgtag-dot); height: var(--kl-msgtag-dot); flex: none; margin-left: var(--kl-space-half); border-radius: var(--kl-radius-round); background: var(--kl-color-selection); }
.kl-msgtag__count {
  position: absolute; top: calc(var(--kl-msgtag-count) / -2); right: calc(var(--kl-msgtag-count) / -2.5);
  display: grid; place-items: center; min-width: var(--kl-msgtag-count); height: var(--kl-msgtag-count); box-sizing: border-box; padding: 0 var(--kl-space-1);
  border-radius: var(--kl-radius-pill); background: var(--kl-color-selection); color: var(--kl-color-text-on-fill);
  box-shadow: 0 0 0 2px var(--kl-color-surface); font: var(--kl-font-caption); font-weight: var(--kl-font-weight-bold);
}
.kl-msgtag--request { --kl-msgtag-edge: var(--kl-color-link); --kl-msgtag-ink: var(--kl-color-link); }
.kl-msgtag--reply { --kl-msgtag-ink: var(--kl-color-text); }
.kl-msgtag.is-read .kl-msgtag__tag { color: var(--kl-color-text-secondary); box-shadow: 0 0 0 1px var(--kl-color-line), var(--kl-shadow-card); }
.kl-msgtag.is-read .kl-msgtag__tag > .kl-icon { color: var(--kl-color-text-secondary); }
.kl-msgtag.is-read .kl-msgtag__unread { display: none; }

/* Peek: an opaque bubble above the tag */
.kl-msgtag__peek {
  position: absolute; left: 50%; bottom: calc(100% + var(--kl-msgtag-gap)); translate: -50% 0; z-index: var(--kl-z-under);
  display: flex; flex-direction: column; gap: var(--kl-space-2); width: var(--kl-msgtag-peek-w); box-sizing: border-box;
  padding: var(--kl-space-3) var(--kl-space-3) var(--kl-space-2); border-radius: var(--kl-radius-menu);
  background: var(--kl-color-surface); color: var(--kl-color-text); box-shadow: var(--kl-shadow-bubble);
  font: var(--kl-font-meta); text-align: left; white-space: normal; opacity: 0; visibility: hidden;
}
.kl-msgtag__peek::before { content: ""; position: absolute; left: 0; right: 0; top: 100%; height: var(--kl-msgtag-gap); }   /* keeps hover across the gap */
.kl-msgtag__peek::after {
  content: ""; position: absolute; left: 50%; bottom: calc(var(--kl-msgtag-tail) / -2 - .5px); width: var(--kl-msgtag-tail); height: var(--kl-msgtag-tail); margin-left: calc(var(--kl-msgtag-tail) / -2); box-sizing: border-box;
  background: inherit; border: 1px solid transparent; border-right-color: var(--kl-color-notice-edge); border-bottom-color: var(--kl-color-notice-edge); rotate: 45deg;
}
.kl-msgtag:hover .kl-msgtag__peek, .kl-msgtag:focus-within .kl-msgtag__peek, .kl-msgtag.is-open .kl-msgtag__peek { opacity: 1; visibility: visible; }
.kl-msgtag--below .kl-msgtag__peek { bottom: auto; top: calc(100% + var(--kl-msgtag-gap)); }
.kl-msgtag--below .kl-msgtag__peek::before { top: auto; bottom: 100%; }
.kl-msgtag--below .kl-msgtag__peek::after { bottom: auto; top: calc(var(--kl-msgtag-tail) / -2 - .5px); rotate: 225deg; }
.kl-msgtag__route { display: flex; align-items: center; gap: var(--kl-space-1); font: var(--kl-font-caption); color: var(--kl-color-text-secondary); white-space: nowrap; }
.kl-msgtag__route b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }
.kl-msgtag__route .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
.kl-msgtag__route time { margin-left: auto; }
.kl-msgtag__mark { flex: none; width: var(--kl-msgtag-mark); height: var(--kl-msgtag-mark); border-radius: var(--kl-msgtag-mark-r); background: var(--kl-pmark, var(--kl-color-primary)); }
.kl-msgtag__text { margin: 0; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.kl-msgtag__open { align-self: flex-start; margin-left: calc(-1 * var(--kl-space-2)); }

/* =====================================================================================================
   Motion. All under prefers-reduced-motion: no-preference; .kl-motion-reduce and the OS setting leave a ≤120 ms fade.
   - Checklist: mark pops (v2 kl-m-dot-pop, dial-scaled), text and mark colour ease (--kl-motion-dot-colour), the bar
     slides (--kl-motion-meter), the count rolls (kl-m-roll), a new item writes in (kl-m-write).
   - A result chip or a workflow chip travels with v2's kl-m-fly kl-m-fly--land (KlMotion.fly: FLIP from
     --kl-fly-x/--kl-fly-y on the dial-written soft spring, then kl-land). v2 fades it in place under reduced motion.
   - The message tag travels its line on --kl-motion-msgtag-travel, ease-out (not dial-scaled, like every link line),
     and pops on arrival with kl-land. v2 has no keyframe for a rider's trip, so kl-agents-travel stays here.
   - A gate passing fills once (--kl-motion-meter); no loop. kl-agents-fill stays here: v2's kl-meter grows a
     width, and the gate's fill is a round node that grows from its centre.
   ===================================================================================================== */
@media (prefers-reduced-motion: no-preference) {
  .kl-tasks__mark { transition: background-color var(--kl-motion-dot-colour) var(--kl-motion-ease-out), box-shadow var(--kl-motion-dot-colour) var(--kl-motion-ease-out); }
  .kl-tasks__text { transition: color var(--kl-motion-dot-colour) var(--kl-motion-ease-out); }
  .kl-tasks__bar > i { transition: width var(--kl-motion-meter) var(--kl-motion-ease-out); }
  .kl-tasks__fold .kl-icon, .kl-fanout__chev { transition: rotate var(--kl-motion-expand) var(--kl-motion-spring-pop); }
  .kl-sub__kind, .kl-sub__task, .kl-sub__tile { transition: color var(--kl-motion-reveal) var(--kl-motion-ease-out), background-color var(--kl-motion-reveal) var(--kl-motion-ease-out); }
  .kl-fanout__dots > i, .kl-flow-mini__dots > i { transition: background-color var(--kl-motion-dot-colour) var(--kl-motion-ease-out); }
  .kl-flow__chip.kl-m-fly { z-index: var(--kl-z-drag); }
  .kl-flow__chip.is-arriving, .kl-sub.is-arriving, .kl-flow__result.is-arriving { animation: kl-reveal var(--kl-motion-reveal) var(--kl-motion-ease-out) calc(var(--i, 0) * var(--kl-motion-reveal-step)) backwards; }
  .kl-flow__gate[data-state="passing"] .kl-flow__node::before { animation: kl-agents-fill var(--kl-motion-meter) var(--kl-motion-ease-out) backwards; }
  .kl-flow__node { transition: background-color var(--kl-motion-dot-colour) var(--kl-motion-ease-out), box-shadow var(--kl-motion-dot-colour) var(--kl-motion-ease-out); }
  .kl-flow__why, .kl-msgtag__peek { transition: opacity var(--kl-motion-fade) ease; }
  .kl-msgtag.is-arriving { animation: kl-agents-travel var(--kl-motion-msgtag-travel) var(--kl-motion-ease-out) backwards; }
  .kl-msgtag.is-arriving .kl-msgtag__tag { animation: kl-land var(--kl-motion-land) ease-out var(--kl-motion-msgtag-travel); }
  .kl-msgtag.is-leaving { animation: kl-fade-out var(--kl-motion-fade-out) ease forwards; pointer-events: none; }
}
@keyframes kl-agents-travel { from { offset-distance: var(--kl-msgtag-from, 4%); } }
@keyframes kl-agents-fill { from { scale: 0; } }

/* Reduced motion: no travel, no springs, no fills; things appear where they end with a short fade */
@media (prefers-reduced-motion: reduce) {
  .kl-flow__chip.is-arriving, .kl-sub.is-arriving, .kl-flow__result.is-arriving, .kl-msgtag.is-arriving { animation: kl-fade-in var(--kl-motion-fade) ease backwards; }
  .kl-msgtag.is-leaving { animation: kl-fade-out var(--kl-motion-fade) ease forwards; }
}
.kl-motion-reduce :is(.kl-tasks__mark, .kl-tasks__text, .kl-tasks__bar > i, .kl-tasks__fold .kl-icon, .kl-fanout__chev, .kl-sub__kind, .kl-sub__task, .kl-sub__tile,
  .kl-fanout__dots > i, .kl-flow-mini__dots > i, .kl-flow__node) { transition: none !important; }
.kl-motion-reduce :is(.kl-flow__why, .kl-msgtag__peek) { transition: opacity var(--kl-motion-fade) ease !important; }
.kl-motion-reduce :is(.kl-flow__chip.is-arriving, .kl-sub.is-arriving, .kl-flow__result.is-arriving, .kl-msgtag.is-arriving) { animation: kl-fade-in var(--kl-motion-fade) ease backwards !important; }
.kl-motion-reduce .kl-msgtag.is-arriving .kl-msgtag__tag, .kl-motion-reduce .kl-flow__gate .kl-flow__node::before { animation: none !important; }
.kl-motion-reduce .kl-msgtag.is-leaving { animation: kl-fade-out var(--kl-motion-fade) ease forwards !important; }

/* Forced colours: marks and dots keep a visible edge */
@media (forced-colors: active) {
  .kl-tasks__mark, .kl-fanout__dots > i, .kl-flow__node, .kl-flow-mini__dots > i, .kl-msgtag__unread { forced-color-adjust: none; border: 1px solid CanvasText; }
  .kl-msgtag__tag, .kl-flow__chip, .kl-sub__result { border: 1px solid ButtonText; }
}

/* ===== harness/memory/memory.css ===== */
/* Klippan master · Harness · Memory and context
   The memory window, the instructions tab, the context breakdown (with its compacting state) and the usage meter.
   Load after ../../../klippan-v2/combined/klippan.css. Builds on the v2 window frame (.kl-win), setting rows,
   lists, buttons, tabs, segmented control, search, badges, toast and status dots, and never restyles them.
   Every colour, type, radius, shadow and motion value is a --kl- token. Literals are only this part's own
   component sizes, kept as local custom properties. */

/* =====================================================================================
   0. Shared bits
   ===================================================================================== */
.kl-win--memory      { --kl-win-w: 460px; }
.kl-win--context     { --kl-win-w: 400px; }
.kl-win--usage       { --kl-win-w: 400px; }
.kl-win--instructions{ --kl-win-w: 480px; }

.kl-win--memory, .kl-win--context, .kl-win--usage, .kl-win--instructions,
.kl-mem-entry, .kl-instr, .kl-ctx, .kl-usage, .kl-mem-toast-dock { --kl-mem-hair: 2px; --kl-mem-tight: 6px; }


/* Small icon inside running text: 14px, secondary ink */
.kl-mem-ico { flex: none; width: 14px; height: 14px; color: var(--kl-color-text-secondary); }

/* =====================================================================================
   1. Memory window  .kl-win--memory
   Bar (icon, Memory, project scope tag) · tools (search, scope filter) · groups of entries · foot (note, Done)
   ===================================================================================== */
.kl-mem__tools { display: flex; flex-direction: column; gap: var(--kl-space-2); }
.kl-mem__tools .kl-search { width: 100%; }
.kl-mem__count { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; font-weight: 400; }

/* One remembered fact */
.kl-mem-entry {
  --kl-mem-entry-pad: 10px;
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--kl-mem-hair) var(--kl-space-2);
  padding: var(--kl-mem-entry-pad) 0;
  overflow: hidden;
  border-radius: var(--kl-radius-row);
}
.kl-mem-entry + .kl-mem-entry { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-mem-entry__fact {
  grid-column: 1;
  margin: 0;
  font: var(--kl-font-meta);
  color: var(--kl-color-text);
  text-wrap: pretty;
  overflow-wrap: anywhere;
}
.kl-mem-entry__from {
  grid-column: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--kl-mem-hair) var(--kl-mem-tight);
  font: var(--kl-font-caption);
  font-weight: 400;
  color: var(--kl-color-text-secondary);
  font-variant-numeric: tabular-nums;
}
.kl-mem-entry__from .kl-mem-ico { width: 12px; height: 12px; }
.kl-mem-entry__from code { font-family: var(--kl-font-mono); font-size: inherit; }
.kl-mem-entry__bit { white-space: nowrap; }
.kl-mem-entry__bit + .kl-mem-entry__bit::before { content: "·"; margin-right: var(--kl-mem-tight); color: var(--kl-color-text-secondary); }
.kl-mem-entry__stale { display: inline-flex; align-items: center; gap: 4px; color: var(--kl-color-status-planning-ink); }
.kl-mem-entry__stale .kl-mem-ico { color: inherit; }

/* Actions: Edit (icon) and Forget. Quiet until the row is hovered or focused, always there for the keyboard */
.kl-mem-entry__actions {
  grid-column: 2;
  grid-row: 1 / span 2;
  display: inline-flex;
  align-items: center;
  gap: var(--kl-mem-hair);
  opacity: .0;
  transition: opacity var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-mem-entry:hover .kl-mem-entry__actions,
.kl-mem-entry:focus-within .kl-mem-entry__actions,
.kl-mem-entry.is-hover .kl-mem-entry__actions,
.kl-mem-entry.is-stale .kl-mem-entry__actions { opacity: 1; }
@media (hover: none) { .kl-mem-entry__actions { opacity: 1; } }
.kl-mem-entry.is-hover,
.kl-mem-entry:hover { background: linear-gradient(var(--kl-color-surface-sunken), var(--kl-color-surface-sunken)) padding-box; }

/* New: just written by an agent or by you. A small badge; the text writes in once (kl-m-write) */
.kl-mem-entry__new { margin-left: var(--kl-mem-tight); vertical-align: 1px; height: 18px; padding: 0 6px; }

/* Editing in place: the fact turns into a textarea, Cancel first, Save is the view's one blue action */
.kl-mem-entry.is-editing { grid-template-columns: minmax(0, 1fr); }
.kl-mem-entry.is-editing .kl-mem-entry__actions { display: none; }
.kl-mem-entry__edit { display: flex; flex-direction: column; gap: var(--kl-space-2); }
.kl-mem-entry__edit .kl-textarea { min-height: 64px; width: 100%; resize: vertical; font: var(--kl-font-meta); }
.kl-mem-entry__editbar { display: flex; align-items: center; justify-content: flex-end; gap: var(--kl-space-2); }
.kl-mem-entry__editbar .kl-fieldhint { margin-right: auto; }

/* Forgetting: the row folds shut on ease-out (no bounce on size), then the Undo toast shows */
.kl-mem-entry.is-forgetting {
  animation: kl-mem-fold var(--kl-motion-collapse) var(--kl-motion-ease-in) forwards;
  pointer-events: none;
}
@keyframes kl-mem-fold {
  0%   { opacity: 1; max-height: var(--kl-mem-h, 96px); }
  45%  { opacity: 0; }
  100% { opacity: 0; max-height: 0; padding-top: 0; padding-bottom: 0; }
}
/* Given back by Undo: opens again and rises in */
.kl-mem-entry.is-restoring { animation: kl-mem-unfold var(--kl-motion-expand) var(--kl-motion-ease-out) backwards; }
@keyframes kl-mem-unfold {
  0%   { opacity: 0; max-height: 0; padding-top: 0; padding-bottom: 0; }
  60%  { opacity: 0; max-height: var(--kl-mem-h, 96px); padding-top: var(--kl-mem-entry-pad); padding-bottom: var(--kl-mem-entry-pad); }
  100% { opacity: 1; max-height: var(--kl-mem-h, 96px); }
}
/* A search match: the matched words get the selection tint, nothing else changes */
.kl-mem-entry mark { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); border-radius: 3px; padding: 0 1px; }

/* Scope header inside a group label: an icon and a quiet hint */
.kl-mem__scope { display: inline-flex; align-items: center; gap: var(--kl-mem-tight); }
.kl-mem__scope-hint { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-weight: 400; letter-spacing: 0; }

/* Empty and no-match */
.kl-mem__empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--kl-space-2);
  padding: var(--kl-space-6, 24px) var(--kl-space-4);
  text-align: center;
  color: var(--kl-color-text-secondary);
}
.kl-mem__empty-tile {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: var(--kl-radius-row);
  background: var(--kl-color-control-fill); color: var(--kl-color-text-secondary);
}
.kl-mem__empty-tile svg { width: 20px; height: 20px; }
.kl-mem__empty h4 { margin: 0; font: var(--kl-font-label-strong); color: var(--kl-color-text); }
.kl-mem__empty p { margin: 0; font: var(--kl-font-meta); max-width: 320px; }

/* Undo toast placement on the board: bottom centre of the scene, above everything */
.kl-mem-toast-dock { position: absolute; left: 50%; bottom: 20px; translate: -50% 0; z-index: 50; display: flex; justify-content: center; pointer-events: none; }
.kl-mem-toast-dock .kl-toast { pointer-events: auto; }
.kl-mem-toast-dock .kl-toast.is-entering { animation: kl-mem-toast-in var(--kl-motion-reveal) var(--kl-motion-spring-pop) backwards; }
@keyframes kl-mem-toast-in { from { opacity: 0; transform: translateY(8px) scale(calc(1 - .06 * var(--kl-motion-k, .35))); } }

/* =====================================================================================
   2. Instructions tab  .kl-instr  (in the project window, beside General)
   Account layer (read only, folded) · this project's own · files from the repository · read order
   ===================================================================================== */
.kl-instr { display: flex; flex-direction: column; gap: var(--kl-space-4); }
.kl-instr__order {
  margin: 0; padding: 0 var(--kl-space-1);
  font: var(--kl-font-caption); font-weight: 400; color: var(--kl-color-text-secondary);
}
.kl-instr__order b { font-weight: 590; color: var(--kl-color-text); }
.kl-instr__order .kl-mem-ico { width: 12px; height: 12px; }

/* A layer: header row (number, name, where it comes from, tokens) then its text */
.kl-instr-layer {
  display: flex;
  flex-direction: column;
  border-radius: var(--kl-radius-groupbox);
  background: var(--kl-color-surface);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
  overflow: hidden;
}
.kl-instr-layer__head {
  display: flex; align-items: center; gap: var(--kl-space-2);
  min-height: 44px; padding: var(--kl-space-2) var(--kl-space-3);
  border: 0; background: transparent; width: 100%; text-align: left; color: inherit; font: inherit;
}
button.kl-instr-layer__head { cursor: pointer; }
button.kl-instr-layer__head:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: -2px; border-radius: var(--kl-radius-groupbox); }
.kl-instr-layer__n {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: var(--kl-radius-pill);
  background: var(--kl-color-control-fill); color: var(--kl-color-text-secondary);
  font: var(--kl-font-badge); font-variant-numeric: tabular-nums;
}
.kl-instr-layer__text { display: flex; flex-direction: column; gap: var(--kl-mem-hair); min-width: 0; flex: 1 1 auto; }
.kl-instr-layer__name { font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); color: var(--kl-color-text); }
.kl-instr-layer__meta { font: var(--kl-font-caption); font-weight: 400; color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-instr-layer__chev { flex: none; width: 16px; height: 16px; color: var(--kl-color-text-secondary); transition: rotate var(--kl-motion-press) var(--kl-motion-spring-pop); }
.kl-instr-layer[aria-expanded="false"] .kl-instr-layer__chev,
.kl-instr-layer.is-folded .kl-instr-layer__chev { rotate: -90deg; }
.kl-instr-layer.is-folded .kl-instr-layer__body { display: none; }
.kl-instr-layer__body { border-top: 1px solid var(--kl-color-line); }
.kl-instr-layer--inherited .kl-instr-layer__body { background: var(--kl-color-surface-sunken); }

/* The text itself: one line per instruction, numbered, so a line can carry a tag */
.kl-instr-lines { list-style: none; margin: 0; padding: var(--kl-space-2) 0; counter-reset: kl-instr; }
.kl-instr-lines li {
  counter-increment: kl-instr;
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  gap: var(--kl-space-2);
  align-items: baseline;
  padding: 3px var(--kl-space-3) 3px 0;
  font: var(--kl-font-meta);
  color: var(--kl-color-text);
}
.kl-instr-lines li::before {
  content: counter(kl-instr);
  text-align: right;
  font: var(--kl-font-caption);
  font-weight: 400;
  color: var(--kl-color-text-tertiary);
  font-variant-numeric: tabular-nums;
}
.kl-instr-layer--inherited .kl-instr-lines li { color: var(--kl-color-text-secondary); }
.kl-instr-lines li.is-replaced span:first-child { text-decoration: line-through; text-decoration-color: var(--kl-color-text-tertiary); }
.kl-instr-lines li.is-new { background: color-mix(in srgb, var(--kl-color-selection-soft) 70%, transparent); }
.kl-instr-lines .kl-setting__tag { align-self: center; }

/* Editing the project's own instructions: a plain textarea filling the layer */
.kl-instr-layer.is-editing { box-shadow: inset 0 0 0 1px var(--kl-color-focus), 0 0 0 3px var(--kl-color-selection-soft); }
.kl-instr__editor {
  display: block; width: 100%; min-height: 168px; margin: 0; padding: var(--kl-space-3);
  border: 0; outline: 0; resize: vertical;
  background: var(--kl-color-surface); color: var(--kl-color-text);
  font: var(--kl-font-meta); line-height: 22px;
}
.kl-instr__editor::placeholder { color: var(--kl-color-text-secondary); }

/* Files from the repository: one row each, Geist Mono path, load switch */
.kl-instr-file { display: flex; align-items: center; gap: var(--kl-space-2); min-height: 44px; padding: var(--kl-space-2) var(--kl-space-3); }
.kl-instr-file + .kl-instr-file { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-instr-file__text { display: flex; flex-direction: column; gap: var(--kl-mem-hair); min-width: 0; flex: 1 1 auto; }
.kl-instr-file__path { font: var(--kl-font-meta); font-family: var(--kl-font-mono); color: var(--kl-color-text); overflow-wrap: anywhere; }
.kl-instr-file__meta { font: var(--kl-font-caption); font-weight: 400; color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-instr-file.is-off .kl-instr-file__path { color: var(--kl-color-text-tertiary); text-decoration: line-through; text-decoration-color: var(--kl-color-text-tertiary); }

/* Total: how much context all layers take at the start of every run */
.kl-instr__total { display: flex; align-items: center; justify-content: space-between; gap: var(--kl-space-2); padding: 0 var(--kl-space-1);
  font: var(--kl-font-caption); font-weight: 400; color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-instr__total b { font-weight: 590; color: var(--kl-color-text); }

/* =====================================================================================
   3. Context breakdown  .kl-ctx
   Head (agent, numbers) · one bar split into what fills it, with the hand-off mark · legend · foot
   The bar spans the agent's whole window (200,000 for Claude); the mark is the hand-off point (150,000).
   Segments are shades of the control blue (meters are control colour in v2); the space left is the plain track.
   ===================================================================================== */
.kl-ctx {
  --kl-ctx-bar-h: 12px;
  --kl-ctx-mark: 75%;
  --kl-ctx-ink: var(--kl-color-control);
  /* Segment fills: Foundations' split-meter steps, darkest first. No five-step ramp holds 3:1 between neighbours,
     so segments keep a 2px gap of surface and the legend names each one (foundations/contrast.md). */
  --kl-ctx-gap: var(--kl-color-surface);
  --kl-ctx-1: var(--kl-color-meter-1);
  --kl-ctx-2: var(--kl-color-meter-2);
  --kl-ctx-3: var(--kl-color-meter-3);
  --kl-ctx-4: var(--kl-color-meter-4);
  --kl-ctx-5: var(--kl-color-meter-5);
  display: grid;
  gap: var(--kl-space-2);
  min-width: 0;
  color: var(--kl-color-text);
}
.kl-ctx--warn { --kl-ctx-ink: var(--kl-color-status-planning); }
.kl-ctx--full { --kl-ctx-ink: var(--kl-color-status-stopped); }
/* Near and at the hand-off mark the steps come from the status colour, as v2's meter turns amber or red */
.kl-ctx--warn, .kl-ctx--full {
  --kl-ctx-1: var(--kl-ctx-ink);
  --kl-ctx-2: color-mix(in srgb, var(--kl-ctx-ink) 72%, var(--kl-color-surface));
  --kl-ctx-3: color-mix(in srgb, var(--kl-ctx-ink) 50%, var(--kl-color-surface));
  --kl-ctx-4: color-mix(in srgb, var(--kl-ctx-ink) 34%, var(--kl-color-surface));
  --kl-ctx-5: color-mix(in srgb, var(--kl-ctx-ink) 20%, var(--kl-color-surface));
}

.kl-ctx__head { display: flex; align-items: baseline; gap: var(--kl-space-2); min-width: 0; }
.kl-ctx__name { flex: 1 1 auto; min-width: 0; font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kl-ctx__nums { flex: none; font: var(--kl-font-label); font-variant-numeric: tabular-nums; white-space: nowrap; }
.kl-ctx__nums span { color: var(--kl-color-text-secondary); font-weight: 400; }
.kl-ctx--warn .kl-ctx__nums { color: var(--kl-color-status-planning-ink); }
.kl-ctx--full .kl-ctx__nums { color: var(--kl-color-status-stopped-ink); }

.kl-ctx__bar {
  position: relative;
  display: flex;
  height: var(--kl-ctx-bar-h);
  margin: 3px 0;
  border-radius: calc(var(--kl-ctx-bar-h) / 2);
  background: var(--kl-color-switch-off);
}
.kl-ctx__seg {
  position: relative;
  flex: none;
  width: var(--kl-seg, 0%);
  height: 100%;
  background: var(--kl-seg-fill, var(--kl-ctx-1));
  box-sizing: border-box;
  border-right: 2px solid var(--kl-ctx-gap);             /* the 2px gap between parts */
  transition: width var(--kl-motion-expand) var(--kl-motion-ease-out), background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-ctx__seg:first-child { border-radius: calc(var(--kl-ctx-bar-h) / 2) 0 0 calc(var(--kl-ctx-bar-h) / 2); }
.kl-ctx__seg--instructions { --kl-seg-fill: var(--kl-ctx-1); }
.kl-ctx__seg--tools        { --kl-seg-fill: var(--kl-ctx-2); }
.kl-ctx__seg--memory       { --kl-seg-fill: var(--kl-ctx-3); }
.kl-ctx__seg--files        { --kl-seg-fill: var(--kl-ctx-4); }
.kl-ctx__seg--conversation { --kl-seg-fill: var(--kl-ctx-5); }
.kl-ctx__seg--conversation { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--kl-ctx-ink) 45%, transparent); }
/* Hover a legend row or a segment: that part stays, the others dim */
.kl-ctx.is-focusing .kl-ctx__seg:not(.is-focus) { opacity: .35; }
.kl-ctx__seg.is-focus { z-index: 1; }

.kl-ctx__mark {
  position: absolute; top: -4px; bottom: -4px; left: var(--kl-ctx-mark);
  width: 2px; margin-left: -1px; border-radius: 1px;
  background: var(--kl-color-text); box-shadow: 0 0 0 1.5px var(--kl-color-surface);
  z-index: 2;
}
.kl-ctx__scale { display: flex; justify-content: space-between; position: relative; font: var(--kl-font-caption); font-weight: 400; color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-ctx__scale-mark { position: absolute; left: var(--kl-ctx-mark); translate: -50% 0; color: var(--kl-color-text); font-weight: 510; white-space: nowrap; }

/* Legend: swatch, part, what is in it, tokens */
.kl-ctx__legend { list-style: none; margin: 0; padding: 0 var(--kl-space-3); border-radius: var(--kl-radius-groupbox); box-shadow: inset 0 0 0 1px var(--kl-color-line); background: var(--kl-color-surface); }
.kl-ctx__row {
  display: grid;
  grid-template-columns: 12px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--kl-space-2);
  min-height: 40px;
  padding: var(--kl-mem-tight) 0;
  font: var(--kl-font-meta);
}
.kl-ctx__row + .kl-ctx__row { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-ctx__swatch { width: 12px; height: 12px; border-radius: 3px; background: var(--kl-seg-fill); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--kl-color-text) 10%, transparent); }
.kl-ctx__row--free .kl-ctx__swatch { background: var(--kl-color-switch-off); }
.kl-ctx__what { display: flex; flex-direction: column; min-width: 0; }
.kl-ctx__what b { font: var(--kl-font-label); color: var(--kl-color-text); }
.kl-ctx__what span { font: var(--kl-font-caption); font-weight: 400; color: var(--kl-color-text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kl-ctx__tok { font: var(--kl-font-label); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
.kl-ctx__tok span { display: block; font: var(--kl-font-caption); font-weight: 400; color: var(--kl-color-text-secondary); }
.kl-ctx__row.is-focus { background: linear-gradient(var(--kl-color-surface-sunken), var(--kl-color-surface-sunken)); }

.kl-ctx__foot { display: flex; align-items: center; gap: var(--kl-space-2); min-height: 20px; font: var(--kl-font-caption); font-weight: 400; color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-ctx__foot .kl-badge { margin-left: auto; }
.kl-ctx__foot .kl-dot { flex: none; }

/* Compacting: the conversation part is being summarised. Its segment takes calm diagonal stripes (no movement,
   the planning dot beside the label is the only thing that pulses), then shrinks on ease-out when done. */
.kl-ctx.is-compacting .kl-ctx__seg--conversation {
  background-image: repeating-linear-gradient(-45deg,
    color-mix(in srgb, var(--kl-color-status-planning) 55%, transparent) 0 3px, transparent 3px 7px);
  background-color: var(--kl-color-status-planning-soft);
  box-shadow: inset 0 0 0 1px var(--kl-color-status-planning);
}
.kl-ctx.is-compacting .kl-ctx__row--conversation .kl-ctx__swatch {
  background: var(--kl-color-status-planning-soft) repeating-linear-gradient(-45deg, var(--kl-color-status-planning) 0 2px, transparent 2px 4px);
}
.kl-ctx__state { display: inline-flex; align-items: center; gap: var(--kl-mem-tight); color: var(--kl-color-status-planning-ink); font-weight: 510; }
.kl-ctx__state--done { color: var(--kl-color-status-executing-ink); }
.kl-ctx__state--done .kl-mem-ico { color: inherit; }
/* Just compacted: the freed space is outlined once for a moment, then fades */
.kl-ctx__freed {
  position: relative; flex: none; width: var(--kl-seg, 0%); height: 100%;
  border-radius: 0 calc(var(--kl-ctx-bar-h) / 2) calc(var(--kl-ctx-bar-h) / 2) 0;
  box-shadow: inset 0 0 0 1px var(--kl-color-status-executing);
  opacity: 0;
}
.kl-ctx__freed.is-held { opacity: 1; }
.kl-ctx.is-compacted .kl-ctx__freed:not(.is-held) { animation: kl-ctx-freed 1600ms var(--kl-motion-ease-out) both; }
@keyframes kl-ctx-freed { 0% { opacity: 0; } 15% { opacity: 1; } 100% { opacity: 0; } }

/* What the agent does at the mark: hand off (Klippan's default) or compact. A setting row with a segmented control. */
.kl-ctx__policy .kl-seg { flex: none; }

/* On a project card's expanded stage: the v2 meter line becomes the breakdown bar, no legend */
.kl-ctx--card { --kl-ctx-bar-h: 7px; gap: 6px; }
.kl-ctx--card .kl-ctx__head { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-ctx--card .kl-ctx__name { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); letter-spacing: 0; }
.kl-ctx--card .kl-ctx__nums { font: var(--kl-font-meta); }
.kl-ctx--card .kl-ctx__bar { margin: 0; }
.kl-ctx--card .kl-ctx__mark { top: -3px; bottom: -3px; }

/* =====================================================================================
   4. Usage meter  .kl-usage
   How much of each runner's plan window is used, in tokens and percent. Never money.
   One block per runner (Claude, Codex): a 5-hour window and the week, each with when it resets.
   ===================================================================================== */
.kl-usage { display: flex; flex-direction: column; gap: var(--kl-space-3); min-width: 0; }
.kl-usage__runner { display: flex; align-items: center; gap: var(--kl-space-2); }
.kl-usage__runner-tile {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: var(--kl-radius-row);
  background: var(--kl-color-control-fill); color: var(--kl-color-text);
}
.kl-usage__runner-tile svg { width: 16px; height: 16px; }
.kl-usage__runner-name { font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-usage__runner-via { font: var(--kl-font-caption); font-weight: 400; color: var(--kl-color-text-secondary); }
.kl-usage__runner .kl-badge { margin-left: auto; }

.kl-usage-meter {
  --kl-usage-value: 0%;
  --kl-usage-fill: var(--kl-color-control);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 4px var(--kl-space-2);
  align-items: baseline;
}
.kl-usage-meter__name { font: var(--kl-font-label); color: var(--kl-color-text); }
.kl-usage-meter__pct { font: var(--kl-font-label-strong); font-variant-numeric: tabular-nums; text-align: right; }
.kl-usage-meter__track {
  grid-column: 1 / -1;
  position: relative; height: 8px; border-radius: 4px; background: var(--kl-color-switch-off); overflow: hidden;
}
.kl-usage-meter__fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: var(--kl-usage-value); border-radius: inherit;
  background: var(--kl-usage-fill);
  transition: width var(--kl-motion-hover) var(--kl-motion-ease-out), background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-usage-meter__foot {
  grid-column: 1 / -1;
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 2px var(--kl-space-2);
  font: var(--kl-font-caption); font-weight: 400; color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums;
}
.kl-usage-meter--near { --kl-usage-fill: var(--kl-color-status-planning); }
.kl-usage-meter--near .kl-usage-meter__pct { color: var(--kl-color-status-planning-ink); }
.kl-usage-meter--limit { --kl-usage-fill: var(--kl-color-status-stopped); }
.kl-usage-meter--limit .kl-usage-meter__pct { color: var(--kl-color-status-stopped-ink); }
.kl-usage-meter--unknown .kl-usage-meter__track { background: transparent; box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); background-image: repeating-linear-gradient(90deg, var(--kl-color-line) 0 4px, transparent 4px 8px); }
.kl-usage-meter--unknown .kl-usage-meter__fill { display: none; }
.kl-usage-meter--unknown .kl-usage-meter__pct { color: var(--kl-color-text-secondary); font-weight: 510; }

.kl-usage__group { display: flex; flex-direction: column; gap: var(--kl-space-3); padding: var(--kl-space-3); border-radius: var(--kl-radius-groupbox); background: var(--kl-color-surface); box-shadow: inset 0 0 0 1px var(--kl-color-line); }

/* Mini: two thin bars and one line, for the Tokenomy card's expanded stage or a tooltip */
.kl-usage--mini { gap: 6px; }
.kl-usage--mini .kl-usage-meter { gap: 3px var(--kl-space-2); }
.kl-usage--mini .kl-usage-meter__name,
.kl-usage--mini .kl-usage-meter__pct { font: var(--kl-font-meta); }
.kl-usage--mini .kl-usage-meter__track { height: 5px; }
.kl-usage--mini .kl-usage-meter__foot { display: none; }

/* =====================================================================================
   5. Accessibility: increased contrast, reduced motion, forced colours
   ===================================================================================== */
[data-contrast="more"] .kl-ctx__seg,
[data-contrast="more"] .kl-ctx__swatch { box-shadow: inset 0 0 0 1px var(--kl-color-text); }
[data-contrast="more"] .kl-mem-entry__actions { opacity: 1; }
@media (prefers-contrast: more) {
  .kl-ctx__seg, .kl-ctx__swatch { box-shadow: inset 0 0 0 1px var(--kl-color-text); }
  .kl-mem-entry__actions { opacity: 1; }
}
.kl-motion-reduce .kl-mem-entry.is-forgetting,
.kl-motion-reduce .kl-mem-entry.is-restoring,
.kl-motion-reduce .kl-mem-toast-dock .kl-toast.is-entering,
.kl-motion-reduce .kl-ctx.is-compacted .kl-ctx__freed { animation-duration: 120ms; animation-timing-function: linear; }
.kl-motion-reduce .kl-ctx__seg, .kl-motion-reduce .kl-usage-meter__fill, .kl-motion-reduce .kl-instr-layer__chev { transition: none; }
@media (prefers-reduced-motion: reduce) {
  .kl-mem-entry.is-forgetting, .kl-mem-entry.is-restoring, .kl-mem-toast-dock .kl-toast.is-entering, .kl-ctx.is-compacted .kl-ctx__freed { animation-duration: 120ms; animation-timing-function: linear; }
  .kl-ctx__seg, .kl-usage-meter__fill, .kl-instr-layer__chev { transition: none; }
}
@media (forced-colors: active) {
  .kl-ctx__seg, .kl-ctx__swatch, .kl-usage-meter__fill { forced-color-adjust: none; outline: 1px solid CanvasText; }
  .kl-ctx__bar, .kl-usage-meter__track { outline: 1px solid CanvasText; }
}

/* ===== harness/inbox/inbox.css ===== */
/* =====================================================================================================
   Klippan master · harness · Routines and inbox
   The routine card, the schedule editor, run history, the Inbox (section card and window) and notification
   rules. Builds on design system v2: load ../../../klippan-v2/combined/klippan.css first, then this file.
   Only --kl-* tokens; literals are this part's own component sizes, kept as local custom properties.
   Icons: the v2 sprite (kl-*) and the shared harness sprite ../icons/sprite.svg (kl-routine, kl-inbox,
   kl-permission, kl-question, kl-plan, kl-mac, kl-phone, kl-event, kl-pause, kl-eye …). Clock is v2 kl-planning,
   quiet hours v2 kl-theme-dark.
   ===================================================================================================== */

:root, [data-theme] {
  --kl-routine-w: 380px;              /* expanded routine card */
  --kl-routine-pip: 8px;              /* one run in the run strip */
  --kl-routine-pip-gap: 4px;
  --kl-sched-day: 32px;               /* weekday toggle */
  --kl-inbox-tile: 28px;              /* kind tile on an Inbox row */
  --kl-notify-dev: 28px;              /* Mac / phone toggle */
  --kl-wait-long: 30;                 /* minutes: from here a wait reads as long (same 30 min as the quiet hours override) */
}

/* =====================================================================================================
   1. Run pips: one small mark per run. Shared by the routine card, the schedule editor and run history.
      Status colours mean status only: a run that is going is executing green, a failed run is stopped red.
      A finished run is neutral ink (done is not a status), a skipped run is hollow, the next run is dashed.
   ===================================================================================================== */
.kl-pip {
  display: inline-block; flex: none; box-sizing: border-box;
  width: var(--kl-routine-pip); height: var(--kl-routine-pip); border-radius: var(--kl-radius-round);
  background: var(--kl-color-text-tertiary);
}
.kl-pip--running { background: var(--kl-color-status-executing); }
.kl-pip--failed  { background: var(--kl-color-status-stopped); }
.kl-pip--skipped { background: transparent; box-shadow: inset 0 0 0 1.5px var(--kl-color-text-tertiary); }
.kl-pip--next    { background: transparent; outline: 1.5px dashed var(--kl-color-text-tertiary); outline-offset: -1.5px; }
/* A new pip pops in with Motion's kl-m-count-pop on the pip itself */

.kl-pips {
  display: flex; align-items: center; gap: var(--kl-routine-pip-gap);
  min-width: 0; overflow: hidden;
}

/* =====================================================================================================
   2. Routine card  .kl-card.kl-routine
      A project-like card: the glass takes the project's hue (.kl-card--p1 … --p8), the dot is centred at the
      left, the name and an agent-written status line are stacked beside it. In place of the agent count it
      shows when it runs (.kl-routine__when). Stages as every project card: 0 name only, 1 compact, 2 full,
      3 expanded. Dot: idle grey between runs and while paused, executing green while a run goes, stopped red
      with rays when a run failed and waits on Alban.
   ===================================================================================================== */
.kl-routine[data-stage="3"] { --kl-card-w: var(--kl-routine-w); }

.kl-routine__when {
  display: inline-flex; align-items: center; gap: 5px; min-width: 0;
  font: var(--kl-font-meta); font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text-secondary);
  font-variant-numeric: tabular-nums;
  opacity: var(--kl-on); translate: 0 calc(5px * (1 - var(--kl-on)));
}
.kl-routine__when .kl-icon { --kl-icon-size: 14px; flex: none; }
.kl-routine__when > span { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
/* A routine is quieter than a project: its name sets in headline, and the when-line runs under the gear and chevron */
.kl-routine .kl-card__name { font: var(--kl-font-headline); }
.kl-routine__when { margin-right: calc(-28px - 56px * var(--kl-oc)); }
.kl-card[data-stage="0"] .kl-routine__when { display: none; }

/* Paused: the dot stays grey, the name and when-line soften and a pause mark sits after the name */
.kl-routine__paused { display: none; flex: none; color: var(--kl-color-text-secondary); }
.kl-routine__paused .kl-icon { --kl-icon-size: 14px; }
.kl-routine.is-paused .kl-routine__paused { display: inline-grid; }
.kl-routine.is-paused .kl-card__name-text,
.kl-routine.is-paused .kl-routine__when { color: var(--kl-color-text-secondary); }
.kl-routine.is-paused .kl-routine__when > span { text-decoration: line-through; text-decoration-color: var(--kl-color-text-tertiary); }

/* The last runs, newest on the right, then the next one. Full stage and up. */
.kl-routine__strip { opacity: var(--kl-ol); }
.kl-card[data-stage="0"] .kl-routine__strip, .kl-card[data-stage="1"] .kl-routine__strip { display: none; }

/* Expanded body */
.kl-routine__block { display: flex; flex-direction: column; gap: 6px; }
.kl-routine__label {
  font: var(--kl-font-caption); font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text-secondary);
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.kl-routine__sentence {
  display: flex; align-items: center; gap: 8px; margin: 0; padding: 8px 10px;
  border-radius: var(--kl-radius-row); background: var(--kl-color-control-fill);
  font: var(--kl-font-label); color: var(--kl-color-text);
}
.kl-routine__sentence > span { flex: 1 1 auto; min-width: 0; }
.kl-routine__sentence .kl-icon { --kl-icon-size: 16px; flex: none; color: var(--kl-color-text-secondary); }
.kl-routine__next { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.kl-routine__next li {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 8px;
  border-radius: var(--kl-radius-pill); box-shadow: inset 0 0 0 1px var(--kl-color-line);
  font: var(--kl-font-meta); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums;
}
.kl-routine__next li.is-skip { color: var(--kl-color-text-tertiary); text-decoration: line-through; }
.kl-routine__foot {
  display: flex; align-items: center; gap: 8px; margin-top: auto; padding-top: 10px;
  border-top: 1px solid var(--kl-color-line);
}
.kl-routine__foot .kl-routine__toggle {
  display: inline-flex; align-items: center; gap: 8px; margin-right: auto;
  font: var(--kl-font-meta); color: var(--kl-color-text-secondary);
}
.kl-routine__tokens { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
/* The failed note inside an expanded card that waits on Alban */
.kl-routine__fail {
  display: flex; gap: 8px; align-items: flex-start; padding: 8px 10px;
  border-radius: var(--kl-radius-row); background: var(--kl-color-status-stopped-soft);
  font: var(--kl-font-meta); color: var(--kl-color-status-stopped-ink);
}
.kl-routine__fail .kl-icon { --kl-icon-size: 16px; flex: none; margin-top: 1px; }

/* The new-routine draft: a dashed card with a single field, from the prompter's "Make it a routine" */
.kl-routine--draft .kl-card__face { border: 1.5px dashed var(--kl-color-line-strong); box-shadow: none; }

/* =====================================================================================================
   3. Runs of a routine
      Run rows and the Runs window come from the Runs part (../runs/runs.css: .kl-runrow, .kl-runrow--card in the
      expanded card, .kl-win--runs with .kl-runs__group). Opened from a routine, the Runs window is scoped to it and
      adds this summary to its tools: 30 days of pips and the counts.
   ===================================================================================================== */
.kl-routine__summary { display: flex; flex-direction: column; gap: 8px; }
.kl-routine__summary .kl-pips { --kl-routine-pip: 10px; --kl-routine-pip-gap: 2px; }
.kl-routine__counts { display: flex; flex-wrap: wrap; gap: 4px 14px; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-routine__counts b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }

/* =====================================================================================================
   5. Schedule editor  .kl-win.kl-sched
      Opaque window beside the routine card. Three ways a routine starts (On a schedule, When something
      happens, Only when I run it), a plain sentence that says what was chosen, the next runs, then what it
      runs. Cancel first, Save is the one blue action.
   ===================================================================================================== */
.kl-sched { --kl-win-w: 460px; }
.kl-sched__days { display: flex; gap: 6px; }
.kl-sched__day {
  width: var(--kl-sched-day); height: var(--kl-sched-day); padding: 0; flex: none;
  display: grid; place-items: center; position: relative;
  border: 0; border-radius: var(--kl-radius-round);
  background: var(--kl-color-control-fill); color: var(--kl-color-text);
  font: var(--kl-font-label-strong); cursor: pointer;
  transition: background-color var(--kl-motion-hover) ease, color var(--kl-motion-hover) ease,
              scale var(--kl-motion-press) var(--kl-motion-spring-pop);
}
.kl-sched__day::before { content: ""; position: absolute; inset: -6px; }   /* 44 px hit area */
.kl-sched__day:hover, .kl-sched__day.is-hover { background: var(--kl-color-control-fill-pressed); }
.kl-sched__day:active, .kl-sched__day.is-pressed { scale: .92; }
.kl-sched__day[aria-pressed="true"], .kl-sched__day.is-on { background: var(--kl-color-control); color: var(--kl-color-text-on-fill); }
.kl-sched__day:focus-visible, .kl-sched__day.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-sched__days.is-error .kl-sched__day { box-shadow: inset 0 0 0 1.5px var(--kl-color-status-stopped); }

.kl-sched__times { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.kl-sched__times { --kl-setting-field-w: 76px; }
.kl-sched__time { width: 76px; text-align: center; font-variant-numeric: tabular-nums; }

/* The sentence: what was chosen, in words */
.kl-sched__sentence {
  display: flex; gap: 10px; align-items: flex-start; margin: 0; padding: 12px;
  border-radius: var(--kl-radius-groupbox); background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink);
  font: var(--kl-font-label);
}
.kl-sched__sentence .kl-icon { --kl-icon-size: 18px; flex: none; }
.kl-sched__sentence.is-error { background: var(--kl-color-status-stopped-soft); color: var(--kl-color-status-stopped-ink); }

/* Next runs, as a short list with a skip reason where one applies */
.kl-sched__next { display: flex; flex-direction: column; margin: 0; padding: 0 12px; list-style: none;
  border-radius: var(--kl-radius-groupbox); box-shadow: inset 0 0 0 1px var(--kl-color-line); }
.kl-sched > .kl-win__body > .kl-seg--fill .kl-seg__item { flex: 1 1 auto; }   /* the long middle label keeps its width */
.kl-sched__next li {
  display: flex; align-items: center; gap: 10px; padding: 8px 0; border-top: 1px solid var(--kl-color-line);
  font: var(--kl-font-meta); color: var(--kl-color-text); font-variant-numeric: tabular-nums;
}
.kl-sched__next li:first-child { border-top: 0; }
.kl-sched__next li > span:last-child { margin-left: auto; color: var(--kl-color-text-secondary); }
.kl-sched__next li.is-skip { color: var(--kl-color-text-secondary); }
.kl-sched__next li.is-skip > span:nth-child(2) { text-decoration: line-through; }

/* Event source: the thing it listens to, as a row with its own small tile */
.kl-sched__source { display: flex; align-items: center; gap: 10px; }
.kl-sched__source .kl-tool__tile { width: 28px; height: 28px; grid-row: auto; }
.kl-sched__source .kl-tool__tile .kl-icon { --kl-icon-size: 16px; }
.kl-sched__hint { margin: 0; padding: 0 4px; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-sched__hint.is-error { color: var(--kl-color-status-stopped-ink); }
.kl-sched .kl-setting__control .kl-textarea { width: 240px; min-height: 56px; }

/* =====================================================================================================
   6. Inbox section card  .kl-tool.kl-section.kl-section--inbox
      Everything waiting on Alban, across projects. Its own kind hue (indigo until Foundations adds
      --kl-glass-card-inbox). The count is a v2 count badge; it bumps when something new arrives (quiet gate).
   ===================================================================================================== */
.kl-section--inbox { --kl-tool-glass: var(--kl-glass-card-inbox); --kl-section-w: 272px; }
.kl-section--inbox .kl-tool__tile { background: var(--kl-color-card-inbox-soft); color: var(--kl-color-card-inbox-ink); }
.kl-section--inbox > .kl-badge--count { position: absolute; top: -8px; right: -8px; }
.kl-section--inbox.is-empty .kl-tool__tile { background: var(--kl-color-control-fill); color: var(--kl-color-text-secondary); }

/* =====================================================================================================
   7. Inbox window  .kl-win.kl-inbox
      Tabs by kind, two groups (Needs you now: an agent is held until you answer; When you have time:
      results to look at), a row per item. Row actions are secondary; Deny comes first. Handled rows fold
      away with an Undo toast. Done is the one blue action.
   ===================================================================================================== */
.kl-inbox { --kl-win-w: 480px; }
.kl-inbox .kl-tabs { width: 100%; }
.kl-inbox__tabcount { margin-left: 4px; color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-inbox__group { display: flex; flex-direction: column; gap: 8px; }

.kl-inbox-item {
  --kl-inbox-hue: var(--kl-color-project-1);
  position: relative;
  display: grid; grid-template-columns: var(--kl-inbox-tile) minmax(0, 1fr); column-gap: 12px; row-gap: 4px;
  padding: 12px 0; border-top: 1px solid var(--kl-color-line);
  transition: opacity var(--kl-motion-fade) ease;
}
.kl-win-list > .kl-inbox-item:first-child,
.kl-win-list > .kl-m-grow:first-child .kl-inbox-item { border-top: 0; }
.kl-inbox-item__tile {
  grid-row: 1 / span 3; width: var(--kl-inbox-tile); height: var(--kl-inbox-tile);
  display: grid; place-items: center; border-radius: var(--kl-radius-tile);
  background: var(--kl-color-control-fill); color: var(--kl-color-text);
}
.kl-inbox-item__tile .kl-icon { --kl-icon-size: 16px; }
.kl-inbox-item__head { display: flex; align-items: center; gap: 6px; min-width: 0; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-inbox-item__head .kl-win-mark { background: var(--kl-inbox-hue); }
.kl-inbox-item__proj { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); white-space: nowrap; }
.kl-inbox-item__who { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kl-inbox-item__time { margin-left: auto; white-space: nowrap; font-variant-numeric: tabular-nums; }
.kl-inbox-item__title { margin: 0; font: var(--kl-font-label-strong); color: var(--kl-color-text); }
.kl-inbox-item__text { margin: 0; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-inbox-item__cmd {
  margin: 0; padding: 6px 8px; border-radius: var(--kl-radius-control); background: var(--kl-color-surface-sunken);
  font: var(--kl-font-meta); font-family: var(--kl-font-mono); color: var(--kl-color-text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.kl-inbox-item__acts { grid-column: 2; display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
/* Kinds: the tile carries the kind, never a status colour */
.kl-inbox-item--permission .kl-inbox-item__tile,
.kl-inbox-item--question .kl-inbox-item__tile,
.kl-inbox-item--plan .kl-inbox-item__tile { background: var(--kl-color-card-inbox-soft); color: var(--kl-color-card-inbox-ink); }
/* Holding an agent: a small "Agent waiting" note in the head, in the approval ink with .kl-dot--approval.
   Waiting on Alban is never "stopped" (v2 .kl-card.is-asking), so this is magenta, not red */
.kl-inbox-item__held { display: inline-flex; align-items: center; gap: 5px; color: var(--kl-card-approval-ink); white-space: nowrap; }
.kl-inbox-item__held .kl-dot { width: 6px; height: 6px; }
/* Keyboard row: the selection edge, as v2 chosen rows */
.kl-inbox-item.is-current::after {
  content: ""; position: absolute; inset: 4px -8px; border-radius: var(--kl-radius-row);
  box-shadow: inset 0 0 0 2px var(--kl-color-selection); pointer-events: none;
}
/* Handled: folds to one grey line with Undo, then leaves */
.kl-inbox-item.is-done { grid-template-columns: var(--kl-inbox-tile) minmax(0, 1fr) auto; align-items: center; padding: 8px 0; }
.kl-inbox-item.is-done .kl-inbox-item__tile { grid-row: auto; background: transparent; color: var(--kl-color-text-secondary); }
.kl-inbox-item__done { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
/* Leaving: each row sits in Motion's grow, <div class="kl-m-grow is-in"><div><article class="kl-inbox-item">…;
   removing .is-in folds the row shut, then the row is removed. .is-settling on the list, for one frame after the
   removal, stops the rows that move up from replaying the grow */
.kl-win-list.is-settling > .kl-m-grow { transition: none; }
.kl-inbox-item.is-new { animation: kl-reveal var(--kl-motion-reveal) var(--kl-motion-ease-out) both; }

.kl-inbox__empty {
  display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 40px 16px; text-align: center;
  font: var(--kl-font-meta); color: var(--kl-color-text-secondary);
}
.kl-inbox__empty .kl-icon { --kl-icon-size: 32px; color: var(--kl-color-text-tertiary); }
.kl-inbox__empty b { font: var(--kl-font-headline); color: var(--kl-color-text); }
.kl-inbox__keys { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; }
/* Undo toast pinned to the bottom of the window body */
.kl-inbox__toast { position: sticky; bottom: 0; align-self: center; margin-top: auto; }

/* =====================================================================================================
   7b. Waiting on you  .kl-inbox-wait  (top of the Inbox window's All tab)
       Everything that holds an agent until Alban answers, across projects: permission asks and plans
       (Approvals' .kl-permit and .kl-plan), open questions (the question card, .kl-ask) and runs that need him
       (Runs' .kl-runrow in the approval state). Each row says which project and agent asked and how long it
       has waited, answers in place, and jumps to the card on the board (Show).
       Colour: the section and its kind tiles are approval magenta (--kl-card-approval*, the colour of an
       asking card); the Inbox's own chrome stays inbox indigo. Status colours keep their single meaning.
       Few asks: one list, longest wait first. Many (more than 6 asks): grouped by
       project, groups ordered by their longest wait, each group folds to one summary line.
       Nothing moves while Alban works: asks that arrive while his pointer is in the window or he is typing
       wait behind the "new" pill and grow in when he presses it, or after the quiet gate opens.
   ===================================================================================================== */
.kl-inbox-wait { display: flex; flex-direction: column; gap: 8px; }
.kl-inbox-wait__head { display: flex; align-items: center; gap: 8px; min-height: 28px; padding: 0 var(--kl-space-1); }
.kl-inbox-wait__title { margin: 0; font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); color: var(--kl-color-text); white-space: nowrap; }
.kl-inbox-wait__count {
  display: inline-flex; align-items: center; justify-content: center; min-width: 22px; height: 20px; padding: 0 6px; box-sizing: border-box;
  border-radius: var(--kl-radius-pill); background: var(--kl-card-approval-soft); color: var(--kl-card-approval-ink);
  font: var(--kl-font-caption); font-weight: var(--kl-font-weight-semibold); font-variant-numeric: tabular-nums;
}
/* The line under the head: how many projects, and the longest wait */
.kl-inbox-wait__sum { margin: -6px 0 0; padding: 0 var(--kl-space-1) 0 calc(var(--kl-space-1) + 18px); font: var(--kl-font-meta); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-inbox-wait__sum b { color: var(--kl-card-approval-ink); font-weight: var(--kl-font-weight-semibold); }
.kl-inbox-wait__sort { margin-left: auto; flex: none; }

/* Asks that arrived while Alban worked: one quiet pill, nothing shifts until he presses it */
.kl-inbox-wait__new {
  align-self: center; display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 12px 0 10px; border: 0; cursor: pointer;
  border-radius: var(--kl-radius-pill); background: var(--kl-color-surface); color: var(--kl-color-text);
  box-shadow: var(--kl-shadow-menu, 0 0 0 1px var(--kl-color-line)); font: var(--kl-font-meta);
  transition: background-color var(--kl-motion-hover) ease, scale var(--kl-motion-press) var(--kl-motion-spring-pop);
}
.kl-inbox-wait__new .kl-dot { width: 8px; height: 8px; }
.kl-inbox-wait__new b { font-weight: var(--kl-font-weight-semibold); }
.kl-inbox-wait__new:hover, .kl-inbox-wait__new.is-hover { background: var(--kl-color-control-fill); }
.kl-inbox-wait__new:active { scale: .96; }
.kl-inbox-wait__new:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }

/* A waiting row is an Inbox row whose kind tile is the approval colour */
.kl-inbox-item--wait .kl-inbox-item__tile { background: var(--kl-card-approval-soft); color: var(--kl-card-approval-ink); }
.kl-inbox-item__agent { display: inline-flex; align-items: center; gap: 4px; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kl-inbox-item__agent .kl-icon { --kl-icon-size: 14px; flex: none; }
/* How long it has waited. Counts up once a minute with no motion. From --kl-wait-long minutes it reads as
   long: the approval ink, semibold, with the clock, so it never relies on colour alone */
.kl-inbox-item__age { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.kl-inbox-item__age .kl-icon { --kl-icon-size: 14px; display: none; }
.kl-inbox-item__age.is-long { color: var(--kl-card-approval-ink); font-weight: var(--kl-font-weight-semibold); }
.kl-inbox-item__age.is-long .kl-icon { display: inline-block; }
/* Show: jump to the asking card on the board. Last in the actions, pushed right, never blue-filled */
.kl-inbox-item__show { margin-left: auto; }
/* A run that needs Alban: the Runs part's compact run row sits in the row as its detail */
.kl-inbox-item .kl-runrow.kl-runrow--card { padding: 6px 8px; border-radius: var(--kl-radius-control); background: var(--kl-color-surface-sunken); }
.kl-inbox-item .kl-runrow.kl-runrow--card:hover { background: var(--kl-color-surface-sunken); }

/* Many: grouped by project */
.kl-inbox-wait__groups { display: flex; flex-direction: column; gap: 6px; }
.kl-inbox-wait__group {
  --kl-inbox-hue: var(--kl-color-project-1);
  border-radius: var(--kl-radius-row); box-shadow: inset 0 0 0 1px var(--kl-color-line);
}
.kl-inbox-wait__ghead {
  display: grid; grid-template-columns: 28px 14px minmax(0, auto) minmax(0, 1fr) auto; align-items: center; column-gap: 8px;
  min-height: 44px; padding: 0 8px 0 4px; box-sizing: border-box;
  border-radius: var(--kl-radius-row); background: color-mix(in srgb, var(--kl-inbox-hue) 8%, transparent);
}
.kl-inbox-wait__group.is-open .kl-inbox-wait__ghead { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.kl-inbox-wait__ghead .kl-win-mark { background: var(--kl-inbox-hue); }
.kl-inbox-wait__fold .kl-icon { transition: rotate var(--kl-motion-reveal) var(--kl-motion-spring-pop); rotate: -90deg; }
.kl-inbox-wait__group.is-open .kl-inbox-wait__fold .kl-icon { rotate: 0deg; }
.kl-inbox-wait__gname { margin: 0; font: var(--kl-font-label-strong); color: var(--kl-color-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The summary may wrap to a second line on a folded group, so the kinds and the longest wait are never cut */
.kl-inbox-wait__gsum { min-width: 0; padding: 6px 0; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-inbox-wait__gsum b { color: var(--kl-card-approval-ink); font-weight: var(--kl-font-weight-semibold); }
.kl-inbox-wait__gbody { padding: 0 12px 0 12px; }
.kl-inbox-wait__gbody .kl-inbox-item:first-child { border-top: 0; }
/* Inside a group the project is already named: the row head leads with the agent */
.kl-inbox-wait__gbody .kl-inbox-item__head .kl-win-mark,
.kl-inbox-wait__gbody .kl-inbox-item__proj { display: none; }
.kl-inbox-wait__more { align-self: flex-start; }

/* Nothing waits: one calm line, the rest of the Inbox carries on below */
.kl-inbox-wait__empty {
  display: grid; grid-template-columns: var(--kl-inbox-tile) minmax(0, 1fr); column-gap: 12px; align-items: center;
  padding: 10px 12px; border-radius: var(--kl-radius-row); background: var(--kl-color-surface-sunken);
  font: var(--kl-font-meta); color: var(--kl-color-text-secondary);
}
.kl-inbox-wait__empty .kl-inbox-item__tile { grid-row: 1 / span 2; background: var(--kl-color-control-fill); color: var(--kl-color-text-secondary); }
.kl-inbox-wait__empty b { font: var(--kl-font-label-strong); color: var(--kl-color-text); }

/* The Inbox card when something waits on Alban: the count badge takes the approval colour */
.kl-section--inbox.is-asking > .kl-badge--count { background: var(--kl-card-approval); color: var(--kl-color-text-on-fill); }
.kl-section--inbox .kl-tool__meta .kl-inbox-item__age.is-long { margin-left: 0; }

/* Increased contrast: the group frame and the empty line get the strong outline */
[data-contrast="more"] .kl-inbox-wait__group { box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
[data-contrast="more"] .kl-inbox-wait__ghead { background: transparent; }
@media (prefers-contrast: more) {
  .kl-inbox-wait__group { box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
  .kl-inbox-wait__ghead { background: transparent; }
}

/* =====================================================================================================
   8. Notification rules  .kl-win.kl-notify
      Which events ping, on which device (Mac, phone, both, or Inbox only), quiet hours, per-project changes.
      Built from v2 setting rows. Changes save as they are made; Done only closes.
   ===================================================================================================== */
.kl-notify { --kl-win-w: 480px; }
.kl-notify__devs { display: inline-flex; gap: 4px; }
.kl-notify__dev {
  width: var(--kl-notify-dev); height: var(--kl-notify-dev); padding: 0; position: relative;
  display: grid; place-items: center; border: 0; border-radius: var(--kl-radius-control);
  background: transparent; color: var(--kl-color-text-tertiary); cursor: pointer;
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
  transition: background-color var(--kl-motion-hover) ease, color var(--kl-motion-hover) ease, scale var(--kl-motion-press) var(--kl-motion-spring-pop);
}
.kl-notify__dev::before { content: ""; position: absolute; inset: -8px -2px; }
.kl-notify__dev .kl-icon { --kl-icon-size: 16px; }
.kl-notify__dev:hover, .kl-notify__dev.is-hover { background: var(--kl-color-control-fill); }
.kl-notify__dev:active { scale: .92; }
.kl-notify__dev[aria-pressed="true"], .kl-notify__dev.is-on { background: var(--kl-color-control); color: var(--kl-color-text-on-fill); box-shadow: none; }
.kl-notify__dev:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-notify__only { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); white-space: nowrap; }
.kl-notify__range { display: inline-flex; align-items: center; gap: 6px; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-notify__range .kl-field { width: 68px; text-align: center; font-variant-numeric: tabular-nums; }

/* Preview of a ping as it lands on the Mac or phone. Glass: it floats briefly. */
.kl-ping {
  display: grid; grid-template-columns: 32px minmax(0, 1fr) auto; column-gap: 10px; row-gap: 2px; align-items: center;
  width: 100%; box-sizing: border-box; padding: 10px 12px;
  border-radius: var(--kl-radius-glass); background: var(--kl-glass-fill-menu, var(--kl-color-surface));
  -webkit-backdrop-filter: var(--kl-glass-filter); backdrop-filter: var(--kl-glass-filter);
  box-shadow: var(--kl-shadow-menu);
}
.kl-ping__mark { grid-row: 1 / span 2; width: 32px; height: 32px; border-radius: 8px; display: grid; place-items: center;
  background: var(--kl-color-surface-sunken); }
.kl-ping__mark img, .kl-ping__mark svg { width: 22px; height: 22px; }
.kl-ping__app { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-ping__time { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-ping__text { grid-column: 2 / 4; margin: 0; font: var(--kl-font-label); color: var(--kl-color-text); }
.kl-ping__acts { grid-column: 2 / 4; display: flex; gap: 6px; margin-top: 6px; }
.kl-ping.is-quiet { opacity: .55; }

/* =====================================================================================================
   9. Reduced motion: only short fades remain
   ===================================================================================================== */
.kl-motion-reduce .kl-inbox-item.is-new { animation: kl-fade-in var(--kl-motion-fade) ease both; }
.kl-motion-reduce .kl-sched__day, .kl-motion-reduce .kl-notify__dev, .kl-motion-reduce .kl-inbox-wait__new,
.kl-motion-reduce .kl-inbox-wait__fold .kl-icon { transition: none; }
@media (prefers-reduced-motion: reduce) {
  .kl-inbox-item.is-new { animation: kl-fade-in var(--kl-motion-fade) ease both; }
  .kl-inbox-wait__new, .kl-inbox-wait__fold .kl-icon { transition: none; }
}

/* ===== harness/delivery/delivery.css ===== */
/* Klippan master design system: delivery (harness task 11).
   Branch chip, pull request chip with checks and review, the checks panel, output chips, the outputs shelf and the
   Outputs window. Builds on ../../../klippan-v2/combined/klippan.css: link that first, then this file.
   Only --kl-* tokens. Literals are this part's own component sizes, held as local custom properties. */

/* =====================================================================================================
   0. Sizes and the shared chip
   ===================================================================================================== */
:root, [data-theme] {
  --kl-dl-chip-h: 26px;          /* branch and PR chips on cards and run rows */
  --kl-dl-chip-h-mini: 22px;     /* the mini form: full card stage, zoomed out, run rows */
  --kl-dl-out-h: 40px;           /* output chip on the shelf: tile + two lines */
  --kl-dl-out-w: 196px;          /* output chip's longest width before the name truncates */
  --kl-dl-tile: 28px;            /* kind tile inside an output chip */
  --kl-dl-panel-w: 340px;        /* checks panel */
  --kl-dl-peek-w: 260px;         /* quick look on an output chip */
}

/* The chip every delivery piece shares: a small pill that sits on glass (cards) or on a surface (windows, rows).
   Its face is Foundations' chip glass, so the card's tint shows through a little; increased contrast makes it solid. */
.kl-branch, .kl-pr, .kl-output {
  --kl-dl-face: var(--kl-glass-chip);
  --kl-dl-ring: var(--kl-color-line);
  --kl-dl-tint: transparent;
  position: relative;
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  min-width: 0; max-width: 100%;
  height: var(--kl-dl-chip-h);
  padding: 0 10px 0 7px;
  border: 0; border-radius: var(--kl-radius-pill);
  background: var(--kl-dl-face) linear-gradient(var(--kl-dl-tint), var(--kl-dl-tint));
  box-shadow: inset 0 0 0 1px var(--kl-dl-ring);
  color: var(--kl-color-text);
  font: var(--kl-font-badge); font-variant-numeric: tabular-nums;
  white-space: nowrap; text-decoration: none;
  cursor: pointer;
  transition: background-color var(--kl-motion-press) var(--kl-motion-ease-out),
              box-shadow var(--kl-motion-press) var(--kl-motion-ease-out),
              scale var(--kl-motion-press) var(--kl-motion-spring);
}
/* 44 px hit area without growing the chip */
.kl-branch::before, .kl-pr::before, .kl-output::before { content: ""; position: absolute; inset: calc((var(--kl-size-target, 44px) - 100%) / -2) -2px; }
.kl-branch .kl-icon, .kl-pr .kl-icon { --kl-icon-size: 14px; color: var(--kl-color-text-secondary); }
:is(.kl-branch, .kl-pr, .kl-output):hover, :is(.kl-branch, .kl-pr, .kl-output).is-hover { --kl-dl-tint: var(--kl-color-control-fill); }
:is(.kl-branch, .kl-pr, .kl-output):active, :is(.kl-branch, .kl-pr, .kl-output).is-pressed { --kl-dl-tint: var(--kl-color-control-fill-pressed); scale: .97; }
:is(.kl-branch, .kl-pr, .kl-output):focus-visible, :is(.kl-branch, .kl-pr, .kl-output).is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
/* Open: its panel or menu is showing */
:is(.kl-branch, .kl-pr, .kl-output)[aria-expanded="true"], :is(.kl-branch, .kl-pr, .kl-output).is-open {
  --kl-dl-ring: var(--kl-color-selection); --kl-dl-tint: var(--kl-color-selection-soft);
}
/* Mini: icon and the shortest name, for the full card stage, zoomed-out cards and run rows */
.kl-branch--mini, .kl-pr--mini { height: var(--kl-dl-chip-h-mini); padding: 0 8px 0 6px; gap: 5px; }
.kl-branch--mini .kl-icon, .kl-pr--mini .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }

/* =====================================================================================================
   1. Branch chip .kl-branch
      icon · name (prefix quiet, leaf strong, mono) · commits not pushed · worktree mark
   ===================================================================================================== */
.kl-branch__name { display: inline-flex; min-width: 0; overflow: hidden; font-family: var(--kl-font-mono); font-size: 11.5px; letter-spacing: 0; }
.kl-branch__pre { color: var(--kl-color-text-secondary); flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.kl-branch__leaf { flex: 0 0 auto; max-width: 18ch; overflow: hidden; text-overflow: ellipsis; font-weight: var(--kl-font-weight-medium); }
.kl-branch--mini .kl-branch__pre { display: none; }
/* Commits not pushed yet: an up arrow and the count, quiet */
.kl-branch__ahead { display: inline-flex; align-items: center; gap: 2px; color: var(--kl-color-text-secondary); font-weight: var(--kl-font-weight-semibold); }
.kl-branch__ahead .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
/* The worktree mark: a small tile at the end. There = the run works in its own copy; gone = it shares the checkout */
.kl-branch__wt {
  display: inline-grid; place-items: center; flex: none;
  width: 18px; height: 18px; margin-right: -6px; border-radius: 50%;
  background: var(--kl-color-neutral-soft); color: var(--kl-color-neutral-ink);
}
.kl-branch .kl-branch__wt .kl-icon { --kl-icon-size: 11px; --kl-icon-stroke: 2; color: inherit; }
/* Straight on the default branch in a shared checkout: a quiet warning mark, never a status colour */
.kl-branch--default .kl-branch__leaf { font-weight: var(--kl-font-weight-semibold); }
.kl-branch__warn { color: var(--kl-color-text-secondary); }

/* The branch menu: glass, like every v2 menu. Rows of facts, then three plain actions. */
.kl-branch-menu { --kl-menu-w: 280px; }
.kl-branch-menu__facts { display: grid; grid-template-columns: auto 1fr; gap: 6px 12px; padding: 8px 10px 10px; font: var(--kl-font-meta); }
.kl-branch-menu__facts dt { color: var(--kl-color-text-secondary); }
.kl-branch-menu__facts dd { margin: 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kl-branch-menu__facts .kl-mono { font-size: 11.5px; }

/* =====================================================================================================
   2. Pull request chip .kl-pr
      data-state draft | open | merged | closed
      data-checks none | queued | running | passed | failed
      data-review none | waiting | yours | approved | changes
   ===================================================================================================== */
.kl-pr__num { font-weight: var(--kl-font-weight-semibold); }
.kl-pr__word { color: var(--kl-color-text-secondary); }
.kl-pr__sep { width: 1px; height: 12px; background: var(--kl-color-line-strong); flex: none; }
.kl-pr__checks, .kl-pr__review { display: inline-flex; align-items: center; gap: 4px; }
.kl-pr__checks .kl-icon, .kl-pr__review .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
/* The check glyph: a 7 px dot while queued or running, a check when all pass, a cross when one fails */
.kl-pr__dot { width: 7px; height: 7px; flex: none; border-radius: 50%; background: currentColor; }
.kl-pr[data-checks="queued"] .kl-pr__checks { color: var(--kl-color-text-secondary); }
.kl-pr[data-checks="queued"] .kl-pr__dot { color: var(--kl-color-status-idle); }
.kl-pr[data-checks="running"] .kl-pr__dot { color: var(--kl-color-status-executing); }
.kl-pr[data-checks="passed"] .kl-pr__checks .kl-icon { color: var(--kl-color-status-executing-ink); }
.kl-pr[data-checks="failed"] .kl-pr__checks { color: var(--kl-color-status-stopped-ink); font-weight: var(--kl-font-weight-semibold); }
.kl-pr[data-checks="failed"] .kl-pr__checks .kl-icon { color: var(--kl-color-status-stopped-ink); }
/* Review: only the two states that ask for something carry weight */
.kl-pr__review { color: var(--kl-color-text-secondary); }
.kl-pr[data-review="yours"] .kl-pr__review { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }
.kl-pr[data-review="approved"] .kl-pr__review, .kl-pr[data-review="approved"] .kl-pr__review .kl-icon { color: var(--kl-color-status-executing-ink); }
.kl-pr[data-review="changes"] .kl-pr__review, .kl-pr[data-review="changes"] .kl-pr__review .kl-icon { color: var(--kl-color-status-planning-ink); }
/* Draft: a dashed edge instead of the hairline */
.kl-pr[data-state="draft"] { --kl-dl-ring: transparent; outline: 1px dashed var(--kl-color-line-strong); outline-offset: -1px; }
.kl-pr[data-state="draft"]:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
/* Merged: done, so the chip goes quiet and solid grey; the merged mark replaces the PR icon */
.kl-pr[data-state="merged"] { --kl-dl-face: var(--kl-color-neutral-soft); --kl-dl-ring: transparent; color: var(--kl-color-neutral-ink); }
.kl-pr[data-state="merged"] .kl-icon, .kl-pr[data-state="merged"] .kl-pr__word { color: var(--kl-color-neutral-ink); }
/* Closed without merging: everything drops to tertiary */
.kl-pr[data-state="closed"] { color: var(--kl-color-text-secondary); }
.kl-pr[data-state="closed"] .kl-pr__num { text-decoration: line-through; text-decoration-color: var(--kl-color-text-tertiary); }

/* The PR line on an expanded card: title over the chip, so the chip never has to hold the title */
.kl-prline { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.kl-prline__title { display: flex; align-items: baseline; gap: 6px; min-width: 0; margin: 0; font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-prline__title span:first-child { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-prline__lines { flex: none; font: var(--kl-font-caption); font-variant-numeric: tabular-nums; color: var(--kl-color-text-secondary); }
.kl-prline__chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0; }
.kl-prline__note { margin: 0; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); display: flex; align-items: center; gap: 5px; }
.kl-prline__note .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }

/* =====================================================================================================
   3. Checks panel .kl-checks: opens beside the PR chip. Opaque, since it is read.
      head (PR, branch into base, state badge) · Checks rows · Review rows · foot (note, one blue action at most)
   ===================================================================================================== */
.kl-checks {
  display: flex; flex-direction: column;
  width: var(--kl-dl-panel-w); max-width: 100%;
  border-radius: var(--kl-radius-menu);
  background: var(--kl-color-surface);
  box-shadow: var(--kl-shadow-menu), 0 0 0 1px var(--kl-color-line);
  color: var(--kl-color-text);
  overflow: hidden;
}
.kl-checks__head { display: grid; grid-template-columns: auto 1fr auto; gap: 2px 10px; align-items: center; padding: 14px 14px 12px; border-bottom: 1px solid var(--kl-color-line); }
.kl-checks__head > .kl-icon-tile { grid-row: span 2; --kl-icon-tile: 32px; }
.kl-checks__head .kl-icon { --kl-icon-size: 16px; }
.kl-checks__title { margin: 0; min-width: 0; font: var(--kl-font-headline); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-checks__route { grid-column: 2 / -1; display: flex; align-items: center; gap: 5px; min-width: 0; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-checks__route .kl-mono { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kl-checks__route .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
.kl-checks__sec { padding: 10px 14px 4px; }
.kl-checks__label { display: flex; justify-content: space-between; margin: 0 0 4px; font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-checks__label span { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-checks__list { list-style: none; margin: 0; padding: 0; }
.kl-checks__row { display: grid; grid-template-columns: 16px 1fr auto; align-items: center; gap: 2px 10px; min-height: 32px; padding: 4px 0; font: var(--kl-font-meta); }
.kl-checks__row + .kl-checks__row { border-top: 1px solid var(--kl-color-line); }
.kl-checks__glyph { display: grid; place-items: center; width: 16px; height: 16px; }
.kl-checks__glyph .kl-icon { --kl-icon-size: 14px; }
.kl-checks__glyph .kl-pr__dot { width: 8px; height: 8px; }
.kl-checks__time { color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-checks__row.is-running .kl-checks__glyph { color: var(--kl-color-status-executing); }
.kl-checks__row.is-queued .kl-checks__glyph { color: var(--kl-color-status-idle); }
.kl-checks__row.is-passed .kl-checks__glyph { color: var(--kl-color-status-executing-ink); }
.kl-checks__row.is-failed .kl-checks__glyph, .kl-checks__row.is-failed .kl-checks__name { color: var(--kl-color-status-stopped-ink); }
.kl-checks__row.is-failed .kl-checks__name { font-weight: var(--kl-font-weight-semibold); }
/* What the agent is doing about a failure: one line under the failed row, agent icon first */
.kl-checks__fix { grid-column: 2 / -1; display: flex; align-items: center; gap: 6px; color: var(--kl-color-text-secondary); font: var(--kl-font-caption); }
.kl-checks__fix .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
.kl-checks__who { display: inline-grid; place-items: center; width: 16px; height: 16px; border-radius: 50%;
  background: var(--kl-color-neutral-soft); color: var(--kl-color-neutral-ink); font: var(--kl-font-caption); font-size: 9px; font-weight: var(--kl-font-weight-bold); }
.kl-checks__row.is-yours .kl-checks__who { background: var(--kl-color-text); color: var(--kl-color-surface); }
.kl-checks__state { color: var(--kl-color-text-secondary); }
.kl-checks__row.is-yours .kl-checks__state { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }
.kl-checks__row.is-approved .kl-checks__state { color: var(--kl-color-status-executing-ink); }
.kl-checks__row.is-changes .kl-checks__state { color: var(--kl-color-status-planning-ink); }
.kl-checks__foot { display: flex; align-items: center; gap: 8px; margin-top: 6px; padding: 10px 14px 12px; border-top: 1px solid var(--kl-color-line); }
.kl-checks__note { flex: 1 1 auto; margin: 0; min-width: 0; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }

/* =====================================================================================================
   4. Output chip .kl-output: a file, page, link or image a run made.
      tile (kind icon) · name over meta · new mark | Retry
      data-kind file | page | link | image | sheet
   ===================================================================================================== */
.kl-output {
  height: var(--kl-dl-out-h); max-width: var(--kl-dl-out-w);
  padding: 0 12px 0 6px; gap: 8px;
  border-radius: var(--kl-radius-row);
  font: var(--kl-font-meta);
}
.kl-output::before { inset: -2px; }
.kl-output__tile {
  display: inline-grid; place-items: center; flex: none;
  width: var(--kl-dl-tile); height: var(--kl-dl-tile); border-radius: var(--kl-radius-tile);
  background: var(--kl-color-control-fill); color: var(--kl-color-text-secondary);
}
.kl-output__tile .kl-icon { --kl-icon-size: 16px; }
.kl-output__text { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
.kl-output__name { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-output__meta { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-output[data-kind="file"] .kl-output__name, .kl-output[data-kind="sheet"] .kl-output__name { font-family: var(--kl-font-mono); font-size: 11.5px; font-weight: var(--kl-font-weight-medium); }
/* New since Alban last looked: a primary dot on the tile's corner, the same blue as v2's unread counts */
.kl-output__tile { position: relative; }
.kl-output.is-new .kl-output__tile::after {
  content: ""; position: absolute; top: -3px; right: -3px; width: 9px; height: 9px; border-radius: 50%;
  background: var(--kl-color-primary); box-shadow: 0 0 0 2px var(--kl-color-surface);
}
/* Couldn't be delivered: red meta line, Retry at the end. The chip stays; nothing is lost. */
.kl-output.is-failed { --kl-dl-ring: var(--kl-color-status-stopped); padding-right: 4px; }
.kl-output.is-failed .kl-output__meta { color: var(--kl-color-status-stopped-ink); font-weight: var(--kl-font-weight-semibold); }
.kl-output.is-failed .kl-output__tile { color: var(--kl-color-status-stopped-ink); background: var(--kl-color-status-stopped-soft); }
.kl-output__retry { --kl-iconbtn: 28px; flex: none; }
.kl-output__retry .kl-icon { --kl-icon-size: 14px; }
/* Being dragged (onto the prompter to attach it, or onto another card) */
.kl-output.is-dragging { --kl-dl-face: var(--kl-color-surface); box-shadow: var(--kl-shadow-card-lifted), inset 0 0 0 1px var(--kl-dl-ring); rotate: var(--kl-motion-lean, 0deg); scale: 1.04; z-index: 44; }
/* Moved to the archive: the chip leaves the shelf and the Undo toast takes over */
.kl-output.is-leaving { opacity: 0; scale: .9; transition: opacity var(--kl-motion-fade-out) var(--kl-motion-ease-in), scale var(--kl-motion-fade-out) var(--kl-motion-ease-in); }
/* Small: one line, for run rows and the transcript */
.kl-output--sm { height: var(--kl-dl-chip-h); padding: 0 10px 0 4px; gap: 6px; border-radius: var(--kl-radius-pill); }
.kl-output--sm .kl-output__tile { width: 20px; height: 20px; border-radius: 50%; }
.kl-output--sm .kl-output__tile .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
.kl-output--sm .kl-output__name { font: var(--kl-font-badge); }
.kl-output--sm .kl-output__meta { display: none; }

/* Quick look: hover or Space on an output chip. Glass, since it floats briefly. */
.kl-peek {
  display: flex; flex-direction: column; gap: 10px;
  width: var(--kl-dl-peek-w); padding: 8px 8px 10px;
  border-radius: var(--kl-radius-menu);
  background: var(--kl-glass-fill-menu); color: var(--kl-color-text);
  -webkit-backdrop-filter: blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));
  backdrop-filter: blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));
  box-shadow: var(--kl-shadow-menu), var(--kl-glass-rim);
}
.kl-peek__shot {
  position: relative; height: 132px; border-radius: var(--kl-radius-row); overflow: hidden;
  background: var(--kl-color-surface); box-shadow: inset 0 0 0 1px var(--kl-color-line);
  padding: 14px 16px; display: flex; flex-direction: column; gap: 7px;
}
/* A drawn stand-in for the preview: headline bar, text lines. The real app shows a thumbnail. */
.kl-peek__shot i { display: block; height: 6px; border-radius: 3px; background: var(--kl-color-control-fill-pressed); }
.kl-peek__shot i:first-child { height: 10px; width: 56%; background: var(--kl-color-line-strong); margin-bottom: 4px; }
.kl-peek__text { display: flex; flex-direction: column; gap: 2px; padding: 0 6px; min-width: 0; }
.kl-peek__name { font: var(--kl-font-label-strong); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-peek__meta { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-peek__acts { display: flex; flex-wrap: wrap; gap: 2px; padding: 0 2px; }

/* =====================================================================================================
   5. Outputs shelf .kl-shelf: the expanded card's tray of outputs, newest first.
      head (Outputs, count, Show all) · tray (two rows of chips at most, then a "+N" chip)
   ===================================================================================================== */
.kl-shelf { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.kl-shelf__head { display: flex; align-items: center; gap: 6px; min-height: 24px; }
.kl-shelf__title { margin: 0; font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); }
.kl-shelf__count { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-shelf__head .kl-btn { margin-left: auto; }
.kl-shelf__tray {
  display: flex; flex-wrap: wrap; align-content: flex-start; gap: 6px;
  max-height: calc(var(--kl-dl-out-h) * 2 + 6px + 12px);
  padding: 6px; border-radius: calc(var(--kl-radius-row) + 6px);
  background: var(--kl-color-control-fill);
  overflow: hidden;
}
.kl-shelf__more {
  display: inline-grid; place-items: center; flex: none;
  min-width: var(--kl-dl-out-h); height: var(--kl-dl-out-h); padding: 0 10px;
  border: 0; border-radius: var(--kl-radius-row);
  background: transparent; box-shadow: inset 0 0 0 1px var(--kl-color-line-strong);
  color: var(--kl-color-text); font: var(--kl-font-label-strong); font-variant-numeric: tabular-nums; cursor: pointer;
}
.kl-shelf__more:hover { background: var(--kl-color-control-fill); }
.kl-shelf__more:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }
.kl-shelf__empty { margin: 0; padding: 8px 6px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
/* A drop target while an output chip or file is dragged over the card */
.kl-shelf.is-target .kl-shelf__tray { box-shadow: inset 0 0 0 2px var(--kl-color-selection); background: var(--kl-color-selection-soft); }

/* The delivery block on an expanded project card: branch, PR line, then the shelf */
.kl-delivery { display: flex; flex-direction: column; gap: 12px; padding-top: 12px; border-top: 1px solid var(--kl-color-line); min-width: 0; }
.kl-delivery__row { display: flex; align-items: center; gap: 6px; min-width: 0; flex-wrap: wrap; }
/* At the full stage, one mini line under the status: PR then branch. It fades with the status line. */
.kl-card__delivery {
  display: flex; align-items: center; gap: 6px; min-width: 0; overflow: hidden;
  opacity: var(--kl-ol); translate: 0 calc(6px * (1 - var(--kl-ol)));
}
.kl-card[data-stage="0"] .kl-card__delivery, .kl-card[data-stage="1"] .kl-card__delivery, .kl-card[data-stage="3"] .kl-card__delivery { display: none; }
.kl-card__delivery > .kl-branch { flex: 0 1 auto; }
.kl-card__delivery .kl-branch__leaf { flex-shrink: 1; min-width: 0; }
/* The delivery line takes the second status line's place, so the full stage keeps its 140 height */
.kl-card[data-stage="2"]:has(.kl-card__delivery) .kl-card__status { -webkit-line-clamp: 1; }

/* =====================================================================================================
   6. Outputs window .kl-win--outputs (v2 window frame): every output of a project, grouped by run
   ===================================================================================================== */
.kl-win--outputs { --kl-win-w: 440px; }
.kl-outrow {
  display: grid; grid-template-columns: auto 1fr auto auto; align-items: center; gap: 10px;
  min-height: 48px; padding: 4px 4px 4px 6px; border-radius: var(--kl-radius-row);
}
.kl-outrow:hover, .kl-outrow.is-hover { background: var(--kl-color-control-fill); }
.kl-outrow .kl-output__tile { width: 32px; height: 32px; }
.kl-outrow__text { display: flex; flex-direction: column; min-width: 0; }
.kl-outrow__name { font: var(--kl-font-label-strong); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-outrow__name.kl-mono { font-size: 12px; font-weight: var(--kl-font-weight-medium); }
.kl-outrow__meta { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-outrow__time { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
.kl-outrow.is-new .kl-output__tile { position: relative; }
.kl-outrow.is-new .kl-output__tile::after { content: ""; position: absolute; top: -3px; right: -3px; width: 9px; height: 9px; border-radius: 50%; background: var(--kl-color-primary); box-shadow: 0 0 0 2px var(--kl-color-surface); }
.kl-outrow.is-failed .kl-outrow__meta { color: var(--kl-color-status-stopped-ink); font-weight: var(--kl-font-weight-semibold); }
.kl-outrow.is-failed .kl-output__tile { background: var(--kl-color-status-stopped-soft); color: var(--kl-color-status-stopped-ink); }

/* =====================================================================================================
   7. Motion. Durations and curves are --kl-motion-* tokens; every overshoot scales with --kl-motion-k.
      Signals (a running check's dot) are allowed; everything else is one-shot and waits for KlMotion's quiet gate.
   ===================================================================================================== */
@media (prefers-reduced-motion: no-preference) {
  /* A running check breathes like an executing status dot (a signal, so not ambient) */
  .kl-pr[data-checks="running"] .kl-pr__dot, .kl-checks__row.is-running .kl-pr__dot { animation: kl-dl-breathe var(--kl-motion-dot-executing) ease-in-out infinite; }
  /* A check glyph that just changed pops once (check, cross, or the dot coming back) */
  .kl-pr__checks.is-changed > :first-child { animation: kl-dl-pop var(--kl-motion-dot-pop) var(--kl-motion-spring-pop); }
  /* A chip whose PR just merged gives one soft swell */
  .kl-pr.is-merging { animation: kl-dl-swell var(--kl-motion-land) var(--kl-motion-spring-soft); }
  /* A new output lands on the shelf: in from a little smaller and above, on the pop spring */
  .kl-output.is-arriving { animation: kl-dl-arrive var(--kl-motion-say-in) var(--kl-motion-spring-pop) backwards; }
  /* Panels and the quick look open like v2 menus */
  .kl-checks.is-opening, .kl-peek.is-opening, .kl-branch-menu.is-opening { animation: kl-dl-menu-in var(--kl-motion-menu-in) var(--kl-motion-spring) backwards; transform-origin: top left; }
}
@keyframes kl-dl-breathe { 0%, 100% { opacity: 1; scale: 1; } 50% { opacity: .55; scale: .82; } }
@keyframes kl-dl-pop { 0% { scale: calc(1 - .5 * var(--kl-motion-k, .35)); opacity: .2; } 100% { scale: 1; opacity: 1; } }
@keyframes kl-dl-swell { 0% { scale: 1; } 40% { scale: calc(1 + .12 * var(--kl-motion-k, .35)); } 100% { scale: 1; } }
@keyframes kl-dl-arrive {
  0% { opacity: 0; scale: calc(1 - .4 * var(--kl-motion-k, .35)); translate: 0 calc(-12px * var(--kl-motion-k, .35)); }
  45% { opacity: 1; }
  100% { opacity: 1; scale: 1; translate: 0 0; }
}
@keyframes kl-dl-menu-in { 0% { opacity: 0; scale: .96; translate: 0 -4px; } 100% { opacity: 1; scale: 1; translate: 0 0; } }
@keyframes kl-dl-fade { 0% { opacity: 0; } 100% { opacity: 1; } }
/* Reduced motion: no breathing, no pops; new things fade in quickly, and that is all */
@media (prefers-reduced-motion: reduce) {
  .kl-output.is-arriving, .kl-checks.is-opening, .kl-peek.is-opening, .kl-branch-menu.is-opening { animation: kl-dl-fade var(--kl-motion-fade) linear backwards; }
  .kl-branch, .kl-pr, .kl-output { transition: none; }
}
.kl-motion-reduce :is(.kl-pr__dot, .kl-pr__checks > :first-child, .kl-pr.is-merging) { animation: none !important; }
.kl-motion-reduce :is(.kl-output.is-arriving, .kl-checks.is-opening, .kl-peek.is-opening, .kl-branch-menu.is-opening) { animation: kl-dl-fade var(--kl-motion-fade) linear backwards !important; }
.kl-motion-reduce :is(.kl-branch, .kl-pr, .kl-output) { transition: none !important; }

/* =====================================================================================================
   8. Increased contrast: chips go solid with a strong edge (cards already turn solid through Foundations)
   ===================================================================================================== */
[data-contrast="more"] :is(.kl-branch, .kl-pr, .kl-output), :is(.kl-branch, .kl-pr, .kl-output)[data-contrast="more"] {
  --kl-dl-face: var(--kl-color-surface); --kl-dl-ring: var(--kl-color-line-strong);
}
[data-contrast="more"] .kl-pr[data-state="merged"] { --kl-dl-ring: var(--kl-color-line-strong); }
[data-contrast="more"] .kl-shelf__tray { background: transparent; box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
@media (prefers-contrast: more) {
  .kl-branch, .kl-pr, .kl-output { --kl-dl-face: var(--kl-color-surface); --kl-dl-ring: var(--kl-color-line-strong); }
  .kl-shelf__tray { background: transparent; box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
}
@media (forced-colors: active) {
  .kl-branch, .kl-pr, .kl-output, .kl-checks, .kl-peek, .kl-shelf__more { border: 1px solid ButtonText; }
  .kl-pr__dot, .kl-output.is-new .kl-output__tile::after { background: Highlight; }
}

/* ===== harness/projects/home.css ===== */
/* =====================================================================================================
   Klippan master DS · Many projects · 1. Projects home
   The whole board seen as projects. A calm layer over the board spreads every project as a tile, in three loose
   groups (Needs you, Running, Quiet), with the Archive stack in a corner and the New project tile with the quiet ones.

   Builds on v2: load ../../../klippan-v2/combined/klippan.css first. Every value is a --kl-* token or a local size
   (--kl-ptile-*, --kl-home-*). New tokens are read through a fallback and listed in NEEDS.md.

   Pieces
     .kl-section.kl-section--projects   the Projects card on the board (v2 section shell, 212 x 72)
     .kl-ptile                          project tile (248 x 116): wrapper holds size and tilt, __face is the glass
     .kl-archive                        the Archive stack: two sheets behind a .kl-tool face
     .kl-archive-win                    the Archive window (.kl-win, opaque, 380)
     .kl-home                           the layer: __group captions, __hint
   ===================================================================================================== */

/* ---- Projects card ------------------------------------------------------------------------------------ */
/* Neutral glass: it holds every hue, so it takes none (NEEDS.md: --kl-glass-card-projects) */
.kl-section--projects { --kl-tool-glass: var(--kl-glass-card-projects); }
.kl-section--projects .kl-tool__meta b, .kl-section--projects .kl-tool__meta.is-waiting { font-weight: var(--kl-font-weight-semibold); color: var(--kl-card-approval-ink); }
.kl-section--projects.is-open .kl-tool__meta b { color: inherit; }
/* Its hover hint names the shortcut */
.kl-section__hint { position: absolute; left: 50%; top: calc(100% + 8px); translate: -50% 0; z-index: 3; }

/* ---- Project tile -------------------------------------------------------------------------------------- */
.kl-ptile {
  --kl-ptile-w: 248px;
  --kl-ptile-h: 116px;
  --kl-ptile-glass: var(--kl-glass-card);
  --kl-ptile-hue: var(--kl-color-accent);
  --kl-ptile-name: var(--kl-font-title);                 /* the project card's name style, so a tile reads as its card */
  position: relative;
  flex: none;
  width: var(--kl-ptile-w);
  height: var(--kl-ptile-h);
  border-radius: var(--kl-radius-card);
}
.kl-ptile--p1 { --kl-ptile-glass: var(--kl-glass-card-project-1); --kl-ptile-hue: var(--kl-color-project-1); }
.kl-ptile--p2 { --kl-ptile-glass: var(--kl-glass-card-project-2); --kl-ptile-hue: var(--kl-color-project-2); }
.kl-ptile--p3 { --kl-ptile-glass: var(--kl-glass-card-project-3); --kl-ptile-hue: var(--kl-color-project-3); }
.kl-ptile--p4 { --kl-ptile-glass: var(--kl-glass-card-project-4); --kl-ptile-hue: var(--kl-color-project-4); }
.kl-ptile--p5 { --kl-ptile-glass: var(--kl-glass-card-project-5); --kl-ptile-hue: var(--kl-color-project-5); }
.kl-ptile--p6 { --kl-ptile-glass: var(--kl-glass-card-project-6); --kl-ptile-hue: var(--kl-color-project-6); }
.kl-ptile--p7 { --kl-ptile-glass: var(--kl-glass-card-project-7); --kl-ptile-hue: var(--kl-color-project-7); }
.kl-ptile--p8 { --kl-ptile-glass: var(--kl-glass-card-project-8); --kl-ptile-hue: var(--kl-color-project-8); }

/* The face is the one big button: click opens the project (Home closes, the board glides to its card) */
.kl-ptile__face {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; justify-content: center; gap: 2px;
  box-sizing: border-box; width: 100%; margin: 0;
  padding: 14px 16px 14px 40px;                         /* 40: the dot column, as on the project card */
  border: 1px solid transparent; border-radius: inherit;
  background: var(--kl-ptile-glass);
  -webkit-backdrop-filter: var(--kl-glass-card-filter); backdrop-filter: var(--kl-glass-card-filter);
  box-shadow: var(--kl-glass-card-shadow);
  color: var(--kl-color-text); font: var(--kl-font-body); text-align: left;
  cursor: pointer; outline: 0;
  transition: box-shadow var(--kl-motion-hover) ease, border-color var(--kl-motion-hover) ease,
              translate var(--kl-motion-lift) var(--kl-motion-spring), scale var(--kl-motion-press) var(--kl-motion-ease-out);
}
/* Status dot: 10 px, centred top to bottom at the left, like the card at compact and full */
.kl-ptile__dot { position: absolute; left: 20px; top: calc(50% - 5px); width: 10px; height: 10px; }
.kl-ptile__dot > .kl-dot { position: absolute; inset: 0; }
.kl-ptile__name {
  display: flex; align-items: center; gap: 6px; min-width: 0; padding-right: 40px;   /* clear of the pin and more */
  font: var(--kl-ptile-name); letter-spacing: var(--kl-font-title-tracking);
}
.kl-ptile__name > span { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.kl-ptile__facts {
  display: inline-flex; align-items: center; gap: 5px; margin-top: 2px;
  font: var(--kl-font-meta); font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text-secondary);
  font-variant-numeric: tabular-nums;
}
.kl-ptile__facts .kl-icon { --kl-icon-size: 14px; }
.kl-ptile__last {
  display: block; min-width: 0;
  font: var(--kl-font-meta); color: var(--kl-color-text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Corner: the pin mark rests here; on hover or focus the more button joins it */
.kl-ptile__corner { position: absolute; top: 10px; right: 10px; z-index: 2; display: flex; align-items: center; gap: 2px; }
.kl-ptile__pin { --kl-icon-size: 14px; display: none; width: 28px; height: 28px; padding: 7px; box-sizing: border-box; color: var(--kl-color-text-secondary); }
.kl-ptile.is-pinned .kl-ptile__pin { display: block; }
.kl-ptile__more { opacity: 0; scale: .9; transition: opacity var(--kl-motion-hover) ease, scale var(--kl-motion-hover) var(--kl-motion-spring-pop); }
.kl-ptile:hover .kl-ptile__more, .kl-ptile:focus-within .kl-ptile__more, .kl-ptile.is-hover .kl-ptile__more,
.kl-ptile.is-menu .kl-ptile__more, .kl-ptile__more[aria-expanded="true"] { opacity: 1; scale: 1; }
.kl-ptile__menu { position: absolute; top: 44px; right: -4px; z-index: var(--kl-z-menu); --kl-menu-w: 196px; --kl-menu-origin: top right; }

/* -- States -- */
/* Hover: lifts a little (2 px, a touch more as the dial rises) and takes the hover glass shadow */
.kl-ptile:hover .kl-ptile__face, .kl-ptile.is-hover .kl-ptile__face, .kl-ptile.is-menu .kl-ptile__face {
  translate: 0 calc(-2px - 2px * var(--kl-motion-k)); box-shadow: var(--kl-glass-card-shadow-hover);
}
.kl-ptile__face:active, .kl-ptile.is-pressed .kl-ptile__face { scale: .98; translate: 0 0; }
/* Keyboard focus: the focus ring, outside the glass */
.kl-ptile__face:focus-visible, .kl-ptile.is-focus .kl-ptile__face { box-shadow: 0 0 0 2px var(--kl-color-focus), 0 0 0 5px var(--kl-color-selection-soft), var(--kl-glass-card-shadow); }

/* Needs you: the approval (magenta) dot held still, short rays round it, the facts in approval ink. Never red: red is stopped */
.kl-ptile.is-waiting .kl-ptile__facts { color: var(--kl-card-approval-ink); }
.kl-ptile__rays {
  position: absolute; inset: -7px; border-radius: var(--kl-radius-round); pointer-events: none;
  /* eight short ticks on a ring: a conic dash masked to a 3 px band */
  background: repeating-conic-gradient(from -11.25deg, var(--kl-card-approval) 0 22.5deg, transparent 22.5deg 45deg);
  -webkit-mask: radial-gradient(closest-side, transparent calc(100% - 3px), var(--kl-color-text) calc(100% - 3px));
  mask: radial-gradient(closest-side, transparent calc(100% - 3px), var(--kl-color-text) calc(100% - 3px));
}
/* Running and planning: the dot pulses as on v2 (kl-m-dot kl-m-dot--executing / --planning on the dot) */
.kl-ptile.is-running .kl-ptile__facts .kl-icon { color: var(--kl-color-status-executing-ink); }
.kl-ptile.is-planning .kl-ptile__facts .kl-icon { color: var(--kl-color-status-planning-ink); }
/* Quiet: idle dot, facts read quieter */
.kl-ptile.is-quiet .kl-ptile__facts { font-weight: var(--kl-font-weight-regular); }

/* Selected (picking several to archive): the selection edge plus the round check */
.kl-ptile.is-selected .kl-ptile__face { border-color: var(--kl-color-selection); box-shadow: 0 0 0 1px var(--kl-color-selection), var(--kl-glass-card-shadow); }
.kl-ptile__check { position: absolute; top: -8px; right: -8px; z-index: 3; box-shadow: 0 0 0 3px var(--kl-color-surface); }
.kl-ptile.is-selected .kl-ptile__corner { visibility: hidden; }
/* Picking: tiles not yet picked show an empty ring where the check lands */
.kl-ptile.is-pickable:not(.is-selected)::after {
  content: ""; position: absolute; top: -6px; right: -6px; z-index: 3; width: 20px; height: 20px; border-radius: var(--kl-radius-round);
  background: var(--kl-color-surface); box-shadow: inset 0 0 0 1.5px var(--kl-color-line-strong);
}
.kl-ptile.is-pickable .kl-ptile__corner { visibility: hidden; }

/* Just archived: leaves toward the Archive stack (--kl-ptile-to-x/y: the vector to it) and shrinks into it.
   .is-frozen holds it mid-flight for the specimen. */
.kl-ptile.is-archiving { pointer-events: none; }
.kl-ptile.is-archiving .kl-ptile__face { translate: var(--kl-ptile-to-x, 0px) var(--kl-ptile-to-y, 0px); scale: .5; opacity: 0; }
.kl-ptile.is-archiving.is-frozen .kl-ptile__face { translate: calc(var(--kl-ptile-to-x, 0px) * .4) calc(var(--kl-ptile-to-y, 0px) * .4); scale: .8; opacity: .6; }
.kl-ptile.is-archiving .kl-ptile__corner { visibility: hidden; }
/* The empty spot it left: a faint outline that fades with the Undo toast */
.kl-ptile__ghost { position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 1.5px var(--kl-color-line); pointer-events: none; }
@media (prefers-reduced-motion: no-preference) {
  .kl-ptile.is-archiving:not(.is-frozen) .kl-ptile__face { animation: kl-ptile-leave var(--kl-motion-collapse) var(--kl-motion-ease-in) both; }
  /* Just restored: rises back into its spot, then the small dial-scaled landing */
  .kl-ptile.is-restored .kl-ptile__face { animation: kl-reveal var(--kl-motion-reveal) var(--kl-motion-ease-out) backwards, kl-land var(--kl-motion-land) ease-out var(--kl-motion-reveal); }
}
@keyframes kl-ptile-leave {
  from { translate: 0 0; scale: 1; opacity: 1; }
  to { translate: var(--kl-ptile-to-x, 0px) var(--kl-ptile-to-y, 0px); scale: .5; opacity: 0; }
}
/* Restored: one soft ring in its hue, gone after the toast */
.kl-ptile.is-restored .kl-ptile__face { box-shadow: 0 0 0 2px color-mix(in srgb, var(--kl-ptile-hue) 60%, transparent), var(--kl-glass-card-shadow); }

/* ---- Archive stack ------------------------------------------------------------------------------------- */
/* Wrapper holds the tilt and the two sheets; the face is a .kl-tool */
.kl-archive {
  --kl-archive-w: 220px;
  --kl-archive-fan: calc(1deg + 2deg * var(--kl-motion-k));   /* how far the sheets fan on hover: scales with the dial */
  position: relative; flex: none; width: var(--kl-archive-w); height: var(--kl-section-h);
  isolation: isolate;
}
.kl-archive__sheet {
  position: absolute; inset: 0; z-index: -1; border-radius: var(--kl-radius-panel);
  background: var(--kl-archive-glass, var(--kl-glass-card));
  -webkit-backdrop-filter: var(--kl-glass-card-filter); backdrop-filter: var(--kl-glass-card-filter);
  box-shadow: var(--kl-glass-card-shadow);
  transition: translate var(--kl-motion-lift) var(--kl-motion-spring), rotate var(--kl-motion-lift) var(--kl-motion-spring);
}
.kl-archive__sheet--back { translate: 10px -10px; rotate: 3deg; }
.kl-archive__sheet--mid { translate: 5px -5px; rotate: 1.5deg; }
.kl-archive > .kl-tool { position: relative; width: 100%; height: 100%; }
.kl-archive .kl-tool__name { font-variant-numeric: tabular-nums; }
.kl-archive:hover .kl-archive__sheet--back, .kl-archive.is-hover .kl-archive__sheet--back { translate: 14px -13px; rotate: calc(3deg + var(--kl-archive-fan)); }
.kl-archive:hover .kl-archive__sheet--mid, .kl-archive.is-hover .kl-archive__sheet--mid { translate: 7px -7px; rotate: calc(1.5deg + var(--kl-archive-fan) / 2); }
.kl-archive.is-hover > .kl-tool { box-shadow: var(--kl-glass-card-shadow-hover); }
/* Each sheet carries the hue of a project filed in it */
.kl-archive__sheet.kl-ptile--p1 { --kl-archive-glass: var(--kl-glass-card-project-1); }
.kl-archive__sheet.kl-ptile--p3 { --kl-archive-glass: var(--kl-glass-card-project-3); }
.kl-archive__sheet.kl-ptile--p6 { --kl-archive-glass: var(--kl-glass-card-project-6); }
.kl-archive__sheet.kl-ptile--p8 { --kl-archive-glass: var(--kl-glass-card-project-8); }
/* Open: its window is up (v2 section open look) */
.kl-archive.is-open > .kl-tool { border-color: var(--kl-color-selection); box-shadow: 0 0 0 1px var(--kl-color-selection), var(--kl-glass-card-shadow); }
.kl-archive.is-open .kl-tool__tile { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
/* Receiving: a tile is on its way in; the stack rises 3 px to take it and the count bumps (kl-m-count-bump) */
.kl-archive.is-receiving > .kl-tool { box-shadow: var(--kl-glass-card-shadow-hover); translate: 0 -3px; }
.kl-archive__n { display: inline-block; }
/* Empty: one dashed sheet, nothing behind */
.kl-archive.is-empty .kl-archive__sheet { display: none; }
.kl-archive.is-empty > .kl-tool { background: transparent; box-shadow: none; border: 1.5px dashed var(--kl-color-line-strong); -webkit-backdrop-filter: none; backdrop-filter: none; }
.kl-archive.is-empty .kl-tool__tile { background: transparent; color: var(--kl-color-text-secondary); box-shadow: inset 0 0 0 1px var(--kl-color-line); }

/* ---- Archive window ------------------------------------------------------------------------------------ */
.kl-archive-win { --kl-win-w: 380px; }
.kl-archive-win__list { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
.kl-archive-row {
  display: grid; grid-template-columns: 12px minmax(0, 1fr) auto; align-items: center; gap: 12px;
  min-height: 52px; padding: 6px 0; border-bottom: 1px solid var(--kl-color-line);
}
.kl-archive-row:last-child { border-bottom: 0; }
.kl-archive-row__mark { width: 12px; height: 12px; border-radius: 4px; background: var(--kl-ptile-hue); }
.kl-archive-row__text { display: flex; flex-direction: column; min-width: 0; }
.kl-archive-row__text b { font: var(--kl-font-label-strong); color: var(--kl-color-text); }
.kl-archive-row__text span { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Restoring: the row fades out as its tile lands back on Home */
.kl-archive-row.is-restoring { opacity: .5; transition: opacity var(--kl-motion-fade) ease; }
.kl-archive-win__empty { margin: 0; padding: 24px 0; text-align: center; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }

/* ---- The Home layer -------------------------------------------------------------------------------------- */
/* Board colour at high opacity over the board, the same dot grid on top; the cards behind fade back and blur a little */
.kl-home {
  --kl-home-veil: 90%;
  position: absolute; inset: 0; z-index: var(--kl-z-home); overflow: hidden;
  background-color: color-mix(in srgb, var(--kl-color-board) var(--kl-home-veil), transparent);
  background-image: radial-gradient(circle, var(--kl-color-board-dot) var(--kl-dot, 1px), transparent calc(var(--kl-dot, 1px) + .5px));
  background-size: var(--kl-grid, 24px) var(--kl-grid, 24px);
  background-position: calc(var(--kl-grid, 24px) / 2) calc(var(--kl-grid, 24px) / 2);
  -webkit-backdrop-filter: blur(var(--kl-glass-blur)); backdrop-filter: blur(var(--kl-glass-blur));
}
/* Increased contrast: the layer turns solid so nothing behind competes with the tiles */
[data-contrast="more"] .kl-home { --kl-home-veil: 100%; -webkit-backdrop-filter: none; backdrop-filter: none; }
@media (prefers-contrast: more) { .kl-home { --kl-home-veil: 100%; -webkit-backdrop-filter: none; backdrop-filter: none; } }

.kl-home > :is(.kl-ptile, .kl-newtile, .kl-archive, .kl-home__group) { position: absolute; }
/* Group captions: meta, secondary, with the count */
.kl-home__group {
  margin: 0; display: inline-flex; align-items: center; gap: 6px;
  font: var(--kl-font-meta); font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text-secondary);
  font-variant-numeric: tabular-nums;
}
.kl-home__group span { font-weight: var(--kl-font-weight-regular); }
/* Quiet hint, bottom centre */
.kl-home__hint {
  position: absolute; left: 50%; bottom: 24px; translate: -50% 0; margin: 0;
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  font: var(--kl-font-caption); color: var(--kl-color-text-secondary);
}
/* The Undo toast sits above the hint */
.kl-home__toast { position: absolute; left: 50%; bottom: 56px; translate: -50% 0; z-index: 2; }

/* -- Motion --
   Opening: the layer fades in on --kl-motion-fade; tiles rise 6 px and fade in on ease-out, spaced by
   --kl-motion-reveal-step (--i on each tile: groups in order, pinned first), then land with v2's dial-scaled squash.
   Closing: everything fades at once (--kl-motion-fade-out). Nothing here moves on its own once it has landed. */
@media (prefers-reduced-motion: no-preference) {
  .kl-home.is-opening { animation: kl-fade-in var(--kl-motion-fade) ease backwards; }
  .kl-home.is-opening > :is(.kl-ptile, .kl-newtile, .kl-archive) {
    animation: kl-reveal var(--kl-motion-reveal) var(--kl-motion-ease-out) calc(var(--kl-motion-reveal-delay) + var(--i, 0) * var(--kl-motion-reveal-step)) backwards,
               kl-land var(--kl-motion-land) ease-out calc(var(--kl-motion-reveal-delay) + var(--i, 0) * var(--kl-motion-reveal-step) + var(--kl-motion-reveal) * .7);
  }
  .kl-home.is-opening > :is(.kl-home__group, .kl-home__hint) { animation: kl-fade-in var(--kl-motion-reveal) ease calc(var(--kl-motion-reveal-delay) + var(--i, 0) * var(--kl-motion-reveal-step)) backwards; }
  .kl-home.is-closing { animation: kl-fade-out var(--kl-motion-fade-out) ease forwards; pointer-events: none; }
}
/* Reduced motion (the OS, or .kl-motion-reduce on the root): one fade for the whole layer; nothing rises, lifts or lands */
@media (prefers-reduced-motion: reduce) {
  .kl-home.is-opening { animation: kl-fade-in var(--kl-motion-fade) ease backwards; }
  .kl-home.is-closing { animation: kl-fade-out var(--kl-motion-fade-out) ease forwards; }
  .kl-home.is-opening > * { animation: none; }
  :is(.kl-ptile__face, .kl-archive__sheet, .kl-ptile__more) { transition-property: opacity, box-shadow, border-color; transition-duration: var(--kl-motion-fade); }
  .kl-ptile:hover .kl-ptile__face, .kl-ptile.is-hover .kl-ptile__face { translate: 0 0; }
}
.kl-motion-reduce .kl-home.is-opening { animation: kl-fade-in var(--kl-motion-fade) ease backwards !important; }
.kl-motion-reduce .kl-home.is-opening > *,
.kl-motion-reduce :is(.kl-ptile.is-restored, .kl-ptile.is-archiving) .kl-ptile__face { animation: none !important; }
.kl-motion-reduce :is(.kl-ptile__face, .kl-archive__sheet, .kl-ptile__more) { transition-property: opacity, box-shadow, border-color !important; transition-duration: var(--kl-motion-fade) !important; }
.kl-motion-reduce :is(.kl-ptile:hover, .kl-ptile.is-hover, .kl-ptile.is-menu) .kl-ptile__face { translate: 0 0; }

/* ---- Specimen only: the motion notes list ------------------------------------------------------------- */
.pj-home-notes { margin: 0; padding: 0; list-style: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px 28px; max-width: 1200px; }
.pj-home-notes li { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.pj-home-notes b { display: block; margin-bottom: 2px; font: var(--kl-font-label-strong); color: var(--kl-color-text); }
.pj-home-notes code { font-family: var(--kl-font-mono); font-size: inherit; color: var(--kl-color-text); }

/* ===== harness/projects/setup.css ===== */
/* =====================================================================================================
   Klippan master DS · Many projects · 2. New project setup and templates
   A New project tile drops a card that opens straight into setup: three steps inside the card at the expanded stage
   (Start from, Name and colour, Checklist), then the card folds to full and sets itself up.

   Builds on v2: load ../../../klippan-v2/combined/klippan.css first. Every value is a --kl-* token or a local size
   (--kl-newtile-*, --kl-setup-*, --kl-tpl-*, --kl-hue-*). New tokens are read through a fallback (NEEDS.md).

   Pieces
     .kl-newtile                        New project tile (same size as a project tile, dashed hairline, plus)
     .kl-card.kl-setup                  setup card, data-stage="3", data-step="1|2|3", tinted by .kl-card--p1..p8
       .kl-setup__step / __pips         "1 of 3" step line
       .kl-setup__tpls > .kl-tpl        template tiles (radio group)
       .kl-hues > .kl-hue               eight hue swatches (radio group)
       .kl-setup__repo                  optional repository field
       .kl-setup__list > .kl-setup__row checklist rows: is-done, is-todo, is-optional, is-signin, is-busy
       .kl-setup__foot                  Cancel first, Back, one primary
     .kl-dialog.kl-savetpl              Save as template dialog
   ===================================================================================================== */

/* ---- New project tile ----------------------------------------------------------------------------------- */
.kl-newtile {
  --kl-newtile-w: var(--kl-ptile-w, 248px);
  --kl-newtile-h: var(--kl-ptile-h, 116px);
  position: relative; flex: none; box-sizing: border-box;
  width: var(--kl-newtile-w); height: var(--kl-newtile-h); margin: 0;
  display: grid; grid-template-columns: var(--kl-tool-tile) minmax(0, 1fr); grid-template-rows: auto auto;
  align-content: center; column-gap: 12px; row-gap: 2px;
  padding: 14px 20px 14px 18px;
  border: 1.5px dashed var(--kl-color-line-strong); border-radius: var(--kl-radius-card);
  background: color-mix(in srgb, var(--kl-glass-card) 60%, transparent);
  -webkit-backdrop-filter: var(--kl-glass-card-filter); backdrop-filter: var(--kl-glass-card-filter);
  color: var(--kl-color-text); font: var(--kl-font-body); text-align: left;
  cursor: pointer; outline: 0;
  transition: border-color var(--kl-motion-hover) ease, background-color var(--kl-motion-hover) ease, box-shadow var(--kl-motion-hover) ease,
              translate var(--kl-motion-lift) var(--kl-motion-spring), scale var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-newtile__plus {
  grid-row: 1 / span 2; display: grid; place-items: center;
  width: var(--kl-tool-tile); height: var(--kl-tool-tile); border-radius: var(--kl-radius-round);
  background: var(--kl-color-control-fill); color: var(--kl-color-text-secondary);
  transition: background-color var(--kl-motion-hover) ease, color var(--kl-motion-hover) ease, scale var(--kl-motion-lift) var(--kl-motion-spring-pop);
}
.kl-newtile__plus .kl-icon { --kl-icon-size: 18px; }
.kl-newtile__name { font: var(--kl-font-headline); color: var(--kl-color-text); white-space: nowrap; }
.kl-newtile__meta { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Hover: the dash and the plus take the selection blue (this is where something new will appear), a small lift */
.kl-newtile:hover, .kl-newtile.is-hover { border-color: var(--kl-color-selection); translate: 0 calc(-2px - 2px * var(--kl-motion-k)); }
.kl-newtile:hover .kl-newtile__plus, .kl-newtile.is-hover .kl-newtile__plus { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); scale: calc(1.04 + .08 * var(--kl-motion-k)); }
.kl-newtile:active, .kl-newtile.is-pressed { scale: .98; translate: 0 0; }
.kl-newtile:focus-visible, .kl-newtile.is-focus { box-shadow: 0 0 0 2px var(--kl-color-focus), 0 0 0 5px var(--kl-color-selection-soft); }
/* Board size: on the board it sits with the tools, so it also comes at the section card's size */
.kl-newtile--sm { --kl-newtile-w: var(--kl-section-w); --kl-newtile-h: var(--kl-section-h); padding: 12px 16px 12px 12px; border-radius: var(--kl-radius-panel); }
.kl-newtile--sm .kl-newtile__name { font: var(--kl-font-headline); }

/* ---- Setup card ------------------------------------------------------------------------------------------ */
.kl-setup { --kl-setup-w: 400px; --kl-card-w: var(--kl-setup-w); }
/* Setup may need the full expanded height; it sets its own (--kl-setup-h) instead of v2's 432 clamp */
.kl-card.kl-setup[data-stage="3"] { height: var(--kl-setup-h, var(--kl-card-h, 400px)); }
/* The tint follows the chosen swatch: the glass colour glides on ease-out */
.kl-setup .kl-card__face {
  transition: box-shadow var(--kl-motion-hover) ease, border-color var(--kl-motion-hover) ease,
              background-color var(--kl-motion-expand) var(--kl-motion-ease-out);
}
.kl-setup .kl-card__head { padding-right: 0; gap: 4px; }
.kl-setup .kl-card__more { flex: 1 1 auto; gap: 14px; overflow: visible; }
.kl-setup .kl-card__name-text.is-placeholder { color: var(--kl-color-text-secondary); }

/* Step line under the name: three pips and "1 of 3 · Start from" */
.kl-setup__step {
  display: flex; align-items: center; gap: 8px; margin: 0; padding-left: 20px;
  font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums;
}
.kl-setup__step b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }
.kl-setup__pips { display: inline-flex; align-items: center; gap: 4px; }
.kl-setup__pips i {
  display: block; width: 12px; height: 4px; border-radius: var(--kl-radius-pill); background: var(--kl-color-switch-off);
  transition: width var(--kl-motion-hover) var(--kl-motion-spring-pop), background-color var(--kl-motion-hover) ease;
}
.kl-setup__pips i.is-done { background: var(--kl-color-control); }
.kl-setup__pips i.is-now { width: 20px; background: var(--kl-color-control); }

/* ---- Step 1: Start from (template tiles) ---------------------------------------------------------------- */
.kl-setup__tpls { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 0; }
.kl-tpl {
  position: relative; box-sizing: border-box; width: 100%; min-width: 0; min-height: 72px; margin: 0;
  display: grid; grid-template-columns: 18px minmax(0, 1fr); align-content: start; column-gap: 8px; row-gap: 4px;
  padding: 10px 12px; border: 0; border-radius: var(--kl-radius-menu);
  background: var(--kl-tpl-bg, color-mix(in srgb, var(--kl-color-surface) 70%, transparent));
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
  color: var(--kl-color-text); font: var(--kl-font-meta); text-align: left;
  cursor: pointer; outline: 0;
  transition: box-shadow var(--kl-motion-hover) ease, background-color var(--kl-motion-hover) ease, scale var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-tpl > .kl-icon { --kl-icon-size: 18px; color: var(--kl-color-text-secondary); align-self: center; }
.kl-tpl__name { align-self: center; padding-right: 20px; font: var(--kl-font-label-strong); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kl-tpl__brings { grid-column: 1 / -1; display: flex; flex-direction: column; gap: 0; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-tpl__brings span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The check is only in the chosen tile; v2's .kl-check pops it in on the small spring */
.kl-tpl__check { position: absolute; top: 8px; right: 8px; }
.kl-tpl:hover, .kl-tpl.is-hover { --kl-tpl-bg: var(--kl-color-surface); box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
.kl-tpl:active, .kl-tpl.is-pressed { scale: .98; }
.kl-tpl:focus-visible, .kl-tpl.is-focus { box-shadow: inset 0 0 0 1px var(--kl-color-line-strong), 0 0 0 2px var(--kl-color-focus), 0 0 0 5px var(--kl-color-selection-soft); }
/* Chosen: the selection edge plus the check (never a fill) */
.kl-tpl[aria-checked="true"], .kl-tpl.is-chosen { --kl-tpl-bg: var(--kl-color-surface); box-shadow: inset 0 0 0 2px var(--kl-color-selection); }
.kl-tpl[aria-checked="true"] > .kl-icon, .kl-tpl.is-chosen > .kl-icon { color: var(--kl-color-selection-ink); }
/* A template Alban saved himself */
.kl-tpl--yours .kl-tpl__brings span:last-child { color: var(--kl-color-text); }

/* ---- Step 2: Name and colour ------------------------------------------------------------------------------ */
.kl-setup__field { display: flex; flex-direction: column; min-width: 0; }
.kl-setup__field .kl-fieldlabel span { color: var(--kl-color-text-secondary); font-weight: var(--kl-font-weight-regular); }
.kl-setup__field .kl-fieldhint { margin-top: 4px; }

.kl-hues { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 4px 4px 2px; }
.kl-hue {
  --kl-hue-c: var(--kl-color-project-1);
  --kl-hue-size: 26px;
  position: relative; display: grid; place-items: center; flex: none;
  width: var(--kl-hue-size); height: var(--kl-hue-size); margin: 0; padding: 0; border: 0; border-radius: var(--kl-radius-round);
  background: var(--kl-hue-c); color: var(--kl-color-text-on-fill);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--kl-color-text) 14%, transparent);
  cursor: pointer; outline: 0;
  transition: scale var(--kl-motion-hover) var(--kl-motion-spring-pop), box-shadow var(--kl-motion-hover) ease;
}
.kl-hue::before { content: ""; position: absolute; inset: calc((var(--kl-hue-size) - var(--kl-size-target)) / 2); border-radius: var(--kl-radius-round); }   /* 44 px hit area */
.kl-hue .kl-icon { --kl-icon-size: 14px; --kl-icon-stroke: 2.4; opacity: 0; scale: .4;
  transition: opacity var(--kl-motion-hover) ease, scale var(--kl-motion-count-pop) var(--kl-motion-spring-pop); }
.kl-hue--p1 { --kl-hue-c: var(--kl-color-project-1); }
.kl-hue--p2 { --kl-hue-c: var(--kl-color-project-2); }
.kl-hue--p3 { --kl-hue-c: var(--kl-color-project-3); }
.kl-hue--p4 { --kl-hue-c: var(--kl-color-project-4); }
.kl-hue--p5 { --kl-hue-c: var(--kl-color-project-5); }
.kl-hue--p6 { --kl-hue-c: var(--kl-color-project-6); }
.kl-hue--p7 { --kl-hue-c: var(--kl-color-project-7); }
.kl-hue--p8 { --kl-hue-c: var(--kl-color-project-8); }
.kl-hue:hover, .kl-hue.is-hover { scale: calc(1.06 + .06 * var(--kl-motion-k)); }
.kl-hue:active, .kl-hue.is-pressed { scale: .94; }
.kl-hue:focus-visible, .kl-hue.is-focus { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--kl-color-text) 14%, transparent), 0 0 0 3px var(--kl-color-surface), 0 0 0 5px var(--kl-color-focus); }
/* Chosen: a ring in its own hue, a hairline gap, and the check */
.kl-hue[aria-checked="true"], .kl-hue.is-chosen { box-shadow: 0 0 0 2px var(--kl-color-surface), 0 0 0 4px var(--kl-hue-c); }
.kl-hue[aria-checked="true"] .kl-icon, .kl-hue.is-chosen .kl-icon { opacity: 1; scale: 1; }
.kl-hue[aria-checked="true"].is-focus, .kl-hue[aria-checked="true"]:focus-visible { box-shadow: 0 0 0 2px var(--kl-color-surface), 0 0 0 4px var(--kl-hue-c), 0 0 0 6px var(--kl-color-focus); }
.kl-hues__note { margin: 6px 0 0; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }

/* Repository field: field look with the branch icon, the value in Geist Mono */
.kl-setup__repo {
  --kl-field-ring: var(--kl-color-field-border); --kl-field-halo: 0 0 0 0 transparent;
  display: flex; align-items: center; gap: 8px; box-sizing: border-box; height: var(--kl-size-button); padding: 0 8px;
  border-radius: var(--kl-radius-control); background: var(--kl-color-surface); color: var(--kl-color-text-secondary);
  box-shadow: inset 0 0 0 1px var(--kl-field-ring), var(--kl-field-halo);
  transition: box-shadow var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-setup__repo:hover { --kl-field-ring: var(--kl-color-line-strong); }
.kl-setup__repo:focus-within, .kl-setup__repo.is-focus { --kl-field-ring: var(--kl-color-focus); --kl-field-halo: 0 0 0 3px var(--kl-color-selection-soft); }
.kl-setup__repo .kl-icon { --kl-icon-size: 14px; }
.kl-setup__repo input {
  flex: 1 1 auto; min-width: 0; height: 100%; margin: 0; padding: 0; border: 0; outline: 0; background: transparent;
  color: var(--kl-color-text); font: var(--kl-font-meta); font-family: var(--kl-font-mono);
}
.kl-setup__repo input::placeholder { color: var(--kl-color-text-secondary); opacity: 1; }

/* ---- Step 3: Checklist ------------------------------------------------------------------------------------- */
.kl-setup__list { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--kl-color-line); }
.kl-setup__row {
  display: grid; grid-template-columns: 20px minmax(0, 1fr) auto; align-items: center; column-gap: 10px;
  min-height: 42px; padding: 5px 0; border-bottom: 1px solid var(--kl-color-line);
}
.kl-setup__mark {
  display: grid; place-items: center; box-sizing: border-box; width: 20px; height: 20px; border-radius: var(--kl-radius-round);
  border: 1.5px dashed var(--kl-color-text-secondary); color: var(--kl-color-text-on-fill);
}
.kl-setup__mark .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2.4; display: none; }
.kl-setup__text { display: flex; flex-direction: column; min-width: 0; }
.kl-setup__label { font: var(--kl-font-label-strong); color: var(--kl-color-text); }
.kl-setup__val {
  display: flex; align-items: center; gap: 6px; min-width: 0;
  font: var(--kl-font-meta); color: var(--kl-color-text-secondary); white-space: nowrap;
}
.kl-setup__val > span:not(.kl-setup__tag) { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.kl-setup__val .kl-icon { --kl-icon-size: 14px; }
.kl-setup__val code { font: var(--kl-font-caption); font-family: var(--kl-font-mono); color: var(--kl-color-text); }
.kl-setup__tag {
  flex: none; display: inline-flex; align-items: center; height: 18px; padding: 0 6px; border-radius: var(--kl-radius-pill);
  background: var(--kl-color-neutral-soft); color: var(--kl-color-neutral-ink); font: var(--kl-font-caption);
}
.kl-setup__tag--changed { background: var(--kl-color-selection-soft); color: var(--kl-color-selection-ink); }
/* Done: a filled check in the control blue */
.kl-setup__row.is-done .kl-setup__mark { border: 0; background: var(--kl-color-control); }
.kl-setup__row.is-done .kl-setup__mark .kl-icon { display: block; }
/* To do: a dashed ring, the value says what is missing */
.kl-setup__row.is-todo .kl-setup__val { color: var(--kl-color-text); }
/* Optional: a lighter dashed ring and the word Optional */
.kl-setup__row.is-optional .kl-setup__mark { border-style: dotted; border-color: var(--kl-color-text-tertiary); }
/* Needs sign-in: says so plainly, in text ink, with Sign in in place of Change */
.kl-setup__row.is-signin .kl-setup__mark { border-style: solid; border-color: var(--kl-color-text-secondary); }
.kl-setup__row.is-signin .kl-setup__ask { color: var(--kl-color-text); }
/* Busy (signing in, connecting): a quarter arc turns; it stops under reduced motion */
.kl-setup__row.is-busy .kl-setup__mark { border: 2px solid var(--kl-color-switch-off); border-top-color: var(--kl-color-control); }
@media (prefers-reduced-motion: no-preference) {
  .kl-setup__row.is-busy .kl-setup__mark { animation: kl-spin var(--kl-motion-spin) linear infinite;   /* Motion's kl-m-spin */ }
}
.kl-motion-reduce .kl-setup__row.is-busy .kl-setup__mark { animation: none !important; }
.kl-setup__row .kl-btn { justify-self: end; }
/* Hover on a row: a faint fill so Change reads as belonging to it */
.kl-setup__row:hover, .kl-setup__row.is-hover { background: linear-gradient(90deg, transparent, var(--kl-color-control-fill) 12%, var(--kl-color-control-fill) 88%, transparent); }

/* ---- Footer: Cancel first, then Back and the one primary ------------------------------------------------------ */
.kl-setup__foot { display: flex; align-items: center; gap: 6px; margin-top: auto; }
.kl-setup__foot .kl-setup__push { margin-left: auto; }
.kl-setup__foot .kl-btn--primary { min-width: 72px; }
.kl-setup__aside { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }

/* ---- After Create ----------------------------------------------------------------------------------------- */
/* Folding: the card glides from expanded to full on ease-out (size never springs); the setup content fades first */
@media (prefers-reduced-motion: no-preference) {
  .kl-setup.is-folding { transition: width var(--kl-motion-collapse) var(--kl-motion-ease-out), height var(--kl-motion-collapse) var(--kl-motion-ease-out); }
  .kl-setup.is-folding .kl-card__more { opacity: 0; transition: opacity var(--kl-motion-fade-out) ease; }
}
.kl-motion-reduce .kl-setup.is-folding { transition: none !important; }

/* ---- Save as template dialog --------------------------------------------------------------------------- */
.kl-savetpl { --kl-dialog-w: 360px; }
.kl-savetpl__keeps { display: flex; flex-direction: column; gap: 0; margin: 0; padding: 0; border: 0; min-width: 0; }
.kl-savetpl__keeps legend { padding: 0; margin: 0 0 4px; font: var(--kl-font-label); color: var(--kl-color-text); }
.kl-savetpl__what { margin-left: 2px; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kl-savetpl .kl-checkbox { min-width: 0; }
.kl-savetpl__note { margin: 0; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }

/* ---- Specimen only ------------------------------------------------------------------------------------------- */
.pj-setup-dlg { position: relative; width: 420px; height: 470px; border-radius: var(--kl-radius-panel); overflow: hidden; --kl-scrim-position: absolute; --kl-scrim-z: 1; }
.pj-setup-panel { width: 364px; padding: 4px 16px; border-radius: var(--kl-radius-card); background: var(--kl-glass-card-project-5);
  -webkit-backdrop-filter: var(--kl-glass-card-filter); backdrop-filter: var(--kl-glass-card-filter); box-shadow: var(--kl-glass-card-shadow); }
.pj-setup-panel .kl-setup__list { border-top: 0; }
.pj-setup-panel .kl-setup__row:last-child { border-bottom: 0; }
.pj-setup-swatches { padding: 16px 20px; border-radius: var(--kl-radius-card); background: var(--kl-glass-card);
  -webkit-backdrop-filter: var(--kl-glass-card-filter); backdrop-filter: var(--kl-glass-card-filter); box-shadow: var(--kl-glass-card-shadow); }

/* ===== harness/projects/switcher.css ===== */
/* Klippan master · Many projects · 3. The ⌘K switcher and global search
   One opaque panel in the prompter's family (surface, radius 24, window shadow). It opens where the prompter sits, the
   prompter fades back under it, and Tab widens the same panel into global search with a preview pane.

   .kl-switcher                       560 wide; the panel
     __field   __glass  __input  .kl-kbd (Esc)   the sunken draft-style field; in search it also holds a scope .kl-chip
     __list    __group  __label  __row            grouped rows, 32 high; the active row is the menu's blue fill
       __row parts: __mark(--p1..8)  __name  __hit (matched letters)  __meta  __tag  __when  __keys
     __empty                                      "Nothing called …" line in the no-match state
     __foot    __hint  __foot-end                 key hints in caption style
   .kl-switcher.is-search             880 wide; adds __bar (.kl-seg filter, __count), __split (__results + __preview)
     __results __head (mark, name, count)  __row--hit (kind icon, __title with <mark class="kl-switcher__hl">, __snippet, __when)
     __preview __pv-head __pv-icon __pv-title __pv-meta __pv-text __pv-label __pv-from __facts __lines __path __pv-actions
     __ph, __ph-row (static placeholders, searching state)   __none (no results)
   Placement: .kl-switcher--anchored (bottom on the prompter's mid-line), .is-held (top pinned while open)
   States:  panel  .is-entering (opens)  .is-leaving (row flash, then fade)  .is-fading (static frame of the fade)
            row    .is-active / [aria-selected=true]  .is-flash (static frame of the flash)  .is-flashing (the one flash)
            parts  __results.is-arriving, __preview.is-arriving (one fade when results land)
   The prompter while the switcher is up: Controls' .kl-prompter.is-behind (v2).
   Every colour, type, radius, shadow and timing is a --kl-* token; sizes are local custom properties (board units). */

/* =====================================================================================
   1. Panel
   ===================================================================================== */
/* Component sizes (board units), shared with a preview pane shown on its own */
.kl-switcher, .kl-switcher__preview {
  --kl-switcher-w: 560px;
  --kl-switcher-w-search: 880px;
  --kl-switcher-pad: var(--kl-space-3);
  --kl-switcher-field-h: 44px;
  --kl-switcher-row-h: 32px;
  --kl-switcher-hit-h: 52px;
  --kl-switcher-list-max: 580px;
  --kl-switcher-split-h: 404px;
  --kl-switcher-pane-w: 340px;
  --kl-switcher-radius: var(--kl-radius-prompter);
  --kl-switcher-radius-in: calc(var(--kl-radius-prompter) - var(--kl-space-3));   /* inner radius = panel radius minus padding */
  --kl-switcher-mark: 10px;
  --kl-switcher-hair: 2px;
  --kl-switcher-tight: 6px;
  --kl-switcher-row-x: 10px;
}
.kl-switcher {
  position: relative;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  width: var(--kl-switcher-w);
  max-width: 100%;
  padding: var(--kl-switcher-pad);
  border-radius: var(--kl-switcher-radius);
  background: var(--kl-color-surface);
  color: var(--kl-color-text);
  box-shadow: var(--kl-shadow-window);
  font: var(--kl-font-meta);
  font-family: var(--kl-font-sans);
  font-variant-numeric: tabular-nums;
  text-align: left;
  -webkit-font-smoothing: antialiased;
  isolation: isolate;
  transform-origin: 50% 100%;            /* rises out of the prompter's spot */
  transition: width var(--kl-motion-collapse) var(--kl-motion-ease-out);
}
.kl-switcher *, .kl-switcher *::before, .kl-switcher *::after { box-sizing: border-box; }
.kl-switcher .kl-icon { --kl-icon-size: 16px; }
.kl-switcher button { font-family: inherit; }

/* On the board: centred on the prompter with its bottom edge half way down the prompter, so it grows upward
   and the prompter's bottom row (destination, model, Send) stays visible, faded, under it */
.kl-switcher--anchored {
  position: absolute;
  left: 50%;
  bottom: var(--kl-switcher-bottom, var(--kl-space-12));
  translate: -50% 0;
  z-index: var(--kl-z-switcher);         /* just above the prompter, under an open card */
}
/* Once open, the board pins the top edge (--kl-switcher-top) so the field never moves while typing:
   the list shortens and grows below it, and search widens around the centre and downward */
.kl-switcher--anchored.is-held { top: var(--kl-switcher-top); bottom: auto; }

/* Scroll areas keep a thin, quiet bar */
.kl-switcher__list, .kl-switcher__results, .kl-switcher__preview { scrollbar-width: thin; scrollbar-color: var(--kl-color-line-strong) transparent; }

/* =====================================================================================
   2. Field: the prompter's draft field, one line, with the magnifier and Esc
   ===================================================================================== */
.kl-switcher__field {
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  flex: none;
  height: var(--kl-switcher-field-h);
  padding: 0 var(--kl-space-2) 0 var(--kl-space-3);
  border: 1px solid var(--kl-color-focus);        /* the field holds the caret the whole time the panel is up */
  border-radius: var(--kl-radius-draft);
  background: var(--kl-color-surface-sunken);
  transition: border-color var(--kl-motion-press) var(--kl-motion-ease-out);
}
.kl-switcher .kl-switcher__glass { --kl-icon-size: 18px; color: var(--kl-color-text-secondary); }
.kl-switcher__input {
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--kl-color-text);
  font: var(--kl-font-body);
  font-family: var(--kl-font-sans);
  -webkit-appearance: none;
  appearance: none;
}
.kl-switcher__input::placeholder { color: var(--kl-color-text-secondary); opacity: 1; }
.kl-switcher__field .kl-kbd { flex: none; }
.kl-switcher__field .kl-chip { height: 28px; }
.kl-switcher__field .kl-chip .kl-switcher__mark { margin-left: var(--kl-switcher-hair); }

/* =====================================================================================
   3. List: groups and rows (the menu's row, 32 high)
   ===================================================================================== */
.kl-switcher__list {
  display: flex;
  flex-direction: column;
  gap: var(--kl-switcher-hair);
  min-height: 0;
  max-height: var(--kl-switcher-list-max);
  margin-top: var(--kl-space-2);
  overflow: auto;
  overscroll-behavior: contain;
}
.kl-switcher__group { display: flex; flex-direction: column; gap: 1px; }
.kl-switcher__group + .kl-switcher__group { margin-top: var(--kl-space-1); }
.kl-switcher__label {
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  padding: var(--kl-switcher-tight) var(--kl-switcher-row-x) var(--kl-space-1);
  font: var(--kl-font-caption);
  color: var(--kl-color-text-secondary);
}

.kl-switcher__row {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  width: 100%;
  min-height: var(--kl-switcher-row-h);
  margin: 0;
  padding: var(--kl-space-1) var(--kl-switcher-row-x);
  border: 0;
  border-radius: var(--kl-radius-row);
  background: transparent;
  color: var(--kl-color-text);
  font: var(--kl-font-label);
  text-align: left;
  cursor: pointer;
  outline: 0;
}
.kl-switcher__row > .kl-icon { color: var(--kl-color-text-secondary); }
.kl-switcher__row:hover:not(.is-active, [aria-selected="true"]),
.kl-switcher__row.is-hover { background: var(--kl-color-control-fill); }

.kl-switcher__name {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* Matched letters while typing: bold, nothing else */
.kl-switcher__hit { font-weight: var(--kl-font-weight-bold); }

.kl-switcher__meta {
  display: inline-flex;
  align-items: center;
  gap: var(--kl-switcher-tight);
  flex: none;
  margin-left: auto;
  font: var(--kl-font-meta);
  color: var(--kl-color-text-secondary);
  white-space: nowrap;
}
.kl-switcher__meta--asking { color: var(--kl-card-approval-ink); }   /* "2 need you": waiting on Alban, in the approval colour */
.kl-switcher .kl-switcher__meta .kl-icon { --kl-icon-size: 14px; }
.kl-switcher__when {
  flex: none;
  min-width: 52px;
  margin-left: auto;
  text-align: right;
  font: var(--kl-font-meta);
  color: var(--kl-color-text-secondary);
  white-space: nowrap;
}
.kl-switcher__keys {
  display: inline-flex;
  align-items: center;
  gap: var(--kl-space-1);
  flex: none;
  margin-left: auto;
}

/* Project mark: the hue square (the prompter's destination mark, a size up) */
.kl-switcher__mark {
  --kl-mark: var(--kl-color-selection);
  flex: none;
  width: var(--kl-switcher-mark);
  height: var(--kl-switcher-mark);
  border-radius: var(--kl-radius-mark);
  background: var(--kl-mark);
}
.kl-switcher__mark--p1 { --kl-mark: var(--kl-color-project-1); }
.kl-switcher__mark--p2 { --kl-mark: var(--kl-color-project-2); }
.kl-switcher__mark--p3 { --kl-mark: var(--kl-color-project-3); }
.kl-switcher__mark--p4 { --kl-mark: var(--kl-color-project-4); }
.kl-switcher__mark--p5 { --kl-mark: var(--kl-color-project-5); }
.kl-switcher__mark--p6 { --kl-mark: var(--kl-color-project-6); }
.kl-switcher__mark--p7 { --kl-mark: var(--kl-color-project-7); }
.kl-switcher__mark--p8 { --kl-mark: var(--kl-color-project-8); }

/* Project tag on a run or a result: mark and name in the badge font */
.kl-switcher__tag {
  display: inline-flex;
  align-items: center;
  gap: var(--kl-switcher-tight);
  flex: none;
  height: 20px;
  padding: 0 var(--kl-space-2) 0 7px;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-neutral-soft);
  color: var(--kl-color-neutral-ink);
  font: var(--kl-font-badge);
  white-space: nowrap;
}
.kl-switcher__tag .kl-switcher__mark { width: 8px; height: 8px; }
.kl-switcher__name + .kl-switcher__tag { margin-left: var(--kl-space-1); }

/* Active row: the menu's active look, blue fill and white ink. Marks and dots get a white ring so they still read. */
.kl-switcher__row.is-active,
.kl-switcher__row[aria-selected="true"] {
  background: var(--kl-color-selection);
  color: var(--kl-color-text-on-fill);
}
.kl-switcher__row:is(.is-active, [aria-selected="true"]) :is(.kl-icon, .kl-switcher__meta, .kl-switcher__when, .kl-switcher__snippet) { color: var(--kl-color-text-on-fill); }
.kl-switcher__row:is(.is-active, [aria-selected="true"]) :is(.kl-dot, .kl-switcher__mark) { box-shadow: 0 0 0 1.5px var(--kl-color-text-on-fill); }
.kl-switcher__row:is(.is-active, [aria-selected="true"]) .kl-switcher__tag {
  background: color-mix(in srgb, var(--kl-color-text-on-fill) 22%, transparent);
  color: var(--kl-color-text-on-fill);
}
.kl-switcher__row:is(.is-active, [aria-selected="true"]) .kl-kbd {
  background: transparent;
  color: var(--kl-color-text-on-fill);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--kl-color-text-on-fill) 55%, transparent);
}
.kl-switcher__row:focus-visible { outline: 2px solid var(--kl-color-focus); outline-offset: 1px; }

/* Opening a result: the static frame of the one flash (a soft ring around the blue row) */
.kl-switcher__row.is-flash { box-shadow: 0 0 0 4px var(--kl-color-selection-soft); }

/* No match: one plain line above the action row */
.kl-switcher__empty {
  margin: 0;
  padding: var(--kl-space-4) var(--kl-switcher-row-x) var(--kl-space-2);
  font: var(--kl-font-meta);
  color: var(--kl-color-text-secondary);
}
.kl-switcher__empty b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }

/* =====================================================================================
   4. Foot: key hints
   ===================================================================================== */
.kl-switcher__foot {
  display: flex;
  align-items: center;
  gap: var(--kl-space-4);
  flex: none;
  min-height: 36px;
  margin: var(--kl-space-2) calc(var(--kl-switcher-pad) * -1) calc(var(--kl-switcher-pad) * -1);
  padding: 0 var(--kl-space-4);
  border-top: 1px solid var(--kl-color-line);
  font: var(--kl-font-caption);
  color: var(--kl-color-text-secondary);
  white-space: nowrap;
}
.kl-switcher__hint { display: inline-flex; align-items: center; gap: var(--kl-space-1); }
.kl-switcher__hint .kl-kbd { height: 16px; min-width: 16px; padding: 0 4px; }
.kl-switcher__foot-end { margin-left: auto; }

/* =====================================================================================
   5. Global search: the same panel, 880 wide, with a filter bar and a preview pane
   ===================================================================================== */
.kl-switcher.is-search {
  width: var(--kl-switcher-w-search);
  transition-duration: var(--kl-motion-expand);
}
.kl-switcher__bar {
  display: flex;
  align-items: center;
  gap: var(--kl-space-3);
  flex: none;
  margin-top: var(--kl-space-3);
}
.kl-switcher__count {
  margin-left: auto;
  font: var(--kl-font-caption);
  color: var(--kl-color-text-secondary);
  white-space: nowrap;
}
.kl-switcher__split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--kl-switcher-pane-w);
  gap: var(--kl-space-3);
  height: var(--kl-switcher-split-h);
  min-height: 0;
  margin-top: var(--kl-space-3);
}
.kl-switcher__results {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-height: 0;
  overflow: auto;
  overscroll-behavior: contain;
}
.kl-switcher__head {
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  padding: var(--kl-space-2) var(--kl-switcher-row-x) var(--kl-space-1);
  font: var(--kl-font-label-strong);
  letter-spacing: var(--kl-font-label-strong-tracking);
}
.kl-switcher__head:first-child { padding-top: var(--kl-space-1); }
.kl-switcher__head:not(:first-child) { margin-top: var(--kl-space-2); }
.kl-switcher__head-count { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-switcher__head--kind { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); letter-spacing: normal; }

/* A result: kind icon, title and snippet stacked, when */
.kl-switcher__row--hit {
  align-items: flex-start;
  min-height: var(--kl-switcher-hit-h);
  padding: var(--kl-space-2) var(--kl-switcher-row-x);
}
.kl-switcher__row--hit > .kl-icon { margin-top: 1px; }
.kl-switcher__text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--kl-switcher-hair); }
.kl-switcher__title { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font: var(--kl-font-label); }
.kl-switcher__snippet {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font: var(--kl-font-meta);
  color: var(--kl-color-text-secondary);
}
.kl-switcher__row--hit .kl-switcher__when { margin-top: 1px; margin-left: 0; }

/* The match inside a title, snippet or preview: bold on a neutral wash (never a status or selection colour) */
.kl-switcher__hl {
  padding: 0 1px;
  border-radius: var(--kl-radius-mark);
  background: var(--kl-color-match);
  color: inherit;
  font-weight: var(--kl-font-weight-bold);
}
.kl-switcher__row:is(.is-active, [aria-selected="true"]) .kl-switcher__hl { background: color-mix(in srgb, var(--kl-color-text-on-fill) 26%, transparent); }

/* Preview pane: the prompter's pane well (sunken, hairline, inner radius) */
.kl-switcher__preview {
  display: flex;
  flex-direction: column;
  gap: var(--kl-space-3);
  min-height: 0;
  padding: var(--kl-space-4);
  border-radius: var(--kl-switcher-radius-in, var(--kl-radius-groupbox));
  background: var(--kl-color-surface-sunken);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
  overflow: auto;
  overscroll-behavior: contain;
}
.kl-switcher__pv-head { display: flex; align-items: flex-start; gap: var(--kl-space-3); }
.kl-switcher__pv-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: var(--kl-icon-tile);
  height: var(--kl-icon-tile);
  border-radius: var(--kl-radius-row);
  background: var(--kl-color-surface);
  color: var(--kl-color-text-secondary);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
}
.kl-switcher__pv-title { margin: 0; font: var(--kl-font-headline); color: var(--kl-color-text); }
.kl-switcher__pv-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--kl-space-1) var(--kl-switcher-tight, 6px);
  margin-top: var(--kl-space-1);
  font: var(--kl-font-caption);
  color: var(--kl-color-text-secondary);
}
.kl-switcher__pv-text { margin: 0; font: var(--kl-font-meta); color: var(--kl-color-text); }
.kl-switcher__pv-label { margin: 0 0 calc(var(--kl-space-1) * -1); font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }

/* Where a memory came from: a small surface row */
.kl-switcher__pv-from {
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  min-height: 36px;
  padding: var(--kl-switcher-tight, 6px) var(--kl-switcher-row-x, 10px);
  border-radius: var(--kl-radius-row);
  background: var(--kl-color-surface);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
  font: var(--kl-font-label);
}
.kl-switcher__pv-from > .kl-icon { color: var(--kl-color-text-secondary); }
.kl-switcher__pv-from .kl-switcher__name { flex: 1 1 auto; }
.kl-switcher__pv-from .kl-switcher__when { min-width: 0; }

/* A run's facts: label column and value */
.kl-switcher__facts {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: var(--kl-space-2) var(--kl-space-3);
  margin: 0;
  font: var(--kl-font-meta);
}
.kl-switcher__facts dt { padding-top: 2px; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }
.kl-switcher__facts dd { display: flex; align-items: center; gap: var(--kl-switcher-tight, 6px); min-width: 0; margin: 0; color: var(--kl-color-text); }
.kl-switcher .kl-switcher__facts dd .kl-icon { --kl-icon-size: 14px; color: var(--kl-color-text-secondary); }

/* Last lines of a run, a few lines of a file: Geist Mono on the surface */
.kl-switcher__lines {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0 var(--kl-space-3);
  margin: 0;
  padding: var(--kl-space-2) var(--kl-space-3);
  border-radius: var(--kl-radius-row);
  background: var(--kl-color-surface);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
  font: var(--kl-font-caption);
  font-family: var(--kl-font-mono);
  font-weight: var(--kl-font-weight-regular);
  line-height: 18px;
  color: var(--kl-color-text);
  overflow: hidden;
}
.kl-switcher__lines--log { grid-template-columns: minmax(0, 1fr); }
.kl-switcher__ln { color: var(--kl-color-text-secondary); text-align: right; user-select: none; }
.kl-switcher__lc { min-width: 0; overflow: hidden; white-space: pre; text-overflow: ellipsis; }
.kl-switcher__lc.is-match { font-weight: var(--kl-font-weight-semibold); }
.kl-switcher__path {
  margin: 0;
  font: var(--kl-font-caption);
  font-family: var(--kl-font-mono);
  font-weight: var(--kl-font-weight-regular);
  color: var(--kl-color-text-secondary);
  overflow-wrap: anywhere;
}
.kl-switcher__pv-actions { display: flex; align-items: center; gap: var(--kl-space-2); margin-top: auto; padding-top: var(--kl-space-1); }
.kl-switcher__pv-actions .kl-switcher__hint { margin-left: auto; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); }

/* Searching: quiet static placeholders, no shimmer */
.kl-switcher__ph {
  display: block;
  width: var(--kl-ph-w, 60%);
  height: 10px;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-color-control-fill);
}
.kl-switcher__ph--sq { flex: none; width: 16px; height: 16px; border-radius: var(--kl-radius-sheet); }
.kl-switcher__ph--tile { flex: none; width: var(--kl-icon-tile); height: var(--kl-icon-tile); border-radius: var(--kl-radius-row); }
.kl-switcher__ph--thin { height: 8px; }
.kl-switcher__ph-row { display: flex; align-items: flex-start; gap: var(--kl-space-2); min-height: var(--kl-switcher-hit-h, 52px); padding: var(--kl-space-2) var(--kl-switcher-row-x, 10px); }
.kl-switcher__ph-text { flex: 1 1 auto; display: flex; flex-direction: column; gap: var(--kl-space-2); padding-top: 3px; }
.kl-switcher__ph-head { padding: var(--kl-space-2) var(--kl-switcher-row-x, 10px) var(--kl-space-1); }

/* No results: a calm line and one way out */
.kl-switcher__none {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--kl-space-3);
  padding: var(--kl-space-6);
  border-radius: var(--kl-switcher-radius-in, var(--kl-radius-groupbox));
  background: var(--kl-color-surface-sunken);
  box-shadow: inset 0 0 0 1px var(--kl-color-line);
  text-align: center;
}
.kl-switcher .kl-switcher__none > .kl-icon { --kl-icon-size: 24px; color: var(--kl-color-text-secondary); }
.kl-switcher__none p { margin: 0; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }
.kl-switcher__none p b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); }

/* =====================================================================================
   6. Motion. Opens on the dial-scaled spring; size changes glide on ease-out; nothing moves while typing
   ===================================================================================== */
@media (prefers-reduced-motion: no-preference) {
  /* Opens: rises 6px out of the prompter's spot, from .98, on the spring (its overshoot scales with the dial) */
  .kl-switcher.is-entering { animation: kl-switcher-in var(--kl-motion-switcher-in) var(--kl-motion-spring) both; }
  /* Opening a result: the active row flashes once, then the panel fades while the board glides to the card */
  .kl-switcher__row.is-flashing { animation: kl-switcher-flash var(--kl-motion-flash) var(--kl-motion-ease-out) both; }
  .kl-switcher.is-leaving { animation: kl-switcher-out var(--kl-motion-fade-out) var(--kl-motion-ease-in) var(--kl-motion-press) forwards; pointer-events: none; }
  .kl-switcher.is-leaving .kl-switcher__row.is-active { animation: kl-switcher-flash var(--kl-motion-flash) var(--kl-motion-ease-out) both; }
  /* Results land with one fade: no stagger, no shimmer */
  .kl-switcher__results.is-arriving, .kl-switcher__preview.is-arriving { animation: kl-switcher-fade var(--kl-motion-fade) var(--kl-motion-ease-out) both; }
  /* Widening into search: the preview fades in once the width has mostly settled */
  .kl-switcher.is-search .kl-switcher__preview { animation: kl-switcher-fade var(--kl-motion-reveal) var(--kl-motion-ease-out) var(--kl-motion-reveal-delay) both; }
}
/* Static frame for the specimen: the panel half way through its fade */
.kl-switcher.is-fading { opacity: .5; scale: .985; }

@media (prefers-reduced-motion: reduce) {
  .kl-switcher { transition: none; }
  .kl-switcher.is-entering, .kl-switcher__results.is-arriving, .kl-switcher__preview.is-arriving,
  .kl-switcher.is-search .kl-switcher__preview { animation: kl-switcher-fade var(--kl-motion-fade) linear both; }
  .kl-switcher.is-leaving { animation: kl-switcher-fade-out var(--kl-motion-fade-out) linear forwards; pointer-events: none; }
  .kl-switcher.is-fading { scale: none; }
}
.kl-motion-reduce .kl-switcher { transition: none; }
.kl-motion-reduce :is(.kl-switcher.is-entering, .kl-switcher__results.is-arriving, .kl-switcher__preview.is-arriving, .kl-switcher.is-search .kl-switcher__preview) { animation: kl-switcher-fade var(--kl-motion-fade) linear both !important; }
.kl-motion-reduce :is(.kl-switcher__row.is-flashing, .kl-switcher.is-leaving .kl-switcher__row.is-active) { animation: none !important; }
.kl-motion-reduce .kl-switcher.is-leaving { animation: kl-switcher-fade-out var(--kl-motion-fade-out) linear forwards !important; }
.kl-motion-reduce .kl-switcher.is-fading { scale: none; }

/* transform, not translate/scale: the anchored panel already uses translate to centre itself */
@keyframes kl-switcher-in { from { opacity: 0; transform: translateY(var(--kl-motion-reveal-shift)) scale(.98); } }
@keyframes kl-switcher-out { to { opacity: 0; transform: scale(.985); } }
@keyframes kl-switcher-fade { from { opacity: 0; } }
@keyframes kl-switcher-fade-out { to { opacity: 0; } }
@keyframes kl-switcher-flash {
  0% { box-shadow: 0 0 0 0 var(--kl-color-selection-soft); }
  40% { box-shadow: 0 0 0 4px var(--kl-color-selection-soft); }
  100% { box-shadow: 0 0 0 0 var(--kl-color-selection-soft); }
}

/* =====================================================================================
   7. Increased contrast and forced colours
   ===================================================================================== */
@media (prefers-contrast: more) {
  .kl-switcher { box-shadow: 0 0 0 1px var(--kl-color-text-secondary), var(--kl-shadow-window); }
  .kl-switcher__preview, .kl-switcher__none, .kl-switcher__lines, .kl-switcher__pv-from { box-shadow: inset 0 0 0 1px var(--kl-color-text-secondary); }
  .kl-switcher__field { border-width: 2px; }
  .kl-switcher__hl { text-decoration: underline; text-underline-offset: 2px; }
}
[data-contrast="more"] .kl-switcher { box-shadow: 0 0 0 1px var(--kl-color-text-secondary), var(--kl-shadow-window); }
[data-contrast="more"] :is(.kl-switcher__preview, .kl-switcher__none, .kl-switcher__lines, .kl-switcher__pv-from) { box-shadow: inset 0 0 0 1px var(--kl-color-text-secondary); }
[data-contrast="more"] .kl-switcher__field { border-width: 2px; }
[data-contrast="more"] .kl-switcher__hl { text-decoration: underline; text-underline-offset: 2px; }

@media (forced-colors: active) {
  .kl-switcher { border: 1px solid CanvasText; }
  .kl-switcher__row:is(.is-active, [aria-selected="true"]) { forced-color-adjust: none; background: Highlight; color: HighlightText; }
  .kl-switcher__mark, .kl-switcher__ph { forced-color-adjust: none; outline: 1px solid CanvasText; }
  .kl-switcher__hl { forced-color-adjust: none; background: Mark; color: MarkText; }
}

/* =====================================================================================
   Specimen only (.pj-sw-*): a frame for preview panes shown on their own, the key list and the motion strips.
   Not part of the component.
   ===================================================================================== */
.pj-sw-frame {
  display: flex;
  flex-direction: column;
  width: 364px;
  padding: var(--kl-space-3);
  border-radius: var(--kl-radius-prompter);
  background: var(--kl-color-surface);
  box-shadow: var(--kl-shadow-window);
  color: var(--kl-color-text);
  font: var(--kl-font-meta);
  font-family: var(--kl-font-sans);
  font-variant-numeric: tabular-nums;
}
.pj-sw-frame > .kl-switcher__preview { flex: 1 1 auto; }
.pj-sw-frame .kl-icon { --kl-icon-size: 16px; }
.pj-sw-card {
  width: 420px;
  padding: var(--kl-space-4) var(--kl-space-5) var(--kl-space-5);
  border-radius: var(--kl-radius-card);
  background: var(--kl-color-surface);
  box-shadow: var(--kl-shadow-card);
  color: var(--kl-color-text);
}
.pj-sw-card h3 { margin: 0 0 var(--kl-space-3); font: var(--kl-font-headline); }
.pj-sw-keys { display: grid; grid-template-columns: 112px minmax(0, 1fr); gap: var(--kl-space-3) var(--kl-space-4); align-items: center; margin: 0; }
.pj-sw-keys dt { display: inline-flex; align-items: center; justify-content: flex-end; gap: var(--kl-space-1); }
.pj-sw-keys dd { margin: 0; font: var(--kl-font-meta); color: var(--kl-color-text); }
.pj-sw-keys dd span { color: var(--kl-color-text-secondary); }
.pj-sw-strip { display: flex; align-items: flex-start; gap: var(--kl-space-3); }
.pj-sw-fw { display: grid; grid-template-rows: 60px auto; justify-items: center; align-items: end; gap: var(--kl-space-2); }
.pj-sw-fl { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); white-space: nowrap; }
.pj-sw-f {
  width: 64px;
  height: 52px;
  border-radius: var(--kl-radius-row);
  background: var(--kl-color-surface);
  box-shadow: var(--kl-shadow-card);
  transform-origin: 50% 100%;
}
.pj-sw-f--wide { width: 104px; }
.pj-sw-f--low { height: 20px; }
.pj-sw-f--ghost { opacity: .38; scale: .97; }
.pj-sw-f--rise { opacity: .6; translate: 0 6px; scale: .98; }
.pj-sw-f--fade { opacity: .5; scale: .985; }
.pj-sw-f--ring { box-shadow: var(--kl-shadow-card), 0 0 0 4px var(--kl-color-selection-soft); background: var(--kl-color-selection); }
.pj-sw-arrow { margin-top: 22px; color: var(--kl-color-text-secondary); }

/* ===== harness/projects/activity.css ===== */
/* Klippan master · Many projects · 4. Activity log
   .kl-win.kl-activity: one project's log (or every project's), opened from a project card's gear menu, a tile's menu
   or the switcher. Built on v2's window frame (.kl-win, __bar, __scope, __body, .kl-win-tether) and controls
   (.kl-select, .kl-seg, .kl-btn, .kl-iconbtn, .kl-badge, .kl-dot, .kl-menu). Opaque, because you read it for a while.
   Every value is a --kl-* token; component sizes are local custom properties. */

/* =====================================================================================
   1. Window
   ===================================================================================== */
.kl-activity {
  --kl-win-w: 420px;
  --kl-act-time-w: 48px;     /* the time column */
  --kl-act-tile: 24px;       /* the agent's round tile */
  --kl-act-min-h: 44px;      /* a row is never shorter than a hit area */
  --kl-act-sub-h: 28px;      /* a line inside an unfolded run */
  --kl-act-pill-h: 28px;     /* the "2 new" pill */
  /* project hue for the agent tiles and marks; the --pN modifiers below set it */
  --kl-act-hue: var(--kl-color-project-1);
  --kl-act-soft: var(--kl-color-project-1-soft);
  --kl-act-ink: var(--kl-color-project-1-ink);
}
.kl-activity .kl-win__scope .kl-win-mark { background: var(--kl-act-hue); }

/* Project hues: on the window (one project) or on a row (every project) */
.kl-activity--p1, .kl-act--p1 { --kl-act-hue: var(--kl-color-project-1); --kl-act-soft: var(--kl-color-project-1-soft); --kl-act-ink: var(--kl-color-project-1-ink); }
.kl-activity--p2, .kl-act--p2 { --kl-act-hue: var(--kl-color-project-2); --kl-act-soft: var(--kl-color-project-2-soft); --kl-act-ink: var(--kl-color-project-2-ink); }
.kl-activity--p3, .kl-act--p3 { --kl-act-hue: var(--kl-color-project-3); --kl-act-soft: var(--kl-color-project-3-soft); --kl-act-ink: var(--kl-color-project-3-ink); }
.kl-activity--p4, .kl-act--p4 { --kl-act-hue: var(--kl-color-project-4); --kl-act-soft: var(--kl-color-project-4-soft); --kl-act-ink: var(--kl-color-project-4-ink); }
.kl-activity--p5, .kl-act--p5 { --kl-act-hue: var(--kl-color-project-5); --kl-act-soft: var(--kl-color-project-5-soft); --kl-act-ink: var(--kl-color-project-5-ink); }
.kl-activity--p6, .kl-act--p6 { --kl-act-hue: var(--kl-color-project-6); --kl-act-soft: var(--kl-color-project-6-soft); --kl-act-ink: var(--kl-color-project-6-ink); }
.kl-activity--p7, .kl-act--p7 { --kl-act-hue: var(--kl-color-project-7); --kl-act-soft: var(--kl-color-project-7-soft); --kl-act-ink: var(--kl-color-project-7-ink); }
.kl-activity--p8, .kl-act--p8 { --kl-act-hue: var(--kl-color-project-8); --kl-act-soft: var(--kl-color-project-8-soft); --kl-act-ink: var(--kl-color-project-8-ink); }

/* Bar: the Activity glyph on v2's neutral icon tile, the scope tag (project mark, or "Every project"), minimise and close */
.kl-activity .kl-win__icon .kl-icon,
.kl-activity .kl-win__ctl .kl-icon { --kl-icon-size: 16px; }

/* Filter row under the bar: the agent select, then the kind segmented control */
.kl-activity__filters {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  padding: var(--kl-space-2) var(--kl-space-3);
  border-bottom: 1px solid var(--kl-color-line);
}
.kl-activity__filters .kl-select { --kl-select-w: 0px; flex: 1 1 auto; min-width: 0; }
.kl-activity__filters .kl-seg { flex: none; margin-left: auto; }
.kl-activity__filters .kl-seg__item { padding: 0 var(--kl-win-tight); }

/* Body: the scrolling log. Day groups stack with a little air; rows inside a group sit tight. */
.kl-activity__body {
  gap: var(--kl-space-1);
  padding: 0 var(--kl-space-2) var(--kl-space-3);
  scrollbar-width: thin;
  scrollbar-color: var(--kl-color-line-strong) transparent;
}
.kl-activity__day { display: flex; flex-direction: column; margin: 0; padding: 0; }
/* Day label in caption style; sticks to the top of the body while its rows scroll under it */
.kl-activity__daylabel {
  position: sticky;
  top: 0;
  z-index: 1;
  margin: 0;
  padding: var(--kl-space-3) var(--kl-space-2) var(--kl-space-1);
  background: var(--kl-color-surface);
  font: var(--kl-font-caption);
  letter-spacing: var(--kl-font-caption-tracking);
  color: var(--kl-color-text-secondary);
}
.kl-activity__list { display: flex; flex-direction: column; gap: var(--kl-win-hair); margin: 0; padding: 0; list-style: none; }

/* =====================================================================================
   2. Row .kl-act
   time | agent tile | who (project tag, agent name, waiting) over what (kind icon + line) | end (tag, Open, chevron)
   ===================================================================================== */
.kl-act {
  position: relative;
  display: grid;
  grid-template-columns: var(--kl-act-time-w) var(--kl-act-tile) minmax(0, 1fr) auto;
  grid-template-areas: "time tile who end" "time tile what end";
  align-items: center;
  column-gap: var(--kl-space-2);
  min-height: var(--kl-act-min-h);
  padding: var(--kl-win-tight) var(--kl-space-2);
  border-radius: var(--kl-radius-row);
  color: var(--kl-color-text);
  transition: background-color var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-act__time {
  grid-area: time;
  align-self: start;
  padding-top: var(--kl-win-hair);
  font: var(--kl-font-meta);
  font-variant-numeric: tabular-nums;
  color: var(--kl-color-text-secondary);
  white-space: nowrap;
}
/* The agent mark: the agent icon in a small round tile tinted with the project hue */
.kl-act__tile {
  grid-area: tile;
  align-self: start;
  display: inline-grid;
  place-items: center;
  width: var(--kl-act-tile);
  height: var(--kl-act-tile);
  margin-top: var(--kl-win-hair);
  border-radius: var(--kl-radius-round);
  background: var(--kl-act-soft);
  color: var(--kl-act-ink);
}
.kl-act__tile .kl-icon { --kl-icon-size: 14px; }
.kl-act__who {
  grid-area: who;
  display: flex;
  align-items: center;
  gap: var(--kl-win-tight);
  min-width: 0;
  font: var(--kl-font-meta);
  color: var(--kl-color-text-secondary);
  white-space: nowrap;
}
.kl-act__agent { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.kl-act__what { grid-area: what; display: flex; align-items: center; gap: var(--kl-win-tight); min-width: 0; }
.kl-act__kind.kl-icon { --kl-icon-size: 14px; color: var(--kl-color-text-secondary); }
.kl-act__line {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: var(--kl-font-label);
  color: var(--kl-color-text);
}
.kl-act__mono { font-family: var(--kl-font-mono); font-weight: var(--kl-font-weight-regular); }
.kl-act__end { grid-area: end; display: inline-flex; align-items: center; gap: var(--kl-win-tight); }

/* Trailing tag: a file name in mono, a pull request, or a token count. v2's neutral badge, kept in the row's flow
   (the combined sheet also carries the board's corner-count .kl-badge, so position and ring are reset here). */
.kl-act__tag.kl-badge { position: static; max-width: 128px; box-shadow: none; }
.kl-act__tagtext { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.kl-act__tag--mono.kl-badge { font-family: var(--kl-font-mono); font-weight: var(--kl-font-weight-regular); }
.kl-act__tag .kl-icon { --kl-icon-size: 12px; }

/* Project tag (every-project scope): the hue mark and the project name, in front of the agent name */
.kl-act__project { display: inline-flex; align-items: center; gap: var(--kl-space-1); flex: none; font: var(--kl-font-label); color: var(--kl-color-text); }
.kl-act__project .kl-win-mark { width: 8px; height: 8px; border-radius: 2px; background: var(--kl-act-hue); }
.kl-act__sep { flex: none; color: var(--kl-color-text-tertiary); }

/* Clickable: the row opens what it is about (the run, the diff, the file). Hover and focus as v2 list rows. */
.kl-act--link { cursor: pointer; }
.kl-act--link:hover, .kl-act.is-hover { background: var(--kl-color-control-fill); }
.kl-act--link:focus-visible, .kl-act.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: -2px; }

/* Waiting on Alban: the approval (magenta) dot and "Waiting on you" in the who line, a faint approval wash, Open on the right.
   Waiting on Alban is never drawn as stopped: red is only for a run that stopped. */
.kl-act__wait { display: inline-flex; align-items: center; gap: var(--kl-space-1); flex: none; font: var(--kl-font-badge); color: var(--kl-card-approval-ink); }
.kl-act__wait .kl-dot { --kl-dot-size: 8px; }
.kl-act.is-waiting { --kl-act-wash: var(--kl-color-status-approval-wash, color-mix(in srgb, var(--kl-card-approval-soft) 55%, transparent)); background: var(--kl-act-wash); }
.kl-act.is-waiting:hover, .kl-act.is-waiting.is-hover { background: var(--kl-card-approval-soft); }
/* Answered: the wait is over; a grey line, a check and when */
.kl-act__done { display: inline-flex; align-items: center; gap: var(--kl-space-1); flex: none; font: var(--kl-font-badge); color: var(--kl-color-status-executing-ink); }
.kl-act__done .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }
.kl-act.is-answered .kl-act__line { color: var(--kl-color-text-secondary); }

/* =====================================================================================
   3. Folded runs: several actions of one kind in a row fold into one line with a chevron
   ===================================================================================== */
.kl-act__fold .kl-icon { transition: rotate var(--kl-motion-expand) var(--kl-motion-spring-pop); }
.kl-act.is-unfolded .kl-act__fold .kl-icon { rotate: 180deg; }
.kl-act__count { font-variant-numeric: tabular-nums; }
/* The folded lines: a grid that grows from 0 to its height on ease-out, so the rows below glide down */
.kl-act-sub {
  display: grid;
  grid-template-rows: 0fr;
  margin: 0;
  padding: 0;
  list-style: none;
  opacity: 0;
  transition: grid-template-rows var(--kl-motion-collapse) var(--kl-motion-ease-out), opacity var(--kl-motion-collapse) var(--kl-motion-ease-out);
}
.kl-act-sub__inner { min-height: 0; overflow: hidden; display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
.kl-act.is-unfolded + .kl-act-sub { grid-template-rows: 1fr; opacity: 1; transition-duration: var(--kl-motion-expand); }
/* Each line hangs under the agent tile on a faint guide, its name in mono */
.kl-act-sub__row {
  display: flex;
  align-items: center;
  gap: var(--kl-space-2);
  min-height: var(--kl-act-sub-h);
  margin-left: calc(var(--kl-space-2) + var(--kl-act-time-w) + var(--kl-space-2) + var(--kl-act-tile) / 2);
  padding: 0 var(--kl-space-2) 0 calc(var(--kl-act-tile) / 2 + var(--kl-space-2));
  box-shadow: inset 1.5px 0 0 var(--kl-color-line);
  color: var(--kl-color-text);
}
.kl-act-sub__row .kl-icon { --kl-icon-size: 14px; color: var(--kl-color-text-secondary); }
.kl-act-sub__name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--kl-font-meta); font-family: var(--kl-font-mono); }
.kl-act-sub__time { flex: none; font: var(--kl-font-caption); font-variant-numeric: tabular-nums; color: var(--kl-color-text-secondary); }

/* =====================================================================================
   4. New rows: rise into place at the top, or wait behind the "2 new" pill
   ===================================================================================== */
@keyframes kl-act-arrive { from { opacity: 0; translate: 0 var(--kl-motion-reveal-shift); } to { opacity: 1; translate: 0 0; } }
@keyframes kl-act-fade { from { opacity: 0; } to { opacity: 1; } }
/* The row rises 6 px and fades in on ease-out; the rows below glide down by its height. Nothing bounces. */
.kl-act.is-new { animation: kl-act-arrive var(--kl-motion-reveal) var(--kl-motion-ease-out) both; }
/* A fresh row's time reads "now" in the selection ink until the next minute */
.kl-act.is-new .kl-act__time { color: var(--kl-color-selection-ink); }

/* While Alban scrolls or types, new rows wait above and a glass pill says how many; a click scrolls to the top */
.kl-activity__new {
  position: sticky;
  top: var(--kl-space-2);
  z-index: 2;
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: var(--kl-space-1);
  height: var(--kl-act-pill-h);
  margin: var(--kl-space-2) 0 calc(-1 * (var(--kl-act-pill-h) + var(--kl-space-2)));
  padding: 0 var(--kl-space-3) 0 var(--kl-space-2);
  border: 0;
  border-radius: var(--kl-radius-pill);
  background: var(--kl-glass-fill-menu);
  -webkit-backdrop-filter: blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));
  backdrop-filter: blur(var(--kl-glass-blur)) saturate(var(--kl-glass-saturate));
  box-shadow: var(--kl-shadow-menu), var(--kl-glass-rim);
  color: var(--kl-color-selection-ink);
  font: var(--kl-font-label-strong);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  animation: kl-act-arrive var(--kl-motion-reveal) var(--kl-motion-ease-out) both;
}
.kl-activity__new::before { content: ""; position: absolute; inset: calc((var(--kl-act-pill-h) - var(--kl-size-target)) / 2) 0; }
.kl-activity__new .kl-icon { --kl-icon-size: 14px; }
.kl-activity__new:hover, .kl-activity__new.is-hover { box-shadow: var(--kl-shadow-menu), var(--kl-glass-rim), inset 0 0 0 100px var(--kl-color-control-fill); }
.kl-activity__new:focus-visible, .kl-activity__new.is-focus { outline: 2px solid var(--kl-color-focus); outline-offset: 2px; }

/* =====================================================================================
   5. Load earlier, the start of the log, and empty
   ===================================================================================== */
.kl-activity__more { display: flex; flex-direction: column; align-items: center; gap: var(--kl-space-1); padding: var(--kl-space-2) 0 0; }
.kl-activity__morenote { margin: 0; font: var(--kl-font-caption); color: var(--kl-color-text-secondary); font-variant-numeric: tabular-nums; }
/* Loading: the button says so and waits over three still placeholder rows. No shimmer. */
.kl-activity__ghost { display: flex; flex-direction: column; gap: var(--kl-win-hair); align-self: stretch; margin-bottom: var(--kl-space-1); }
.kl-activity__ghost span { display: block; height: var(--kl-act-min-h); border-radius: var(--kl-radius-row); background: var(--kl-color-surface-sunken); }
.kl-activity__ghost span:nth-child(2) { opacity: .66; }
.kl-activity__ghost span:nth-child(3) { opacity: .33; }
.kl-activity__end { display: inline-flex; align-items: center; gap: var(--kl-space-1); }
.kl-activity__end .kl-icon { --kl-icon-size: 12px; --kl-icon-stroke: 2; }

.kl-activity__empty { display: flex; flex-direction: column; align-items: center; gap: var(--kl-space-2); padding: var(--kl-space-12) var(--kl-space-6); text-align: center; }
.kl-activity__empty-tile { display: inline-grid; place-items: center; width: 40px; height: 40px; margin-bottom: var(--kl-space-1); border-radius: var(--kl-radius-tile); background: var(--kl-act-soft); color: var(--kl-act-ink); }
.kl-activity__empty-tile .kl-icon { --kl-icon-size: 20px; }
.kl-activity__empty-title { margin: 0; font: var(--kl-font-label-strong); color: var(--kl-color-text); }
.kl-activity__empty-text { margin: 0; max-width: 240px; font: var(--kl-font-meta); color: var(--kl-color-text-secondary); }

/* =====================================================================================
   6. Increased contrast, reduced motion, forced colours
   ===================================================================================== */
[data-contrast="more"] .kl-act.is-waiting { box-shadow: inset 0 0 0 1px var(--kl-card-approval); }
[data-contrast="more"] .kl-act__tag.kl-badge { box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
[data-contrast="more"] .kl-act-sub__row { box-shadow: inset 1.5px 0 0 var(--kl-color-line-strong); }

/* Only fades of 120 ms or less remain: a new row and the pill fade in, unfolding is instant, the chevron just flips */
@media (prefers-reduced-motion: reduce) {
  .kl-act.is-new, .kl-activity__new { animation: kl-act-fade var(--kl-motion-fade) ease both; }
  .kl-act, .kl-act-sub, .kl-act__fold .kl-icon { transition: none; }
}
.kl-motion-reduce :is(.kl-act.is-new, .kl-activity__new) { animation: kl-act-fade var(--kl-motion-fade) ease both; }
.kl-motion-reduce :is(.kl-act, .kl-act-sub, .kl-act__fold .kl-icon) { transition: none; }

@media (forced-colors: active) {
  .kl-act.is-waiting { outline: 1px solid CanvasText; outline-offset: -1px; }
}

/* ===== harness/projects/templates.css ===== */
/* =====================================================================================================
   Klippan master DS · Many projects · 5. Templates in Settings
   Alban's project templates in one list: see them, rename, duplicate, delete (to Garbage, with Undo) and start a
   new project from one. It is the Settings window's body, swapped in from "Project templates" (v2's account-to-project
   swap), so it stays an ordinary v2 window: opaque, 480 wide, non-modal, beside the Settings card.

   Builds on v2: load ../../../klippan-v2/combined/klippan.css first, then setup.css (the template icons and the
   setup card). Every value is a --kl-* token or a local size (--kl-tplrow-*).

   Pieces
     .kl-win.kl-win--settings.kl-tplwin   the window (title "Templates", scope "Your account")
       .kl-tplwin__group                  "Yours" and "Built in", each a v2 .kl-setting-group with a .kl-win-list
       .kl-tplrow                         one template: tile, name, what it brings, who uses it, New project, more
         .is-hover / :hover               a faint fill and the New project button
         .is-menu                         its more menu is open (.kl-menu.kl-tplrow__menu)
         .is-renaming                     the name is an inline field; Return saves, Esc keeps the old name
         .is-new                          just duplicated: rises 6 px and fades in, a short selection wash fades out
         .is-leaving                      deleted: folds its height on ease-out and fades, then Garbage has it
       .kl-tplwin__empty                  no templates of your own yet
     .kl-tplentry                         the Project templates row in the account Settings window
     .kl-setup__from                      the line in a setup card started from a template
   ===================================================================================================== */

.kl-tplwin, .kl-tplrow, .kl-tplwin__empty {
  --kl-tplrow-tile: 32px;
  --kl-tplrow-min-h: 60px;
}
.kl-tplwin .kl-win__body { gap: var(--kl-space-5, 20px); }
.kl-tplwin__group .kl-win-list { padding: 0; overflow: visible; }
.kl-tplwin__group .kl-setting-group__label { justify-content: flex-start; gap: var(--kl-space-1); }

/* ---- Row ---------------------------------------------------------------------------------------------------- */
.kl-tplrow {
  position: relative;
  display: grid;
  grid-template-columns: var(--kl-tplrow-tile) minmax(0, 1fr) auto;
  align-items: center;
  column-gap: var(--kl-space-3);
  min-height: var(--kl-tplrow-min-h);
  padding: var(--kl-space-2) var(--kl-space-2) var(--kl-space-2) var(--kl-space-3);
  border-radius: var(--kl-radius-groupbox);
  transition: background-color var(--kl-motion-hover) ease;
}
.kl-tplrow + .kl-tplrow { box-shadow: 0 -1px 0 var(--kl-color-line); }
.kl-tplrow__tile {
  display: grid; place-items: center;
  width: var(--kl-tplrow-tile); height: var(--kl-tplrow-tile);
  border-radius: var(--kl-radius-row);
  background: var(--kl-color-control-fill);
  color: var(--kl-color-text-secondary);
}
.kl-tplrow__tile .kl-icon { --kl-icon-size: 18px; width: 18px; height: 18px; }
.kl-tplrow__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.kl-tplrow__name {
  display: flex; align-items: center; gap: var(--kl-space-2); min-width: 0;
  font: var(--kl-font-label-strong); letter-spacing: var(--kl-font-label-strong-tracking); color: var(--kl-color-text);
}
.kl-tplrow__name > span:first-child { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.kl-tplrow__name .kl-setting__tag { flex: none; }
.kl-tplrow__brings,
.kl-tplrow__uses { font: var(--kl-font-caption); color: var(--kl-color-text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kl-tplrow__uses b { font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text); }

/* The project marks in "Used by": the projects' own hues, small squares as in windows */
.kl-tplrow__uses .kl-win-mark { width: 8px; height: 8px; border-radius: 2px; margin: 0 3px 0 1px; vertical-align: 0; }
.kl-tplrow__uses .kl-win-mark--p1 { background: var(--kl-color-project-1); }
.kl-tplrow__uses .kl-win-mark--p2 { background: var(--kl-color-project-2); }
.kl-tplrow__uses .kl-win-mark--p3 { background: var(--kl-color-project-3); }
.kl-tplrow__uses .kl-win-mark--p4 { background: var(--kl-color-project-4); }
.kl-tplrow__uses .kl-win-mark--p5 { background: var(--kl-color-project-5); }
.kl-tplrow__uses .kl-win-mark--p6 { background: var(--kl-color-project-6); }
.kl-tplrow__uses .kl-win-mark--p7 { background: var(--kl-color-project-7); }
.kl-tplrow__uses .kl-win-mark--p8 { background: var(--kl-color-project-8); }

/* Actions: New project shows on hover or keyboard focus; more is always there (it is how the keyboard gets in) */
.kl-tplrow__acts { display: inline-flex; align-items: center; gap: var(--kl-space-1); }
.kl-tplrow__new {
  opacity: 0; translate: 4px 0;
  transition: opacity var(--kl-motion-hover) ease, translate var(--kl-motion-hover) var(--kl-motion-ease-out);
}
.kl-tplrow:hover, .kl-tplrow.is-hover, .kl-tplrow.is-menu, .kl-tplrow:focus-within { background: var(--kl-color-control-fill); }
.kl-tplrow:hover .kl-tplrow__new, .kl-tplrow.is-hover .kl-tplrow__new, .kl-tplrow:focus-within .kl-tplrow__new,
.kl-tplrow.is-menu .kl-tplrow__new { opacity: 1; translate: 0 0; }
.kl-tplrow.is-menu .kl-tplrow__more { background: var(--kl-color-neutral-soft); }
.kl-tplrow:hover + .kl-tplrow, .kl-tplrow.is-hover + .kl-tplrow, .kl-tplrow.is-menu + .kl-tplrow,
.kl-tplrow:focus-within + .kl-tplrow, .kl-tplrow.is-renaming + .kl-tplrow { box-shadow: none; }

/* More menu: hangs from the more button, right-aligned, above the next rows */
.kl-tplrow__menu { position: absolute; right: var(--kl-space-2); top: calc(100% - var(--kl-space-1)); z-index: 3; --kl-menu-w: 220px; }
.kl-tplrow__menu.is-up { top: auto; bottom: calc(100% - var(--kl-space-1)); }   /* the last rows open upward, inside the window */

/* Renaming: the name becomes a field in place; the rest of the row holds still */
.kl-tplrow.is-renaming { background: var(--kl-color-surface); box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
.kl-tplrow__field { display: flex; flex-direction: column; min-width: 0; }
.kl-tplrow__field .kl-field { width: 100%; height: 28px; font: var(--kl-font-label-strong); }
.kl-tplrow__field .kl-fieldhint { margin-top: 4px; }
.kl-tplrow.is-renaming .kl-tplrow__new { display: none; }

/* Just duplicated: rises into place, a selection wash says "this one is new" and fades on its own once */
@keyframes kl-tplrow-new { from { opacity: 0; translate: 0 var(--kl-motion-reveal-shift); } to { opacity: 1; translate: 0 0; } }
@keyframes kl-tplrow-wash { from { background-color: var(--kl-color-selection-soft); } to { background-color: transparent; } }
.kl-tplrow.is-new { animation: kl-tplrow-new var(--kl-motion-reveal) var(--kl-motion-ease-out) both, kl-tplrow-wash 1400ms ease-out 400ms both; }
.kl-tplrow.is-new.is-still { animation: none; background: var(--kl-color-selection-soft); }   /* specimen: the wash held */

/* Deleted: the row folds away on ease-out (sizes never spring), the rows below close the gap */
@keyframes kl-tplrow-leave { to { opacity: 0; min-height: 0; height: 0; padding-top: 0; padding-bottom: 0; } }
.kl-tplrow.is-leaving { overflow: hidden; pointer-events: none; animation: kl-tplrow-leave var(--kl-motion-collapse) var(--kl-motion-ease-out) forwards; }
.kl-tplrow.is-leaving.is-still { animation: none; opacity: .4; }   /* specimen: halfway */

/* ---- Group headings and the empty state --------------------------------------------------------------------- */
.kl-tplwin__group .kl-setting-group__label span { font: var(--kl-font-meta); color: var(--kl-color-text-secondary); font-weight: var(--kl-font-weight-regular); }
.kl-tplwin__empty {
  display: grid; grid-template-columns: var(--kl-tplrow-tile) minmax(0, 1fr); column-gap: var(--kl-space-3); align-items: center;
  padding: var(--kl-space-3);
  font: var(--kl-font-meta); color: var(--kl-color-text-secondary);
}
.kl-tplwin__empty b { display: block; font: var(--kl-font-label-strong); color: var(--kl-color-text); }
.kl-tplwin__empty .kl-tplrow__tile { background: transparent; box-shadow: inset 0 0 0 1.5px var(--kl-color-line-strong); }

/* ---- The entry row in the account Settings window ---------------------------------------------------------- */
.kl-tplentry .kl-setting__hint b { font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text); }

/* ---- Setup card started from a template: says where it came from, step 1 is already done -------------------- */
.kl-setup__from {
  display: flex; align-items: center; gap: var(--kl-space-2); min-width: 0; margin: 0;
  padding: 6px 6px 6px 10px; border-radius: var(--kl-radius-menu);
  background: color-mix(in srgb, var(--kl-color-surface) 70%, transparent); box-shadow: inset 0 0 0 1px var(--kl-color-line);
  font: var(--kl-font-meta); color: var(--kl-color-text-secondary);
}
.kl-setup__from .kl-icon { --kl-icon-size: 16px; width: 16px; height: 16px; flex: none; color: var(--kl-color-text-secondary); }
.kl-setup__from b { color: var(--kl-color-text); font-weight: var(--kl-font-weight-semibold); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kl-setup__from .kl-btn { margin-left: auto; }

/* ---- Reduced motion and increased contrast ------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .kl-tplrow.is-new { animation: kl-win-fade-in var(--kl-motion-fade) ease both; }
  .kl-tplrow.is-leaving { animation: kl-win-fade-out var(--kl-motion-fade) ease forwards; }
  .kl-tplrow__new { translate: 0 0; }
}
.kl-motion-reduce .kl-tplrow.is-new { animation: kl-win-fade-in var(--kl-motion-fade) ease both; }
.kl-motion-reduce .kl-tplrow.is-leaving { animation: kl-win-fade-out var(--kl-motion-fade) ease forwards; }
.kl-motion-reduce .kl-tplrow__new { translate: 0 0; }
@media (prefers-contrast: more) {
  .kl-tplrow:hover, .kl-tplrow.is-hover, .kl-tplrow.is-menu, .kl-tplrow:focus-within { box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
  .kl-tplrow__tile { box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
}
[data-contrast="more"] .kl-tplrow:hover, [data-contrast="more"] .kl-tplrow.is-hover,
[data-contrast="more"] .kl-tplrow.is-menu, [data-contrast="more"] .kl-tplrow:focus-within { box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }
[data-contrast="more"] .kl-tplrow__tile { box-shadow: inset 0 0 0 1px var(--kl-color-line-strong); }

/* ===== harness/projects/recolor.css ===== */
/* =====================================================================================================
   Klippan master DS · Many projects · 6. Recolouring a project
   A project's colour is a row in its settings window (the gear, or Settings in a tile's menu): the same eight
   swatches as setup. Picking one recolours the project everywhere at once: its card, its tile in Home, its links,
   any stack that took its hue, and its marks in windows, the switcher, search and the prompter. Changes save as
   they are made (v2 Settings rule); an Undo toast comes up.

   Hues are shared: with more than eight projects most hues are on two. A shared hue is allowed and only explained.
   When the other project is linked to this one, the note says the link will be harder to read and offers a swap.

   Builds on v2: load ../../../klippan-v2/combined/klippan.css first, then setup.css (.kl-hues and .kl-hue).

   Pieces
     .kl-win--project.kl-pset--p1..p8    a project's settings window, its marks in the project hue
     .kl-setting.kl-recolor               the Colour row: label left, .kl-hues.kl-hues--row right
     .kl-recolor__note                    one line under the group: who else has the hue, and Swap when it helps
       .is-linked                         the other project is linked to this one (warning icon, Swap offered first)
     .is-recoloring                       on everything carrying the hue, for the length of the glide (Motion's
                                          --kl-motion-recolor; leaf elements can carry kl-m-recolor instead)
   ===================================================================================================== */

.kl-pset--p1 { --kl-pset-hue: var(--kl-color-project-1); --kl-pset-soft: var(--kl-color-project-1-soft); --kl-pset-ink: var(--kl-color-project-1-ink); }
.kl-pset--p2 { --kl-pset-hue: var(--kl-color-project-2); --kl-pset-soft: var(--kl-color-project-2-soft); --kl-pset-ink: var(--kl-color-project-2-ink); }
.kl-pset--p3 { --kl-pset-hue: var(--kl-color-project-3); --kl-pset-soft: var(--kl-color-project-3-soft); --kl-pset-ink: var(--kl-color-project-3-ink); }
.kl-pset--p4 { --kl-pset-hue: var(--kl-color-project-4); --kl-pset-soft: var(--kl-color-project-4-soft); --kl-pset-ink: var(--kl-color-project-4-ink); }
.kl-pset--p5 { --kl-pset-hue: var(--kl-color-project-5); --kl-pset-soft: var(--kl-color-project-5-soft); --kl-pset-ink: var(--kl-color-project-5-ink); }
.kl-pset--p6 { --kl-pset-hue: var(--kl-color-project-6); --kl-pset-soft: var(--kl-color-project-6-soft); --kl-pset-ink: var(--kl-color-project-6-ink); }
.kl-pset--p7 { --kl-pset-hue: var(--kl-color-project-7); --kl-pset-soft: var(--kl-color-project-7-soft); --kl-pset-ink: var(--kl-color-project-7-ink); }
.kl-pset--p8 { --kl-pset-hue: var(--kl-color-project-8); --kl-pset-soft: var(--kl-color-project-8-soft); --kl-pset-ink: var(--kl-color-project-8-ink); }

/* The window's icon tile and scope mark take the project's hue (v2 draws them in selection blue) */
.kl-pset .kl-win__icon--project { background: var(--kl-pset-soft); color: var(--kl-pset-ink);
  transition: background-color var(--kl-motion-recolor) var(--kl-motion-ease-out), color var(--kl-motion-recolor) var(--kl-motion-ease-out); }
.kl-pset .kl-win__scope--project { background: var(--kl-color-neutral-soft); color: var(--kl-color-neutral-ink); }
.kl-pset .kl-win__scope .kl-win-mark { background: var(--kl-pset-hue); transition: background-color var(--kl-motion-recolor) var(--kl-motion-ease-out); }

/* ---- The Colour row ------------------------------------------------------------------------------------------ */
.kl-recolor { --kl-setting-min-h: 52px; }
.kl-recolor .kl-setting__text { flex: 0 0 auto; min-width: 64px; }
.kl-hues--row { flex-wrap: nowrap; gap: 8px; padding: 4px 2px; }
.kl-recolor .kl-setting__control { flex: 1 1 auto; justify-content: flex-end; }

/* ---- The note under the group ----------------------------------------------------------------------------------
   One line, in the note style. It answers the swatch under the pointer (or keyboard focus) before Alban picks it:
   "Teal is on Beacon and Pebble". After a pick it says who else has the hue, and offers Swap when exactly one other
   project has it. Linked: a warning icon, because two linked cards in one hue make their link hard to follow. */
.kl-recolor__note {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--kl-space-1) var(--kl-space-2);
  min-height: 28px; margin: 0; padding: 0 var(--kl-space-1);
  font: var(--kl-font-meta); color: var(--kl-color-text-secondary);
}
.kl-recolor__note > span { min-width: 0; }
.kl-recolor__note b { font-weight: var(--kl-font-weight-semibold); color: var(--kl-color-text); }
.kl-recolor__note .kl-win-mark { width: 8px; height: 8px; border-radius: 2px; margin: 0 3px 0 1px; vertical-align: 0; }
.kl-recolor__note .kl-icon { --kl-icon-size: 14px; width: 14px; height: 14px; margin-right: 6px; vertical-align: -2px; }
.kl-recolor__note.is-linked { color: var(--kl-color-text); }
.kl-recolor__note.is-linked .kl-icon { color: var(--kl-color-text-secondary); }
.kl-recolor__note .kl-btn { margin-left: auto; }
/* Marks for the projects the note names */
.kl-recolor__note .kl-win-mark--p1, .kl-recolor-mark--p1 { background: var(--kl-color-project-1); }
.kl-recolor__note .kl-win-mark--p2, .kl-recolor-mark--p2 { background: var(--kl-color-project-2); }
.kl-recolor__note .kl-win-mark--p3, .kl-recolor-mark--p3 { background: var(--kl-color-project-3); }
.kl-recolor__note .kl-win-mark--p4, .kl-recolor-mark--p4 { background: var(--kl-color-project-4); }
.kl-recolor__note .kl-win-mark--p5, .kl-recolor-mark--p5 { background: var(--kl-color-project-5); }
.kl-recolor__note .kl-win-mark--p6, .kl-recolor-mark--p6 { background: var(--kl-color-project-6); }
.kl-recolor__note .kl-win-mark--p7, .kl-recolor-mark--p7 { background: var(--kl-color-project-7); }
.kl-recolor__note .kl-win-mark--p8, .kl-recolor-mark--p8 { background: var(--kl-color-project-8); }

/* A swatch someone else has: a small notch under it, in text grey, only while the pointer or focus is in the row,
   so the row is quiet at rest and still says "taken" before a click. The chosen swatch never shows it. */
.kl-recolor .kl-hue.is-taken::after {
  content: ""; position: absolute; left: 50%; bottom: -7px; width: 4px; height: 4px; margin-left: -2px;
  border-radius: var(--kl-radius-round); background: var(--kl-color-text-tertiary);
  opacity: 0; transition: opacity var(--kl-motion-hover) ease;
}
.kl-recolor:hover .kl-hue.is-taken::after, .kl-recolor:focus-within .kl-hue.is-taken::after,
.kl-recolor.is-hover .kl-hue.is-taken::after { opacity: 1; }
.kl-recolor .kl-hue[aria-checked="true"]::after { display: none; }

/* ---- The glide --------------------------------------------------------------------------------------------------
   Everything carrying the project's hue cross-fades to the new one together over Motion's --kl-motion-recolor, on
   ease-out (colour never springs; calmer is slower, and reduced motion makes it a short fade). A leaf that carries the
   hue itself can take v2's kl-m-recolor class; the card face, tile face, link and stack need the selectors below, as
   the board sets .is-recoloring on their outer element for the glide, then removes it. The card's status dot takes
   kl-m-dot-colour and pops once (kl-m-dot-pop): the only playful part, and it happens at Alban's click. */
.kl-card.is-recoloring > .kl-card__face,
.kl-ptile.is-recoloring .kl-ptile__face,
.kl-ptile.is-recoloring.kl-archive__sheet {
  transition: background-color var(--kl-motion-recolor) var(--kl-motion-ease-out), border-color var(--kl-motion-recolor) var(--kl-motion-ease-out),
              box-shadow var(--kl-motion-hover) ease;
}
.kl-link.is-recoloring { transition: color var(--kl-motion-recolor) var(--kl-motion-ease-out); }
.kl-stack.is-recoloring { transition-duration: var(--kl-motion-recolor); }
.is-recoloring :is(.kl-win-mark, .kl-switcher__mark, .kl-prompter__mark, .kl-card__web-dot, .kl-act__tile) {
  transition: background-color var(--kl-motion-recolor) var(--kl-motion-ease-out), color var(--kl-motion-recolor) var(--kl-motion-ease-out);
}

/* ---- Specimen only --------------------------------------------------------------------------------------------- */
.pj-glide { display: flex; align-items: center; gap: 2px; }
.pj-glide i { display: block; width: 28px; height: 18px; border-radius: 5px; }
.pj-glide i:first-child { border-radius: 9px 5px 5px 9px; }
.pj-glide i:last-child { border-radius: 5px 9px 9px 5px; }
.pj-follows { display: grid; grid-template-columns: 1fr 1fr; gap: 28px 40px; align-items: start; }
.pj-follows__cell { display: flex; flex-direction: column; gap: 10px; align-items: flex-start; min-width: 0; }
.pj-link-scene { position: relative; width: 640px; height: 200px; }
