@import "tailwindcss"; /* ────────────────────────────────────────────────────────────────────────── Design tokens. Exposed both as plain CSS variables (for raw `var()` use) and as Tailwind theme keys so utilities like `bg-surface-1`, `text-ink-100`, `border-stroke` work without a separate config file. ────────────────────────────────────────────────────────────────────────── */ @theme { --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display", "Inter", system-ui, sans-serif; --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace; --color-ink-50: #f8fafc; --color-ink-100: #e8eaef; --color-ink-200: #c6cad3; --color-ink-300: #8b94a1; --color-ink-400: #5e6772; --color-ink-500: #3a4049; --color-ink-700: #1c2026; --color-ink-800: #14171d; --color-ink-900: #0a0c11; --color-ink-950: #07090c; --color-surface-1: rgba(255, 255, 255, 0.045); --color-surface-2: rgba(255, 255, 255, 0.075); --color-surface-3: rgba(255, 255, 255, 0.11); --color-stroke: rgba(255, 255, 255, 0.10); --color-stroke-soft: rgba(255, 255, 255, 0.06); --color-accent: #0a84ff; --color-accent-2: #5aa9ff; --color-ok: #30d158; --color-warn: #ffd60a; --color-err: #ff453a; --color-info: #64d2ff; --radius-md: 12px; --radius-lg: 16px; --radius-xl: 22px; --radius-2xl: 28px; --shadow-glass: 0 24px 60px -20px rgba(0, 0, 0, 0.55), 0 8px 24px -12px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.04); --shadow-soft: 0 8px 24px -12px rgba(0, 0, 0, 0.45); --blur-glass: blur(32px) saturate(180%); } /* ────────────────────────────────────────────────────────────────────────── Root + page chrome. The body gradient sits behind every glass card. ────────────────────────────────────────────────────────────────────────── */ :root { color-scheme: dark; } html, body, #app { min-height: 100%; margin: 0; background-color: var(--color-ink-950); color: var(--color-ink-100); font-family: var(--font-sans); font-feature-settings: "ss01", "ss03", "cv11"; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; } body { background: radial-gradient( 120vw 70vh at 88% -12%, rgba(10, 132, 255, 0.18), transparent 60% ), radial-gradient( 90vw 60vh at -10% 110%, rgba(100, 210, 255, 0.10), transparent 60% ), radial-gradient(60vw 40vh at 50% 50%, rgba(20, 24, 36, 0.45), transparent 70%), linear-gradient(180deg, #05070a 0%, #090c12 55%, #050608 100%); background-attachment: fixed; } #app { display: flex; flex-direction: column; } ::selection { background: rgba(10, 132, 255, 0.45); color: #fff; } a { color: var(--color-accent-2); text-decoration: none; transition: color 150ms ease-out; } a:hover { color: #9ec9ff; } /* ────────────────────────────────────────────────────────────────────────── Reusable utility classes layered on top of Tailwind. ────────────────────────────────────────────────────────────────────────── */ .glass { background: var(--color-surface-1); backdrop-filter: var(--blur-glass); -webkit-backdrop-filter: var(--blur-glass); border: 1px solid var(--color-stroke); box-shadow: var(--shadow-glass); } .glass-flat { background: var(--color-surface-1); border: 1px solid var(--color-stroke); } .hairline { border-color: var(--color-stroke-soft); } .tabular { font-variant-numeric: tabular-nums; } .eyebrow { font-size: 10.5px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--color-ink-300); } /* ────────────────────────────────────────────────────────────────────────── Pills — capsule status tags, tabular, hairline outline. Tints are flat (no glow); the only colour is the text + a hairline border. ────────────────────────────────────────────────────────────────────────── */ .pill { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 500; letter-spacing: 0.02em; border: 1px solid var(--color-stroke); background: rgba(255, 255, 255, 0.04); color: var(--color-ink-200); white-space: nowrap; font-variant-numeric: tabular-nums; } .pill.queued { color: #9ec9ff; border-color: rgba(100, 175, 255, 0.32); background: rgba(10, 132, 255, 0.10); } .pill.running { color: #ffe26b; border-color: rgba(255, 214, 10, 0.32); background: rgba(255, 214, 10, 0.08); } .pill.done { color: #7fe5a3; border-color: rgba(48, 209, 88, 0.32); background: rgba(48, 209, 88, 0.08); } .pill.failed { color: #ff8e85; border-color: rgba(255, 69, 58, 0.36); background: rgba(255, 69, 58, 0.08); } .pill.skipped { color: var(--color-ink-300); border-color: rgba(255, 255, 255, 0.10); background: rgba(255, 255, 255, 0.03); } .pill.open { color: #9ec9ff; border-color: rgba(100, 175, 255, 0.32); background: rgba(10, 132, 255, 0.08); } .pill.closed { color: #d8b4ff; border-color: rgba(186, 130, 255, 0.32); background: rgba(186, 130, 255, 0.08); } .pill.dot::before { content: ""; width: 6px; height: 6px; border-radius: 999px; background: currentColor; display: inline-block; } /* Pulsing dot for running pills. */ .pill.running.dot::before { animation: pulse-dot 1.8s ease-in-out infinite; } @keyframes pulse-dot { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.55; transform: scale(0.75); } } /* ────────────────────────────────────────────────────────────────────────── Buttons. ────────────────────────────────────────────────────────────────────────── */ button, .btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; font: inherit; font-weight: 500; padding: 7px 14px; border-radius: 10px; border: 1px solid var(--color-stroke); background: var(--color-surface-1); color: var(--color-ink-100); cursor: pointer; transition: background 150ms ease-out, border-color 150ms ease-out, color 150ms ease-out, transform 80ms ease-out; user-select: none; } button:hover:not(:disabled), .btn:hover:not(:disabled) { background: var(--color-surface-2); border-color: rgba(255, 255, 255, 0.18); } button:active:not(:disabled), .btn:active:not(:disabled) { transform: translateY(1px); } button:disabled, .btn:disabled { opacity: 0.45; cursor: not-allowed; } button.primary, .btn.primary { background: linear-gradient(180deg, #1f95ff 0%, #0a84ff 100%); border-color: rgba(10, 132, 255, 0.7); color: #fff; box-shadow: 0 6px 16px -6px rgba(10, 132, 255, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.18); } button.primary:hover:not(:disabled), .btn.primary:hover:not(:disabled) { background: linear-gradient(180deg, #34a0ff 0%, #1d8eff 100%); } button.ghost, .btn.ghost { background: transparent; border-color: transparent; color: var(--color-ink-300); } button.ghost:hover:not(:disabled), .btn.ghost:hover:not(:disabled) { background: var(--color-surface-1); color: var(--color-ink-100); border-color: var(--color-stroke); } button.danger, .btn.danger { color: #ff8e85; border-color: rgba(255, 69, 58, 0.32); background: rgba(255, 69, 58, 0.08); } button.danger:hover:not(:disabled), .btn.danger:hover:not(:disabled) { background: rgba(255, 69, 58, 0.16); border-color: rgba(255, 69, 58, 0.6); color: #ffb1a8; } button.tiny, .btn.tiny { padding: 3px 9px; font-size: 11.5px; border-radius: 8px; } /* ────────────────────────────────────────────────────────────────────────── Form controls. ────────────────────────────────────────────────────────────────────────── */ input[type="text"], input[type="search"], input[type="password"], select { font: inherit; background: rgba(0, 0, 0, 0.28); color: var(--color-ink-100); border: 1px solid var(--color-stroke); border-radius: 10px; padding: 7px 11px; outline: none; transition: border-color 150ms ease-out, background 150ms ease-out, box-shadow 150ms ease-out; } input[type="text"]::placeholder, input[type="search"]::placeholder { color: var(--color-ink-400); } input[type="text"]:focus, input[type="search"]:focus, input[type="password"]:focus, select:focus { border-color: rgba(10, 132, 255, 0.55); box-shadow: 0 0 0 3px rgba(10, 132, 255, 0.16); } select { appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--color-ink-300) 50%), linear-gradient(135deg, var(--color-ink-300) 50%, transparent 50%); background-position: calc(100% - 18px) calc(50% - 2px), calc(100% - 13px) calc(50% - 2px); background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; padding-right: 30px; } input[type="checkbox"] { accent-color: var(--color-accent); } /* ────────────────────────────────────────────────────────────────────────── Tables. ────────────────────────────────────────────────────────────────────────── */ table.t { width: 100%; border-collapse: separate; border-spacing: 0; font-variant-numeric: tabular-nums; font-size: 13px; } table.t thead th { text-align: left; font-size: 10.5px; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-ink-400); padding: 9px 14px; border-bottom: 1px solid var(--color-stroke); background: rgba(255, 255, 255, 0.015); white-space: nowrap; } table.t tbody td { padding: 9px 14px; border-bottom: 1px solid var(--color-stroke-soft); vertical-align: top; color: var(--color-ink-100); } table.t tbody tr { transition: background 120ms ease-out; } table.t tbody tr:hover td { background: rgba(255, 255, 255, 0.025); } table.t tbody tr:last-child td { border-bottom: none; } table.t td .meta-line { display: block; margin-top: 2px; color: var(--color-ink-400); font-size: 11px; } .err-cell { color: #ffa39c; white-space: pre-wrap; word-break: break-word; max-width: 460px; font-size: 12px; } /* ────────────────────────────────────────────────────────────────────────── Code chips inline. ────────────────────────────────────────────────────────────────────────── */ code, .code { font-family: var(--font-mono); font-size: 11.5px; background: rgba(255, 255, 255, 0.05); border: 1px solid var(--color-stroke-soft); padding: 1px 6px; border-radius: 6px; color: var(--color-ink-200); } /* ────────────────────────────────────────────────────────────────────────── Scrollbar styling on opt-in containers. ────────────────────────────────────────────────────────────────────────── */ .scrollable { scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, 0.12) transparent; } .scrollable::-webkit-scrollbar { width: 8px; height: 8px; } .scrollable::-webkit-scrollbar-track { background: transparent; } .scrollable::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.08); border-radius: 999px; } .scrollable::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.18); } /* ────────────────────────────────────────────────────────────────────────── Log viewer. ────────────────────────────────────────────────────────────────────────── */ .logs { font-family: var(--font-mono); font-size: 11.5px; line-height: 1.55; max-height: 60vh; overflow: auto; } .log-row { display: grid; grid-template-columns: 80px 60px 160px 1fr; gap: 12px; padding: 4px 16px; border-bottom: 1px solid var(--color-stroke-soft); align-items: baseline; } .log-row:hover { background: rgba(255, 255, 255, 0.025); } .log-row .ts { color: var(--color-ink-400); white-space: nowrap; } .log-row .lvl { font-weight: 600; letter-spacing: 0.04em; } .log-row .logger { color: var(--color-ink-400); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .log-row .msg { white-space: pre-wrap; word-break: break-word; color: var(--color-ink-100); } .log-row .extras { color: var(--color-ink-300); margin-left: 6px; } .log-row .extras b { color: var(--color-ink-200); font-weight: 500; } .log-row .exc { color: #ffa39c; white-space: pre-wrap; display: block; margin-top: 4px; } .lvl.INFO { color: #6fb0ff; } .lvl.DEBUG { color: var(--color-ink-400); } .lvl.WARNING { color: #ffd66b; } .lvl.ERROR { color: #ff8e85; } .lvl.RAW { color: var(--color-ink-400); } /* ────────────────────────────────────────────────────────────────────────── Reveal animation for the dashboard's first paint. Honour reduced motion. ────────────────────────────────────────────────────────────────────────── */ @keyframes glass-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } } .glass-rise { animation: glass-rise 360ms cubic-bezier(0.16, 1, 0.3, 1) both; } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; } } /* Tighter form rows. */ .form-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; } /* Card section heading. */ .section-heading { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding: 14px 18px 10px 18px; } .section-heading h2 { font-size: 11px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-ink-300); margin: 0; } .section-heading .accessory { font-size: 11px; color: var(--color-ink-400); display: flex; align-items: center; gap: 10px; } .empty { padding: 24px; color: var(--color-ink-400); font-style: italic; text-align: center; }