/* RequestTaskTemplates.css - Module-specific styles for template builder */
/* Atomic components handle their own styling. This covers layout and builder-specific patterns. */

/* View tabs render via the shared SegmentedControl molecule. The wrapper
   stops the cross-axis stretch from VerticalStackTemplate (flex column)
   so the pill sits at its natural inline-flex width. Mirrors the
   .policies-rules-sub-tabs pattern. */
.templates-view-tabs {
    display: flex;
}

/* ============================================================
   ROW ACTIONS
   ============================================================ */

.templates-row-actions {
    display: flex;
    gap: var(--space-1);
    justify-content: flex-end;
}

/* ============================================================
   TEAM ASSIGNMENT (Task Authoring -> Team column + bulk apply)
   ============================================================ */

.templates-team-cell {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
}

/* Team column header: keeps the column label and the bulk-assign Combobox
   on a single row inside the <th>. Label hugs the left; Combobox takes the
   remaining width. Same width budget as the Team data column (320px). */
.templates-team-header {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
}

.templates-team-header > span:first-child {
    flex: 0 0 auto;
    white-space: nowrap;
}

.templates-team-header .combobox {
    flex: 1 1 auto;
    min-width: 0;
}

.templates-team-header-count {
    font-weight: 400;
    color: var(--text-muted);
    font-size: var(--text-xs);
}

.templates-dirty-bar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    background: var(--color-warning-light);
    border: var(--border-width-1) solid var(--color-warning);
    border-radius: var(--border-radius-md);
    margin-bottom: var(--space-3);
}

.templates-dirty-bar-label {
    flex: 1;
    font-size: var(--text-sm);
    color: var(--text-primary);
    font-weight: 600;
}

/* ============================================================
   TASK BUILDER (WYSIWYG shell, Phase 1)
   ============================================================ */

.task-builder-shell {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    /* Builder dimensional constants -- one place, consumed below. The frame
       width mirrors the staff mobile viewport; both the phone frame and the
       request-form preview share it so the column never jumps on mode swap. */
    --builder-frame-width: 375px;
    --builder-palette-col: 200px;
    --builder-preview-col: 480px;
    --builder-columns-height: clamp(480px, 65vh, 720px);
}

/* Phase 5: removed .task-settings-strip / .task-settings-summary /
   .task-settings-body / .task-settings-row -- task-level fields moved
   into the inspector's Task mode, so the modal-top collapsible strip is
   gone. */

.task-builder-columns {
    display: grid;
    /* Middle column holds the phone-frame preview + a comfortable margin;
       the right column gets all remaining width so the widget properties
       form has room to breathe. */
    grid-template-columns: var(--builder-palette-col) var(--builder-preview-col) 1fr;
    gap: var(--space-3);
    /* Stable height so the modal doesn't resize when the composer's selected
       step changes. Columns scroll internally if their content overflows. */
    height: var(--builder-columns-height);
}

.task-builder-palette,
.task-builder-composer,
.task-builder-inspector {
    overflow-y: auto;
    min-height: 0; /* required for grid items to shrink below content size */
}

/* ----- Palette ----- */

.task-builder-palette {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-3);
    background: var(--bg-layer-3);
    border: var(--border-width-1) solid var(--border-subtle);
    border-radius: var(--border-radius-md);
}

.palette-header {
    font-size: var(--text-sm);
    font-weight: 700;
    color: var(--text-primary);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-wide);
}

.palette-group {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.palette-group-label {
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-wide);
    margin-bottom: var(--space-1);
}

.palette-group-items {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.palette-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-height: var(--space-8);
    padding: var(--space-2);
    background: var(--bg-layer-4);
    border: var(--border-width-1) solid var(--border-default);
    border-radius: var(--border-radius-md);
    font-size: var(--text-sm);
    color: var(--text-primary);
    cursor: pointer;
    transition: background var(--duration-150) var(--easing-out),
                border-color var(--duration-150) var(--easing-out);
}

.palette-item:hover:not([disabled]) {
    background: var(--bg-layer-2);
    border-color: var(--color-primary);
}

.palette-item:hover:not([disabled]) .palette-item-icon {
    color: var(--color-primary);
}

.palette-item[disabled] {
    /* Phase 7 P3: stronger "disabled because no step selected" treatment.
       Greyed text + reduced opacity + not-allowed cursor makes the state
       obvious before the operator hovers for the title tooltip. */
    opacity: 0.45;
    cursor: not-allowed;
    color: var(--text-muted);
    background: var(--bg-layer-3);
}

.palette-item[disabled] .palette-item-icon {
    color: var(--text-muted);
}

/* Phase 7 P3: empty-state hint that only paints when no step is selected.
   Sits between the palette header and the groups so the dimmed tiles below
   read as "consequences of no step yet" rather than "broken". */
.palette-empty-hint {
    padding: var(--space-2);
    background: var(--bg-layer-4);
    border: var(--border-width-1) dashed var(--border-default);
    border-radius: var(--border-radius-sm);
    font-size: var(--text-xs);
    color: var(--text-muted);
    text-align: center;
    line-height: 1.3;
}

.palette-item-icon {
    display: flex;
    align-items: center;
    color: var(--text-muted);
    transition: color var(--duration-150) var(--easing-out);
}

