@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: ""; 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 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); }