/* Orchestrator — Workflow Builder Styles */

/* ═══════════════════════════════════════════ */
/* THE CANVAS PANEL                            */
/* ═══════════════════════════════════════════ */

/*
 * #2281/#2272 — THE LAYOUT THAT USED TO BE HERE IS GONE.
 *
 * .orchestrator-wrapper was a flex row: canvas | 5px .panel-splitter | a 420–620px
 * .code-exec-panel holding .code-panel over .exec-panel. #2267 replaced all of it with the
 * .flow-workbench CSS grid (flow-workbench.css) and moved the source editor and the run log
 * into the bottom drawer. Neither Orchestrator page has rendered any of those five classes
 * since, and orchestrator.js has no splitter to drive, so the rules were inert — but they
 * were also the first thing anyone opening this sheet for the workbench had to read past,
 * and .orchestrator-wrapper carried `height: calc(100vh - 140px)`, the exact magic number
 * #876 spent a ticket removing. Deleted here, with the ≤992px branch that stacked them.
 *
 * What stays in this file: the canvas panel and its #2259 watermark, the top bar, #lispEditor
 * and #executionLog (the drawer's two panes still use them), .exec-step, the workflow list,
 * the overlays and bars, and the chat. What owns the LAYOUT is flow-workbench.css.
 */

.flow-panel {
    position: relative;
    /* #2259: a very shallow vertical wash rather than one flat gray. It reads as depth
       behind the blocks without becoming a thing anyone notices — the nodes carry the
       color on this canvas, the ground carries none. */
    background: linear-gradient(180deg, #fbfcfd 0%, #f4f6f8 100%);
    overflow: hidden;
    min-width: 200px;
}

/* ═══════════════════════════════════════════ */
/* #2259 — THE WATERMARK BEHIND THE CANVAS     */
/* ═══════════════════════════════════════════ */

/*
 * Jamie, 2026-09-05: "maybe a light large watermarking behind the canvas also of our
 * large version of our logo in the middle."
 *
 * WHY IT IS ITS OWN IMAGE. Every logo we ship is RGBA with an OPAQUE WHITE background —
 * the corner pixels of dbf-icon-512.png are (255,255,255,255). Laid behind the canvas
 * as-is that is a white rectangle, which reads as a box rather than a watermark.
 * butterfly-watermark.png is the same mark with alpha derived from distance-from-white,
 * so the white is gone and the antialiased curve survives. Nothing was recolored: it
 * keeps the brand blue and the navy document outline, and the opacity below is what
 * makes it faint.
 *
 * WHY IT SITS ON THE PANEL AND NOT IN THE WORKSPACE. Painting it into Blockly's own SVG
 * would make it part of the scrollable surface — it would pan away, scale with zoom, and
 * tile or smear at the edges. On the panel it is a fixed backdrop the workspace moves
 * over, which is what a watermark is. It also cannot be dragged, selected or exported
 * with a workflow, because Blockly never knows it exists.
 *
 * `pointer-events: none` is not decoration: this element covers the entire canvas, and
 * without it every click, drag and block connection on the page would land on a
 * decorative div instead of the workspace.
 *
 * NO DARK VARIANT, DELIBERATELY. The portal has no dark mode — there is not one
 * prefers-color-scheme or data-bs-theme rule in any of its stylesheets. A media query
 * keyed to the visitor's OS preference would dim this for a dark canvas that never
 * renders, on a page that stays light around it. When the portal gets a real theme
 * switch, this gets a variant with it.
 */
.flow-panel::before {
    content: "";
    position: absolute;
    /* #2266: the inset is 0 now, and the variable stays.
       It existed because Blockly's toolbox was an opaque ~300px column INSIDE this panel,
       so centering the mark on the panel put it visibly left of the canvas — which is how
       it first shipped and how the screenshot caught it. orchestrator.js measured the
       toolbox after injection and wrote the variable. There is no toolbox inside the
       panel any more (the palette is its own grid column, outside), so the measurement is
       gone and 0 — which was always the fallback — is now the answer. The variable is
       kept so a future overlay inside the panel has somewhere to say so. */
    inset: 0 0 0 var(--orch-canvas-left, 0px);
    background-image: url("../images/logos/butterfly-watermark.png");
    background-repeat: no-repeat;
    background-position: center;
    /* Height-driven so the mark stays whole on a short window and never spills past the
       panel on a wide one. The cap keeps it from ballooning on a large display. */
    background-size: auto min(55%, 26rem);
    opacity: 0.055;
    pointer-events: none;
    z-index: 0;
}

/*
 * #2266 — the flow canvas draws into #flowViewport (flow-workbench.css). The two rules
 * that used to live here were about Blockly's own DOM: #blocklyDiv's size, and clearing
 * .blocklySvg / .injectionDiv's flat background-color so the watermark showed through.
 * Neither element is on the page any more.
 *
 * The one thing that has to stay true is why they existed: the mark sits on the PANEL and
 * everything drawn over it is transparent, so the workflow moves across a fixed backdrop
 * rather than dragging it along. The viewport's dot grid is painted over the mark for the
 * same reason — it is a background-image, not an opaque layer.
 */

/* ═══════════════════════════════════════════ */
/* THE DRAWER'S TWO PANES (#2267)              */
/* ═══════════════════════════════════════════ */

/*
 * These two IDs are the Source pane and the Run pane inside the bottom dock. The panels
 * that used to hold them (.code-panel / .exec-panel, and their .panel-header rules) went
 * with .orchestrator-wrapper in #2281 — the dock draws its own header and tabs. The
 * elements themselves are unchanged, and orchestrator.js still writes to both by id.
 */

#lispEditor {
    flex: 1;
    resize: none;
    border: none;
    outline: none;
    font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;
    font-size: 0.82rem;
    line-height: 1.5;
    padding: 12px;
    background: #1e1e1e;
    color: #d4d4d4;
    tab-size: 2;
    min-height: 0;
    overflow: auto;
}