/* ----- Composer (Phase 4: phone-frame preview) ----- */
/*
 * The middle column is a phone-frame mirror of the staff-app task screen.
 * Three vertical sections: task summary card, step counter row (operator
 * control, outside the frame), and the phone frame itself (~375px wide).
 * The widget overlay system continues to operate inside the frame.
 */

.task-builder-composer {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    background: var(--bg-layer-2);
    border: var(--border-width-1) solid var(--border-subtle);
    border-radius: var(--border-radius-md);
    overflow-y: auto;
}

/* Task summary card: title + description echo of the task-settings strip.
   Sized to align with the phone frame below. Card is clickable as a
   deselect target -- clicking it drops widget selection. */
.task-preview-summary {
    width: 100%;
    max-width: var(--builder-frame-width);
    padding: var(--space-3);
    background: var(--bg-layer-4);
    border: var(--border-width-1) solid var(--border-subtle);
    border-radius: var(--border-radius-md);
    cursor: pointer;
    transition: border-color var(--duration-150) var(--easing-out);
}

.task-preview-summary:hover {
    border-color: var(--color-primary);
}

/* Task mode: the summary card is the selected surface (same selection
   language as the widget overlays -- ring, no left accent). */
.task-preview-summary.selected {
    border-color: var(--color-primary);
    background: color-mix(in srgb, var(--color-primary) 6%, var(--bg-layer-4));
}

.task-preview-summary-title {
    margin: 0;
    font-size: var(--text-md);
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1.3;
}

.task-preview-summary-desc {
    margin: var(--space-1) 0 0 0;
    font-size: var(--text-sm);
    color: var(--text-body);
    line-height: 1.4;
}

/* Step counter row: arrows, label, inline CRUD, add button. Sits ABOVE the
   phone frame because it's an operator-only control. Pinned to the frame
   width for visual alignment. */
.task-preview-step-counter {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    max-width: var(--builder-frame-width);
    padding: var(--space-1) var(--space-2);
}

.step-counter-arrow,
.step-counter-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--space-6);
    height: var(--space-6);
    background: transparent;
    border: var(--border-width-1) solid var(--border-default);
    border-radius: var(--border-radius-sm);
    color: var(--text-primary);
    cursor: pointer;
    padding: 0;
}

.step-counter-arrow:hover:not([disabled]),
.step-counter-action:hover:not([disabled]) {
    background: var(--bg-layer-3);
    border-color: var(--color-primary);
}

.step-counter-arrow[disabled],
.step-counter-action[disabled] {
    opacity: 0.4;
    cursor: not-allowed;
}

.step-counter-danger:hover:not([disabled]) {
    border-color: var(--color-error);
    color: var(--color-error);
}

/* The label is a BUTTON: on a 1-step template both arrows are disabled, so
   clicking "Step N of M" is the route from the Task-mode request canvas into
   the step canvas (data-action="select-step"). */
.step-counter-label {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--text-primary);
    padding: 0 var(--space-1);
    background: transparent;
    border: none;
    border-radius: var(--border-radius-sm);
    cursor: pointer;
}

.step-counter-label:hover {
    color: var(--color-primary);
    background: var(--bg-layer-3);
}

.step-counter-spacer {
    flex: 1;
}

.step-counter-add {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-2);
    background: transparent;
    border: var(--border-width-1) dashed var(--border-default);
    border-radius: var(--border-radius-sm);
    font-size: var(--text-xs);
    color: var(--text-muted);
    cursor: pointer;
}

.step-counter-add:hover {
    color: var(--text-primary);
    border-color: var(--color-primary);
}

/* Phone frame: iPhone-class viewport. Subtle border + shadow to suggest a
   device chrome without skeuomorphism. Click on the frame background
   (anywhere not occupied by a widget overlay) deselects. */
.task-preview-frame {
    width: 100%;
    max-width: var(--builder-frame-width);
    background: var(--bg-layer-4);
    border: var(--border-width-1) solid var(--border-default);
    border-radius: var(--border-radius-lg);
    box-shadow: var(--shadow-md);
    /* The frame is a flex child of the composer column and shrinks to the
       leftover height. overflow-x stays hidden so the rounded corners keep
       clipping widget overlays; overflow-y scrolls so steps with many widgets
       stay reachable instead of being silently clipped below the fold.
       min-height is what LICENSES that shrink -- without it the frame only
       shrinks because overflow-y incidentally zeroes the automatic minimum
       size, so a future overflow edit would silently reintroduce the clipping
       (flex-chain rule: the growing child is flex: 1; min-height: 0). */
    overflow-x: hidden;
    overflow-y: auto;
    min-height: 0;
    cursor: pointer;
}

.task-preview-frame-inner {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-3);
    cursor: default;
}

/* Mirrors the staff-app step header inside the frame. Title bold, then an
   instruction paragraph below. Placeholders are italicised + muted so the
   operator knows the field is empty. */
.task-preview-step-header {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding-bottom: var(--space-2);
    border-bottom: var(--border-width-1) solid var(--border-subtle);
}

.task-preview-step-title {
    margin: 0;
    font-size: var(--text-md);
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1.3;
}

.task-preview-step-title-placeholder {
    font-weight: 400;
    font-style: italic;
    color: var(--text-muted);
}

.task-preview-step-instruction {
    margin: 0;
    font-size: var(--text-sm);
    color: var(--text-body);
    line-height: 1.4;
}

.task-preview-step-instruction-placeholder {
    font-style: italic;
    color: var(--text-muted);
}

