flow / src /index.css
mfn
Your own agent: hosted relay by default (api.mrfake.name/relay), MCP over HTTP snippets, local relay moved to Advanced
e5b3e51
Raw History Blame Contribute Delete
143 kB
@source "../node_modules/@cloudflare/kumo/dist/**/*.{js,jsx,ts,tsx}";
@import "@cloudflare/kumo/styles/tailwind";
@import "tailwindcss";
@import "@xyflow/react/dist/base.css";
/* ------------------------------------------------------------------ */
/* Tokens */
/* ------------------------------------------------------------------ */
@theme static {
--font-sans: "Source Sans 3", "Source Sans Pro", ui-sans-serif, system-ui, -apple-system, sans-serif;
--font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
/* Port / data-type colours. Tuned so both themes keep the same hue. */
--color-port-text: light-dark(oklch(72% 0.17 85), oklch(84% 0.16 92));
--color-port-number: light-dark(oklch(62% 0.12 190), oklch(76% 0.11 190));
--color-port-boolean: light-dark(oklch(62% 0.16 150), oklch(76% 0.15 150));
--color-port-image: light-dark(oklch(60% 0.16 245), oklch(74% 0.13 240));
--color-port-audio: light-dark(oklch(68% 0.18 55), oklch(78% 0.16 60));
--color-port-video: light-dark(oklch(66% 0.2 340), oklch(78% 0.16 340));
--color-port-file: light-dark(oklch(58% 0.15 270), oklch(74% 0.12 270));
--color-port-gallery: light-dark(oklch(62% 0.16 300), oklch(76% 0.13 300));
--color-port-json: light-dark(oklch(62% 0.2 25), oklch(72% 0.17 25));
--color-port-any: light-dark(oklch(60% 0 0), oklch(70% 0 0));
--ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
--ease-spring: cubic-bezier(0.34, 1.3, 0.64, 1);
/* Soft, slightly overdamped curve used for most micro-interactions. */
--ease-soft: cubic-bezier(0.32, 0.72, 0, 1);
--t-fast: 120ms var(--ease-soft);
--t-med: 200ms var(--ease-soft);
}
/* ------------------------------------------------------------------ */
/* Palette: Hugging Face. Tailwind cool grays (as on huggingface.co), */
/* #0b0f19 night background, HF yellow (#FFD21E) as the single accent. */
/* Every Kumo semantic token is re-pointed so the whole UI follows. */
/* ------------------------------------------------------------------ */
:root {
--hf-yellow: #ffd21e;
--hf-gray-50: #f9fafb;
--hf-gray-100: #f3f4f6;
--hf-gray-200: #e5e7eb;
--hf-gray-300: #d1d5db;
--hf-gray-400: #9ca3af;
--hf-gray-500: #6b7280;
--hf-gray-600: #4b5563;
--hf-gray-700: #374151;
--hf-gray-800: #1f2937;
--hf-gray-850: #172030;
--hf-gray-900: #111827;
--hf-gray-950: #0b0f19;
}
:root[data-mode="dark"] {
--hf-red: #f87171;
--hf-orange: #fb923c;
--hf-amber: #fbbf24;
--hf-yellow-soft: #fde68a;
--hf-green: #4ade80;
--hf-emerald: #34d399;
--hf-cyan: #67e8f9;
--hf-sky: #7dd3fc;
--hf-indigo: #a5b4fc;
--hf-pink: #f9a8d4;
--hf-fuchsia: #e879f9;
--color-kumo-canvas: var(--hf-gray-950);
--color-kumo-base: #0e1320;
--color-kumo-elevated: #131a29;
--color-kumo-overlay: #161e2e;
--color-kumo-recessed: #080b13;
--color-kumo-control: var(--hf-gray-950);
--color-kumo-tint: var(--hf-gray-850);
--color-kumo-fill: var(--hf-gray-800);
--color-kumo-fill-hover: #29364a;
--color-kumo-interact: var(--hf-gray-700);
--color-kumo-line: var(--hf-gray-800);
--color-kumo-hairline: #1a2232;
--color-kumo-contrast: var(--hf-gray-200);
--color-kumo-shadow-edge: rgba(229, 231, 235, 0.06);
--color-kumo-shadow-drop: rgba(0, 0, 0, 0.4);
--color-kumo-arrow-edge: transparent;
--color-kumo-arrow-stroke: var(--hf-gray-800);
--color-kumo-brand: var(--hf-yellow);
--color-kumo-brand-hover: #ffdc4d;
--color-kumo-focus: var(--hf-yellow);
--color-kumo-success: var(--hf-green);
--color-kumo-danger: var(--hf-red);
--color-kumo-warning: var(--hf-orange);
--color-kumo-info: var(--hf-sky);
--color-kumo-success-tint: rgba(74, 222, 128, 0.12);
--color-kumo-danger-tint: rgba(248, 113, 113, 0.12);
--color-kumo-warning-tint: rgba(251, 146, 60, 0.13);
--color-kumo-info-tint: rgba(125, 211, 252, 0.12);
--text-color-kumo-default: var(--hf-gray-200);
--text-color-kumo-strong: var(--hf-gray-50);
--text-color-kumo-subtle: var(--hf-gray-400);
--text-color-kumo-placeholder: var(--hf-gray-500);
--text-color-kumo-inactive: var(--hf-gray-600);
--text-color-kumo-inverse: var(--hf-gray-950);
--text-color-kumo-brand: var(--hf-yellow);
--text-color-kumo-link: var(--hf-yellow-soft);
--text-color-kumo-success: var(--hf-green);
--text-color-kumo-danger: var(--hf-red);
--text-color-kumo-warning: var(--hf-orange);
--text-color-kumo-info: var(--hf-sky);
--accent-soft: rgba(255, 210, 30, 0.12);
--accent-ink: var(--hf-gray-950);
--color-port-text: var(--hf-amber);
--color-port-number: var(--hf-cyan);
--color-port-boolean: var(--hf-green);
--color-port-image: var(--hf-sky);
--color-port-audio: var(--hf-orange);
--color-port-video: var(--hf-pink);
--color-port-file: var(--hf-indigo);
--color-port-gallery: var(--hf-fuchsia);
--color-port-json: var(--hf-red);
--color-port-any: var(--hf-gray-500);
}
:root:not([data-mode="dark"]) {
--hf-red: #dc2626;
--hf-orange: #ea580c;
--hf-amber: #d97706;
--hf-amber-ink: #a16207;
--hf-green: #16a34a;
--hf-cyan: #0891b2;
--hf-sky: #0284c7;
--hf-indigo: #4f46e5;
--hf-pink: #db2777;
--hf-fuchsia: #c026d3;
--color-kumo-canvas: var(--hf-gray-50);
--color-kumo-base: #ffffff;
--color-kumo-elevated: #ffffff;
--color-kumo-overlay: #ffffff;
--color-kumo-recessed: var(--hf-gray-100);
--color-kumo-control: #ffffff;
--color-kumo-tint: var(--hf-gray-100);
--color-kumo-fill: var(--hf-gray-100);
--color-kumo-fill-hover: var(--hf-gray-200);
--color-kumo-interact: var(--hf-gray-300);
--color-kumo-line: var(--hf-gray-200);
--color-kumo-hairline: #edeff2;
--color-kumo-contrast: var(--hf-gray-900);
--color-kumo-shadow-edge: rgba(17, 24, 39, 0.1);
--color-kumo-shadow-drop: rgba(17, 24, 39, 0.06);
--color-kumo-arrow-edge: rgba(17, 24, 39, 0.1);
--color-kumo-arrow-stroke: transparent;
--color-kumo-brand: var(--hf-yellow);
--color-kumo-brand-hover: #f5c400;
--color-kumo-focus: #f59e0b;
--color-kumo-success: var(--hf-green);
--color-kumo-danger: var(--hf-red);
--color-kumo-warning: var(--hf-orange);
--color-kumo-info: var(--hf-sky);
--color-kumo-success-tint: rgba(22, 163, 74, 0.1);
--color-kumo-danger-tint: rgba(220, 38, 38, 0.08);
--color-kumo-warning-tint: rgba(234, 88, 12, 0.1);
--color-kumo-info-tint: rgba(2, 132, 199, 0.08);
--text-color-kumo-default: var(--hf-gray-700);
--text-color-kumo-strong: var(--hf-gray-900);
--text-color-kumo-subtle: var(--hf-gray-500);
--text-color-kumo-placeholder: var(--hf-gray-400);
--text-color-kumo-inactive: var(--hf-gray-300);
--text-color-kumo-inverse: #ffffff;
/* Yellow text is unreadable on white; brand text uses HF's amber ink. */
--text-color-kumo-brand: var(--hf-amber-ink);
--text-color-kumo-link: var(--hf-amber-ink);
--text-color-kumo-success: var(--hf-green);
--text-color-kumo-danger: var(--hf-red);
--text-color-kumo-warning: #c2410c;
--text-color-kumo-info: var(--hf-sky);
--accent-soft: rgba(255, 210, 30, 0.2);
--accent-ink: var(--hf-gray-900);
--color-port-text: var(--hf-amber);
--color-port-number: var(--hf-cyan);
--color-port-boolean: var(--hf-green);
--color-port-image: var(--hf-sky);
--color-port-audio: var(--hf-orange);
--color-port-video: var(--hf-pink);
--color-port-file: var(--hf-indigo);
--color-port-gallery: var(--hf-fuchsia);
--color-port-json: var(--hf-red);
--color-port-any: var(--hf-gray-400);
}
/* Kumo's primary button lightens the brand with white and forces white
text, which falls apart on yellow. Keep the fill solid, flat, dark ink.
Lives in `base` so its !important outranks the utility layer's. */
@layer base {
[data-kumo-component="Button"][style*="kumo-button-emphasis"] {
--kumo-button-emphasis-bg: var(--color-kumo-brand) !important;
--kumo-button-emphasis-ring: color-mix(in oklch, var(--color-kumo-brand), black 12%) !important;
--kumo-button-emphasis-gradient-start: var(--color-kumo-brand) !important;
--kumo-button-emphasis-gradient-end: var(--color-kumo-brand) !important;
color: var(--accent-ink) !important;
}
[data-kumo-component="Button"][style*="kumo-button-emphasis"]:hover {
--kumo-button-emphasis-bg: var(--color-kumo-brand-hover) !important;
--kumo-button-emphasis-gradient-start: var(--color-kumo-brand-hover) !important;
--kumo-button-emphasis-gradient-end: var(--color-kumo-brand-hover) !important;
}
}
/* Kumo's Switch hard-codes Tailwind blue; follow the accent instead. */
[data-kumo-component="Switch"][data-checked] {
background: var(--color-kumo-brand);
--tw-ring-color: var(--color-kumo-brand);
}
[data-kumo-component="Switch"][data-checked] > * {
background: var(--accent-ink);
}
@layer base {
html,
body,
#root {
height: 100%;
margin: 0;
overscroll-behavior: none;
}
body {
font-family: var(--font-sans);
font-feature-settings: "tnum";
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
background: var(--color-kumo-canvas);
color: var(--text-color-kumo-default);
user-select: none;
}
::selection {
background: color-mix(in oklch, var(--color-kumo-brand) 28%, transparent);
color: var(--text-color-kumo-strong);
}
input,
textarea {
user-select: text;
}
button {
font: inherit;
}
*:focus-visible {
outline: 2px solid var(--color-kumo-brand);
outline-offset: 2px;
}
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-thumb {
background: var(--color-kumo-interact);
border: 3px solid transparent;
border-radius: 999px;
background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover {
background: var(--text-color-kumo-subtle);
background-clip: padding-box;
border: 3px solid transparent;
}
::-webkit-scrollbar-track {
background: transparent;
}
}
/* ------------------------------------------------------------------ */
/* Theme switch: a short root crossfade; the mode thumb slides in its */
/* own layer so it glides instead of jumping. */
/* ------------------------------------------------------------------ */
::view-transition {
pointer-events: none;
}
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 180ms;
animation-timing-function: var(--ease-soft);
}
html[data-vt="theme"] .mode-toggle__thumb {
view-transition-name: mode-thumb;
}
html[data-vt="theme"] .mode-toggle > [data-mode="light"] {
view-transition-name: mode-light;
}
html[data-vt="theme"] .mode-toggle > [data-mode="dark"] {
view-transition-name: mode-dark;
}
::view-transition-group(mode-thumb),
::view-transition-group(mode-light),
::view-transition-group(mode-dark) {
animation-duration: 320ms;
animation-timing-function: var(--ease-soft);
}
::view-transition-group(mode-light),
::view-transition-group(mode-dark) {
z-index: 1;
}
/* Light / Dark segmented toggle with a sliding thumb. Driven by */
/* html[data-mode] so it never desyncs from the actual theme. */
.mode-toggle {
position: relative;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2px;
padding: 3px;
border-radius: 8px;
background: var(--color-kumo-tint);
}
.mode-toggle__thumb {
position: absolute;
top: 3px;
bottom: 3px;
left: 3px;
width: calc(50% - 4px);
border-radius: 6px;
background: var(--color-kumo-elevated);
box-shadow: 0 0 0 1px var(--color-kumo-hairline);
transition: translate 240ms var(--ease-soft);
}
html[data-mode="dark"] .mode-toggle__thumb {
translate: calc(100% + 2px) 0;
}
.mode-toggle > button {
position: relative;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
height: 26px;
border: 0;
border-radius: 6px;
background: transparent;
color: var(--text-color-kumo-subtle);
font-size: 12px;
font-weight: 500;
cursor: pointer;
transition: color var(--t-fast);
}
.mode-toggle > button:hover,
html[data-mode="light"] .mode-toggle > [data-mode="light"],
html[data-mode="dark"] .mode-toggle > [data-mode="dark"] {
color: var(--text-color-kumo-strong);
}
/* Entrance for freshly mounted panels / sections. */
@keyframes rise-in {
from {
opacity: 0;
transform: translateY(5px);
}
to {
opacity: 1;
transform: none;
}
}
.rise-in {
animation: rise-in 240ms var(--ease-soft) both;
}
/* ------------------------------------------------------------------ */
/* Utilities */
/* ------------------------------------------------------------------ */
@utility hairline-b {
border-bottom: 1px solid var(--color-kumo-hairline);
}
@utility hairline-t {
border-top: 1px solid var(--color-kumo-hairline);
}
@utility hairline-l {
border-left: 1px solid var(--color-kumo-hairline);
}
@utility hairline-r {
border-right: 1px solid var(--color-kumo-hairline);
}
@utility tabular {
font-variant-numeric: tabular-nums;
}
/* Port colour helper: `port-color-image` sets --port-color */
.port-color-text {
--port-color: var(--color-port-text);
}
.port-color-number {
--port-color: var(--color-port-number);
}
.port-color-boolean {
--port-color: var(--color-port-boolean);
}
.port-color-image {
--port-color: var(--color-port-image);
}
.port-color-audio {
--port-color: var(--color-port-audio);
}
.port-color-video {
--port-color: var(--color-port-video);
}
.port-color-file {
--port-color: var(--color-port-file);
}
.port-color-gallery {
--port-color: var(--color-port-gallery);
}
.port-color-json {
--port-color: var(--color-port-json);
}
.port-color-any {
--port-color: var(--color-port-any);
}
/* ------------------------------------------------------------------ */
/* React Flow overrides */
/* ------------------------------------------------------------------ */
.react-flow {
--xy-background-color: var(--color-kumo-canvas);
--xy-selection-background-color: color-mix(
in oklch,
var(--color-kumo-brand) 8%,
transparent
);
--xy-selection-border: 1px solid
color-mix(in oklch, var(--color-kumo-brand) 60%, transparent);
--xy-edge-stroke: var(--color-kumo-interact);
--xy-edge-stroke-width: 2;
--xy-minimap-background-color: var(--color-kumo-base);
--xy-minimap-mask-background-color: color-mix(
in oklch,
var(--color-kumo-canvas) 70%,
transparent
);
--xy-minimap-mask-stroke-color: var(--color-kumo-line);
--xy-minimap-node-background-color: var(--color-kumo-interact);
--xy-minimap-node-stroke-color: transparent;
background: var(--color-kumo-canvas);
font-size: 12px;
}
.react-flow__pane {
cursor: default;
}
.react-flow__pane.dragging {
cursor: grabbing;
}
/* The whole node body is a drag surface; only live controls opt out. */
.react-flow__node {
cursor: grab;
/* Promote each node to its own compositor layer so a move is a pure
transform update rather than a repaint of the node's contents. */
will-change: transform;
}
.react-flow__node.dragging {
cursor: grabbing;
}
.react-flow__node.dragging .canvas-node {
border-color: var(--color-kumo-interact);
box-shadow:
0 0 0 1px color-mix(in oklch, var(--node-accent) 35%, transparent),
0 12px 32px -12px var(--color-kumo-shadow-drop);
}
.react-flow__node.dragging .canvas-node .canvas-node__header {
cursor: grabbing;
}
.react-flow__nodesselection-rect,
.react-flow__selection {
border-radius: 4px;
}
.react-flow__node.selected .canvas-node,
.react-flow__node:focus-visible .canvas-node {
--port-color: var(--color-port-any);
--node-ring: var(--color-kumo-brand);
--node-ring-width: 1.5px;
}
.react-flow__node:focus-visible {
outline: none;
}
.react-flow__edge.selectable:hover .canvas-edge-path,
.react-flow__edge.selected .canvas-edge-path {
stroke-width: 3;
}
.react-flow__edge.updating .canvas-edge-path {
stroke-dasharray: 6 6;
opacity: 0.6;
}
.react-flow__edge.selected .canvas-edge-path {
filter: saturate(1.3) brightness(1.15);
}
.react-flow__edge .canvas-edge-hit {
stroke-width: 18;
stroke: transparent;
fill: none;
cursor: pointer;
}
.react-flow__connectionline {
pointer-events: none;
}
.react-flow__minimap {
border-radius: 10px;
border: 1px solid var(--color-kumo-line);
overflow: hidden;
margin: 0 !important;
}
.react-flow__minimap svg {
display: block;
}
/* ------------------------------------------------------------------ */
/* Nodes */
/* ------------------------------------------------------------------ */
@keyframes node-in {
from {
opacity: 0;
transform: scale(0.96) translateY(4px);
}
to {
opacity: 1;
transform: none;
}
}
@keyframes node-pulse {
0%,
100% {
box-shadow: 0 0 0 1.5px
color-mix(in oklch, var(--node-accent) 70%, transparent);
}
50% {
box-shadow: 0 0 0 1.5px
color-mix(in oklch, var(--node-accent) 25%, transparent);
}
}
.canvas-node {
--node-ring: var(--color-kumo-line);
--node-ring-width: 1px;
--node-accent: var(--color-kumo-interact);
position: relative;
background: var(--color-kumo-base);
border-radius: 10px;
box-shadow: 0 0 0 var(--node-ring-width) var(--node-ring);
transition:
box-shadow var(--t-fast),
opacity 160ms var(--ease-soft),
background-color var(--t-med);
animation: node-in 220ms var(--ease-soft) both;
}
.canvas-node[data-status="running"] {
animation: node-pulse 1.4s ease-in-out infinite;
}
.canvas-node[data-status="done"] {
--node-ring: color-mix(in oklch, var(--color-kumo-success) 70%, transparent);
}
.canvas-node[data-status="error"] {
--node-ring: var(--color-kumo-danger);
}
.react-flow__node.selected .canvas-node[data-status="running"] {
animation: none;
}
.canvas-node[data-bypassed="true"] {
opacity: 0.55;
}
.canvas-node[data-bypassed="true"] .canvas-node__header {
background: repeating-linear-gradient(
-45deg,
color-mix(in oklch, var(--node-accent) 18%, transparent) 0 6px,
transparent 6px 12px
);
}
.canvas-node__header {
display: flex;
align-items: center;
gap: 8px;
height: 32px;
padding: 0 8px 0 12px;
border-radius: 10px 10px 0 0;
background: var(--color-kumo-tint);
cursor: grab;
overflow: hidden;
}
.canvas-node__header:active {
cursor: grabbing;
}
.canvas-node__header {
transition: border-radius 220ms var(--ease-soft);
}
.canvas-node[data-collapsed="true"] .canvas-node__header {
border-radius: 10px;
}
/* A soft light that travels around the node's edge while it runs. Nothing
paints over the content. */
@property --run-angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.canvas-node__shimmer {
position: absolute;
inset: 0;
z-index: 5;
border-radius: 10px;
padding: 1.5px;
pointer-events: none;
background: conic-gradient(
from var(--run-angle),
transparent 0deg,
transparent 250deg,
color-mix(in oklch, var(--node-accent) 55%, transparent) 300deg,
var(--node-accent) 330deg,
transparent 360deg
);
mask:
linear-gradient(#000 0 0) content-box,
linear-gradient(#000 0 0);
mask-composite: exclude;
-webkit-mask-composite: xor;
animation: run-light 2.2s linear infinite;
}
@keyframes run-light {
to {
--run-angle: 360deg;
}
}
.canvas-node__dot {
width: 8px;
height: 8px;
border-radius: 999px;
background: var(--node-accent);
flex: none;
}
.canvas-node__title {
flex: 1;
min-width: 0;
font-size: 12.5px;
font-weight: 500;
letter-spacing: -0.005em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: var(--text-color-kumo-strong);
}
/* Collapse/expand animates the body's grid track from 1fr to 0fr. The
padding lives on an inner element so the track can really reach 0. */
.canvas-node__body-wrap {
display: grid;
grid-template-rows: 1fr;
transition:
grid-template-rows 220ms var(--ease-soft),
opacity 140ms var(--ease-soft);
}
.canvas-node[data-collapsed="true"] .canvas-node__body-wrap {
grid-template-rows: 0fr;
opacity: 0;
pointer-events: none;
}
.canvas-node__body {
min-height: 0;
/* Clip vertically only: port dots hang 5px outside the node. */
overflow-x: visible;
overflow-y: clip;
}
.canvas-node__body-inner {
padding: 6px 0 8px;
}
.canvas-node__progress {
position: absolute;
left: 10px;
right: 10px;
bottom: 0;
height: 2px;
border-radius: 2px;
background: color-mix(in oklch, var(--node-accent) 20%, transparent);
overflow: hidden;
}
.canvas-node__progress > i {
display: block;
height: 100%;
border-radius: 2px;
background: var(--node-accent);
transform-origin: left;
transition: transform 120ms linear;
}
/* Extrapolated from past runs: softer, and eased to match the 250ms tick. */
.canvas-node__progress[data-estimated] i {
opacity: 0.6;
transition: transform 260ms linear;
}
/* Ports ----------------------------------------------------------- */
.port-row {
display: grid;
grid-template-columns: 1fr 1fr;
height: 24px;
align-items: center;
}
.port {
display: flex;
align-items: center;
gap: 8px;
height: 24px;
font-size: 11.5px;
color: var(--text-color-kumo-default);
white-space: nowrap;
min-width: 0;
}
.port--in {
padding-left: 0;
}
.port--out {
flex-direction: row-reverse;
padding-right: 0;
text-align: right;
}
.port__label {
overflow: hidden;
text-overflow: ellipsis;
}
.port__type {
font-family: var(--font-mono);
font-size: 9.5px;
letter-spacing: 0.04em;
color: var(--text-color-kumo-placeholder);
flex: none;
}
.port--in > .port__type { margin-left: -2px; }
.port--out > .port__type { margin-right: -2px; }
/* Widget rows: the type and the "pull out into an input node" button sit over the row's top-right
corner and only show on hover, so the widget keeps its full width. */
.port__meta {
position: absolute;
top: 2px;
right: 0;
height: 24px;
display: flex;
align-items: center;
gap: 4px;
padding-left: 6px;
opacity: 0;
pointer-events: none;
transition: opacity 120ms;
}
.port-row--widget:hover .port__meta,
.port-row--widget:focus-within .port__meta {
opacity: 1;
pointer-events: auto;
}
.port__extract {
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
border-radius: 5px;
color: var(--text-color-kumo-subtle);
background: var(--color-kumo-elevated, var(--color-kumo-base));
box-shadow: 0 0 0 1px var(--color-kumo-line);
}
.port__extract:hover {
color: var(--text-color-kumo-strong);
background: var(--color-kumo-fill);
}
/* Handles are laid out inline in each row rather than absolutely
positioned. React Flow measures their DOM rect, so this is safe. */
.canvas-node .react-flow__handle,
.canvas-node .port__ghost {
position: relative;
top: auto;
left: auto;
right: auto;
bottom: auto;
transform: none;
width: 10px;
height: 10px;
min-width: 0;
min-height: 0;
border-radius: 999px;
border: 2px solid var(--color-kumo-base);
background: var(--port-color);
box-shadow: 0 0 0 1px var(--port-color);
margin-left: -5px;
transition:
transform 120ms var(--ease-spring),
opacity 120ms,
box-shadow 120ms;
cursor: crosshair;
}
.canvas-node .react-flow__handle.react-flow__handle-right,
.canvas-node .port--out .port__ghost {
margin-left: 0;
margin-right: -5px;
}
/* Stand-in dot while the body animates shut; the live handles sit in the header. */
.canvas-node .port__ghost {
flex: none;
pointer-events: none;
}
/* Generous invisible hit target: the dot stays 10px, the grab zone is 28px. */
.canvas-node .react-flow__handle::before {
content: "";
position: absolute;
inset: -9px;
border-radius: 999px;
}
/* Ports announce themselves when the pointer is over the node. */
.react-flow__node:hover .canvas-node .react-flow__handle {
box-shadow:
0 0 0 1px var(--port-color),
0 0 0 4px color-mix(in oklch, var(--port-color) 22%, transparent);
}
.canvas-node .react-flow__handle:hover,
.canvas-node .react-flow__handle.connectingfrom {
transform: scale(1.35);
}
.canvas-node .react-flow__handle.valid-target {
transform: scale(1.35);
box-shadow:
0 0 0 1px var(--port-color),
0 0 0 5px color-mix(in oklch, var(--port-color) 30%, transparent);
}
.canvas-node .react-flow__handle.invalid-target {
opacity: 0.25;
}
/* Widgets --------------------------------------------------------- */
.widget {
display: flex;
align-items: center;
height: 24px;
margin: 2px 10px;
padding: 0 8px;
border-radius: 6px;
background: var(--color-kumo-recessed);
font-size: 11.5px;
color: var(--text-color-kumo-default);
transition: background-color 120ms;
}
.widget:hover {
background: var(--color-kumo-fill-hover);
}
[data-mode="dark"] .widget:hover {
background: color-mix(in oklch, var(--color-kumo-recessed), white 4%);
}
.widget__label {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--text-color-kumo-subtle);
}
.widget__value {
font-family: var(--font-mono);
font-size: 11px;
font-variant-numeric: tabular-nums;
color: var(--text-color-kumo-strong);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 60%;
}
.widget__arrow {
display: inline-flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
margin: 0 -4px;
border-radius: 4px;
color: var(--text-color-kumo-placeholder);
opacity: 0;
transition:
opacity 120ms,
background-color 120ms,
color 120ms;
}
.widget:hover .widget__arrow {
opacity: 1;
}
.widget__arrow:hover {
background: var(--color-kumo-fill);
color: var(--text-color-kumo-strong);
}
.widget__arrow:active {
transform: translateY(0.5px);
}
.widget--number {
cursor: grab;
}
.widget--number .widget__value {
cursor: ew-resize;
/* Give the scrub zone real width so it is easy to hit. */
min-width: 40%;
text-align: right;
padding-left: 8px;
}
.widget--number .widget__arrow {
cursor: pointer;
}
.widget--number.is-editing {
cursor: text;
background: var(--color-kumo-control);
box-shadow: 0 0 0 1.5px var(--color-kumo-brand);
}
.widget__input {
flex: 1;
min-width: 0;
background: transparent;
border: 0;
outline: 0;
padding: 0;
font: inherit;
font-family: var(--font-mono);
font-size: 11px;
text-align: right;
color: var(--text-color-kumo-strong);
}
.widget--slider {
position: relative;
overflow: hidden;
cursor: ew-resize;
}
.widget--slider::before {
content: "";
position: absolute;
inset: 0;
width: calc(var(--fill, 0) * 100%);
background: color-mix(in oklch, var(--node-accent) 14%, transparent);
transition: width 60ms linear;
pointer-events: none;
}
/* No easing while the pointer is down: the fill must track the hand. */
.widget--slider:active::before {
transition: none;
}
.widget--slider > * {
position: relative;
}
.widget--toggle {
cursor: pointer;
}
.widget--select {
cursor: pointer;
}
.widget--select[data-popup-open] {
background: var(--color-kumo-fill);
}
.widget--text {
cursor: grab;
}
.widget--text .widget__label {
flex: none;
max-width: 45%;
}
.widget__text {
flex: 1;
min-width: 0;
height: 24px;
line-height: 24px;
margin: 0;
padding: 0;
border: 0;
outline: 0;
resize: none;
overflow: hidden;
background: transparent;
font: inherit;
font-family: var(--font-mono);
font-size: 11px;
text-align: right;
white-space: pre;
color: var(--text-color-kumo-strong);
cursor: text;
}
.widget__text-preview {
flex: 1;
max-width: none;
margin-left: 8px;
text-align: right;
cursor: text;
}
.widget__text-preview[data-empty] {
color: var(--text-color-kumo-placeholder);
}
.widget__text::placeholder {
color: var(--text-color-kumo-placeholder);
}
.widget--text[data-multi] {
flex-wrap: wrap;
align-items: flex-start;
height: auto;
padding: 5px 8px 6px;
cursor: default;
}
.widget--text[data-multi] .widget__label {
flex: 0 0 100%;
max-width: none;
margin-bottom: 3px;
font-size: 10.5px;
line-height: 14px;
}
.widget--text[data-multi] .widget__text {
flex: 0 0 100%;
height: auto;
min-height: 40px;
max-height: 260px;
overflow: auto;
line-height: 1.45;
text-align: left;
white-space: pre-wrap;
font-family: inherit;
font-size: 11.5px;
color: var(--text-color-kumo-default);
}
.widget__fold {
flex: none;
order: 3;
display: inline-flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
margin-left: 4px;
border-radius: 4px;
color: var(--text-color-kumo-subtle);
cursor: pointer;
}
.widget__fold:hover {
background: var(--color-kumo-fill);
color: var(--text-color-kumo-strong);
}
.widget--text[data-multi] {
position: relative;
}
.widget--text[data-multi] .widget__label {
padding-right: 20px;
}
.widget--text[data-multi] .widget__fold {
position: absolute;
top: 4px;
right: 6px;
margin: 0;
}
.widget--text:focus-within {
background: var(--color-kumo-control);
box-shadow: inset 0 0 0 1.5px var(--color-kumo-brand);
}
/* Preview thumbnail ------------------------------------------------- */
.node-preview {
margin: 4px 10px 0;
border-radius: 6px;
overflow: hidden;
aspect-ratio: 1;
background: var(--color-kumo-recessed);
position: relative;
}
.node-preview > svg,
.node-preview > img {
display: block;
width: 100%;
height: 100%;
}
.node-preview__empty {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
font-size: 11px;
color: var(--text-color-kumo-placeholder);
}
/* Edges ------------------------------------------------------------ */
@keyframes edge-flow {
to {
stroke-dashoffset: -24;
}
}
.canvas-edge-path {
fill: none;
stroke: var(--edge-color);
stroke-width: 2;
stroke-linecap: round;
transition:
stroke-width var(--t-fast),
opacity 160ms var(--ease-soft);
}
.canvas-edge-flow {
fill: none;
stroke: color-mix(in oklch, var(--edge-color), white 40%);
stroke-width: 2;
stroke-linecap: round;
stroke-dasharray: 6 18;
animation: edge-flow 600ms linear infinite;
pointer-events: none;
}
[data-mode="light"] .canvas-edge-flow,
:root:not([data-mode="dark"]) .canvas-edge-flow {
stroke: color-mix(in oklch, var(--edge-color), black 25%);
}
.canvas-edge-dim {
opacity: 0.35;
}
/* A selected edge's SVG is lifted to z 1000; the label layer holding the
remove button must sit above it or the stroke swallows the click. */
.react-flow__edgelabel-renderer {
z-index: 1001;
}
.edge-delete {
display: inline-flex;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
border-radius: 999px;
background: var(--color-kumo-base);
color: var(--text-color-kumo-subtle);
box-shadow: 0 0 0 1px var(--color-kumo-line);
pointer-events: all;
cursor: pointer;
transition:
transform 120ms var(--ease-spring),
color 120ms,
box-shadow 120ms;
}
.edge-delete:hover {
transform: scale(1.15);
color: var(--text-color-kumo-danger);
box-shadow: 0 0 0 1px var(--color-kumo-danger);
}
/* Library ----------------------------------------------------------- */
.lib-item {
display: flex;
align-items: center;
gap: 8px;
height: 30px;
padding: 0 8px 0 10px;
margin: 0 8px;
border-radius: 7px;
font-size: 12.5px;
color: var(--text-color-kumo-default);
cursor: grab;
transition:
background-color var(--t-fast),
transform 160ms var(--ease-soft);
}
.lib-item:hover {
background: var(--color-kumo-tint);
}
.lib-item:active {
cursor: grabbing;
transform: scale(0.985);
}
.lib-item[data-drop="true"] {
background: var(--accent-soft);
}
.lib-item__dots {
display: flex;
gap: 3px;
margin-left: auto;
opacity: 0.9;
}
.lib-item__dots > i {
display: block;
width: 6px;
height: 6px;
border-radius: 999px;
background: var(--port-color);
}
/* Drag ghost rendered while dragging from the library */
.drag-ghost {
position: fixed;
top: -1000px;
left: -1000px;
pointer-events: none;
padding: 6px 12px;
border-radius: 8px;
background: var(--color-kumo-base);
box-shadow: 0 0 0 1px var(--color-kumo-line);
font-size: 12px;
font-weight: 500;
color: var(--text-color-kumo-strong);
display: flex;
align-items: center;
gap: 8px;
}
/* Panels ------------------------------------------------------------ */
.panel-section-title {
font-size: 11px;
font-weight: 500;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--text-color-kumo-subtle);
}
.kbd {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 18px;
height: 18px;
padding: 0 5px;
border-radius: 4px;
background: var(--color-kumo-recessed);
box-shadow: inset 0 0 0 1px var(--color-kumo-hairline);
font-family: var(--font-sans);
font-size: 10.5px;
font-weight: 500;
color: var(--text-color-kumo-subtle);
}
.history-thumb {
border-radius: 6px;
overflow: hidden;
aspect-ratio: 1;
background: var(--color-kumo-recessed);
flex: none;
}
.history-thumb svg {
display: block;
width: 100%;
height: 100%;
}
/* Inspector slider (Base UI Slider primitive styled flat) */
.k-slider {
position: relative;
display: flex;
align-items: center;
height: 20px;
width: 100%;
touch-action: none;
}
.k-slider__track {
position: relative;
height: 4px;
width: 100%;
border-radius: 999px;
background: var(--color-kumo-fill);
}
.k-slider__indicator {
position: absolute;
height: 100%;
border-radius: 999px;
background: var(--color-kumo-brand);
}
.k-slider__thumb {
width: 14px;
height: 14px;
border-radius: 999px;
background: var(--color-kumo-base);
box-shadow: 0 0 0 1.5px var(--color-kumo-brand);
transition: transform 120ms var(--ease-spring);
}
.k-slider__thumb:hover,
.k-slider__thumb:focus-visible {
transform: scale(1.15);
outline: none;
}
.k-slider__thumb[data-dragging] {
transform: scale(1.2);
}
/* ------------------------------------------------------------------ */
/* Menus. Every menu is a Kumo DropdownMenu (Base UI underneath). */
/* Base UI portals them to <body> with no z-index, so a selected node */
/* (z 1000) or the minimap paints over them: lift the positioner. */
/* Kumo's popup animates on data-[state=open], which Base UI never sets */
/* (it emits data-starting-style / data-ending-style), hence no motion. */
/* ------------------------------------------------------------------ */
[data-base-ui-portal] > [role="presentation"][data-side] {
z-index: 60;
}
[role="menu"][data-side],
[role="listbox"][data-side] {
min-width: 180px;
padding: 5px;
border-radius: 10px;
/* Opaque: a menu is dense text and the canvas must not read through. */
background: var(--color-kumo-elevated);
color: var(--text-color-kumo-default);
box-shadow:
0 0 0 1px var(--color-kumo-line),
0 10px 28px -14px var(--color-kumo-shadow-drop);
transform-origin: var(--transform-origin);
transition:
opacity 130ms ease,
transform 190ms var(--ease-soft);
}
[role="menu"][data-side][data-starting-style],
[role="menu"][data-side][data-ending-style],
[role="listbox"][data-side][data-starting-style],
[role="listbox"][data-side][data-ending-style] {
opacity: 0;
transform: scale(0.96) translateY(-5px);
}
/* Slide from whichever edge the menu is anchored to. */
[role="menu"][data-side="top"][data-starting-style],
[role="menu"][data-side="top"][data-ending-style],
[role="listbox"][data-side="top"][data-starting-style],
[role="listbox"][data-side="top"][data-ending-style] {
transform: scale(0.96) translateY(5px);
}
[role="menu"][data-side="right"][data-starting-style],
[role="menu"][data-side="right"][data-ending-style],
[role="menu"][data-side="inline-end"][data-starting-style],
[role="menu"][data-side="inline-end"][data-ending-style] {
transform: scale(0.96) translateX(-6px);
}
[role="menu"][data-side="left"][data-starting-style],
[role="menu"][data-side="left"][data-ending-style],
[role="menu"][data-side="inline-start"][data-starting-style],
[role="menu"][data-side="inline-start"][data-ending-style] {
transform: scale(0.96) translateX(6px);
}
/* Hopping between sibling menus swaps instantly; dismissals still fade. */
[role="menu"][data-side][data-instant="group"],
[role="menu"][data-side][data-instant="trigger-change"] {
transition-duration: 0s;
}
/* Rows ------------------------------------------------------------- */
[data-kumo-component="DropdownMenu"][role^="menuitem"] {
gap: 8px;
min-height: 30px;
padding: 5px 8px;
border-radius: 6px;
font-size: 13px;
font-weight: 450;
line-height: 1.4;
letter-spacing: -0.003em;
color: var(--text-color-kumo-default);
transition:
background-color var(--t-fast),
color var(--t-fast);
}
[data-kumo-component="DropdownMenu"][role^="menuitem"] > a {
gap: 8px;
}
/* data-highlighted paints the row; the brand focus ring on top is noise. */
[data-kumo-component="DropdownMenu"][role^="menuitem"]:focus,
[data-kumo-component="DropdownMenu"][role^="menuitem"]:focus-visible {
outline: none;
box-shadow: none;
--tw-ring-shadow: 0 0 #0000;
}
[data-kumo-component="DropdownMenu"][role^="menuitem"][data-highlighted],
[data-kumo-component="DropdownMenu"][role^="menuitem"][data-popup-open] {
background: var(--color-kumo-tint);
color: var(--text-color-kumo-strong);
}
[data-kumo-component="DropdownMenu"][role^="menuitem"][data-disabled] {
color: var(--text-color-kumo-inactive);
opacity: 1;
}
[data-kumo-component="DropdownMenu"][role^="menuitem"][class*="text-kumo-danger"] {
color: var(--text-color-kumo-danger);
}
[data-kumo-component="DropdownMenu"][role^="menuitem"][class*="text-kumo-danger"][data-highlighted] {
background: color-mix(in oklch, var(--color-kumo-danger) 14%, transparent);
color: var(--text-color-kumo-danger);
}
/* The 16px leading gutter: Kumo renders an icon three ways (raw element,
12px wrapper span, `mr-2 h-4 w-4` on sub-triggers). Every leading mark
becomes one 16px box in the same place so labels line up. */
[data-kumo-component="DropdownMenu"][role^="menuitem"] > svg:first-child:not([class*="ml-auto"]),
[data-kumo-component="DropdownMenu"][role^="menuitem"] > a > svg:first-child:not([class*="ml-auto"]),
[data-kumo-component="DropdownMenu"][role^="menuitem"] > span:first-child:has(> svg) {
flex: none;
width: 16px;
height: 16px;
margin: 0;
color: var(--text-color-kumo-subtle);
transition: color var(--t-fast);
}
[data-kumo-component="DropdownMenu"][role^="menuitem"]:not([data-kumo-part="checkbox-item"]) > span:first-child:has(> svg) > svg {
width: 16px;
height: 16px;
}
[data-kumo-component="DropdownMenu"][role^="menuitem"][data-highlighted] > svg:first-child:not([class*="ml-auto"]),
[data-kumo-component="DropdownMenu"][role^="menuitem"][data-highlighted] > span:first-child:has(> svg) {
color: inherit;
}
/* The submenu caret sits at the far end, quieter than the label. */
[data-kumo-component="DropdownMenu"][data-kumo-part="submenu-trigger"] > svg[class*="ml-auto"] {
flex: none;
width: 14px;
height: 14px;
margin-inline-start: auto;
margin-inline-end: -2px;
color: var(--text-color-kumo-subtle);
}
/* Ticks share the icon's box. */
[data-kumo-component="DropdownMenu"][data-kumo-part="checkbox-item"] {
padding-left: 32px;
}
[data-kumo-component="DropdownMenu"][data-kumo-part="checkbox-item"] > span:first-child {
left: 8px;
color: var(--color-kumo-brand);
}
/* Kumo's radio item draws no tick of its own, so draw one and grow it in. */
[data-kumo-component="DropdownMenu"][data-kumo-part="radio-item"] {
padding-left: 32px;
}
[data-kumo-component="DropdownMenu"][data-kumo-part="radio-item"]::before {
content: "";
position: absolute;
left: 8px;
width: 16px;
height: 16px;
background: var(--color-kumo-brand);
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z'/%3E%3C/svg%3E")
center / 12px 12px no-repeat;
opacity: 0;
transform: scale(0.7);
transition:
opacity var(--t-fast),
transform 160ms var(--ease-soft);
}
[data-kumo-component="DropdownMenu"][data-kumo-part="radio-item"][data-checked]::before {
opacity: 1;
transform: none;
}
[data-kumo-component="DropdownMenu"][data-kumo-part="radio-item"][data-checked] {
color: var(--text-color-kumo-strong);
}
/* `selected` puts a tick after the label; keep it small and in the accent. */
[data-kumo-component="DropdownMenu"][role^="menuitem"] > span:last-child:not(:first-child):has(> svg) {
flex: none;
margin-inline-start: auto;
padding-inline-start: 8px;
color: var(--color-kumo-brand);
}
[data-kumo-component="DropdownMenu"][role^="menuitem"] > span:last-child:not(:first-child):has(> svg) > svg {
width: 14px;
height: 14px;
}
/* A menu with any leading mark indents its plain rows, so labels line up. */
[role="menu"][data-side]:has([role^="menuitem"] > svg:first-child:not([class*="ml-auto"])),
[role="menu"][data-side]:has([role^="menuitem"] > a > svg:first-child:not([class*="ml-auto"])),
[role="menu"][data-side]:has([data-kumo-part="checkbox-item"]),
[role="menu"][data-side]:has([data-kumo-part="radio-item"]) {
--menu-gutter: 32px;
}
[role="menu"][data-side] [role^="menuitem"]:not([data-kumo-part="checkbox-item"]):not([data-kumo-part="radio-item"]):not(:has(> svg:first-child:not([class*="ml-auto"]))):not(:has(> a > svg:first-child:not([class*="ml-auto"]))):not(:has(> span:first-child > svg)) {
padding-left: var(--menu-gutter, 8px);
}
/* Trimmings ------------------------------------------------------- */
[role="menu"][data-side] [role="separator"] {
height: 1px;
margin: 5px -1px;
background: var(--color-kumo-hairline);
}
[role="menu"][data-side] [role="group"] > [role="presentation"] {
padding: 6px 8px 4px;
font-size: 10.5px;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--text-color-kumo-subtle);
}
/* Keyboard hints stay quiet and hug the right edge. */
[role="menu"][data-side] [role^="menuitem"] > span[class*="ml-auto"] {
margin-inline-start: auto;
padding-inline-start: 16px;
font-family: var(--font-mono);
font-size: 10.5px;
font-variant-numeric: tabular-nums;
letter-spacing: 0;
opacity: 1;
color: var(--text-color-kumo-inactive);
}
/* Grid dots only show while snapping is on. */
.react-flow__background.canvas-grid {
transition: opacity 200ms var(--ease-soft);
}
/* Canvas controls (bottom-left) */
.canvas-ctls {
display: flex;
align-items: center;
gap: 2px;
padding: 3px;
border-radius: 9px;
background: var(--color-kumo-base);
box-shadow: 0 0 0 1px var(--color-kumo-line);
}
.canvas-ctls__sep {
width: 1px;
height: 14px;
margin: 0 3px;
background: var(--color-kumo-line);
}
.canvas-ctl {
display: inline-flex;
align-items: center;
justify-content: center;
height: 26px;
min-width: 26px;
padding: 0;
border-radius: 6px;
color: var(--color-kumo-subtle);
transition:
background-color 120ms var(--ease-soft),
color 120ms var(--ease-soft);
}
.canvas-ctl:hover {
background: var(--color-kumo-tint);
color: var(--color-kumo-strong);
}
.canvas-ctl:active {
background: var(--color-kumo-fill);
}
.canvas-ctl[data-active] {
color: var(--color-kumo-brand);
}
.canvas-ctl:focus-visible {
outline: 2px solid var(--color-kumo-brand);
outline-offset: -2px;
}
.canvas-ctl--zoom {
min-width: 44px;
padding: 0 6px;
font-family: var(--font-mono);
font-size: 11px;
font-variant-numeric: tabular-nums;
color: var(--color-kumo-default);
}
/* View layers (canvas / pipeline) --------------------------------------- */
.view-layer {
position: absolute;
inset: 0;
transition:
opacity 220ms var(--ease-soft),
transform 260ms var(--ease-soft),
visibility 0s linear 220ms;
}
.view-layer[data-active="false"] {
opacity: 0;
visibility: hidden;
transform: scale(0.985);
pointer-events: none;
}
.view-layer[data-active="true"] {
opacity: 1;
visibility: visible;
transform: none;
transition-delay: 0s;
}
.view-switch {
display: flex;
gap: 2px;
padding: 2px;
border-radius: 8px;
background: var(--color-kumo-tint);
}
.view-switch__btn {
position: relative;
display: inline-flex;
align-items: center;
gap: 6px;
height: 26px;
padding: 0 10px;
border-radius: 6px;
font-size: 12px;
font-weight: 500;
color: var(--color-kumo-subtle);
transition: color 140ms var(--ease-soft);
}
.view-switch__btn:hover { color: var(--color-kumo-default); }
.view-switch__btn[data-active="true"] { color: var(--color-kumo-strong); }
.view-switch__btn:focus-visible { outline: 2px solid var(--color-kumo-brand); outline-offset: -2px; }
.view-switch__pill {
position: absolute;
inset: 0;
border-radius: 6px;
background: var(--color-kumo-base);
box-shadow: 0 0 0 1px var(--color-kumo-line), 0 1px 2px rgb(0 0 0 / 0.12);
}
/* Pipeline view --------------------------------------------------------- */
.pipe {
position: absolute;
inset: 0;
overflow-y: auto;
overflow-x: hidden;
padding: 28px 24px 120px;
}
.pipe__col {
width: min(100%, 560px);
margin: 0 auto;
min-height: 100%;
}
.pipe__list { list-style: none; margin: 0; padding: 0; }
.pipe-item { position: relative; list-style: none; }
.pipe__empty {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
padding: 72px 24px;
border-radius: 12px;
border: 1px dashed var(--color-kumo-line);
}
/* connector between steps, with an insert button on the spine */
.pipe-insert {
position: relative;
display: flex;
align-items: center;
justify-content: center;
height: 28px;
transition: height 160ms var(--ease-soft);
}
.pipe-insert[data-spine="true"]::before {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 50%;
width: 2px;
margin-left: -1px;
border-radius: 1px;
background: var(--color-kumo-line);
}
.pipe-insert__btn {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
border-radius: 999px;
background: var(--color-kumo-base);
color: var(--color-kumo-placeholder);
box-shadow: 0 0 0 1px var(--color-kumo-line);
opacity: 0;
transform: scale(0.7);
transition:
opacity 140ms var(--ease-soft),
transform 160ms var(--ease-soft),
color 140ms var(--ease-soft),
background-color 140ms var(--ease-soft);
}
.pipe-insert:hover .pipe-insert__btn,
.pipe-insert__btn:focus-visible,
.pipe-insert[data-over="true"] .pipe-insert__btn {
opacity: 1;
transform: scale(1);
}
.pipe-insert__btn:hover,
.pipe-insert[data-over="true"] .pipe-insert__btn {
background: var(--color-kumo-brand);
color: var(--accent-ink);
box-shadow: none;
}
.pipe-insert[data-over="true"] { height: 44px; }
.pipe-insert[data-over="true"]::after {
content: "";
position: absolute;
left: 8px;
right: 8px;
top: 50%;
height: 2px;
margin-top: -1px;
border-radius: 1px;
background: color-mix(in oklch, var(--color-kumo-brand) 55%, transparent);
}
/* block */
.pipe-block {
--node-accent: var(--color-kumo-interact);
position: relative;
border-radius: 10px;
background: var(--color-kumo-base);
box-shadow: 0 0 0 1px var(--color-kumo-line);
overflow: hidden;
transition:
box-shadow 160ms var(--ease-soft),
opacity 160ms var(--ease-soft);
}
.pipe-block[data-selected="true"] {
box-shadow:
0 0 0 1px var(--node-accent),
0 0 0 4px color-mix(in oklch, var(--node-accent) 22%, transparent);
}
.pipe-block[data-bypassed="true"],
.pipe-block[data-muted="true"] { opacity: 0.62; }
.pipe-block[data-status="running"] {
box-shadow: 0 0 0 1px color-mix(in oklch, var(--node-accent) 60%, var(--color-kumo-line));
}
.pipe-block__head {
position: relative;
display: flex;
align-items: center;
gap: 8px;
height: 36px;
padding: 0 8px 0 6px;
background: var(--color-kumo-tint);
border-bottom: 1px solid var(--color-kumo-line);
overflow: hidden;
transition: border-color 200ms var(--ease-soft);
}
.pipe-block[data-collapsed="true"] .pipe-block__head { border-bottom-color: transparent; }
.pipe-block__grip {
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: 24px;
border-radius: 5px;
color: var(--color-kumo-placeholder);
cursor: grab;
touch-action: none;
transition: color 120ms var(--ease-soft), background-color 120ms var(--ease-soft);
}
.pipe-block__grip:hover { color: var(--color-kumo-strong); background: var(--color-kumo-fill); }
.pipe-block__grip:active { cursor: grabbing; }
.pipe-block__index {
min-width: 18px;
font-family: var(--font-mono);
font-size: 10.5px;
font-variant-numeric: tabular-nums;
color: var(--color-kumo-placeholder);
}
.pipe-block__title {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 12.5px;
font-weight: 600;
color: var(--color-kumo-strong);
}
.pipe-block__tag {
padding: 1px 6px;
border-radius: 4px;
background: var(--color-kumo-fill);
font-family: var(--font-mono);
font-size: 9px;
font-weight: 500;
letter-spacing: 0.06em;
color: var(--color-kumo-subtle);
}
.pipe-block__icon-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
border-radius: 5px;
color: var(--color-kumo-subtle);
transition: color 120ms var(--ease-soft), background-color 120ms var(--ease-soft);
}
.pipe-block__icon-btn:hover,
.pipe-block__icon-btn[data-popup-open] { color: var(--color-kumo-strong); background: var(--color-kumo-fill); }
/* collapse via grid track so it animates */
.pipe-block__body-wrap { display: grid; grid-template-rows: 1fr; transition: grid-template-rows 220ms var(--ease-soft); }
.pipe-block[data-collapsed="true"] .pipe-block__body-wrap { grid-template-rows: 0fr; }
.pipe-block__body { min-height: 0; overflow-y: clip; }
.pipe-block__body-inner { padding: 6px 0 8px; }
.pipe-block__inputs { padding: 2px 8px 4px; }
.pipe-input {
display: flex;
flex-direction: column;
min-height: 28px;
}
.pipe-input__head {
display: flex;
align-items: flex-start;
gap: 8px;
min-height: 28px;
padding: 2px 0;
min-width: 0;
}
/* Rows grow when a text widget expands; the dot and source picker stay on the first line. */
.pipe-input__head > .pipe-input__dot { margin-top: 8px; }
.pipe-input__head > .pipe-input__name { line-height: 24px; }
.pipe-input__head > .min-w-0 > .widget { margin: 0 10px; }
.pipe-input__dot {
width: 8px;
height: 8px;
flex: none;
border-radius: 999px;
background: var(--port-color);
box-shadow: 0 0 0 2px color-mix(in oklch, var(--port-color) 25%, transparent);
}
.pipe-input__name {
width: 96px;
flex: none;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 11.5px;
color: var(--color-kumo-default);
}
.pipe-input__src {
display: flex;
align-items: center;
gap: 6px;
flex: 1;
min-width: 0;
height: 24px;
padding: 0 6px 0 8px;
border-radius: 6px;
background: var(--color-kumo-tint);
box-shadow: inset 0 0 0 1px var(--color-kumo-line);
font-size: 11.5px;
color: var(--color-kumo-strong);
cursor: pointer;
transition: background-color 120ms var(--ease-soft), box-shadow 120ms var(--ease-soft);
}
.pipe-input__src:hover,
.pipe-input__src[data-popup-open] { background: var(--color-kumo-fill); }
.pipe-input__src[data-empty="true"] { color: var(--color-kumo-placeholder); }
.pipe-input__src[data-empty="true"] { box-shadow: none; border: 1px dashed var(--color-kumo-line); }
.pipe-input__src-port {
flex: none;
padding: 0 5px;
border-radius: 4px;
background: var(--color-kumo-fill);
font-family: var(--font-mono);
font-size: 9.5px;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--color-kumo-subtle);
}
.pipe-input__src-icon { display: none; }
.pipe-block__widgets { padding: 0 2px; }
.pipe-block__outputs {
display: flex;
flex-wrap: wrap;
gap: 6px;
padding: 6px 8px 0;
}
.pipe-out {
display: inline-flex;
align-items: center;
gap: 5px;
height: 20px;
padding: 0 8px 0 6px;
border-radius: 999px;
background: var(--color-kumo-tint);
font-family: var(--font-mono);
font-size: 10px;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--color-kumo-subtle);
}
.pipe-out[data-used="true"] { color: var(--color-kumo-default); }
.pipe-out > i {
width: 6px;
height: 6px;
border-radius: 999px;
background: var(--port-color);
}
.lib-item__remove {
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
margin-right: -4px;
border-radius: 5px;
color: var(--color-kumo-placeholder);
opacity: 0;
transition: opacity 120ms var(--ease-soft), color 120ms var(--ease-soft);
}
.lib-item:hover .lib-item__remove { opacity: 1; }
.lib-item__remove:hover { color: var(--color-kumo-danger); background: var(--color-kumo-fill); }
/* ---- Group node (canvas) ------------------------------------------- */
.group-node {
position: relative;
width: 100%;
height: 100%;
border-radius: 12px;
border: 1px solid color-mix(in oklab, var(--color-kumo-brand) 35%, var(--color-kumo-line));
background: color-mix(in oklab, var(--color-kumo-brand) 6%, transparent);
transition: border-color 160ms ease, background-color 160ms ease, box-shadow 160ms ease;
}
.group-node[data-selected="true"] {
border-color: var(--color-kumo-brand);
box-shadow: 0 0 0 1px color-mix(in oklab, var(--color-kumo-brand) 40%, transparent);
}
.group-node[data-collapsed="true"] {
background: var(--color-kumo-base);
border-color: var(--color-kumo-line);
box-shadow: 0 1px 2px rgb(0 0 0 / 0.06), 0 8px 24px -12px rgb(0 0 0 / 0.25);
}
.group-node[data-collapsed="true"][data-selected="true"] {
border-color: var(--color-kumo-brand);
}
.group-node__header {
display: flex;
align-items: center;
gap: 6px;
height: 36px;
padding: 0 10px 0 8px;
border-bottom: 1px solid color-mix(in oklab, var(--color-kumo-brand) 20%, transparent);
border-radius: 12px 12px 0 0;
background: color-mix(in oklab, var(--color-kumo-brand) 8%, var(--color-kumo-base));
cursor: grab;
user-select: none;
}
.group-node[data-collapsed="true"] .group-node__header {
background: transparent;
border-bottom-color: var(--color-kumo-line);
}
.group-node__title {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 12.5px;
font-weight: 600;
color: var(--color-kumo-strong);
}
.group-node__count {
font-family: var(--font-mono);
font-size: 10px;
color: var(--color-kumo-subtle);
}
.group-node__ports { padding: 4px 0 6px; }
.group-node__ports .port-row { display: grid; grid-template-columns: 1fr 1fr; }
.group-node[data-status="running"] .group-node__header { position: relative; overflow: hidden; }
/* ---- Pipeline groups ------------------------------------------------- */
.pipe-group {
position: relative;
border-radius: 12px;
border: 1px solid color-mix(in oklab, var(--color-kumo-brand) 35%, var(--color-kumo-line));
background: color-mix(in oklab, var(--color-kumo-brand) 5%, var(--color-kumo-base));
transition: border-color 160ms ease, box-shadow 160ms ease;
}
.pipe-group[data-selected="true"] {
border-color: var(--color-kumo-brand);
box-shadow: 0 0 0 1px color-mix(in oklab, var(--color-kumo-brand) 40%, transparent);
}
.pipe-group[data-collapsed="true"] { background: var(--color-kumo-base); }
.pipe-group__head {
display: flex;
align-items: center;
gap: 6px;
height: 38px;
padding: 0 8px 0 6px;
}
.pipe-group__name {
flex: 1;
min-width: 0;
background: transparent;
border: 0;
outline: 0;
padding: 2px 4px;
margin-left: -4px;
border-radius: 6px;
font-size: 12.5px;
font-weight: 600;
color: var(--color-kumo-strong);
}
.pipe-group__name:hover { background: color-mix(in oklab, var(--color-kumo-fill) 60%, transparent); }
.pipe-group__name:focus { background: var(--color-kumo-fill); }
.pipe-group__count {
font-family: var(--font-mono);
font-size: 10px;
color: var(--color-kumo-subtle);
white-space: nowrap;
}
.pipe-group__body, .pipe-group__summary { overflow: hidden; }
.pipe-group__body-inner {
padding: 0 10px 4px;
border-top: 1px dashed color-mix(in oklab, var(--color-kumo-brand) 25%, transparent);
}
.pipe-group__summary-inner {
display: flex;
align-items: center;
gap: 8px;
padding: 0 10px 10px;
}
.pipe-group__ports { display: flex; flex-wrap: wrap; gap: 4px; }
.pipe-group__body-inner > .pipe__list > .pipe-insert:first-child { height: 18px; }
.pipe-group__body-inner > .pipe__list > .pipe-item:last-child > .pipe-insert { height: 18px; }
.pipe-group__empty {
margin: 4px 0 0;
padding: 10px;
text-align: center;
font-size: 11px;
color: var(--color-kumo-placeholder);
border: 1px dashed var(--color-kumo-line);
border-radius: 8px;
}
/* ---- Pipeline drag state -------------------------------------------- */
.pipe[data-dragging="true"] { cursor: grabbing; user-select: none; }
.pipe[data-dragging="true"] .pipe-insert { height: 22px; }
.pipe[data-dragging="true"] .pipe-insert[data-over="true"] { height: 44px; }
.pipe-item[data-dragging="true"] {
z-index: 20;
pointer-events: none;
transition: none;
}
.pipe-item[data-dragging="true"] > .pipe-block,
.pipe-item[data-dragging="true"] > .pipe-group {
box-shadow: 0 12px 32px -8px rgb(0 0 0 / 0.35), 0 0 0 1px var(--color-kumo-brand);
opacity: 0.94;
}
.pipe-item[data-dragging="true"] > .pipe-insert { visibility: hidden; }
/* Several outputs on one node: cap the stack so five music nodes still fit on a screen. */
.canvas-node__outputs {
max-height: 360px;
overflow: auto;
overscroll-behavior: contain;
}
/* Output view ------------------------------------------------------- */
.node-output {
margin: 4px 10px 0;
border-radius: 6px;
overflow: hidden;
background: var(--color-kumo-recessed);
position: relative;
min-height: 28px;
}
.node-output > img,
.node-output > video {
display: block;
width: 100%;
max-height: 320px;
object-fit: contain;
background: var(--color-kumo-recessed);
}
.node-output > audio {
display: block;
width: 100%;
height: 32px;
}
.node-output__text {
margin: 0;
padding: 7px 9px;
font-family: var(--font-mono);
font-size: 11px;
line-height: 1.45;
color: var(--text-color-kumo-default);
white-space: pre-wrap;
word-break: break-word;
max-height: 160px;
overflow: auto;
}
.node-output__file {
display: flex;
align-items: center;
gap: 6px;
padding: 6px 9px;
font-size: 11px;
color: var(--text-color-kumo-default);
text-decoration: none;
}
.node-output__file:hover {
color: var(--color-kumo-brand);
}
.node-output__grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2px;
}
.node-output__grid img {
display: block;
width: 100%;
aspect-ratio: 1;
object-fit: cover;
}
.node-output__empty {
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
height: 28px;
font-size: 11px;
color: var(--text-color-kumo-placeholder);
}
.node-output__open {
position: absolute;
top: 4px;
right: 4px;
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
border-radius: 5px;
background: color-mix(in oklab, var(--color-kumo-base) 80%, transparent);
color: var(--text-color-kumo-default);
opacity: 0;
transition: opacity 120ms ease-out;
}
.node-output:hover .node-output__open {
opacity: 1;
}
.node-status {
margin: 4px 10px 0;
font-size: 10.5px;
line-height: 1.4;
color: var(--text-color-kumo-subtle);
font-family: var(--font-mono);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.node-error {
margin: 4px 10px 0;
padding: 5px 8px;
border-radius: 5px;
font-size: 11px;
line-height: 1.4;
color: var(--text-color-kumo-danger);
background: color-mix(in oklab, var(--color-kumo-danger) 12%, transparent);
word-break: break-word;
}
/* Port row with an inline widget --------------------------------------- */
.port-row--widget {
grid-template-columns: 1fr;
padding-right: 0;
}
.port-row--widget {
height: auto;
min-height: 24px;
}
.port-row--widget .port--in {
position: relative;
padding-left: 0;
min-width: 0;
height: auto;
min-height: 24px;
align-items: flex-start;
}
/* Keep the dot on the first line when the widget grows taller. */
.port-row--widget .port--in > .react-flow__handle,
.port-row--widget .port--in > .port__ghost {
margin-top: 7px;
}
.port-row--widget .port--in > .widget {
flex: 1;
min-width: 0;
margin: 0 10px 0 0;
}
.port-row--widget .port__label {
display: none;
}
.port--in.is-linked .widget {
opacity: 0.45;
pointer-events: none;
}
/* File widget ------------------------------------------------------- */
.widget--file {
gap: 6px;
}
.widget--file .widget__input {
min-width: 0;
flex: 1;
}
.widget__thumb {
width: 18px;
height: 18px;
border-radius: 4px;
object-fit: cover;
flex: none;
background: var(--color-kumo-recessed);
}
.widget--file .widget__arrow {
opacity: 1;
width: 18px;
height: 18px;
}
/* Space search ------------------------------------------------------- */
.space-row {
display: flex;
align-items: center;
gap: 8px;
height: 40px;
padding: 0 10px 0 14px;
cursor: pointer;
transition: background 100ms ease-out;
}
.space-row:hover {
background: var(--color-kumo-tint);
}
.space-row[data-usable="false"] {
opacity: 0.5;
}
.space-row__emoji {
width: 20px;
text-align: center;
font-size: 14px;
flex: none;
}
.space-row__main {
min-width: 0;
flex: 1;
line-height: 1.25;
}
.space-row__title {
font-size: 12.5px;
font-weight: 500;
color: var(--text-color-kumo-strong);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.space-row__meta {
display: flex;
align-items: center;
gap: 5px;
font-size: 10.5px;
font-family: var(--font-mono);
color: var(--text-color-kumo-subtle);
overflow: hidden;
white-space: nowrap;
}
.space-row__meta > span {
overflow: hidden;
text-overflow: ellipsis;
}
.stage-dot {
display: inline-block;
width: 6px;
height: 6px;
border-radius: 50%;
flex: none;
background: var(--color-kumo-hairline);
}
.stage-dot[data-stage="RUNNING"] {
background: var(--color-kumo-success);
}
.stage-dot[data-stage="SLEEPING"],
.stage-dot[data-stage="BUILDING"],
.stage-dot[data-stage="APP_STARTING"] {
background: var(--color-kumo-warning);
}
.stage-dot[data-stage="RUNTIME_ERROR"],
.stage-dot[data-stage="BUILD_ERROR"],
.stage-dot[data-stage="CONFIG_ERROR"] {
background: var(--color-kumo-danger);
}
.wf-space__fix { flex: none; padding: 2px 8px; border-radius: 6px; font-size: 11px; font-weight: 500; color: var(--color-kumo-brand); text-decoration: none; }
.wf-space__fix:hover { background: var(--color-kumo-tint); }
.hw-tag {
display: inline-block;
padding: 0 4px;
border-radius: 3px;
font-size: 9.5px;
font-weight: 600;
letter-spacing: 0.02em;
line-height: 14px;
background: var(--color-kumo-fill);
color: var(--text-color-kumo-subtle);
flex: none;
}
.hw-tag[data-zero="true"] {
background: color-mix(in oklab, var(--color-kumo-brand) 18%, transparent);
color: var(--color-kumo-brand);
}
.history-thumb img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
.avatar {
width: 22px;
height: 22px;
border-radius: 50%;
object-fit: cover;
background: var(--color-kumo-recessed);
}
/* ---- Library: pin / hide / reorder --------------------------------- */
.lib-item__actions {
display: none;
align-items: center;
gap: 2px;
margin-right: -4px;
}
.lib-item:hover .lib-item__actions,
.lib-item:focus-visible .lib-item__actions {
display: inline-flex;
}
.lib-item:hover .lib-item__dots {
display: none;
}
.lib-item__btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
border-radius: 5px;
color: var(--text-color-kumo-subtle);
transition: color var(--t-fast), background-color var(--t-fast);
}
.lib-item__btn:hover {
color: var(--text-color-kumo-strong);
background: var(--color-kumo-fill);
}
.lib-item__btn.is-danger:hover {
color: var(--color-kumo-danger);
}
.lib-item__btn[data-active] {
color: var(--color-kumo-brand);
}
.lib-item[data-hidden] {
opacity: 0.55;
}
.lib-item[data-over] {
position: relative;
}
.lib-item[data-over]::before {
content: "";
position: absolute;
left: 8px;
right: 8px;
height: 2px;
border-radius: 2px;
background: var(--color-kumo-brand);
}
.lib-item[data-over="before"]::before { top: -1px; }
.lib-item[data-over="after"]::before { bottom: -1px; }
.lib-footer {
display: flex;
align-items: center;
gap: 6px;
height: 28px;
margin: 6px 8px 0;
padding: 0 10px;
border-radius: 7px;
font-size: 11px;
color: var(--text-color-kumo-placeholder);
transition: background-color var(--t-fast), color var(--t-fast);
}
.lib-footer:hover {
color: var(--text-color-kumo-default);
background: var(--color-kumo-tint);
}
/* ---- Context menu -------------------------------------------------- */
.ctx-menu {
position: fixed;
z-index: 60;
min-width: 196px;
padding: 4px;
border-radius: 9px;
background: var(--color-kumo-elevated, var(--color-kumo-base));
box-shadow:
0 0 0 1px var(--color-kumo-hairline),
0 12px 32px -8px rgb(0 0 0 / 0.45);
animation: ctx-in 120ms var(--ease-soft);
}
@keyframes ctx-in {
from { opacity: 0; transform: scale(0.97) translateY(-2px); }
to { opacity: 1; transform: none; }
}
.ctx-menu__item {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
height: 28px;
padding: 0 8px;
border-radius: 6px;
font-size: 12.5px;
color: var(--text-color-kumo-default);
text-align: left;
}
.ctx-menu__item:hover:not(:disabled) {
background: var(--color-kumo-tint);
color: var(--text-color-kumo-strong);
}
.ctx-menu__item:disabled { opacity: 0.45; }
.ctx-menu__item.is-danger:hover:not(:disabled) { color: var(--color-kumo-danger); }
.ctx-menu__sep {
height: 1px;
margin: 4px 6px;
background: var(--color-kumo-hairline);
}
.ctx-menu__kbd {
font-family: var(--font-mono);
font-size: 10px;
color: var(--text-color-kumo-placeholder);
}
/* ---- Copilot dock -------------------------------------------------- */
.copilot {
position: absolute;
right: 12px;
bottom: 12px;
z-index: 30;
display: flex;
flex-direction: column;
width: 380px;
max-height: min(68vh, 640px);
border-radius: 12px;
background: var(--color-kumo-base);
box-shadow:
0 0 0 1px var(--color-kumo-hairline),
0 20px 48px -16px rgb(0 0 0 / 0.5);
overflow: hidden;
}
.copilot__header {
display: flex;
align-items: center;
gap: 6px;
height: 38px;
padding: 0 6px 0 10px;
border-bottom: 1px solid var(--color-kumo-hairline);
flex: none;
}
.copilot__header > .flex-1 { min-width: 4px; }
.copilot--side {
position: static;
width: 100%;
height: 100%;
max-height: none;
border-radius: 0;
box-shadow: none;
}
.copilot__pick {
display: inline-flex;
align-items: center;
gap: 4px;
height: 24px;
max-width: 150px;
padding: 0 4px 0 6px;
border-radius: 6px;
font-size: 12px;
font-weight: 500;
color: var(--text-color-kumo-strong);
transition: background-color var(--t-fast);
}
.copilot__pick:hover { background: var(--color-kumo-tint); }
.copilot__pick[data-bad] { color: var(--color-kumo-danger); }
.copilot__pick-caret { flex: none; color: var(--text-color-kumo-placeholder); }
.copilot__list {
flex: 1 1 auto;
min-height: 120px;
overflow-y: auto;
padding: 12px 12px 6px;
display: flex;
flex-direction: column;
gap: 8px;
scroll-behavior: smooth;
}
/* Never let flex squash a message; the list scrolls instead. */
.copilot__list > * { flex: none; }
.copilot--side { min-height: 0; }
.copilot__empty {
display: flex;
flex-direction: column;
gap: 10px;
padding: 8px 2px 4px;
font-size: 12px;
line-height: 1.5;
color: var(--text-color-kumo-subtle);
}
.copilot__chip {
text-align: left;
padding: 7px 10px;
border-radius: 8px;
font-size: 12px;
color: var(--text-color-kumo-default);
box-shadow: inset 0 0 0 1px var(--color-kumo-hairline);
transition: background-color var(--t-fast), color var(--t-fast);
}
.copilot__chip:hover { background: var(--color-kumo-tint); color: var(--text-color-kumo-strong); }
.copilot__msg {
font-size: 12.5px;
line-height: 1.5;
white-space: pre-wrap;
overflow-wrap: anywhere;
}
.copilot__msg--user {
align-self: flex-end;
max-width: 88%;
padding: 6px 10px;
border-radius: 10px 10px 3px 10px;
background: var(--color-kumo-brand);
color: var(--accent-ink);
}
.copilot__msg--ai { color: var(--text-color-kumo-default); padding: 0 2px; }
.copilot__msg--error {
display: flex;
gap: 6px;
padding: 6px 8px;
border-radius: 8px;
font-size: 12px;
color: var(--color-kumo-danger);
background: color-mix(in oklab, var(--color-kumo-danger) 10%, transparent);
}
.copilot__tools {
display: flex;
flex-direction: column;
border-radius: 9px;
box-shadow: inset 0 0 0 1px var(--color-kumo-hairline);
overflow: hidden;
}
.copilot__tools[data-awaiting="true"] {
box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--color-kumo-brand) 55%, var(--color-kumo-hairline));
}
.copilot__tool {
position: relative;
display: flex;
flex-direction: column;
font-size: 12px;
color: var(--text-color-kumo-default);
}
.copilot__tool + .copilot__tool { border-top: 1px solid var(--color-kumo-hairline); }
.copilot__tool-row {
display: flex;
align-items: stretch;
min-height: 30px;
}
.copilot__tool-main {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
flex: 1;
padding: 4px 4px 4px 10px;
text-align: left;
transition: background-color var(--t-fast);
}
.copilot__tool-main:not(:disabled):hover { background: var(--color-kumo-tint); }
.copilot__tool[data-kind="read"] .copilot__tool-text { color: var(--text-color-kumo-subtle); }
.copilot__tool[data-decision="rejected"] .copilot__tool-text > :first-child { color: var(--text-color-kumo-placeholder); text-decoration: line-through; }
.copilot__tool-kind {
flex: none;
width: 30px;
font-family: var(--font-mono);
font-size: 9.5px;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--text-color-kumo-placeholder);
}
.copilot__tool[data-kind="edit"] .copilot__tool-kind { color: var(--color-kumo-brand); }
.copilot__tool[data-kind="run"] .copilot__tool-kind { color: var(--color-kumo-warning); }
.copilot__tool-text {
display: flex;
min-width: 0;
flex: 1;
align-items: baseline;
gap: 6px;
}
.copilot__tool-text > :first-child { min-width: 0; flex: 0 1 auto; }
.copilot__tool-text > :last-child:not(:first-child) { min-width: 0; flex: 1 1 auto; font-size: 10.5px; }
.copilot__tool-end {
display: inline-flex;
width: 22px;
height: 22px;
flex: none;
align-items: center;
justify-content: center;
}
.copilot__tool-caret {
color: var(--text-color-kumo-placeholder);
transition: transform var(--t-fast) var(--ease-soft);
}
.copilot__tool[data-expanded] .copilot__tool-caret { transform: rotate(90deg); }
.copilot__tool-decide {
display: flex;
flex: none;
align-items: center;
gap: 2px;
padding-right: 4px;
}
.copilot__tool-body {
padding: 2px 10px 8px 48px;
font-size: 10.5px;
}
.copilot__tool-body pre {
margin: 2px 0 6px;
padding: 6px 8px;
border-radius: 6px;
background: var(--color-kumo-tint);
font-family: var(--font-mono);
font-size: 10px;
line-height: 1.45;
max-height: 180px;
overflow: auto;
white-space: pre-wrap;
word-break: break-word;
color: var(--text-color-kumo-default);
}
.copilot__tool-label {
display: block;
font-size: 9.5px;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--text-color-kumo-placeholder);
}
.copilot__tool-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 14px;
height: 14px;
flex: none;
color: var(--text-color-kumo-subtle);
}
.copilot__tool[data-status="done"] .copilot__tool-icon { color: var(--color-kumo-success); }
.copilot__tool[data-status="error"] .copilot__tool-icon { color: var(--color-kumo-danger); }
.copilot__tool[data-decision="rejected"] .copilot__tool-icon { color: var(--text-color-kumo-placeholder); }
.copilot__tool[data-kind="run"] .copilot__tool-dot { background: var(--color-kumo-warning); }
.copilot__tool-dot {
width: 6px;
height: 6px;
border-radius: 999px;
background: var(--color-kumo-brand);
}
.copilot__mini {
display: inline-flex;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
border-radius: 6px;
color: var(--text-color-kumo-subtle);
transition: background-color var(--t-fast), color var(--t-fast);
}
.copilot__mini:hover { background: var(--color-kumo-fill); }
.copilot__mini.is-yes:hover { color: var(--color-kumo-success); }
.copilot__mini.is-no:hover { color: var(--color-kumo-danger); }
.copilot__tools-actions {
display: flex;
align-items: center;
gap: 6px;
height: 28px;
padding: 0 4px 0 10px;
border-top: 1px solid var(--color-kumo-hairline);
font-size: 10.5px;
color: var(--text-color-kumo-subtle);
}
.copilot__act {
display: inline-flex;
align-items: center;
gap: 5px;
height: 22px;
padding: 0 7px;
border-radius: 5px;
font-size: 11.5px;
font-weight: 500;
color: var(--text-color-kumo-subtle);
transition: background-color var(--t-fast), color var(--t-fast);
}
.copilot__act:hover { background: var(--color-kumo-fill); color: var(--text-color-kumo-strong); }
.copilot__act.is-yes { color: var(--color-kumo-brand); }
.copilot__act.is-yes:hover { background: color-mix(in oklab, var(--color-kumo-brand) 14%, transparent); }
.copilot__act .kbd { font-size: 9px; opacity: 0.7; }
.copilot__thinking {
display: flex;
gap: 4px;
padding: 4px 2px;
}
.copilot__thinking span {
width: 5px;
height: 5px;
border-radius: 999px;
background: var(--text-color-kumo-placeholder);
animation: think 1s ease-in-out infinite;
}
.copilot__thinking span:nth-child(2) { animation-delay: 0.15s; }
.copilot__thinking span:nth-child(3) { animation-delay: 0.3s; }
@keyframes think { 0%, 100% { opacity: 0.3; transform: translateY(0); } 50% { opacity: 1; transform: translateY(-2px); } }
.copilot__composer {
display: flex;
align-items: flex-end;
gap: 6px;
padding: 8px 8px 8px 12px;
border-top: 1px solid var(--color-kumo-hairline);
flex: none;
}
.copilot__textarea {
flex: 1;
min-height: 24px;
max-height: 140px;
padding: 3px 0;
resize: none;
background: transparent;
font-size: 12.5px;
line-height: 1.45;
color: var(--text-color-kumo-strong);
outline: none;
}
.copilot__textarea::placeholder { color: var(--text-color-kumo-placeholder); }
.copilot__send {
display: inline-flex;
align-items: center;
justify-content: center;
width: 26px;
height: 26px;
flex: none;
border-radius: 8px;
background: var(--color-kumo-brand);
color: var(--accent-ink);
transition: opacity var(--t-fast), transform 120ms var(--ease-soft);
}
.copilot__send:disabled { opacity: 0.35; }
.copilot__send:not(:disabled):active { transform: scale(0.94); }
.copilot__send.is-stop { background: var(--color-kumo-fill); color: var(--text-color-kumo-strong); }
.copilot__input {
width: 100%;
padding: 0 8px;
border-radius: 6px;
font-size: 12px;
color: var(--text-color-kumo-strong);
background: var(--color-kumo-control);
box-shadow: inset 0 0 0 1px var(--color-kumo-hairline);
outline: none;
}
.copilot__input:focus { box-shadow: inset 0 0 0 1.5px var(--color-kumo-brand); }
/* ---- Resizable side panels ----------------------------------------- */
/* Message turns: hover actions under each bubble */
.copilot__turn { display: flex; flex-direction: column; gap: 2px; }
.copilot__turn--user { align-items: flex-end; }
.copilot__turn--user .copilot__msg--user { max-width: 100%; }
.copilot__turn--ai { align-items: flex-start; }
.copilot__actions {
display: flex;
align-items: center;
gap: 1px;
height: 20px;
opacity: 0;
transition: opacity var(--t-fast);
}
.copilot__turn:hover .copilot__actions,
.copilot__actions:focus-within { opacity: 1; }
.copilot__actions .copilot__mini { width: 20px; height: 20px; color: var(--text-color-kumo-placeholder); }
.copilot__actions .copilot__mini:hover { color: var(--text-color-kumo-strong); }
.copilot__actions .copilot__mini:disabled { opacity: 0.4; pointer-events: none; }
.copilot__versions {
display: inline-flex;
align-items: center;
gap: 1px;
margin-right: 4px;
font-family: var(--font-mono);
font-size: 10px;
color: var(--text-color-kumo-subtle);
}
.copilot__turn:has(.copilot__versions) .copilot__actions { opacity: 1; }
.copilot__edit {
display: flex;
flex-direction: column;
gap: 4px;
padding: 6px;
border-radius: 10px;
box-shadow: inset 0 0 0 1.5px var(--color-kumo-brand);
}
.copilot__edit .copilot__textarea { padding: 2px 4px; }
.copilot__edit-actions { display: flex; align-items: center; gap: 2px; }
.copilot__edit-actions > :first-child { flex: 1; min-width: 0; }
.copilot__act:disabled { opacity: 0.4; pointer-events: none; }
.copilot__msg--error .copilot__act { height: 20px; padding: 0 6px; font-size: 11px; }
.copilot__signin {
display: flex;
align-items: center;
gap: 6px;
height: 36px;
padding: 0 6px 0 12px;
border-top: 1px solid var(--color-kumo-hairline);
font-size: 11.5px;
color: var(--text-color-kumo-subtle);
}
.copilot__signin > span { flex: 1; }
/* Copilot history ----------------------------------------------------- */
.copilot__hist-list { display: flex; flex-direction: column; gap: 1px; }
.copilot__hist {
position: relative;
display: flex;
align-items: center;
border-radius: 8px;
transition: background-color var(--t-fast);
}
.copilot__hist:hover { background: var(--color-kumo-tint); }
.copilot__hist[data-active] { background: var(--color-kumo-tint); box-shadow: inset 2px 0 0 var(--color-kumo-brand); }
.copilot__hist-main {
display: flex;
min-width: 0;
flex: 1;
flex-direction: column;
gap: 1px;
padding: 7px 34px 7px 10px;
text-align: left;
font-size: 12.5px;
color: var(--text-color-kumo-strong);
}
.copilot__hist-meta { font-size: 10.5px; color: var(--text-color-kumo-placeholder); }
.copilot__hist-del {
position: absolute;
right: 6px;
top: 50%;
display: inline-flex;
width: 24px;
height: 24px;
align-items: center;
justify-content: center;
border-radius: 6px;
color: var(--text-color-kumo-placeholder);
opacity: 0;
transform: translateY(-50%);
transition: opacity var(--t-fast), color var(--t-fast), background-color var(--t-fast);
}
.copilot__hist:hover .copilot__hist-del,
.copilot__hist-del:focus-visible { opacity: 1; }
.copilot__hist-del:hover { background: var(--color-kumo-fill); color: var(--color-kumo-danger); }
/* Copilot markdown ---------------------------------------------------- */
.md { font-size: 12.5px; line-height: 1.55; overflow-wrap: anywhere; }
.md > * + * { margin-top: 6px; }
.md p { margin: 0; }
.md-h { margin: 0; font-weight: 600; color: var(--text-color-kumo-strong); }
.md > .md-h { margin-top: 10px; }
.md-h4 { font-size: 13px; }
.md-h5, .md-h6 { font-size: 12.5px; }
.md ul, .md ol { margin: 0; padding-left: 18px; }
.md ul { list-style: disc; }
.md ol { list-style: decimal; }
.md li + li { margin-top: 2px; }
.md li::marker { color: var(--text-color-kumo-placeholder); }
.md blockquote {
margin: 0;
padding: 2px 0 2px 10px;
border-left: 2px solid var(--color-kumo-hairline);
color: var(--text-color-kumo-subtle);
}
.md hr { margin: 8px 0; border: 0; border-top: 1px solid var(--color-kumo-hairline); }
.md-code {
padding: 1px 4px;
border-radius: 4px;
background: var(--color-kumo-tint);
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-color-kumo-strong);
}
.md-pre {
position: relative;
margin: 0;
padding: 8px 10px;
border-radius: 8px;
background: var(--color-kumo-tint);
box-shadow: inset 0 0 0 1px var(--color-kumo-hairline);
font-family: var(--font-mono);
font-size: 11px;
line-height: 1.5;
overflow: auto;
white-space: pre;
color: var(--text-color-kumo-strong);
}
.md-pre[data-lang]:not([data-lang=""])::before {
content: attr(data-lang);
position: absolute;
top: 5px;
right: 8px;
font-size: 9.5px;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--text-color-kumo-placeholder);
}
.md-link { color: inherit; font-weight: 500; text-decoration: underline; text-decoration-color: var(--color-kumo-brand); text-decoration-thickness: 2px; text-underline-offset: 3px; overflow-wrap: anywhere; }
.md-link:hover { text-decoration-color: currentColor; }
.md strong { font-weight: 600; color: var(--text-color-kumo-strong); }
@keyframes pulse-dot {
0%, 100% { opacity: 1; }
50% { opacity: 0.35; }
}
/* Per-token fade in while streaming */
.tok {
display: inline;
animation: tok-in 280ms var(--ease-soft) both;
}
@keyframes tok-in {
from { opacity: 0; filter: blur(2px); }
to { opacity: 1; filter: blur(0); }
}
.copilot__msg--ai[data-streaming] .md > :last-child::after {
content: "";
display: inline-block;
width: 5px;
height: 12px;
margin-left: 2px;
vertical-align: -1px;
border-radius: 1px;
background: var(--color-kumo-brand);
animation: pulse-dot 1s ease-in-out infinite;
}
.panel-resize {
position: absolute;
top: 0;
bottom: 0;
width: 9px;
z-index: 20;
cursor: col-resize;
touch-action: none;
}
.panel-resize[data-side="left"] { right: -5px; }
.panel-resize[data-side="right"] { left: -5px; }
.panel-resize::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 4px;
width: 1px;
background: var(--color-kumo-brand);
opacity: 0;
transition: opacity 120ms ease 80ms;
}
.panel-resize:hover::after,
.panel-resize[data-active]::after {
opacity: 1;
}
.panel-resize[data-active]::after {
transition-delay: 0s;
}
@media (prefers-reduced-motion: reduce) {
.tok { animation: none; }
*,
*::before,
*::after {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
}
}
/* Collapsed-node handles stack on the header's edges */
.canvas-node__collapsed-handles {
position: absolute;
inset: 0;
pointer-events: none;
}
.canvas-node .react-flow__handle.handle--collapsed {
position: absolute;
top: 11px;
margin: 0;
pointer-events: all;
}
.canvas-node .react-flow__handle.handle--collapsed-left {
left: -5px;
}
.canvas-node .react-flow__handle.handle--collapsed-right {
right: -5px;
}
/* React Flow attribution: keep it, but make it quiet */
.react-flow__attribution {
background: transparent;
font-size: 9px;
color: var(--text-color-kumo-placeholder);
margin: 4px 6px;
}
.react-flow__attribution a {
color: inherit;
text-decoration: none;
}
/* Agent bridge dialog ------------------------------------------------- */
.bridge { display: flex; flex-direction: column; gap: 12px; padding: 18px 20px 16px; font-size: 12.5px; }
.bridge__title { font-size: 14px; font-weight: 600; color: var(--text-color-kumo-strong); }
.bridge__desc { color: var(--text-color-kumo-subtle); line-height: 1.45; margin-top: -6px; }
.bridge__row { display: flex; align-items: center; gap: 12px; min-height: 24px; }
.bridge__status { display: inline-flex; align-items: center; gap: 6px; color: var(--text-color-kumo-subtle); font-size: 12px; min-width: 0; }
.bridge__status > i { width: 6px; height: 6px; border-radius: 50%; background: var(--text-color-kumo-placeholder); flex: none; }
.bridge__status.is-connected > i { background: var(--color-kumo-success); }
.bridge__status.is-connecting > i { background: var(--color-kumo-warning); animation: pulse-dot 1.2s ease-in-out infinite; }
.bridge__status.is-error { color: var(--color-kumo-danger); }
.bridge__status.is-error > i { background: var(--color-kumo-danger); }
.bridge__grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: 10px; }
.bridge__field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.bridge__field > span { font-size: 11px; font-weight: 500; color: var(--text-color-kumo-subtle); display: flex; align-items: center; gap: 6px; }
.bridge__hint { font-style: normal; font-weight: 400; color: var(--text-color-kumo-placeholder); font-size: 11px; }
.bridge__input, .bridge__token {
height: 28px; display: flex; align-items: center; gap: 2px; padding: 0 4px 0 8px; border-radius: 6px;
background: var(--color-kumo-recessed); border: 1px solid var(--color-kumo-hairline);
font-family: var(--font-mono); font-size: 11.5px; color: var(--text-color-kumo-default); min-width: 0;
}
.bridge__input { width: 100%; outline: none; padding-right: 8px; }
.bridge__input:focus { border-color: var(--color-kumo-brand); }
.bridge__token > code { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bridge__snip { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.bridge__snip-head { display: flex; align-items: center; gap: 8px; font-size: 11px; font-weight: 500; color: var(--text-color-kumo-subtle); min-height: 22px; }
.bridge__snip-head > .flex-1 { min-width: 4px; }
.bridge__pre {
margin: 0; padding: 8px 10px; border-radius: 6px; background: var(--color-kumo-recessed); border: 1px solid var(--color-kumo-hairline);
font-family: var(--font-mono); font-size: 11px; line-height: 1.5; color: var(--text-color-kumo-default);
white-space: pre-wrap; word-break: break-all; max-height: 180px; overflow: auto;
}
.bridge__tabs { align-self: flex-start; }
.bridge__foot { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--text-color-kumo-subtle); border-top: 1px solid var(--color-kumo-hairline); padding-top: 10px; margin-top: 2px; }
.bridge__foot > .flex-1 { min-width: 4px; }
.bridge__link { color: var(--color-kumo-brand); text-decoration: none; }
.bridge__link:hover { text-decoration: underline; }
.bridge__dot { color: var(--text-color-kumo-placeholder); }
.bridge__calls { font-family: var(--font-mono); font-size: 10.5px; color: var(--text-color-kumo-placeholder); }
.bridge__keyrow { gap: 8px; }
.bridge__keyrow > .bridge__hint { line-height: 1.4; }
.bridge__adv > summary { cursor: pointer; font-size: 11.5px; font-weight: 500; color: var(--text-color-kumo-subtle); width: max-content; }
.bridge__adv-body { display: flex; flex-direction: column; gap: 10px; padding-top: 10px; }
/* Beginner surfaces: quick start, shortcuts, pre-run check, empty canvas ---- */
/* Every dialog: sits a little below the top, never taller than the viewport, scrolls inside when it is.
(Kumo's Dialog ships with no padding and no height cap; the history dialog manages its own panes.) */
[role="dialog"]:not(.ctx-menu):not(.explorer) { top: 48px !important; }
[role="dialog"]:not(.ctx-menu):not(.explorer):not(.hist) { max-height: calc(100dvh - 96px); }
[role="dialog"]:not(.ctx-menu):not(.explorer):not(.hist) { overflow-y: auto; overscroll-behavior: contain; }
.batch { display: flex; flex-direction: column; padding: 18px 20px 16px; font-size: 12.5px; }
.batch .precheck__foot { position: sticky; bottom: -16px; margin: 4px -20px -16px; padding: 12px 20px 16px; background: var(--color-kumo-base); border-top: 1px solid var(--color-kumo-hairline); }
.welcome {
display: flex; flex-direction: column; gap: 14px; padding: 20px;
max-height: calc(100dvh - 4rem); overflow-y: auto; font-size: 13.5px; line-height: 1.45;
}
@media (min-width: 640px) { .welcome { max-height: calc(100dvh - 8rem); } }
.welcome__head { display: flex; flex-direction: column; gap: 4px; }
.welcome__title { margin: 0; font-size: 20px; font-weight: 600; line-height: 1.25; letter-spacing: -0.005em; color: var(--text-color-kumo-strong); }
.welcome__lede { margin: 0; font-size: 14px; color: var(--text-color-kumo-subtle); }
.welcome__entries { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.welcome__entry {
display: flex; align-items: center; gap: 12px; padding: 12px; text-align: left;
border-radius: 10px; border: 1px solid var(--color-kumo-line); background: var(--color-kumo-recessed);
color: var(--text-color-kumo-default); transition: border-color 0.15s var(--ease-soft), background 0.15s var(--ease-soft);
}
.welcome__entry:hover { border-color: var(--color-kumo-interact); background: var(--color-kumo-tint); }
.welcome__entry[data-brand] { border-color: color-mix(in oklab, var(--color-kumo-brand) 55%, var(--color-kumo-line)); }
.welcome__entry[data-brand]:hover { border-color: var(--color-kumo-brand); }
.welcome__icon {
flex: none; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 8px;
background: var(--color-kumo-fill); color: var(--text-color-kumo-strong);
}
.welcome__entry[data-brand] .welcome__icon { background: var(--color-kumo-brand); color: var(--accent-ink); }
.welcome__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.welcome__text strong { font-size: 14px; font-weight: 600; color: var(--text-color-kumo-strong); }
.welcome__text span { font-size: 13px; color: var(--text-color-kumo-subtle); }
.welcome__go { flex: none; color: var(--text-color-kumo-subtle); transition: transform 0.15s var(--ease-soft), color 0.15s; }
.welcome__entry:hover .welcome__go { transform: translateX(2px); color: var(--text-color-kumo-strong); }
.welcome__section { display: flex; flex-direction: column; gap: 8px; }
.welcome__label {
display: flex; align-items: center; gap: 6px; margin: 0; font-size: 12px; font-weight: 600;
letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-color-kumo-subtle);
}
.welcome__templates { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin: 0; padding: 0; list-style: none; }
.welcome__templates button {
display: flex; flex-direction: column; gap: 2px; width: 100%; height: 100%; padding: 10px 12px; text-align: left;
border-radius: 8px; border: 1px solid var(--color-kumo-line); background: transparent;
transition: border-color 0.15s var(--ease-soft), background 0.15s var(--ease-soft);
}
.welcome__templates button:hover { border-color: var(--color-kumo-interact); background: var(--color-kumo-tint); }
.welcome__templates b { font-size: 13.5px; font-weight: 600; color: var(--text-color-kumo-strong); }
.welcome__templates span {
font-size: 12.5px; color: var(--text-color-kumo-subtle);
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.welcome__steps {
display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; margin: 0; padding: 0; list-style: none;
font-size: 13px; color: var(--text-color-kumo-default);
}
.welcome__steps li { display: flex; align-items: center; gap: 8px; }
.welcome__n {
flex: none; display: grid; place-items: center; width: 20px; height: 20px; border-radius: 6px;
background: var(--color-kumo-fill); color: var(--text-color-kumo-strong); font-size: 11.5px; font-weight: 600;
}
.welcome__foot {
display: flex; align-items: center; justify-content: space-between; gap: 12px;
padding-top: 14px; border-top: 1px solid var(--color-kumo-hairline); font-size: 13px; color: var(--text-color-kumo-subtle);
}
@media (max-width: 639px) {
.welcome { padding: 16px; gap: 12px; }
.welcome__title { font-size: 18px; }
.welcome__entries, .welcome__templates { grid-template-columns: minmax(0, 1fr); }
.welcome__templates span { -webkit-line-clamp: 1; }
.welcome__steps { flex-direction: column; align-items: flex-start; }
.welcome__foot { flex-direction: column; align-items: stretch; }
}
.shortcuts { padding: 18px 20px 16px; }
.shortcuts__list { display: flex; flex-direction: column; gap: 2px; margin-top: 12px; font-size: 12.5px; }
.shortcuts__list > div { display: grid; grid-template-columns: 132px 1fr; align-items: center; gap: 10px; padding: 5px 0; border-bottom: 1px solid var(--color-kumo-hairline); }
.shortcuts__list > div:last-child { border-bottom: 0; }
.shortcuts__list dt { display: flex; flex-wrap: wrap; gap: 4px; }
.shortcuts__list dd { color: var(--text-color-kumo-default); }
.precheck { display: flex; flex-direction: column; gap: 12px; padding: 18px 20px 16px; font-size: 12.5px; }
.precheck__list { display: flex; flex-direction: column; gap: 4px; max-height: 320px; overflow: auto; }
.precheck__list button {
display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px; border-radius: 8px; text-align: left;
background: var(--color-kumo-recessed); border: 1px solid var(--color-kumo-hairline); color: var(--text-color-kumo-default);
}
.precheck__list button:hover { border-color: var(--color-kumo-brand); background: var(--color-kumo-tint); }
.precheck__list button > svg:first-child { flex: none; color: var(--color-kumo-warning); }
.precheck__list button > svg:last-child { flex: none; margin-left: auto; color: var(--text-color-kumo-subtle); }
.precheck__list span { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.precheck__list strong { font-weight: 500; color: var(--text-color-kumo-strong); }
.precheck__list em { font-style: normal; font-size: 11.5px; color: var(--text-color-kumo-subtle); }
.precheck__foot { display: flex; justify-content: flex-end; gap: 8px; padding-top: 4px; }
.canvas-empty { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; z-index: 4; }
.canvas-empty__card {
display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 22px 26px; pointer-events: auto;
border-radius: 14px; background: color-mix(in oklab, var(--color-kumo-base) 88%, transparent); backdrop-filter: blur(8px);
border: 1px solid var(--color-kumo-hairline); box-shadow: 0 8px 30px -12px rgb(0 0 0 / 0.35); text-align: center;
}
.canvas-empty__title { font-size: 15px; font-weight: 600; color: var(--text-color-kumo-strong); }
.canvas-empty__sub { margin-top: -8px; font-size: 12.5px; color: var(--text-color-kumo-subtle); }
.canvas-empty__row { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.canvas-empty__btn {
display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px; border-radius: 8px; font-size: 12.5px; font-weight: 500;
border: 1px solid var(--color-kumo-hairline); background: var(--color-kumo-recessed); color: var(--text-color-kumo-strong);
}
.canvas-empty__btn:hover { background: var(--color-kumo-tint); border-color: var(--color-kumo-line); }
.canvas-empty__btn--brand { background: var(--color-kumo-brand); border-color: transparent; color: var(--accent-ink); }
.canvas-empty__btn--brand:hover { background: var(--color-kumo-brand); filter: brightness(1.08); }
.canvas-empty__btn--brand .kbd { background: rgb(255 255 255 / 0.18); color: inherit; border-color: transparent; }
.canvas-empty__link { font-size: 12px; color: var(--text-color-kumo-subtle); text-decoration: underline; text-underline-offset: 3px; }
.canvas-empty__link:hover { color: var(--text-color-kumo-strong); }
.node-error__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin-top: 5px; }
.node-error__ask { display: inline-block; font-weight: 500; text-decoration: underline; text-underline-offset: 2px; color: inherit; opacity: 0.85; }
.node-error__ask:hover { opacity: 1; }
.node-error__act {
display: inline-flex; align-items: center; height: 22px; padding: 0 9px; border-radius: 6px; font-weight: 600; font-size: 11px;
color: var(--color-kumo-base); background: var(--color-kumo-danger); text-decoration: none;
}
.node-error__act:hover { filter: brightness(1.08); }
.node-error__act:active { transform: translateY(0.5px); }
@keyframes spin { to { transform: rotate(360deg); } }
/* Run history dialog: list of runs on the left, compare / grid on the right. */
.hist { display: flex; flex-direction: column; gap: 0; width: min(96vw, 1040px) !important; max-width: none !important; max-height: min(calc(100dvh - 96px), 760px); padding: 0; overflow: hidden; }
.hist__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 14px 14px 10px 20px; border-bottom: 1px solid var(--color-kumo-hairline); }
.hist__head h2 { margin: 0; }
.hist__empty { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 48px 24px; text-align: center; }
.hist__body { display: grid; grid-template-columns: 260px minmax(0, 1fr); min-height: 0; flex: 1 1 auto; }
.hist__list { display: flex; flex-direction: column; gap: 4px; padding: 10px; overflow-y: auto; border-right: 1px solid var(--color-kumo-hairline); background: var(--color-kumo-recessed); }
.hist__card { display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px; border-radius: 10px; text-align: left; border: 1px solid transparent; }
.hist__card:hover { background: var(--color-kumo-tint); }
.hist__card[data-active] { background: var(--color-kumo-base); border-color: var(--color-kumo-line); box-shadow: 0 1px 4px -2px rgb(0 0 0 / 0.2); }
.hist__thumb { display: grid; flex: none; place-items: center; width: 44px; height: 44px; border-radius: 8px; overflow: hidden; color: var(--text-color-kumo-placeholder); background: var(--color-kumo-fill); }
.hist__thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.hist__thumb--grid { display: grid; grid-template-columns: 1fr 1fr; grid-auto-rows: 1fr; gap: 1px; place-items: stretch; }
.hist__thumb--grid img { width: 100%; height: 100%; }
.hist__thumb--grid > svg { grid-column: 1 / -1; place-self: center; }
.hist__meta { display: block; margin-top: 2px; font-family: var(--font-mono); font-size: 10.5px; color: var(--text-color-kumo-subtle); font-variant-numeric: tabular-nums; }
.hist__vary { display: flex; flex-wrap: wrap; gap: 3px; margin-top: 4px; }
.hist__vary > span { max-width: 100%; padding: 1px 6px; border-radius: 999px; font-size: 10px; color: var(--text-color-kumo-default); background: var(--color-kumo-fill); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hist__main { display: flex; flex-direction: column; gap: 14px; min-height: 0; padding: 16px 18px 14px; overflow-y: auto; }
.hist__cols { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.hist__col { min-width: 0; }
.hist__col[data-then] { --node-accent: var(--color-kumo-brand); }
.hist__col-title { display: flex; align-items: center; gap: 6px; margin: 0 0 8px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-color-kumo-subtle); }
.hist__outs { display: flex; flex-direction: column; gap: 8px; }
.hist__out .node-output { margin: 0; }
.hist__out .node-output img, .hist__out .node-output video { width: 100%; max-height: 300px; object-fit: contain; border-radius: 8px; background: var(--color-kumo-recessed); }
.hist__out .node-output__text { max-height: 140px; }
.hist__out-cap { margin-top: 3px; font-size: 11px; color: var(--text-color-kumo-subtle); }
.hist__none { padding: 24px 12px; border-radius: 10px; border: 1px dashed var(--color-kumo-line); font-size: 12px; text-align: center; color: var(--text-color-kumo-subtle); }
.hist__diff { padding-top: 12px; border-top: 1px solid var(--color-kumo-hairline); }
.hist__table { width: 100%; border-collapse: collapse; font-size: 12px; }
.hist__table th { display: flex; flex-direction: column; gap: 1px; width: 180px; padding: 5px 8px 5px 0; text-align: left; font-weight: 500; color: var(--text-color-kumo-strong); }
.hist__table th em { font-style: normal; font-size: 10.5px; color: var(--text-color-kumo-subtle); }
.hist__table td { max-width: 0; padding: 5px 8px; vertical-align: top; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-family: var(--font-mono); font-size: 11.5px; color: var(--text-color-kumo-default); }
.hist__table td[data-then] { color: var(--color-kumo-brand); }
.hist__table tr + tr { border-top: 1px solid var(--color-kumo-hairline); }
.hist__hint { margin: 6px 0 0; font-size: 11px; color: var(--text-color-kumo-subtle); }
.hist__foot { display: flex; align-items: center; gap: 12px; margin-top: auto; padding-top: 12px; border-top: 1px solid var(--color-kumo-hairline); }
.hist__grid-wrap { overflow: auto; }
.hist__grid { display: grid; gap: 8px; align-items: stretch; }
.hist__row-label { display: flex; align-items: center; padding: 4px 6px; font-size: 11.5px; line-height: 1.35; color: var(--text-color-kumo-default); overflow: hidden; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; }
.hist__cell { position: relative; display: flex; flex-direction: column; aspect-ratio: 1; border-radius: 10px; overflow: hidden; background: var(--color-kumo-recessed); box-shadow: 0 0 0 1px var(--color-kumo-hairline); transition: transform 120ms var(--ease-soft), box-shadow 120ms var(--ease-soft); }
.hist__cell:not(:disabled):hover { transform: translateY(-1px); box-shadow: 0 0 0 2px var(--color-kumo-brand); }
.hist__cell:disabled { cursor: default; opacity: 0.7; }
.hist__cell img { width: 100%; height: 100%; object-fit: cover; }
.hist__cell-empty { margin: auto; font-size: 11px; color: var(--text-color-kumo-placeholder); }
.hist__cell[data-status="error"] .hist__cell-empty { color: var(--color-kumo-danger); }
.hist__cell-cap { position: absolute; left: 0; right: 0; bottom: 0; padding: 3px 6px; font-size: 10px; font-family: var(--font-mono); color: #fff; background: linear-gradient(transparent, rgb(0 0 0 / 0.55)); text-align: left; }
/* Run strip (phones): under the top bar while a run is active. */
.run-strip {
position: relative; z-index: 45; display: flex; flex: none; align-items: center; gap: 8px; width: 100%; padding: 0 14px; overflow: hidden;
font-size: 12.5px; text-align: left; color: var(--text-color-kumo-strong); background: var(--color-kumo-recessed); border-bottom: 1px solid var(--color-kumo-hairline);
}
.run-strip[data-state="done"] { color: var(--color-kumo-success); background: color-mix(in oklab, var(--color-kumo-success) 10%, var(--color-kumo-base)); }
.run-strip[data-state="failed"] { color: var(--color-kumo-danger); background: color-mix(in oklab, var(--color-kumo-danger) 10%, var(--color-kumo-base)); }
.run-strip__main { flex: 1 1 auto; min-width: 0; font-weight: 600; }
.run-strip__meta { display: inline-flex; flex: none; align-items: center; gap: 2px; max-width: 45%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 11.5px; font-variant-numeric: tabular-nums; opacity: 0.8; }
.run-strip__spinner { flex: none; width: 12px; height: 12px; border-radius: 50%; border: 2px solid color-mix(in oklab, var(--color-kumo-brand) 30%, transparent); border-top-color: var(--color-kumo-brand); animation: spin 0.8s linear infinite; }
.run-strip__bar { position: absolute; left: 0; bottom: 0; height: 2px; width: 100%; transform-origin: left; background: var(--color-kumo-brand); transition: transform 400ms var(--ease-soft); }
/* Toast: bottom centre of the work area. */
.toast {
position: absolute; left: 50%; bottom: 16px; z-index: 60; display: flex; align-items: center; gap: 10px; max-width: calc(100% - 24px); padding: 8px 8px 8px 14px; border-radius: 10px;
transform: translateX(-50%); font-size: 12.5px; color: var(--text-color-kumo-strong); background: var(--color-kumo-base);
border: 1px solid var(--color-kumo-hairline); box-shadow: 0 10px 30px -10px rgb(0 0 0 / 0.35);
}
.toast > span { min-width: 0; }
.toast__act { display: inline-flex; flex: none; align-items: center; gap: 4px; height: 26px; padding: 0 10px; border-radius: 7px; font-weight: 600; color: var(--color-kumo-brand); background: color-mix(in oklab, var(--color-kumo-brand) 12%, transparent); }
.toast__act:hover { background: color-mix(in oklab, var(--color-kumo-brand) 18%, transparent); }
.toast__close { display: grid; flex: none; place-items: center; width: 26px; height: 26px; border-radius: 7px; color: var(--text-color-kumo-subtle); }
.toast__close:hover { background: var(--color-kumo-fill); color: var(--text-color-kumo-strong); }
/* Results sheet (phones). */
.m-results { height: 100%; overflow-y: auto; padding: 12px 12px calc(24px + env(safe-area-inset-bottom)); }
.m-results__empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; height: 100%; padding: 24px; text-align: center; }
.m-result { margin-bottom: 18px; }
.m-result__title { margin: 0 2px 8px; font-size: 14px; font-weight: 600; color: var(--text-color-kumo-strong); }
.m-result__label { margin: 8px 2px 4px; font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-color-kumo-subtle); }
.m-result__port { margin-bottom: 10px; }
.m-result .node-output { margin: 0; }
.m-result .node-output img, .m-result .node-output video { width: 100%; max-height: 70vh; object-fit: contain; border-radius: 10px; }
.m-result .node-output audio { width: 100%; }
.m-result .node-output__text { max-height: 40vh; font-size: 13px; }
.m-result .node-output__grid { grid-template-columns: repeat(2, 1fr); gap: 6px; }
.m-result__actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
/* Pipeline pull-to-refresh + page dots (phones). */
.pipe__ptr {
position: absolute; top: 0; left: 50%; z-index: 5; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%;
color: var(--text-color-kumo-subtle); background: var(--color-kumo-base); border: 1px solid var(--color-kumo-hairline); box-shadow: 0 4px 14px -6px rgb(0 0 0 / 0.3); pointer-events: none;
}
.pipe__ptr[data-armed] { color: var(--color-kumo-brand); }
.pipe__dots { position: absolute; left: 0; right: 0; bottom: 10px; z-index: 5; display: flex; justify-content: center; gap: 6px; padding: 6px; pointer-events: none; }
.pipe__dot { width: 7px; height: 7px; padding: 0; border-radius: 50%; background: color-mix(in oklab, var(--text-color-kumo-subtle) 40%, transparent); transition: transform 160ms var(--ease-soft), background 160ms var(--ease-soft); pointer-events: auto; }
.pipe__dot[data-active] { background: var(--color-kumo-brand); transform: scale(1.3); }
.canvas-tip {
display: flex; align-items: center; gap: 8px; max-width: 520px; padding: 7px 8px 7px 12px; border-radius: 10px; font-size: 12px; line-height: 1.4;
color: var(--text-color-kumo-default); background: color-mix(in oklab, var(--color-kumo-base) 92%, transparent); backdrop-filter: blur(8px);
border: 1px solid var(--color-kumo-hairline); box-shadow: 0 6px 24px -10px rgb(0 0 0 / 0.3);
}
.canvas-tip > svg { flex: none; color: var(--color-kumo-warning); }
.canvas-tip button { flex: none; height: 22px; padding: 0 8px; border-radius: 6px; font-weight: 500; color: var(--text-color-kumo-strong); background: var(--color-kumo-fill); }
.canvas-tip button:hover { background: var(--color-kumo-tint); }
/* Node explorer ------------------------------------------------------- */
.explorer__backdrop { position: fixed; inset: 0; z-index: 60; display: grid; place-items: start center; padding: 7vh 16px 16px; background: color-mix(in srgb, var(--color-kumo-base) 55%, transparent); backdrop-filter: blur(6px); }
.explorer { display: flex; flex-direction: column; width: min(960px, 100%); height: min(640px, 84vh); overflow: hidden; border: 1px solid var(--color-kumo-line); border-radius: 14px; background: var(--color-kumo-base); box-shadow: 0 24px 80px -20px rgb(0 0 0 / 0.5), 0 0 0 1px rgb(0 0 0 / 0.04); }
.explorer__head { display: flex; flex: none; align-items: center; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--color-kumo-hairline); }
.explorer__search { display: flex; flex: 1; align-items: center; gap: 8px; height: 36px; padding: 0 8px 0 12px; border-radius: 9px; background: var(--color-kumo-recessed); border: 1px solid var(--color-kumo-hairline); color: var(--text-color-kumo-subtle); transition: border-color 0.12s; }
.explorer__search:focus-within { border-color: var(--color-kumo-brand); }
.explorer__search input { flex: 1; min-width: 0; background: none; border: 0; outline: 0; font-size: 13.5px; color: var(--text-color-kumo-strong); }
.explorer__search input::placeholder { color: var(--text-color-kumo-placeholder); }
.explorer__icon-btn { display: grid; place-items: center; width: 26px; height: 26px; flex: none; border-radius: 7px; color: var(--text-color-kumo-subtle); }
.explorer__icon-btn:hover { background: var(--color-kumo-fill); color: var(--text-color-kumo-strong); }
.explorer__panes { display: grid; flex: 1; min-height: 0; grid-template-columns: 280px 1fr; }
.explorer__left { min-height: 0; overflow-y: auto; padding: 6px 8px 12px; border-right: 1px solid var(--color-kumo-hairline); background: var(--color-kumo-recessed); }
.explorer__right { min-height: 0; overflow-y: auto; padding: 6px 14px 14px; }
@media (max-width: 640px) { .explorer__panes { grid-template-columns: 1fr; grid-template-rows: auto 1fr; } .explorer__left { max-height: 40%; border-right: 0; border-bottom: 1px solid var(--color-kumo-hairline); } }
.explorer__label { display: flex; align-items: center; gap: 6px; margin: 10px 4px 5px; font-size: 10.5px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-color-kumo-subtle); }
.explorer__hint { margin: 4px 4px; font-size: 11.5px; line-height: 1.45; color: var(--text-color-kumo-placeholder); }
.explorer__chips { display: flex; flex-wrap: wrap; gap: 4px; padding: 0 4px; }
.explorer__chip { display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 8px 0 7px; border-radius: 999px; border: 1px solid var(--color-kumo-hairline); background: var(--color-kumo-base); font-size: 11.5px; color: var(--text-color-kumo-default); transition: border-color 0.12s, background 0.12s; }
.explorer__chip:hover, .explorer__chip:focus-visible { border-color: var(--chip-accent); background: var(--color-kumo-tint); color: var(--text-color-kumo-strong); outline: none; }
.explorer__chip-dot { width: 7px; height: 7px; flex: none; border-radius: 999px; background: var(--chip-accent); }
.explorer__row { display: flex; align-items: center; gap: 7px; width: 100%; height: 28px; padding: 0 6px 0 8px; border-radius: 7px; font-size: 12.5px; text-align: left; color: var(--text-color-kumo-default); transition: background 0.12s; }
.explorer__row[data-nested] { padding-left: 26px; font-size: 12px; }
.explorer__row:hover, .explorer__row:focus-visible { background: var(--color-kumo-tint); color: var(--text-color-kumo-strong); outline: none; }
.explorer__space { margin-top: 2px; border-radius: 8px; }
.explorer__space[data-fresh] { background: color-mix(in srgb, var(--color-kumo-brand) 10%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-kumo-brand) 40%, transparent); }
.explorer__space-head { display: flex; align-items: center; gap: 6px; height: 26px; padding: 0 8px; font-size: 12px; font-weight: 600; color: var(--text-color-kumo-strong); }
.explorer__fresh { margin-left: auto; font-size: 10px; font-weight: 500; color: var(--color-kumo-brand); white-space: nowrap; }
.explorer__ports { display: flex; gap: 3px; margin-left: auto; flex: none; }
.explorer__ports > i { display: block; width: 6px; height: 6px; border-radius: 999px; background: var(--port-color); }
.explorer__pin { display: grid; place-items: center; width: 20px; height: 20px; flex: none; border-radius: 5px; color: var(--text-color-kumo-placeholder); opacity: 0; transition: opacity 0.12s; }
.explorer__pin:hover { background: var(--color-kumo-fill); color: var(--text-color-kumo-strong); }
.explorer__pin[data-active] { opacity: 1; color: var(--color-kumo-brand); }
.explorer__row:hover .explorer__pin, .explorer__row:focus-visible .explorer__pin { opacity: 1; }
.explorer__emoji { width: 16px; flex: none; text-align: center; font-size: 13px; line-height: 1; }
.explorer__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 8px; }
.explorer__card { position: relative; display: flex; flex-direction: column; gap: 3px; min-width: 0; padding: 10px 12px; overflow: hidden; text-align: left; border: 1px solid var(--color-kumo-hairline); border-radius: 10px; background: var(--color-kumo-base); transition: border-color 0.12s, background 0.12s; }
.explorer__card::before { content: ""; position: absolute; inset: 0; background: var(--card-gradient); opacity: 0.16; pointer-events: none; transition: opacity 0.12s; }
.explorer__card:hover::before, .explorer__card:focus-visible::before { opacity: 0.26; }
.explorer__card > * { position: relative; }
.explorer__card-emoji { display: grid; place-items: center; width: 28px; height: 28px; flex: none; border-radius: 8px; background: var(--card-gradient); font-size: 15px; line-height: 1; box-shadow: 0 1px 2px rgb(0 0 0 / 0.25); }
.explorer__card:hover, .explorer__card:focus-visible { border-color: var(--color-kumo-brand); background: var(--color-kumo-tint); outline: none; }
.explorer__card:disabled { opacity: 0.5; }
.explorer__card[data-usable="false"] { opacity: 0.6; }
.explorer__card-top { display: flex; align-items: center; gap: 7px; min-width: 0; }
.explorer__card-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 600; color: var(--text-color-kumo-strong); }
.explorer__card-id { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--font-mono); font-size: 10.5px; color: var(--text-color-kumo-subtle); }
.explorer__desc { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; margin-top: 2px; font-size: 11.5px; line-height: 1.4; color: var(--text-color-kumo-default); }
.explorer__meta { display: flex; align-items: center; gap: 6px; margin-top: 5px; font-size: 10.5px; color: var(--text-color-kumo-subtle); }
.explorer__add { margin-left: auto; padding: 2px 9px; border-radius: 999px; background: var(--color-kumo-brand); color: var(--accent-ink); font-size: 10.5px; font-weight: 600; opacity: 0; transition: opacity 0.12s; }
.explorer__card:hover .explorer__add, .explorer__card:focus-visible .explorer__add { opacity: 1; }
.explorer__likes { flex: none; font-size: 10.5px; color: var(--text-color-kumo-subtle); font-variant-numeric: tabular-nums; }
.explorer__foot { display: flex; flex: none; gap: 14px; padding: 7px 14px; border-top: 1px solid var(--color-kumo-hairline); font-size: 11px; color: var(--text-color-kumo-subtle); }
.explorer__foot > span { display: inline-flex; align-items: center; gap: 5px; }
.explorer__tabs { display: flex; flex: none; gap: 4px; padding: 0 10px 8px; }
.explorer__tab { display: inline-flex; flex: 1; align-items: center; justify-content: center; gap: 6px; height: 34px; border-radius: 9px; background: var(--color-kumo-recessed); font-size: 13px; font-weight: 500; color: var(--text-color-kumo-subtle); transition: background 0.12s, color 0.12s; }
.explorer__tab[data-active] { background: color-mix(in srgb, var(--color-kumo-brand) 14%, transparent); color: var(--text-color-kumo-strong); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-kumo-brand) 40%, transparent); }
.explorer__switch { display: block; width: 100%; margin-top: 8px; height: 40px; border-radius: 10px; background: var(--color-kumo-brand); color: var(--accent-ink); font-size: 13.5px; font-weight: 600; }
/* Workflow sidebar ----------------------------------------------------- */
.wf-h { display: flex; align-items: center; gap: 6px; margin: 16px 12px 6px; font-size: 10.5px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-color-kumo-subtle); }
.wf-h__count { padding: 0 5px; border-radius: 999px; background: var(--color-kumo-fill); font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0; }
.wf-hint { margin: 4px 12px 0; font-size: 11px; line-height: 1.45; color: var(--text-color-kumo-placeholder); }
.dock { display: flex; flex-wrap: wrap; gap: 5px; padding: 0 12px; }
.dock-chip { display: inline-flex; align-items: center; gap: 5px; max-width: 100%; height: 26px; padding: 0 9px 0 7px; border-radius: 999px; border: 1px solid var(--color-kumo-hairline); background: var(--color-kumo-recessed); font-size: 12px; color: var(--text-color-kumo-default); cursor: grab; transition: border-color 0.12s, background 0.12s, transform 0.12s; }
.dock-chip:hover { border-color: var(--chip-accent); background: var(--color-kumo-tint); color: var(--text-color-kumo-strong); }
.dock-chip:active { cursor: grabbing; transform: scale(0.97); }
.dock-chip__swatch { width: 8px; height: 8px; flex: none; border-radius: 999px; background: var(--chip-accent); }
.dock-chip__emoji { font-size: 12px; line-height: 1; }
.dock-chip__pin { flex: none; color: var(--color-kumo-brand); }
.wf-space { margin: 2px 6px 0; border-radius: 8px; transition: background 0.12s; }
.wf-space[data-open] { background: var(--color-kumo-recessed); }
.wf-space__row { display: flex; align-items: center; gap: 6px; padding: 6px 6px 6px 4px; border-radius: 8px; cursor: pointer; user-select: none; }
.wf-space__row:hover { background: var(--color-kumo-tint); }
.wf-space__toggle { display: grid; place-items: center; width: 18px; height: 18px; flex: none; border-radius: 4px; color: var(--text-color-kumo-subtle); }
.wf-space__toggle:hover { background: var(--color-kumo-fill); color: var(--text-color-kumo-strong); }
.wf-space__emoji { width: 16px; flex: none; text-align: center; font-size: 14px; line-height: 1; }
.wf-space__title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; font-weight: 500; color: var(--text-color-kumo-strong); }
.wf-space__meta { display: flex; align-items: center; gap: 5px; overflow: hidden; white-space: nowrap; font-size: 10.5px; color: var(--text-color-kumo-subtle); }
.wf-space__meta [data-bad] { color: var(--color-kumo-warning); }
.wf-space__endpoints { padding: 0 4px 6px 14px; }
.wf-outline { display: flex; flex-direction: column; gap: 1px; padding: 0 6px; }
.wf-node { display: flex; align-items: center; gap: 7px; width: 100%; height: 28px; padding-right: 8px; border-radius: 7px; font-size: 12px; text-align: left; color: var(--text-color-kumo-default); transition: background 0.12s; }
.wf-node:hover { background: var(--color-kumo-tint); color: var(--text-color-kumo-strong); }
.wf-node[data-selected] { background: color-mix(in srgb, var(--color-kumo-brand) 12%, transparent); color: var(--text-color-kumo-strong); }
.wf-node[data-mode] { opacity: 0.55; }
.wf-node__status { display: grid; place-items: center; width: 14px; flex: none; color: var(--text-color-kumo-placeholder); }
.wf-node[data-status="queued"] .wf-node__status { color: var(--text-color-kumo-subtle); }
.wf-node[data-status="running"] .wf-node__status { color: var(--color-kumo-brand); }
.wf-node[data-status="done"] .wf-node__status { color: var(--color-kumo-success); }
.wf-node[data-status="error"] .wf-node__status { color: var(--color-kumo-danger); }
.wf-node__dot { width: 6px; height: 6px; border-radius: 999px; background: currentColor; }
.wf-node[data-status="queued"] .wf-node__dot { animation: pulse-dot 1.2s ease-in-out infinite; }
.wf-node__emoji { width: 14px; flex: none; text-align: center; font-size: 12px; line-height: 1; }
.wf-node__swatch { width: 8px; height: 8px; flex: none; margin: 0 3px; border-radius: 2px; }
.wf-node__meta { margin-left: auto; flex: none; font-family: var(--font-mono); font-size: 10px; color: var(--text-color-kumo-subtle); }
.wf-node[data-status="error"] .wf-node__meta { color: var(--color-kumo-danger); }
.wf-node__jump { flex: none; color: var(--text-color-kumo-placeholder); opacity: 0; transition: opacity 0.12s; }
.wf-node:hover .wf-node__jump { opacity: 1; }
.wf-node__error { margin: 0 6px 4px 0; padding: 4px 8px 4px 22px; border-radius: 6px; font-size: 11px; line-height: 1.4; color: var(--color-kumo-danger); background: color-mix(in srgb, var(--color-kumo-danger) 8%, transparent); cursor: pointer; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.dock-chip[data-dim] { opacity: 0.5; }
.dock-chip--ghost { border-style: dashed; color: var(--text-color-kumo-subtle); cursor: pointer; }
/* Node colour tags, notes, locks ------------------------------------ */
.canvas-node[data-color] {
--node-accent: var(--node-tint);
}
.canvas-node[data-color] .canvas-node__header {
background: color-mix(in srgb, var(--node-tint) 22%, var(--color-kumo-tint));
}
.canvas-node[data-color]:not([data-selected="true"]) {
--node-ring: color-mix(in srgb, var(--node-tint) 45%, var(--color-kumo-line));
}
.canvas-node__note {
margin: 0 0 6px;
padding: 6px 8px;
border-radius: 6px;
background: color-mix(in srgb, var(--color-kumo-warning) 12%, transparent);
border-left: 2px solid color-mix(in srgb, var(--color-kumo-warning) 60%, transparent);
color: var(--text-color-kumo-default);
font-size: 11px;
line-height: 1.4;
white-space: pre-wrap;
word-break: break-word;
}
.canvas-node[data-locked] .canvas-node__header {
cursor: default;
}
.ctx-menu__row {
display: flex;
align-items: center;
gap: 6px;
padding: 6px 10px;
}
.ctx-swatch {
width: 16px;
height: 16px;
border-radius: 999px;
background: var(--swatch);
box-shadow: 0 0 0 1px color-mix(in srgb, var(--swatch) 40%, transparent);
cursor: pointer;
transition: transform 120ms var(--ease-soft);
}
.ctx-swatch:hover {
transform: scale(1.18);
}
.ctx-swatch[data-active="true"] {
box-shadow: 0 0 0 2px var(--color-kumo-base), 0 0 0 3.5px var(--swatch);
}
.ctx-swatch--none {
background: transparent;
box-shadow: inset 0 0 0 1.5px var(--color-kumo-line);
position: relative;
}
.ctx-swatch--none::after {
content: "";
position: absolute;
left: 3px;
right: 3px;
top: 50%;
height: 1.5px;
background: var(--color-kumo-line);
transform: rotate(-45deg);
}
/* Find bar ----------------------------------------------------------- */
.findbar {
display: flex;
align-items: center;
gap: 8px;
height: 36px;
padding: 0 6px 0 10px;
border-radius: 10px;
background: var(--color-kumo-base);
box-shadow: 0 0 0 1px var(--color-kumo-line), 0 8px 24px -8px rgb(0 0 0 / 0.35);
width: min(360px, calc(100vw - 32px));
}
.findbar input {
flex: 1;
min-width: 0;
background: transparent;
border: 0;
outline: 0;
font-size: 13px;
color: var(--text-color-kumo-strong);
}
.findbar input::placeholder {
color: var(--text-color-kumo-placeholder);
}
.findbar__count {
flex: none;
font-family: var(--font-mono);
font-size: 10.5px;
color: var(--text-color-kumo-subtle);
white-space: nowrap;
}
.findbar__btn {
flex: none;
display: grid;
place-items: center;
width: 24px;
height: 24px;
border-radius: 6px;
color: var(--text-color-kumo-subtle);
}
.findbar__btn:hover {
background: var(--color-kumo-fill);
color: var(--text-color-kumo-strong);
}
.canvas-node[data-found="true"] {
--node-ring: var(--color-kumo-warning);
--node-ring-width: 2px;
}
/* Keyboard-focused widget values ------------------------------------- */
.widget__value:focus-visible {
outline: 0;
box-shadow: 0 0 0 1.5px var(--color-kumo-brand);
border-radius: 4px;
}
/* Run history outputs ------------------------------------------------ */
.hist-outs {
display: flex;
flex-wrap: wrap;
gap: 4px;
margin-top: 6px;
}
.hist-outs__img {
width: 44px;
height: 44px;
border-radius: 6px;
object-fit: cover;
background: var(--color-kumo-recessed);
box-shadow: 0 0 0 1px var(--color-kumo-hairline);
}
.hist-outs__text {
flex: 1 1 100%;
font-size: 11px;
line-height: 1.4;
color: var(--text-color-kumo-default);
background: var(--color-kumo-recessed);
border-radius: 6px;
padding: 5px 7px;
max-height: 64px;
overflow: hidden;
white-space: pre-wrap;
word-break: break-word;
}
.explorer__more { display: grid; place-items: center; height: 40px; color: var(--text-color-kumo-subtle); }
/* ZeroGPU quota (user menu) ------------------------------------------- */
.quota {
--quota-color: var(--color-kumo-success);
display: flex;
flex-direction: column;
gap: 6px;
margin: 2px 4px 6px;
padding: 8px 10px 9px;
border-radius: 8px;
background: var(--color-kumo-recessed);
font-size: 11.5px;
color: var(--text-color-kumo-default);
}
.quota[data-level="low"] { --quota-color: var(--color-kumo-warning); }
.quota[data-level="empty"] { --quota-color: var(--color-kumo-danger); }
.quota[data-loading] .quota__bar { opacity: 0.6; }
.quota__head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.quota__head b { font-weight: 500; font-family: var(--font-mono); font-size: 11px; color: var(--text-color-kumo-strong); }
.quota__bar {
position: relative;
height: 5px;
border-radius: 999px;
overflow: hidden;
background: var(--color-kumo-fill);
}
.quota__bar i,
.quota-strip i {
position: absolute;
inset: 0;
transform-origin: left;
background: var(--quota-color);
border-radius: inherit;
transition: transform 300ms var(--ease-soft);
}
.quota__meta { display: flex; justify-content: space-between; gap: 12px; font-size: 11px; color: var(--text-color-kumo-subtle); }
.quota__meta b { font-weight: 500; color: var(--text-color-kumo-default); }
.quota__meta--warn, .quota__meta--warn b { color: var(--color-kumo-warning); }
.quota__refresh { color: var(--text-color-kumo-subtle); text-decoration: underline dotted; text-underline-offset: 2px; cursor: pointer; }
.quota__refresh:hover { color: var(--text-color-kumo-strong); }
.quota__refresh:disabled { opacity: 0.5; cursor: default; }
.quota__note { font-size: 11px; line-height: 1.4; color: var(--quota-color); }
.quota__sub { display: flex; flex-direction: column; gap: 5px; margin-top: 2px; padding-top: 6px; border-top: 1px solid var(--color-kumo-line); }
.quota__toggle { width: 100%; cursor: pointer; text-align: left; }
.quota__toggle:hover { color: var(--text-color-kumo-strong); }
.quota__sub-body { display: flex; flex-direction: column; gap: 5px; padding-left: 13px; }
.quota__bar--neutral { --quota-color: var(--color-kumo-brand); height: 4px; }
/* Same quota as a 2px strip along the bottom of the user button. */
.quota-strip {
--quota-color: var(--color-kumo-success);
position: absolute;
left: 6px;
right: 6px;
bottom: 0;
height: 2px;
border-radius: 999px;
overflow: hidden;
background: var(--color-kumo-fill);
pointer-events: none;
}
.quota-strip[data-level="low"] { --quota-color: var(--color-kumo-warning); }
.quota-strip[data-level="empty"] { --quota-color: var(--color-kumo-danger); }
/* Same quota as a ring around the avatar (phones only). */
.quota-ring { position: relative; display: grid; place-items: center; flex: none; --quota-color: var(--color-kumo-success); }
.quota-ring[data-level="low"] { --quota-color: var(--color-kumo-warning); }
.quota-ring[data-level="empty"] { --quota-color: var(--color-kumo-danger); }
.quota-ring::before {
content: "";
display: none;
position: absolute;
inset: -3px;
border-radius: 50%;
background: conic-gradient(var(--quota-color) calc(var(--frac, 0) * 360deg), var(--color-kumo-fill) 0);
mask: radial-gradient(farthest-side, transparent calc(100% - 2.5px), #000 calc(100% - 2px));
-webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2.5px), #000 calc(100% - 2px));
pointer-events: none;
}
.quota-ring:not([data-level])::before { display: none !important; }
/* Phones ------------------------------------------------------------- */
/* Panels become full-height sheets, a bottom bar replaces the side toggles
and the view switch, and the pipeline view is the default. */
.m-bar {
position: relative;
z-index: 50;
display: flex;
flex: none;
align-items: stretch;
height: calc(56px + env(safe-area-inset-bottom));
padding: 0 4px env(safe-area-inset-bottom);
background: var(--color-kumo-base);
border-top: 1px solid var(--color-kumo-hairline);
}
.m-bar__btn {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 3px;
min-width: 0;
font-size: 10.5px;
font-weight: 500;
color: var(--text-color-kumo-subtle);
-webkit-tap-highlight-color: transparent;
}
.m-bar__btn[data-active] { color: var(--color-kumo-brand); }
.m-bar__btn:active { color: var(--text-color-kumo-strong); }
.m-bar__add {
display: grid;
place-items: center;
width: 40px;
height: 30px;
border-radius: 10px;
background: var(--color-kumo-brand);
color: var(--accent-ink);
}
.m-bar__btn--add { gap: 2px; }
.m-bar__dot {
position: absolute;
top: -1px;
right: -3px;
width: 7px;
height: 7px;
border-radius: 999px;
background: var(--color-kumo-brand);
box-shadow: 0 0 0 2px var(--color-kumo-base);
}
.m-sheet {
position: absolute;
inset: 0;
z-index: 40;
display: flex;
flex-direction: column;
background: var(--color-kumo-base);
}
.m-sheet__head {
display: flex;
flex: none;
align-items: center;
justify-content: space-between;
gap: 8px;
height: 42px;
padding: 0 8px 0 14px;
border-bottom: 1px solid var(--color-kumo-hairline);
font-size: 13px;
font-weight: 600;
color: var(--text-color-kumo-strong);
}
.m-sheet__close {
display: grid;
place-items: center;
width: 30px;
height: 30px;
border-radius: 8px;
color: var(--text-color-kumo-subtle);
}
.m-sheet__close:active { background: var(--color-kumo-fill); }
.m-fab {
display: grid;
place-items: center;
width: 44px;
height: 44px;
border-radius: 14px;
background: var(--color-kumo-base);
color: var(--text-color-kumo-strong);
box-shadow:
0 0 0 1px var(--color-kumo-line),
0 8px 24px -8px rgb(0 0 0 / 0.5);
}
/* Narrow desktops: avatar-only user button (quota as a ring) and an icon-only view switch. */
@media (max-width: 1023px) {
.quota-strip { display: none; }
.quota-ring::before { display: block; }
.view-switch__btn > span:last-child { display: none; }
.view-switch__btn { padding-inline: 8px; }
}
@media (max-width: 767px) {
.view-switch { display: none; }
html, body, #root { height: 100dvh; }
/* Pipeline: every top-level step is a page. The whole pipeline scrolls vertically as one; the row of
pages slides sideways under JS control (touch-action keeps the browser out of the horizontal axis). */
.pipe { padding: 12px 0 96px; overflow-x: hidden; }
.pipe__col { width: 100%; min-height: 0; }
.pipe__pages > .pipe__list { display: flex; align-items: flex-start; touch-action: pan-y; will-change: transform; transform: translateX(calc(var(--page, 0) * -100%)); transition: transform 320ms cubic-bezier(0.16, 1, 0.3, 1); }
.pipe__pages > .pipe__list > .pipe-item { flex: 0 0 100%; width: 100%; padding: 0 12px; }
.pipe__pages > .pipe__list > .pipe-item[data-inactive] { max-height: calc(100dvh - 140px); overflow: hidden; }
.pipe__pages > .pipe__list > .pipe-insert, .pipe__pages > .pipe__list > .pipe-item > .pipe-insert { display: none; }
.pipe__empty { margin: 0 12px; }
.pipe-group__body-inner .pipe-insert { height: 14px; }
/* Input rows: an unlinked widget gets the full width; its source picker shrinks to a plug button,
and disappears when nothing above could feed it. */
.pipe-input__head > .min-w-0 > .widget { margin: 0 2px; }
.pipe-input__src[data-compact] { flex: none; width: 30px; justify-content: center; padding: 0; margin-top: 2px; }
.pipe-input__src[data-compact] .pipe-input__src-label,
.pipe-input__src[data-compact] .pipe-input__src-caret { display: none; }
.pipe-input__src[data-compact] .pipe-input__src-icon { display: block; }
.pipe-input__src[data-none] { display: none; }
.pipe-input__name { width: 84px; }
/* Node explorer: a full-screen sheet with a big search box, one pane at a time (tabs), one scroll region. */
.explorer__backdrop { padding: 0; place-items: stretch; backdrop-filter: none; }
.explorer { width: 100%; max-width: none; height: 100%; max-height: none; border: 0; border-radius: 0; box-shadow: none; }
.explorer__head { padding: calc(8px + env(safe-area-inset-top)) 10px 8px; gap: 6px; border-bottom: 0; }
.explorer__search { height: 42px; padding-left: 12px; border-radius: 12px; }
.explorer__search input { font-size: 16px; }
.explorer__icon-btn { width: 36px; height: 36px; border-radius: 10px; }
.explorer__panes { display: block; border-top: 1px solid var(--color-kumo-hairline); }
.explorer__left, .explorer__right { height: 100%; max-height: none; border: 0; padding: 4px 10px calc(20px + env(safe-area-inset-bottom)); background: transparent; }
.explorer__label { margin: 14px 2px 7px; }
.explorer__hint { margin: 6px 2px; font-size: 13px; }
.explorer__chips { gap: 6px; padding: 0; }
.explorer__chip { height: 34px; padding: 0 12px 0 10px; font-size: 13px; }
.explorer__row { height: 44px; padding-right: 2px; border-radius: 10px; font-size: 14px; }
.explorer__row[data-nested] { padding-left: 30px; font-size: 13.5px; }
.explorer__space { margin-top: 4px; }
.explorer__space-head { height: 36px; font-size: 13.5px; }
.explorer__pin { width: 34px; height: 34px; opacity: 1; }
.explorer__grid { grid-template-columns: 1fr; gap: 8px; }
.explorer__card { gap: 4px; padding: 12px 14px; border-radius: 12px; }
.explorer__card-title { font-size: 14px; }
.explorer__desc { font-size: 12.5px; }
.explorer__meta { margin-top: 7px; font-size: 11px; }
.explorer__add { opacity: 1; padding: 4px 12px; font-size: 11.5px; }
.explorer__foot { display: none; }
.copilot--side .copilot__list { padding: 10px 12px 6px; }
.quota { margin: 2px 2px 6px; }
.hist { max-height: calc(100dvh - 20px); }
.hist__body { grid-template-columns: 1fr; grid-template-rows: minmax(0, 38%) minmax(0, 1fr); }
.hist__list { border-right: 0; border-bottom: 1px solid var(--color-kumo-hairline); }
.hist__cols { grid-template-columns: 1fr; }
.hist__table th { width: 120px; }
/* Dialogs fill the width with a small gutter. */
[role="dialog"]:not(.ctx-menu):not(.explorer) {
top: 10px !important;
width: calc(100vw - 20px) !important;
max-width: calc(100vw - 20px) !important;
max-height: calc(100dvh - 20px);
}
.react-flow__panel.bottom.left { margin-bottom: 10px !important; }
}
/* Fingers, not pointers: bigger hit areas, and no hover-only affordances. */
@media (pointer: coarse) {
.canvas-node .react-flow__handle::before { inset: -14px; }
.widget__fold, .pipe-block__icon-btn, .explorer__icon-btn { min-width: 30px; min-height: 30px; }
.pipe-block__grip { padding: 6px; }
.panel-resize { display: none; }
}
/* Cloud sync ------------------------------------------------------------- */
.sync-ind { display: inline-flex; height: 28px; width: 28px; flex: none; align-items: center; justify-content: center; border-radius: 6px; transition: background-color 120ms; }
.sync-ind:hover { background: var(--color-kumo-tint); color: var(--text-color-kumo-strong); }
.wfl, .commit { display: flex; flex-direction: column; gap: 12px; padding: 18px 20px 16px; font-size: 13.5px; }
@media (min-width: 640px) { .wfl, .commit { width: min(560px, calc(100vw - 2rem)); } }
.wfl__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.wfl__title { font-size: 18px; font-weight: 600; line-height: 1.25; }
.wfl__lede { margin: -4px 0 0; color: var(--text-color-kumo-subtle); }
.wfl__lede a { color: var(--text-color-kumo-link, inherit); text-decoration: underline; text-underline-offset: 2px; }
.wfl__empty { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; padding: 14px; border: 1px dashed var(--color-kumo-line); border-radius: 8px; color: var(--text-color-kumo-subtle); }
.wfl__empty p { margin: 0; }
.wfl__warn, .commit__ok { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 10px; border-radius: 8px; background: var(--color-kumo-recessed); font-size: 13px; }
.wfl__warn { color: var(--text-color-kumo-warning, inherit); }
.wfl__list { display: flex; flex-direction: column; max-height: min(420px, calc(100dvh - 260px)); overflow: auto; margin: 0; padding: 0; list-style: none; border: 1px solid var(--color-kumo-hairline); border-radius: 8px; }
.wfl__list li { display: flex; align-items: center; gap: 8px; min-height: 48px; padding: 4px 6px 4px 4px; border-bottom: 1px solid var(--color-kumo-hairline); }
.wfl__list li:last-child { border-bottom: 0; }
.wfl__list li[data-current] { box-shadow: inset 3px 0 0 var(--hf-yellow); }
.wfl__open { display: flex; min-width: 0; flex: 1; flex-direction: column; align-items: flex-start; gap: 1px; padding: 5px 8px; border-radius: 6px; text-align: left; }
.wfl__open:hover { background: var(--color-kumo-tint); }
.wfl__name { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; color: var(--text-color-kumo-strong); }
.wfl__meta { font-size: 12px; color: var(--text-color-kumo-subtle); }
.wfl__input { flex: 1; height: 30px; margin: 4px; padding: 0 8px; border-radius: 6px; background: var(--color-kumo-control); color: var(--text-color-kumo-strong); font: inherit; font-weight: 600; outline: none; box-shadow: 0 0 0 1.5px var(--color-kumo-brand); }
.wfl__actions { display: flex; flex: none; align-items: center; gap: 2px; }
.wfl__ask { margin-right: 4px; font-size: 12.5px; color: var(--text-color-kumo-subtle); }
.wfl .precheck__foot, .commit .precheck__foot { align-items: center; padding-top: 0; }
.commit__form { display: flex; flex-direction: column; gap: 10px; }
.commit__row { display: grid; grid-template-columns: 130px 1fr; gap: 8px; align-items: end; }
.commit__repo { min-width: 0; }
.commit__hint { margin: -4px 0 0; font-size: 12px; color: var(--text-color-kumo-subtle); }
.commit__link { display: inline-flex; flex: none; align-items: center; gap: 4px; font-weight: 600; color: var(--text-color-kumo-link, inherit); }
.commit__busy { margin-right: auto; font-size: 12.5px; color: var(--text-color-kumo-subtle); }
.commit__open { margin-right: auto; font-size: 12.5px; color: var(--text-color-kumo-link, inherit); text-decoration: underline; text-underline-offset: 2px; }
.commit__busy + .commit__open { margin-right: 0; }
@media (max-width: 639px) { .commit__row { grid-template-columns: 1fr; } }
.sync-ind[data-problem] { width: auto; gap: 5px; padding: 0 8px; font-size: 12px; font-weight: 600; white-space: nowrap; }
.sync-ind__label { line-height: 1; }
@media (max-width: 640px) { .sync-ind__label { display: none; } .sync-ind[data-problem] { width: 28px; padding: 0; } }
.expired { display: flex; align-items: center; gap: 10px; padding: 6px 12px; background: var(--color-kumo-recessed); color: var(--text-color-kumo-default); font-size: 13px; border-bottom: 1px solid var(--color-kumo-line); }
.expired > svg { color: var(--text-color-kumo-danger, #d33); }
.expired__text { flex: 1; min-width: 0; }
.expired__actions { display: flex; flex: none; gap: 6px; }
@media (max-width: 640px) { .expired { flex-wrap: wrap; } .expired__actions { width: 100%; justify-content: flex-end; } }
/* Sign-in gate: the only thing shown until the account's storage is open. */
.gate { display: flex; min-height: 100%; align-items: center; justify-content: center; padding: 24px 16px; background: var(--color-kumo-canvas); color: var(--text-color-kumo-default); }
.gate__card { display: flex; width: 100%; max-width: 380px; flex-direction: column; align-items: flex-start; gap: 14px; }
.gate__brand { display: flex; align-items: center; gap: 10px; }
.gate__title { margin: 0; font-size: 22px; font-weight: 700; letter-spacing: -0.01em; color: var(--text-color-kumo-strong); }
.gate__lede { margin: 0 0 6px; font-size: 15px; line-height: 1.45; color: var(--text-color-kumo-default); }
.gate__msg { margin: 0; font-size: 14px; line-height: 1.5; }
.gate__msg strong { color: var(--text-color-kumo-strong); }
.gate__loading { display: flex; align-items: center; gap: 8px; color: var(--text-color-kumo-subtle); }
.gate__actions { display: flex; flex-wrap: wrap; gap: 8px; }
.gate__cta { width: 100%; justify-content: center; }
.gate__err { margin: 0; font-size: 13px; line-height: 1.45; color: var(--text-color-kumo-danger, #d33); }
.gate__fine { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--text-color-kumo-subtle); }
.gate__link { padding: 0; border: 0; background: none; color: inherit; font: inherit; text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.gate__link:hover { color: var(--text-color-kumo-strong); }
.welcome__brand { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; font-size: 13px; font-weight: 700; color: var(--text-color-kumo-strong); }
/* Copilot links: user bubble is brand-coloured, so links there use the bubble's ink. */
.copilot__msg--user .md-link { color: inherit; text-decoration-color: color-mix(in oklab, currentColor 45%, transparent); }
.md-media { display: block; margin: 6px 0 2px; max-width: 100%; }
.md-media--image { width: fit-content; border-radius: 6px; overflow: hidden; border: 1px solid var(--color-kumo-line); background: var(--color-kumo-recessed); line-height: 0; }
.md-media--image img { display: block; max-width: 100%; max-height: 220px; object-fit: contain; }
.md-media audio { display: block; width: 100%; max-width: 320px; height: 32px; }
.md-media video { display: block; max-width: 100%; max-height: 240px; border-radius: 6px; background: #000; }
.beta-tag { display: inline-flex; align-items: center; height: 18px; padding: 0 6px; border-radius: 4px; font-size: 10.5px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; line-height: 1; color: #6b4e00; background: #fff4c2; border: 1px solid #f5d76e; cursor: default; }
html[data-mode="dark"] .beta-tag { color: #ffd21e; background: rgba(255, 210, 30, 0.1); border-color: rgba(255, 210, 30, 0.35); }
/* Share dialog */
.share__row { display: flex; align-items: center; gap: 8px; }
.share__title { flex: 1; min-width: 0; }
.share__row > :first-child { flex: 1; min-width: 0; }
.share__link { flex: 1; min-width: 0; height: 32px; padding: 0 10px; border-radius: 6px; border: 1px solid var(--color-kumo-hairline); background: var(--color-kumo-recessed); color: var(--text-color-kumo-strong); font: inherit; font-size: 13px; outline: none; }
.share__link:focus { box-shadow: 0 0 0 1.5px var(--color-kumo-brand); }
.share__made { display: flex; flex-direction: column; gap: 6px; }
.share__mine { display: flex; flex-direction: column; gap: 8px; padding-top: 4px; }
.share__h { margin: 0; font-size: 13px; font-weight: 600; color: var(--text-color-kumo-strong); }
.share__list { max-height: min(260px, calc(100dvh - 380px)); }
.share__by { margin: 0 0 -6px; font-size: 12.5px; font-weight: 600; color: var(--text-color-kumo-subtle); }
.share__note { margin: 0; font-size: 13px; line-height: 1.45; }
.gate__share { padding: 10px 12px; border-radius: 8px; background: var(--color-kumo-recessed); }