#lispEditor::placeholder {
    color: #6a6a6a;
}

#executionLog {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 12px;
    font-size: 0.82rem;
    min-height: 0;
}

/* ═══════════════════════════════════════════ */
/* TOP BAR                                     */
/* ═══════════════════════════════════════════ */

.orchestrator-topbar {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
    flex-wrap: wrap;
}

.orchestrator-topbar .workflow-name-input {
    max-width: 280px;
    font-weight: 600;
}

.orchestrator-topbar .btn-group .btn {
    font-size: 0.85rem;
}

.token-cost-badge {
    font-size: 0.8rem;
    padding: 4px 10px;
}

/* ═══════════════════════════════════════════ */
/* EXECUTION LOG                               */
/* ═══════════════════════════════════════════ */

/* #573: the empty-state play button is muted at rest but it IS the run control, so
   hovering (or tabbing to it) must say so. Bootstrap's .text-muted sets color with
   !important, so the hover color has to be !important too or it silently loses. */
#execPlaceholderRun:hover,
#execPlaceholderRun:focus-visible {
    color: #0d6efd !important;
}

.exec-step {
    padding: 8px 10px;
    border-radius: 6px;
    margin-bottom: 6px;
    border: 1px solid #e9ecef;
    background: #fff;
}

.exec-step.pending {
    opacity: 0.5;
}

.exec-step.running {
    border-color: #0d6efd;
    background: #e8f0fe;
    animation: pulse-border 1.5s ease-in-out infinite;
}

.exec-step.success {
    border-color: #198754;
    background: #d1e7dd;
}

.exec-step.error {
    border-color: #dc3545;
    background: #f8d7da;
}

.exec-step .step-header {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 600;
    font-size: 0.82rem;
}

.exec-step .step-header .status-icon {
    font-size: 1rem;
}

.exec-step .step-detail {
    font-size: 0.78rem;
    color: #6c757d;
    margin-top: 4px;
    max-height: 120px;
    overflow-y: auto;
}

.exec-step .step-detail pre {
    margin: 0;
    font-size: 0.75rem;
    background: rgba(0,0,0,0.05);
    padding: 6px;
    border-radius: 4px;
    max-height: 100px;
    overflow: auto;
    white-space: pre-wrap;
    word-break: break-all;
}