/* Staff-style Next button at the bottom of the frame. Disabled in builder
   mode -- it's just preview. */
.task-preview-next-row {
    display: flex;
    justify-content: flex-end;
    padding-top: var(--space-2);
    border-top: var(--border-width-1) solid var(--border-subtle);
}

.task-preview-next-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-2) var(--space-3);
    background: var(--color-primary);
    color: var(--text-inverse);
    border: none;
    border-radius: var(--border-radius-md);
    font-size: var(--text-sm);
    font-weight: 600;
    cursor: not-allowed;
    opacity: 0.7;
}

/* No gap here: the TaskStepRenderer's own .step-container owns the internal
   widget spacing. min-height keeps the drop zone hittable when empty. */
.composer-widgets {
    display: flex;
    flex-direction: column;
    min-height: var(--space-20);
}

.composer-widgets-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-4);
    color: var(--text-muted);
    font-size: var(--text-sm);
    border: var(--border-width-1) dashed var(--border-default);
    border-radius: var(--border-radius-md);
}

/* Each rendered widget is wrapped via .composer-widget-host (added by
   stepBuilder._decorateWidgetOverlays). Provides positioning context for the
   absolute overlay layered on top. */
.composer-widget-host {
    position: relative;
}

.composer-widget-overlay {
    position: absolute;
    inset: 0;
    border-radius: var(--border-radius-md);
    cursor: pointer;
    background: transparent;
    border: var(--border-width-2) solid transparent;
    z-index: 1;
}

.composer-widget-overlay:hover {
    background: color-mix(in srgb, var(--color-primary) 6%, transparent);
}

.composer-widget-overlay.selected {
    border-color: var(--color-primary);
    background: color-mix(in srgb, var(--color-primary) 8%, transparent);
}

/* Ghost remove affordance: error-coloured glyph on a transparent button,
   visible ONLY on the selected overlay (select first, then remove -- no
   red chrome on a casual hover). pointer-events gate so the invisible
   button can never eat a click. */
.composer-widget-remove {
    position: absolute;
    top: var(--space-1);
    right: var(--space-1);
    width: var(--space-5);
    height: var(--space-5);
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    color: var(--color-error);
    border: none;
    border-radius: var(--border-radius-sm);
    font-size: var(--text-base);
    line-height: 1;
    cursor: pointer;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--duration-150) var(--easing-out),
                background var(--duration-150) var(--easing-out);
    z-index: 2;
}

.composer-widget-overlay.selected .composer-widget-remove {
    opacity: 1;
    pointer-events: auto;
}

.composer-widget-remove:hover {
    background: color-mix(in srgb, var(--color-error) 10%, transparent);
}

/* The TaskStepRenderer paints its own .step-actions (Previous/Next) and
   .step-header inside the composer-widgets host -- they're meaningless in
   builder preview, so collapse them. */
.composer-widgets .step-actions,
.composer-widgets .step-header {
    display: none !important;
}

.composer-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    padding: var(--space-6);
    color: var(--text-muted);
    text-align: center;
    border: var(--border-width-1) dashed var(--border-default);
    border-radius: var(--border-radius-md);
}

.composer-empty-text {
    margin: 0;
    font-size: var(--text-sm);
    color: var(--text-body);
}

/* ----- Request-form preview (Task mode canvas) ----- */
/*
 * PREVIEW SKIN OF ANOTHER APP: this block deliberately approximates the
 * guest app's dark frosted-glass look (deep blue-grey gradient, translucent
 * white-alpha controls) so the operator sees the form the way the guest
 * will -- unmistakably NOT the operator theme. Colour literals inside this
 * scoped block are therefore intentional; dimensions and spacing still come
 * from tokens. It styles the classes RequestFormRenderer emits
 * (.request-field / .quantity-selector / .choice-pills / .glass-toggle ...).
 * The neutral variant (non-guest visibility) re-skins the same structure
 * with operator tokens further down.
 */

.request-form-preview {
    width: 100%;
    max-width: var(--builder-frame-width);
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-3);
    border-radius: var(--border-radius-lg);
    box-shadow: var(--shadow-md);
    background: linear-gradient(165deg, #22314f 0%, #182540 55%, #101b31 100%);
    border: var(--border-width-1) solid rgba(255, 255, 255, 0.14);
    color: rgba(255, 255, 255, 0.92);
    overflow-x: hidden;
    overflow-y: auto;
    min-height: 0;
}

.request-form-caption {
    font-size: var(--text-xs);
    text-align: center;
    line-height: 1.3;
    color: rgba(255, 255, 255, 0.55);
}

.request-form-host {
    display: flex;
    flex-direction: column;
}

.request-form-preview .modal-request-fields {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.request-form-preview .request-field {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.request-form-preview .request-field-inline {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
}

.request-form-preview .request-field-label {
    font-size: var(--text-sm);
    font-weight: 500;
    color: rgba(255, 255, 255, 0.85);
}

.request-form-preview .request-field-input {
    width: 100%;
    padding: var(--space-2) var(--space-3);
    background: rgba(255, 255, 255, 0.08);
    border: var(--border-width-1) solid rgba(255, 255, 255, 0.16);
    border-radius: var(--border-radius-md);
    color: rgba(255, 255, 255, 0.92);
    font-size: var(--text-sm);
    font-family: inherit;
}

.request-form-preview .request-field-input::placeholder {
    color: rgba(255, 255, 255, 0.4);
}

.request-form-preview .quantity-selector {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
}

.request-form-preview .qty-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--space-6);
    height: var(--space-6);
    padding: 0;
    border-radius: var(--radius-full);
    background: rgba(255, 255, 255, 0.1);
    border: var(--border-width-1) solid rgba(255, 255, 255, 0.18);
    color: rgba(255, 255, 255, 0.9);
    cursor: default;
}

/* The renderer's +/- glyphs reference the guest app's SVG sprite
   (#icon-plus / #icon-minus), which the operator page does not carry.
   Hide the empty svg and draw the glyphs from the data-action instead. */
.request-form-preview .qty-btn .btn-icon {
    display: none;
}

.request-form-preview .qty-btn::before {
    font-size: var(--text-md);
    line-height: 1;
}

.request-form-preview .qty-btn[data-action="decrease"]::before {
    content: "-";
}

.request-form-preview .qty-btn[data-action="increase"]::before {
    content: "+";
}

.request-form-preview .quantity-value {
    min-width: var(--space-5);
    text-align: center;
    font-size: var(--text-sm);
    font-weight: 600;
}

.request-form-preview .choice-pills {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.request-form-preview .choice-pill {
    padding: var(--space-1_5) var(--space-3);
    border-radius: var(--border-radius-full);
    background: rgba(255, 255, 255, 0.08);
    border: var(--border-width-1) solid rgba(255, 255, 255, 0.16);
    color: rgba(255, 255, 255, 0.85);
    font-size: var(--text-sm);
    font-family: inherit;
    cursor: default;
}

.request-form-preview .choice-pill.selected {
    background: rgba(255, 255, 255, 0.9);
    border-color: transparent;
    color: #182540;
}

/* Rating scale (TLP-998): the same pill language as a choice, laid out as an
   even ruler so a 1-10 scale previews the way the guest sees it. */
.request-form-preview .rating-scale {
    display: flex;
    gap: var(--space-1);
}

.request-form-preview .rating-option {
    flex: 1 1 0;
    min-width: 0;
    padding: var(--space-1_5) 0;
    border-radius: var(--radius-sm);
    background: rgba(255, 255, 255, 0.08);
    border: var(--border-width-1) solid rgba(255, 255, 255, 0.16);
    color: rgba(255, 255, 255, 0.85);
    font-size: var(--text-sm);
    font-family: inherit;
    cursor: default;
}

.request-form-preview .rating-option.selected {
    background: rgba(255, 255, 255, 0.9);
    border-color: transparent;
    color: #182540;
}

/* A field hidden by its showWhen. Not redundant: .request-field is display:flex
   in the preview too, which beats the user-agent [hidden] rule. */
.request-form-preview .request-field[hidden] {
    display: none;
}

.request-form-preview .glass-toggle {
    position: relative;
    width: var(--space-10);
    height: var(--space-6);
    padding: 0;
    flex-shrink: 0;
    border-radius: var(--border-radius-full);
    background: rgba(255, 255, 255, 0.15);
    border: var(--border-width-1) solid rgba(255, 255, 255, 0.2);
    cursor: default;
}

.request-form-preview .glass-toggle-thumb {
    position: absolute;
    top: var(--space-0_5);
    left: var(--space-0_5);
    width: var(--space-4);
    height: var(--space-4);
    border-radius: var(--radius-full);
    background: rgba(255, 255, 255, 0.95);
    transition: transform var(--duration-150) var(--easing-out);
}

.request-form-preview .glass-toggle.on {
    background: #34c759;
}

.request-form-preview .glass-toggle.on .glass-toggle-thumb {
    transform: translateX(var(--space-4));
}

/* Echo of the guest modal's footer pill. Disabled: preview only. */
.request-form-actions {
    display: flex;
    justify-content: flex-end;
    padding-top: var(--space-2);
    border-top: var(--border-width-1) solid rgba(255, 255, 255, 0.12);
}

.request-form-submit {
    padding: var(--space-2) var(--space-5);
    border-radius: var(--border-radius-full);
    background: rgba(255, 255, 255, 0.92);
    border: none;
    color: #182540;
    font-size: var(--text-sm);
    font-weight: 600;
    font-family: inherit;
    opacity: 0.85;
    cursor: not-allowed;
}

.request-form-empty {
    padding: var(--space-4);
    text-align: center;
    font-size: var(--text-sm);
    line-height: 1.4;
    color: rgba(255, 255, 255, 0.5);
    border: var(--border-width-1) dashed rgba(255, 255, 255, 0.25);
    border-radius: var(--border-radius-md);
}

/* Neutral variant: same structure, operator tokens. Used whenever the
   template is not guest-visible (the form fires from the Create Task
   modal, so it should read as operator chrome, not guest glass). */
.request-form-preview--neutral {
    background: var(--bg-layer-4);
    border-color: var(--border-default);
    color: var(--text-primary);
}

.request-form-preview--neutral .request-form-caption {
    color: var(--text-muted);
}

.request-form-preview--neutral .request-field-label {
    color: var(--text-primary);
}

.request-form-preview--neutral .request-field-input {
    background: var(--bg-layer-2);
    border-color: var(--border-default);
    color: var(--text-primary);
}

.request-form-preview--neutral .request-field-input::placeholder {
    color: var(--text-muted);
}

.request-form-preview--neutral .qty-btn {
    background: var(--bg-layer-2);
    border-color: var(--border-default);
    color: var(--text-primary);
}

.request-form-preview--neutral .choice-pill {
    background: var(--bg-layer-2);
    border-color: var(--border-default);
    color: var(--text-body);
}

.request-form-preview--neutral .choice-pill.selected {
    background: var(--color-primary);
    border-color: transparent;
    color: var(--text-inverse);
}

.request-form-preview--neutral .rating-option {
    background: var(--bg-layer-2);
    border-color: var(--border-default);
    color: var(--text-body);
}

.request-form-preview--neutral .rating-option.selected {
    background: var(--color-primary);
    border-color: transparent;
    color: var(--text-inverse);
}

.request-form-preview--neutral .glass-toggle {
    background: var(--bg-layer-1);
    border-color: var(--border-default);
}

.request-form-preview--neutral .glass-toggle-thumb {
    background: var(--bg-layer-4);
    box-shadow: var(--shadow-sm);
}

.request-form-preview--neutral .glass-toggle.on {
    background: var(--color-primary);
}

.request-form-preview--neutral .request-form-empty {
    color: var(--text-muted);
    border-color: var(--border-default);
}

/* ----- Inspector ----- */

.task-builder-inspector {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-3);
    background: var(--bg-layer-3);
    border: var(--border-width-1) solid var(--border-subtle);
    border-radius: var(--border-radius-md);
}