.exec-step .step-preview {
    margin-top: 6px;
}

.exec-step .step-preview img {
    max-width: 100%;
    max-height: 200px;
    border-radius: 4px;
    border: 1px solid #dee2e6;
}

.exec-step .step-preview .preview-btn {
    font-size: 0.78rem;
    margin-top: 4px;
}

@keyframes pulse-border {
    0%, 100% { border-color: #0d6efd; }
    50% { border-color: #6ea8fe; }
}

/* ═══════════════════════════════════════════ */
/* WORKFLOW PICKER MODAL                       */
/* ═══════════════════════════════════════════ */

.workflow-list-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px;
    border: 1px solid #e9ecef;
    border-radius: 6px;
    margin-bottom: 6px;
    cursor: pointer;
    transition: background 0.15s;
}

.workflow-list-item:hover {
    background: #f0f4ff;
    border-color: #0d6efd;
}

.workflow-list-item .wf-name {
    font-weight: 600;
    font-size: 0.9rem;
}

.workflow-list-item .wf-date {
    font-size: 0.75rem;
    color: #6c757d;
}

.workflow-list-item .wf-desc {
    font-size: 0.78rem;
    color: #6c757d;
}

/* ═══════════════════════════════════════════ */
/* LOADING OVERLAY                             */
/* ═══════════════════════════════════════════ */

.loading-overlay {
    position: fixed;
    inset: 0;
    background: rgba(255,255,255,0.8);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999;
}

.loading-content {
    text-align: center;
}

/* ═══════════════════════════════════════════ */
/* PARSE ERROR                                 */
/* ═══════════════════════════════════════════ */

.parse-error-bar {
    padding: 4px 12px;
    background: #f8d7da;
    color: #842029;
    font-size: 0.78rem;
    border-top: 1px solid #f5c2c7;
    flex-shrink: 0;
}

.type-warning-bar {
    padding: 4px 12px;
    background: #fff3cd;
    color: #664d03;
    font-size: 0.78rem;
    border-top: 1px solid #ffecb5;
    flex-shrink: 0;
}

/* ═══════════════════════════════════════════ */
/* RESPONSIVE                                  */
/* ═══════════════════════════════════════════ */

/* ═══════════════════════════════════════════ */
/* AI CHAT FAB + PANEL                        */
/* ═══════════════════════════════════════════ */

/* #2334 — one bottom-right stack, and its inset is MEASURED.
   --orch-overlay-bottom / --orch-overlay-right are written on <html> by orchestrator.js
   from the zoom pill, the dock's tab strip and the cookie notice. They are only ever set
   on these two pages; the 24px fallbacks are what every other page keeps.
   Bottom to top: FAB, then the hint bubble, then the toast. */
.ai-chat-fab {
    position: fixed;
    bottom: var(--orch-overlay-bottom, 24px);
    right: var(--orch-overlay-right, 24px);
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    color: #fff;
    border: none;
    font-size: 1.3rem;
    cursor: pointer;
    z-index: 1040;
    box-shadow: 0 4px 16px rgba(99, 102, 241, 0.4);
    transition: transform 0.2s, box-shadow 0.2s;
    display: flex;
    align-items: center;
    justify-content: center;
}

.ai-chat-fab:hover {
    transform: scale(1.1);
    box-shadow: 0 6px 24px rgba(99, 102, 241, 0.5);
}

.ai-chat-fab.active {
    background: linear-gradient(135deg, #4f46e5, #7c3aed);
}

.ai-chat-panel {
    position: fixed;
    /* Anchored to its own FAB (52px + an 12px gap), and CLAMPED: on a 1366x768 laptop a
       fixed 500px panel hung off a lifted anchor ran off the top of the window. */
    bottom: calc(var(--orch-overlay-bottom, 24px) + 64px);
    right: var(--orch-overlay-right, 24px);
    width: 380px;
    height: min(500px, calc(100vh - var(--orch-overlay-bottom, 24px) - 80px));
    z-index: 1039;
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border: 1px solid #e5e7eb;
}

.ai-chat-header {
    padding: 12px 16px;
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    color: #fff;
    font-weight: 600;
    font-size: 0.9rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-shrink: 0;
}

.ai-chat-header i {
    margin-right: 6px;
}

.ai-chat-close {
    background: none;
    border: none;
    color: #fff;
    font-size: 1.3rem;
    cursor: pointer;
    line-height: 1;
    opacity: 0.8;
    padding: 0 4px;
}

.ai-chat-close:hover {
    opacity: 1;
}

.ai-chat-messages {
    flex: 1;
    overflow-y: auto;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-height: 0;
}

.chat-msg {
    display: flex;
    max-width: 90%;
}

.chat-msg.user {
    align-self: flex-end;
}

.chat-msg.assistant {
    align-self: flex-start;
}

.chat-bubble {
    padding: 8px 12px;
    border-radius: 12px;
    font-size: 0.82rem;
    line-height: 1.5;
    word-break: break-word;
}

.chat-msg.user .chat-bubble {
    background: #6366f1;
    color: #fff;
    border-bottom-right-radius: 4px;
}

.chat-msg.assistant .chat-bubble {
    background: #f3f4f6;
    color: #1f2937;
    border-bottom-left-radius: 4px;
}

.chat-bubble code {
    background: rgba(0, 0, 0, 0.08);
    padding: 1px 4px;
    border-radius: 3px;
    font-size: 0.78rem;
}

.chat-msg.user .chat-bubble code {
    background: rgba(255, 255, 255, 0.2);
}

.chat-code-block {
    margin: 6px 0;
    border-radius: 6px;
    overflow: hidden;
}

.chat-code-block pre {
    background: #1e1e1e;
    color: #d4d4d4;
    padding: 10px;
    margin: 0;
    font-size: 0.75rem;
    line-height: 1.4;
    overflow-x: auto;
    white-space: pre-wrap;
    word-break: break-all;
    max-height: 200px;
    overflow-y: auto;
}

.chat-apply-btn {
    display: block;
    width: 100%;
    padding: 6px 10px;
    background: #10b981;
    color: #fff;
    border: none;
    font-size: 0.78rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s;
}

.chat-apply-btn:hover {
    background: #059669;
}

.chat-apply-btn:disabled {
    background: #6b7280;
    cursor: default;
}

.ai-chat-input {
    padding: 10px 12px;
    border-top: 1px solid #e5e7eb;
    display: flex;
    gap: 8px;
    flex-shrink: 0;
    background: #f9fafb;
}

.ai-chat-input input, .ai-chat-input textarea {
    flex: 1;
    border: 1px solid #d1d5db;
    border-radius: 8px;
    padding: 8px 12px;
    font-size: 0.82rem;
    outline: none;
    transition: border-color 0.15s;
}

.ai-chat-input input:focus, .ai-chat-input textarea:focus {
    border-color: #6366f1;
    box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.15);
}

/* #735: multiline chat input for pasted JSON payloads */
.ai-chat-input textarea {
    resize: none;
    font-family: inherit;
    line-height: 1.4;
    max-height: 120px;
    overflow-y: auto;
}

.ai-chat-input button {
    background: #6366f1;
    color: #fff;
    border: none;
    border-radius: 8px;
    padding: 8px 14px;
    cursor: pointer;
    font-size: 0.85rem;
    transition: background 0.15s;
}

.ai-chat-input button:hover {
    background: #4f46e5;
}

.ai-chat-input button:disabled {
    background: #9ca3af;
    cursor: default;
}

/* AI Chat Callout (initial prominent bubble) */
.ai-chat-callout {
    position: fixed;
    /* #2334 — slot two of the stack: clear of the FAB below it, and therefore clear of
       the zoom pill and the dock tab strip the FAB is already clear of. */
    bottom: calc(var(--orch-overlay-bottom, 24px) + 60px);
    right: var(--orch-overlay-right, 24px);
    width: 300px;
    background: linear-gradient(135deg, #6366f1, #8b5cf6);
    color: #fff;
    border-radius: 12px;
    padding: 14px 16px;
    z-index: 1041;
    box-shadow: 0 8px 32px rgba(99, 102, 241, 0.45);
    cursor: pointer;
    animation: callout-appear 0.4s ease-out;
}

.ai-chat-callout::after {
    content: '';
    position: absolute;
    bottom: -8px;
    right: 20px;
    width: 16px;
    height: 16px;
    background: #8b5cf6;
    transform: rotate(45deg);
    border-radius: 2px;
}

.ai-chat-callout-close {
    position: absolute;
    top: 6px;
    right: 8px;
    background: none;
    border: none;
    color: rgba(255, 255, 255, 0.7);
    font-size: 1.1rem;
    cursor: pointer;
    line-height: 1;
    padding: 2px 4px;
}

.ai-chat-callout-close:hover {
    color: #fff;
}

.ai-chat-callout-title {
    font-weight: 700;
    font-size: 0.88rem;
    margin-bottom: 6px;
}

.ai-chat-callout-title i {
    margin-right: 4px;
}

.ai-chat-callout-body {
    font-size: 0.8rem;
    line-height: 1.5;
    opacity: 0.92;
}

.ai-chat-callout-body em {
    font-style: italic;
}

.ai-chat-callout-hiding {
    opacity: 0;
    transform: translateY(8px) scale(0.95);
    transition: opacity 0.3s, transform 0.3s;
}

@keyframes callout-appear {
    from {
        opacity: 0;
        transform: translateY(12px) scale(0.9);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

/* Typing animation */
.chat-typing {
    display: inline-flex;
    gap: 4px;
    padding: 4px 0;
}

.chat-typing span {
    width: 6px;
    height: 6px;
    background: #9ca3af;
    border-radius: 50%;
    animation: chat-bounce 1.4s infinite ease-in-out both;
}

.chat-typing span:nth-child(1) { animation-delay: -0.32s; }
.chat-typing span:nth-child(2) { animation-delay: -0.16s; }
.chat-typing span:nth-child(3) { animation-delay: 0s; }

@keyframes chat-bounce {
    0%, 80%, 100% { transform: scale(0); }
    40% { transform: scale(1); }
}

/*
 * #2281 — the ≤992px branch went with the layout it stacked. It turned the flex row into a
 * column of two 50vh halves, and its `.flow-panel { height: 50vh; border-bottom }` was
 * actively wrong once the panel became a grid cell: it fought flow-workbench.css's own
 * ≤991.98px rule, which stacks palette / canvas / dock and gives the canvas a
 * minmax(18rem, 1fr) row. That file owns the narrow layout now, alone.
 */

/* ═══════════════════════════════════════════ */
/* AD-HOC FILE INPUTS (#404 / #405)            */
/* ═══════════════════════════════════════════ */

.files-panel {
    border: 1px solid #dee2e6;
    border-radius: 8px;
    background: #fafbfc;
    padding: 12px 14px;
    margin-bottom: 8px;
}

.file-drop-zone {
    border: 2px dashed #c5ccd6;
    border-radius: 8px;
    background: #fff;
    text-align: center;
    padding: 18px 12px;
    color: #6c757d;
    font-size: 0.85rem;
    transition: border-color 0.15s, background 0.15s;
}

.file-drop-zone.dragover {
    border-color: #0d6efd;
    background: #f0f6ff;
    color: #0d6efd;
}

.file-browse-link {
    color: #0d6efd;
    text-decoration: underline;
    cursor: pointer;
    margin: 0;
}

.file-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.file-chip {
    display: flex;
    align-items: center;
    gap: 8px;
    background: #fff;
    border: 1px solid #e3e7ec;
    border-radius: 6px;
    padding: 6px 10px;
    font-size: 0.8rem;
}

.file-chip .file-name {
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 240px;
}

.file-chip .file-meta {
    color: #6c757d;
    font-size: 0.72rem;
}

.file-chip .file-actions {
    margin-left: auto;
    display: flex;
    gap: 4px;
    align-items: center;
}

.file-chip .input-badge {
    font-size: 0.66rem;
}