.inspector-header {
    font-size: var(--text-sm);
    font-weight: 700;
    color: var(--text-primary);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-wide);
}

/* Phase 5: persistent breadcrumb at the top of the inspector.
   Task > Step N > Widget. Parent segments are buttons (clickable);
   the current segment is a span (non-clickable, bold). Inline-flex so
   the chevron separator sits inline without an extra layout layer. */
.inspector-breadcrumb {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    flex-wrap: wrap;
    padding: var(--space-1) 0;
    font-size: var(--text-xs);
    color: var(--text-muted);
}

.inspector-breadcrumb-link {
    background: transparent;
    border: none;
    padding: 0;
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-family: inherit;
    cursor: pointer;
    text-decoration: underline dotted;
    text-underline-offset: var(--space-0_5);
}

.inspector-breadcrumb-link:hover {
    color: var(--color-primary);
}

.inspector-breadcrumb-current {
    color: var(--text-primary);
    font-weight: 700;
}

.inspector-breadcrumb-sep {
    color: var(--text-muted);
    font-size: var(--text-sm);
    line-height: 1;
}

.inspector-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-4);
    color: var(--text-muted);
    text-align: center;
    border: var(--border-width-1) dashed var(--border-default);
    border-radius: var(--border-radius-md);
}

.inspector-placeholder-icon {
    color: var(--text-muted);
}

.inspector-placeholder-title {
    margin: 0;
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text-body);
}

.inspector-placeholder-body {
    margin: 0;
    font-size: var(--text-xs);
    color: var(--text-muted);
}

.inspector-selected {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-3);
    background: var(--bg-layer-4);
    border-radius: var(--border-radius-md);
}

.inspector-selected-header {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    padding-bottom: var(--space-1);
    border-bottom: var(--border-width-1) solid var(--border-subtle);
}

.inspector-type {
    font-size: var(--text-sm);
    font-weight: 700;
    color: var(--text-primary);
}

.inspector-name {
    font-size: var(--text-xs);
    color: var(--text-muted);
    font-family: var(--font-mono);
}

/* Phase 3 inspector form -- compact stack of label/input rows + an options
   editor. Each row is a column with a label-then-input layout (label sits
   above the input). Help text is small + muted below the input. */

.inspector-form {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding-top: var(--space-2);
}

/* Phase 7 follow-up: pair compact fields on one row (duration + status,
   visibility + team) so the Task-mode form is denser. min-width: 0 lets
   each cell collapse below its content's natural width when the inspector
   column narrows. */
.inspector-form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-2);
}

.inspector-form-row > * {
    min-width: 0;
}

.inspector-row {
    display: flex;
    flex-direction: column;
    gap: var(--space-0_5);
}

.inspector-row-label {
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-wide);
}

/* Widget-config text/number/select rows render via the FormField molecule
   (same as the Task/Step modes) -- the atom owns input styling + focus. */

.inspector-row-help {
    font-size: var(--text-xs);
    color: var(--text-muted);
    line-height: 1.3;
}

/* Tri-state visibility control (Department | Hotel | Guest). The
   SegmentedControl is inline-flex; align-items keeps the flex column
   from stretching it to full row width (templates-view-tabs precedent). */
.inspector-visibility,
.inspector-handling {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    align-items: flex-start;
}

.inspector-visibility .inspector-row-help,
.inspector-handling .inspector-row-help {
    max-width: 100%;
}

/* Node 2 (TLP-315): inline compliance-threshold panel on a numeric core field.
   Mirrors the dashed-separator treatment of .inspector-options. */
.inspector-threshold,
.inspector-tolerance {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding-top: var(--space-2);
    margin-top: var(--space-1);
    border-top: var(--border-width-1) dashed var(--border-subtle);
}

.inspector-options {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding-top: var(--space-1);
    border-top: var(--border-width-1) dashed var(--border-subtle);
}

.inspector-options-label {
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-wide);
}

.inspector-options-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

/* Option editor rows render via the Input atom (label/value/colour) + an Icon
   remove + a Button add -- no bespoke input/button styling. The atoms wrap each
   field in .input-wrapper; flex lets label + value share the row while the
   colour select + remove icon sit at their natural width. */
.inspector-option-row {
    display: flex;
    gap: var(--space-1);
    align-items: center;
}

.inspector-option-row .input-wrapper {
    flex: 1;
    min-width: 0;
}

/* The colour select only ever holds one short word (Default/Success/Danger/
   Neutral), so it sits at its intrinsic width instead of taking an equal
   third of the row -- that third belongs to the label + value fields the
   operator actually types into. */
.inspector-option-row .input-wrapper:has(select) {
    flex: 0 0 auto;
}

/* ----- Inspector step-settings mode (Phase 4) ----- */
/*
 * When no widget is selected, the inspector shows the current step's
 * metadata (title, instructions, guidance, photo flag, media).
 * Each cluster sits in its own vertical group with a muted label header.
 */

.inspector-step-settings .inspector-form > * {
    /* Compact gap between step-settings groups -- denser than widget-config
       because there are more rows. */
    margin: 0;
}

.inspector-step-photo,
.inspector-step-media {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding-top: var(--space-2);
    border-top: var(--border-width-1) dashed var(--border-subtle);
}

/* ============================================================
   ICON BUTTONS (compact actions in cards)
   ============================================================ */

/* Icon-only actions use Icon.build({ clickable: true }) from Icon atom -- no size override. */

/* Extra small buttons */
.btn-xs {
    padding: var(--space-0_5) var(--space-2);
    font-size: var(--text-xs);
}

/* ============================================================
   REQUEST BUILDER (inside modal)
   ============================================================ */

.request-builder {
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
}

.request-builder-details {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.request-builder-row {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: var(--space-3);
}

/* Workflow visibility (Department | Hotel) -- same treatment as the task
   builder's tri-state control. */
.request-builder-visibility {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    align-items: flex-start;
}

.request-builder-visibility-help {
    font-size: var(--text-xs);
    color: var(--text-muted);
    line-height: 1.3;
}

/* Tasks Section */
.request-builder-tasks {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.request-builder-tasks-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-bottom: var(--space-2);
    border-bottom: var(--border-width-1) solid var(--border-subtle);
}

.request-builder-tasks-title {
    font-size: var(--text-md);
    font-weight: 600;
    color: var(--text-primary);
    margin: 0;
}

.request-builder-picker {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.request-builder-picker-row {
    display: flex;
    gap: var(--space-2);
    align-items: center;
}

.request-builder-picker-row .form-select {
    flex: 1;
}

.request-builder-picker-empty,
.request-builder-tasks-empty {
    text-align: center;
    padding: var(--space-4);
    color: var(--text-muted);
    font-size: var(--text-sm);
    background: var(--bg-layer-2);
    border-radius: var(--border-radius-md);
}

/* Task List (selected tasks in request) */
.request-builder-task-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.request-task-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-2) var(--space-3);
    background: var(--bg-layer-4);
    border: var(--border-width-1) solid var(--border-default);
    border-radius: var(--border-radius-md);
}

.request-task-card-missing {
    border-color: var(--color-error);
    background: var(--color-error-light);
}

.request-task-card-left {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-width: 0;
}

.request-task-number {
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--space-6);
    height: var(--space-6);
    border-radius: 50%;
    background: var(--bg-layer-2);
    color: var(--text-primary);
    font-size: var(--text-xs);
    font-weight: 700;
    flex-shrink: 0;
}

.request-task-info {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.request-task-title {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.request-task-meta {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
    font-size: var(--text-xs);
    color: var(--text-muted);
}

/* TLP-883: the team a step hands its work to, and the warning when there is
   none. Same border treatment as the missing-template card -- an unrunnable
   step is the same class of problem, so it should not look like a new one. */
.request-task-team {
    color: var(--text-secondary);
}

.request-task-card-unrunnable {
    border-color: var(--color-warning);
    background: var(--color-warning-light);
}

.request-task-card-right {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    flex-shrink: 0;
}

/* ============================================================
   STEP MEDIA ITEMS (inside the Composer's collapsible Media extra)
   ============================================================ */

.step-media-items {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.step-media-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-1_5) var(--space-2);
    background: var(--bg-layer-4);
    border: var(--border-width-1) solid var(--border-subtle);
    border-radius: var(--border-radius-md);
}

.step-media-item-info {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
}

.step-media-name {
    font-size: var(--text-xs);
    color: var(--text-body);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Compact upload zone inside the inspector's step-settings Media field. */
.inspector-step-media .file-upload-zone {
    padding: var(--space-2);
    min-height: auto;
}

.inspector-step-media .file-upload-zone .upload-icon {
    display: none;
}

.inspector-step-media .file-upload-zone .upload-title {
    font-size: var(--text-xs);
    margin: 0;
}

.inspector-step-media .file-upload-zone .upload-subtitle,
.inspector-step-media .file-upload-zone .upload-hint {
    font-size: var(--text-xs);
    margin: 0;
}

/* ============================================================
   REQUEST FIELDS LIST (inspector Task mode)
   ============================================================ */
/* Compact cards mirroring .step-media-item: icon, label, guest-language
   type chip, danger remove icon. Rows select the field (composer overlay +
   widget-config inspector follow). Adding happens in the palette only. */

.inspector-request-fields {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding-top: var(--space-2);
    border-top: var(--border-width-1) dashed var(--border-subtle);
}

.inspector-request-fields-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.inspector-request-field-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-1_5) var(--space-2);
    background: var(--bg-layer-4);
    border: var(--border-width-1) solid var(--border-subtle);
    border-radius: var(--border-radius-md);
    cursor: pointer;
    transition: border-color var(--duration-150) var(--easing-out);
}

.inspector-request-field-row:hover {
    border-color: var(--color-primary);
}

.inspector-request-field-row.selected {
    border-color: var(--color-primary);
    background: color-mix(in srgb, var(--color-primary) 6%, var(--bg-layer-4));
}

.inspector-request-field-icon {
    display: flex;
    align-items: center;
    color: var(--text-muted);
    flex-shrink: 0;
}

.inspector-request-field-label {
    flex: 1;
    min-width: 0;
    font-size: var(--text-sm);
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.inspector-request-field-type {
    flex-shrink: 0;
    padding: 0 var(--space-1_5);
    font-size: var(--text-xs);
    color: var(--text-muted);
    background: var(--bg-layer-2);
    border-radius: var(--border-radius-sm);
}

.inspector-request-fields-empty {
    padding: var(--space-2);
    text-align: center;
    font-size: var(--text-xs);
    line-height: 1.3;
    color: var(--text-muted);
    border: var(--border-width-1) dashed var(--border-default);
    border-radius: var(--border-radius-sm);
}

/* Phase 7 follow-up: compact textareas in the inspector. The Textarea atom
   carries a min-height for full-form contexts; in the inspector's
   constrained right column we want 2 visual lines, not 3. The rows="2"
   attribute already requests 2 lines; this override removes the min-height
   floor that was inflating to ~3 lines. */
.task-builder-inspector textarea {
    min-height: 0;
}

/* ============================================================
   PHASE 2: DRAG-AND-DROP VISUALS
   ============================================================ */

/* Palette tile + widget overlay + step pill: when grabbed (via mouse or
   keyboard) we mark with aria-grabbed=true and the dnd-grabbed class so
   the badge becomes visible and the source dims slightly. */

.dnd-grabbed-badge {
    display: none;
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-wide);
    color: var(--color-primary);
    padding: 0 var(--space-1);
    border-radius: var(--border-radius-sm);
    background: color-mix(in srgb, var(--color-primary) 12%, transparent);
}

[aria-grabbed="true"] .dnd-grabbed-badge,
.dnd-grabbed .dnd-grabbed-badge {
    display: inline-block;
}

[aria-grabbed="true"],
.dnd-grabbed {
    opacity: 0.7;
    outline: var(--border-width-2) dashed var(--color-primary);
    outline-offset: var(--space-0_5);
}

/* Composer widgets container -- ring outline while a palette drag is in flight
   and dragover is firing. Removed on dragleave + drop. */
.composer-widgets.dnd-drop-target {
    outline: var(--border-width-2) solid var(--color-primary);
    outline-offset: var(--space-1);
    background: color-mix(in srgb, var(--color-primary) 4%, transparent);
}

/* Insert-position indicator on widget overlays. Top edge in primary --
   shows where the moved item will land. */
.composer-widget-overlay.dnd-insert-target {
    box-shadow: inset 0 var(--border-width-2) 0 0 var(--color-primary);
}

/* Phase 5: dropped .composer-step-pill.dnd-insert-target -- the step-pill
   nav strip was retired in Phase 4, no element matches the selector. */

/* Keyboard-grabbed elements need an unmistakable focus ring. Browsers vary
   on :focus-visible; force outline on the keyboard-grabbed marker. */
.composer-widget-overlay:focus-visible {
    outline: var(--border-width-2) solid var(--border-focus);
    outline-offset: var(--space-0_5);
}

/* ============================================================
   DATA-HIDDEN TOGGLE (QA bindings + misc legacy hooks)
   ============================================================ */

[data-hidden] {
    display: none;
}

/* ============================================================
   RESPONSIVE
   ============================================================ */

@media (max-width: 1023px) {
    .task-builder-columns {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 768px) {
    .request-builder-row {
        grid-template-columns: 1fr;
    }
}

/* ============================================================
   QA Obligations sub-view + per-entity overlay editor (Node 2, TLP-317)
   Tokens only. The triad was dormant + unstyled; this revives it.
   ============================================================ */

.qa-control-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.qa-control-row {
    border: var(--border-width-1) solid var(--border-subtle);
    border-radius: var(--border-radius-sm);
    background: var(--bg-surface);
}

.qa-control-header {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    cursor: pointer;
}

.qa-control-header:hover { background: var(--bg-layer-1); }

/* Expand/collapse is a CSS class flip (no re-render): the .expanded class on the
   row reveals its content and points the chevron down. Canonical expandable-row
   pattern (MenuCatalog / Team / Bookings). */
.qa-control-expand {
    display: inline-flex;
    transition: transform var(--duration-200) var(--easing-out);
}
.qa-control-row:not(.expanded) .qa-control-expand { transform: rotate(-90deg); }
.qa-control-row:not(.expanded) .qa-expanded-content { display: none; }

.qa-control-id {
    font-weight: 600;
    font-size: var(--text-xs);
    color: var(--text-muted);
    min-width: 90px;
}

.qa-control-title { flex: 1; font-size: var(--text-sm); color: var(--text-primary); }
.qa-control-meta { display: flex; gap: var(--space-1); flex-wrap: wrap; }
.qa-control-actions { margin-left: auto; }

.qa-expanded-content {
    padding: var(--space-3);
    border-top: var(--border-width-1) solid var(--border-subtle);
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.qa-procedure-preview h4,
.qa-obligation-list h4 {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-wide);
    color: var(--text-muted);
    margin-bottom: var(--space-2);
}

.qa-step-list { padding-left: var(--space-4); display: flex; flex-direction: column; gap: var(--space-1); }
.qa-step-instruction { color: var(--text-muted); font-size: var(--text-xs); }
.qa-version-notice { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-2); color: var(--text-muted); font-size: var(--text-xs); }
.qa-obligation-actions { display: flex; gap: var(--space-1); justify-content: flex-end; }

/* Setup modal binding sections -- the radio toggles which is visible. */
.qa-setup-binding[data-hidden] { display: none; }
.qa-setup-meta { display: flex; gap: var(--space-1); margin-top: var(--space-2); }
/* The control's own "applies to" line (TLP-972): the same voice as the schedule
   prompt's "The control asks for:" -- guidance for the person binding it. */
.qa-setup-applies { font-size: var(--text-sm); color: var(--text-primary); }
.qa-no-assets { color: var(--text-muted); font-size: var(--text-sm); }
/* Setup modal: the team that will look after the obligation (TLP-888). Gap-only
   spacing -- the modal body owns the rhythm, the field carries no margin. */
.qa-setup-team { display: flex; flex-direction: column; }

/* An obligation with no pinned location is a real gap the QA manager should see
   (TLP-889), so the cell reads as absent rather than looking empty. */
.qa-location-unset { color: var(--text-muted); }

/* Schedule prompt (TLP-892). The control's stated cadence, verbatim, above the
   shared recurrence picker. */
.qa-schedule-modal { display: flex; flex-direction: column; gap: var(--space-3); }
.qa-schedule-cadence { font-size: var(--text-sm); color: var(--text-primary); }
.qa-schedule-scope { font-size: var(--text-sm); color: var(--text-secondary); }
.qa-schedule-hint { font-size: var(--text-xs); color: var(--text-muted); line-height: 1.4; }

.qa-schedule-note {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border: var(--border-width-1) solid var(--color-warning);
    border-radius: var(--border-radius-sm);
    background: var(--color-warning-light);
    color: var(--color-warning-hover);
    font-size: var(--text-xs);
    line-height: 1.4;
}


/* Overlay editor */
.qa-overlay-editor { display: flex; flex-direction: column; gap: var(--space-3); }
.qa-overlay-help { color: var(--text-muted); font-size: var(--text-xs); line-height: 1.4; }
.qa-overlay-steps { display: flex; flex-direction: column; gap: var(--space-2); }

.qa-overlay-step {
    border: var(--border-width-1) solid var(--border-subtle);
    border-radius: var(--border-radius-sm);
    padding: var(--space-2) var(--space-3);
}

.qa-overlay-step-head { display: flex; align-items: center; gap: var(--space-2); }
.qa-overlay-step-title { font-size: var(--text-sm); font-weight: 600; color: var(--text-primary); }
.qa-overlay-hide-note { font-size: var(--text-xs); color: var(--text-muted); margin-left: auto; }

.qa-overlay-fields { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-2); padding-top: var(--space-2); border-top: var(--border-width-1) dashed var(--border-subtle); }
.qa-overlay-field-label { font-size: var(--text-xs); color: var(--text-muted); display: flex; gap: var(--space-2); align-items: baseline; }
.qa-overlay-core-note { color: var(--text-muted); font-style: italic; }
.qa-overlay-field-row { display: flex; gap: var(--space-1); align-items: center; flex-wrap: wrap; }

.qa-overlay-addsteps { display: flex; flex-direction: column; gap: var(--space-2); padding-top: var(--space-2); border-top: var(--border-width-1) solid var(--border-subtle); }
.qa-overlay-addsteps-head { font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--letter-spacing-wide); color: var(--text-muted); }
.qa-overlay-addstep { display: flex; gap: var(--space-1); align-items: center; flex-wrap: wrap; }
.qa-overlay-empty { color: var(--text-muted); font-size: var(--text-sm); padding: var(--space-3) 0; }

/* Read-only control-point step preview shown above the builder when editing a QA
   obligation (the builder edits the obligation's added steps below). */
.task-builder-core-preview { margin-bottom: var(--space-4); padding-bottom: var(--space-3); border-bottom: var(--border-width-1) solid var(--border-subtle); }
.qa-overlay-section-label { font-size: var(--text-xs); font-weight: 600; text-transform: uppercase; letter-spacing: var(--letter-spacing-wide); color: var(--text-muted); margin-bottom: var(--space-2); }
.qa-overlay-step--readonly { background: var(--bg-layer-2); }
.qa-overlay-field--readonly { display: flex; gap: var(--space-2); align-items: baseline; }

/* Obligation row, execution columns (PO 2026-09-03): the plan and the last run
   are read live from the schedules and the compliance records. A sub-line
   carries the secondary fact (next fire, result) under the primary one. */
.qa-sched-cell { display: flex; flex-direction: column; gap: var(--space-1); }
.qa-sched-line { color: var(--text-primary); font-size: var(--text-sm); }
.qa-sched-sub { color: var(--text-muted); font-size: var(--text-xs); }
