/*
 * The task widget (assets/js/task.js) on the page shell.
 *
 * The widget's markup was written for Minton: a card per part (parameters, run details, result,
 * history), centred coloured headings, Bootstrap's striped blue progress bar and loud badges. On
 * the shell that reads as a stack of boxes inside a box. Here it becomes flat sections inside
 * whatever surface the page puts around it - a heading with a hairline under it, spacing between
 * sections, and one table look shared with the rest of the shell.
 *
 * HOW IT IS HOOKED. task.js puts fixed task-* classes next to every cls(key, default) - the root is
 * .task-widget, then .task-parameters, .task-actions, .task-details, .task-history and so on. They
 * are hooks, not defaults: a product that overrides a class through options.classes still gets
 * them, so its override keeps working on classic layouts and this file still finds the widget on
 * the shell. A product that wants its own look on the shell as well removes the bundle key
 * shell-task-css (see ShellConfiguration).
 *
 * WHY !important APPEARS. Only against Bootstrap utilities that the default classes carry and that
 * are themselves !important (text-center, text-secondary, mt-5, shadow-sm, bg-success, ...). Every
 * rule is scoped to body.shell, so a classic page is untouched even if the file were loaded there.
 *
 * Bootstrap is 5.1.3: no --bs-btn-* / --bs-card-* component variables, so real properties are set.
 * Loaded from the asset bundle, which the shell links before shell.css; the selectors carry
 * .task-widget so they win regardless of order.
 */

body.shell .task-widget,
body.shell .task-type-picker {
    --task-radius-sm: var(--shell-radius-sm, 4px);
    --task-radius: var(--shell-radius, 6px);
    --task-radius-lg: var(--shell-radius-lg, 8px);
    --task-gap: 28px;

    /* Status colours. The shell's palette has a brand and a neutral scale and nothing semantic, so
       these are the one place a task state gets a colour; each can be themed like the shell's. */
    --task-ok-bg: var(--shell-success-50, #ecfdf5);
    --task-ok-fg: var(--shell-success-700, #047857);
    --task-fail-bg: var(--shell-danger-50, #fef2f2);
    --task-fail-border: var(--shell-danger-200, #fecaca);
    --task-fail-fg: var(--shell-danger-700, #b91c1c);
    --task-run-bg: var(--brand-50);
    --task-run-fg: var(--brand-700);
    --task-wait-bg: var(--sl-100);
    --task-wait-fg: var(--sl-600);
}

/*
 * The dark theme. Only the status colours move, and only these six lines: everything else in this
 * file already reads --sl-* or --brand-*, which the theme re-points.
 *
 * Each pair is a very pale ground carrying a dark ink - #ecfdf5 with #047857 on it - which is
 * legible on a white card and a lit chip on a dark one. The roles swap: a translucent wash of the
 * same hue as the ground, the hue lightened as the ink. Hue is preserved because a reader tells
 * FINISHED from FAILED by colour before reading the word.
 *
 * --shell-success-* and --shell-danger-* stay in front: an application that compiles its own
 * semantic scale still wins, exactly as in light mode.
 */
[data-bs-theme="dark"] body.shell .task-widget {
    --task-ok-bg: var(--shell-success-dark-bg, rgba(25, 135, 84, .18));
    --task-ok-fg: var(--shell-success-dark-fg, #6ee7a8);
    --task-fail-bg: var(--shell-danger-dark-bg, rgba(220, 53, 69, .18));
    --task-fail-border: var(--shell-danger-dark-border, rgba(220, 53, 69, .38));
    --task-fail-fg: var(--shell-danger-dark-fg, #ff8d98);
    --task-wait-bg: var(--sl-200);
    --task-wait-fg: var(--sl-600);
}

body.shell .task-widget {
    color: var(--sl-800);
}

/* ── sections ───────────────────────────────────────────────────────── */

/* Every part that used to be a card is a flat section. */
body.shell .task-widget .task-parameters,
body.shell .task-widget .task-details,
body.shell .task-widget .task-result,
body.shell .task-widget .task-history {
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none !important;
    margin: 0 0 var(--task-gap) !important;
    padding: 0 !important;
}

body.shell .task-widget .task-details > .card-body,
body.shell .task-widget .task-result > .card-body,
body.shell .task-widget .task-history > .card-body {
    padding: 0 !important;
}

body.shell .task-widget .task-section-title {
    text-align: left !important;
    color: var(--sl-900) !important;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: -.01em;
    line-height: 1.4;
    margin: 0 0 14px !important;
    padding: 0 0 8px;
    border-bottom: 1px solid var(--sl-200);
}

body.shell .task-widget pre,
body.shell .task-widget .task-log {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 11.5px;
    line-height: 1.55;
    color: var(--sl-700);
    margin: 0;
}

/* ── controls ───────────────────────────────────────────────────────── */

body.shell .task-widget .form-control,
body.shell .task-widget .form-select,
body.shell .task-widget .page-link,
body.shell .task-widget .btn {
    border-radius: var(--task-radius);
}

body.shell .task-widget .form-control {
    min-height: 32px;
}

body.shell .task-widget textarea.form-control {
    min-height: 64px;
}

body.shell .task-widget .form-label {
    display: block;
}

body.shell .task-widget .form-text,
body.shell .task-widget small.form-text {
    display: block;
    font-size: 11.5px;
    color: var(--sl-500) !important;
    margin-top: 4px !important;
}

/* A list's description sits between its label and its input, not under the input. */
body.shell .task-widget p.form-text {
    margin: 0 0 6px !important;
}

body.shell .task-widget .form-check-input {
    border-color: var(--sl-300);
    border-radius: var(--task-radius-sm);
}

body.shell .task-widget .form-check-input:checked {
    background-color: var(--brand-600);
    border-color: var(--brand-600);
}

body.shell .task-widget .form-check-input:focus {
    border-color: var(--brand-500);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-500) 14%, transparent);
}

body.shell .task-widget .form-check-label {
    color: var(--sl-700);
}

body.shell .task-widget .text-danger {
    color: var(--task-fail-fg) !important;
}

body.shell .task-widget .spinner-border.text-primary {
    color: var(--brand-600) !important;
}

/* vue-select, which draws its own control instead of a .form-control */
body.shell .task-widget .v-select .vs__dropdown-toggle {
    min-height: 32px;
    padding: 0 0 2px;
    background: var(--sl-surface, #fff);
    border: 1px solid var(--sl-200);
    border-radius: var(--task-radius);
}

body.shell .task-widget .v-select .vs__selected {
    font-size: 12.5px;
    color: var(--sl-800);
}

body.shell .task-widget .v-select.vs--open .vs__dropdown-toggle {
    border-color: var(--brand-500);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-500) 14%, transparent);
}

body.shell .task-widget .v-select .vs__open-indicator,
body.shell .task-widget .v-select .vs__clear {
    fill: var(--sl-400);
}

body.shell .task-widget .v-select.is-invalid .vs__dropdown-toggle {
    border-color: var(--task-fail-fg);
}

/* Buttons the shell stylesheet does not draw. btn-outline-error is not a Bootstrap class at all -
   the widget's cancel and clear buttons rendered as bare text on every layout. */
body.shell .task-widget .btn-outline-secondary,
body.shell .task-widget .btn-success {
    color: var(--sl-700);
    background-color: var(--sl-surface, #fff);
    border-color: var(--sl-200);
    box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
}

body.shell .task-widget .btn-outline-secondary:hover,
body.shell .task-widget .btn-success:hover {
    color: var(--sl-900);
    background-color: var(--sl-50);
    border-color: var(--sl-300);
}

body.shell .task-widget .btn-outline-primary,
body.shell .task-widget .btn-outline-success {
    color: var(--brand-700);
    background-color: var(--sl-surface, #fff);
    border-color: var(--brand-200);
}

body.shell .task-widget .btn-outline-primary:hover,
body.shell .task-widget .btn-outline-success:hover {
    color: var(--brand-800);
    background-color: var(--brand-50);
    border-color: var(--brand-200);
}

body.shell .task-widget .btn-outline-error,
body.shell .task-widget .btn-outline-danger {
    color: var(--task-fail-fg);
    background-color: var(--sl-surface, #fff);
    border-color: var(--sl-200);
}

body.shell .task-widget .btn-outline-error:hover,
body.shell .task-widget .btn-outline-danger:hover {
    color: var(--task-fail-fg);
    background-color: var(--task-fail-bg);
    border-color: var(--task-fail-border);
}

body.shell .task-widget .btn-danger {
    color: var(--task-fail-fg);
    background-color: var(--task-fail-bg);
    border-color: var(--task-fail-border);
}

body.shell .task-widget .btn-danger:hover {
    color: #fff;
    background-color: var(--task-fail-fg);
    border-color: var(--task-fail-fg);
}

body.shell .task-widget .btn-link {
    color: var(--brand-600);
    font-weight: 600;
    text-decoration: none;
}

body.shell .task-widget .btn-link:hover {
    color: var(--brand-800);
}

body.shell .task-widget .btn:disabled,
body.shell .task-widget .btn.disabled {
    opacity: .45;
    box-shadow: none;
}

/* ── parameters ─────────────────────────────────────────────────────── */

body.shell .task-widget .task-parameters {
    max-width: 880px;
}

body.shell .task-widget .task-parameters .task-parameters {
    max-width: none;
    margin: 0 !important;
}

/* The form is a .row.card-body holding one .row per display row. Take the gutters out of both
   and space the rows evenly instead of by m-1 p-1 mt-2. */
body.shell .task-widget .task-parameters > .card-body {
    --bs-gutter-x: 0;
    --bs-gutter-y: 0;
    margin: 0;
    padding: 0;
}

/* No gutter padding, so labels line up with the section heading; columns get a gap instead. */
body.shell .task-widget .task-parameter-row {
    --bs-gutter-x: 0;
    column-gap: 20px;
    flex-wrap: nowrap;
    margin: 0 !important;
    padding: 0 !important;
}

@media (max-width: 767.98px) {
    body.shell .task-widget .task-parameter-row {
        flex-wrap: wrap;
        row-gap: 18px;
    }

    body.shell .task-widget .task-parameter-row > .col {
        flex: 1 1 100%;
    }
}

body.shell .task-widget .task-parameter-row + .task-parameter-row {
    margin-top: 18px !important;
}

/* A structured parameter is a group, marked by a rule down its left, not a nested card. */
body.shell .task-widget .task-parameter-group {
    border: 0;
    border-left: 2px solid var(--sl-200);
    border-radius: 0;
    background: transparent;
    box-shadow: none !important;
    padding: 2px 0 2px 14px;
    margin: 0;
}

body.shell .task-widget .task-parameter-group > .card-header {
    padding: 0;
    background: transparent;
    border: 0;
}

body.shell .task-widget .task-parameter-group > .card-header .card-title {
    font-size: 12px;
    font-weight: 700;
    color: var(--sl-800);
    margin: 0;
}

body.shell .task-widget .task-parameter-group > .card-body {
    padding: 12px 0 0;
}

body.shell .task-widget .task-checkbox-list {
    background: var(--sl-surface, #fff);
    border: 1px solid var(--sl-200) !important;
    border-radius: var(--task-radius) !important;
    padding: 6px 10px !important;
}

body.shell .task-widget .task-checkbox-list .form-check {
    margin: 0;
    padding-top: 3px;
    padding-bottom: 3px;
}

body.shell .task-widget .task-checkbox-list.is-invalid {
    border-color: var(--task-fail-fg) !important;
}

body.shell .task-widget .advanced-parameter-list,
body.shell .task-widget [data-bs-toggle="collapse"].bg-light {
    background: var(--sl-50) !important;
    border: 1px solid var(--sl-200) !important;
    border-radius: var(--task-radius);
    box-shadow: none !important;
}

/* ── run controls ───────────────────────────────────────────────────── */

body.shell .task-widget .task-actions {
    --bs-gutter-x: 0;
    margin: 0 0 var(--task-gap) !important;
}

body.shell .task-widget .task-actions > [class*="col"] {
    flex: 1 1 100%;
    width: 100%;
    max-width: 100%;
}

body.shell .task-widget .task-actions .form-check {
    margin: 0 0 10px !important;
}

body.shell .task-widget .task-actions .d-flex {
    flex-wrap: wrap;
    gap: 8px;
}

body.shell .task-widget .task-actions .ms-2,
body.shell .task-widget .task-actions .ms-3 {
    margin-left: 0 !important;
}

/* The schedule column renders even when scheduling is off; empty, it would add a gap. */
body.shell .task-widget .task-actions .flex-column:empty {
    display: none !important;
}

body.shell .task-widget .task-actions .btn-sm {
    font-size: 12.5px;
    padding: 6px 14px;
}

body.shell .task-widget .task-actions .btn-primary {
    min-width: 96px;
}

body.shell .task-widget .task-actions .form-control-sm {
    min-height: 32px;
    font-size: 12.5px;
    border-radius: var(--task-radius);
}

/* ── the running task ───────────────────────────────────────────────── */

body.shell .task-widget .task-stats {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: wrap;
    justify-content: flex-start !important;
    gap: 12px 40px;
    text-align: left !important;
    margin-bottom: 14px !important;
}

body.shell .task-widget .task-stats .card-text {
    margin: 0 !important;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    color: var(--sl-800);
}

body.shell .task-widget .task-stats strong {
    display: block;
    margin-bottom: 3px;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--sl-500);
}

body.shell .task-widget .task-stats br {
    display: none;
}

body.shell .task-widget .task-stats .text-info {
    color: var(--sl-800) !important;
}

body.shell .task-widget .task-progress {
    height: 16px !important;
    margin-bottom: 12px !important;
    background: var(--sl-100);
    border-radius: var(--task-radius-sm);
    box-shadow: inset 0 0 0 1px var(--sl-200);
    font-size: 10px;
    overflow: hidden;
}

body.shell .task-widget .task-progress .progress-bar {
    background-color: var(--brand-600);
    background-image: none;
    font-weight: 600;
    transition: width .4s ease;
}

body.shell .task-widget .task-step {
    font-size: 12.5px;
    color: var(--sl-700);
    margin-bottom: 12px !important;
}

body.shell .task-widget .task-step strong {
    font-weight: 600;
    color: var(--sl-800);
    margin-right: 4px;
}

body.shell .task-widget .task-log-box {
    background: var(--sl-50);
    border: 1px solid var(--sl-200) !important;
    border-radius: var(--task-radius) !important;
    padding: 10px 12px !important;
    margin-bottom: 12px !important;
}

body.shell .task-widget .task-log-title {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--sl-500) !important;
    margin-bottom: 6px !important;
}

body.shell .task-widget .task-log-copy {
    top: 6px !important;
    right: 8px !important;
    color: var(--sl-400);
    font-size: 15px;
    line-height: 1;
}

body.shell .task-widget .task-log-copy:hover {
    color: var(--brand-600);
}

body.shell .task-widget .task-failure {
    background: var(--task-fail-bg);
    border: 1px solid var(--task-fail-border);
    border-radius: var(--task-radius);
    color: var(--task-fail-fg);
    padding: 10px 12px !important;
}

body.shell .task-widget .task-failure .alert-heading {
    font-size: 12px;
    font-weight: 700;
    color: var(--task-fail-fg);
}

/*
 * Colour only. The wrap and the cap that keep a stack trace inside the alert are inline on the
 * element in task.js, not here: this file is scoped to body.shell, and the widget is mounted on
 * classic pages too (see ShellConfiguration#theShellStylesTheTaskWidget - searchindex,
 * maintenance, init and products' own pages load task.js themselves). A cap written here would
 * leave exactly those pages with the unwrapped, uncapped trace. The log box above it caps itself
 * inline for the same reason. .task-failure-trace is a hook for a product that wants its own cap.
 */
body.shell .task-widget .task-failure pre {
    color: var(--task-fail-fg);
}

/* ── status ─────────────────────────────────────────────────────────── */

body.shell .task-widget .task-status {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 8px 2px 7px;
    border-radius: var(--task-radius-sm);
    font-size: 10.5px !important;
    font-weight: 700;
    letter-spacing: .03em;
    line-height: 1.6;
    white-space: nowrap;
    background: var(--task-wait-bg) !important;
    color: var(--task-wait-fg) !important;
}

body.shell .task-widget .task-status::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
}

body.shell .task-widget .task-status[data-status="FINISHED"] {
    background: var(--task-ok-bg) !important;
    color: var(--task-ok-fg) !important;
}

body.shell .task-widget .task-status[data-status="FAILED"] {
    background: var(--task-fail-bg) !important;
    color: var(--task-fail-fg) !important;
}

body.shell .task-widget .task-status[data-status="RUNNING"] {
    background: var(--task-run-bg) !important;
    color: var(--task-run-fg) !important;
}

body.shell .task-widget .task-status[data-status="RUNNING"]::before {
    animation: task-status-pulse 1.4s ease-in-out infinite;
}

@keyframes task-status-pulse {
    50% {
        opacity: .3;
    }
}

/* ── result ─────────────────────────────────────────────────────────── */

body.shell .task-widget .task-result pre {
    background: var(--sl-50);
    border: 1px solid var(--sl-200);
    border-radius: var(--task-radius);
    padding: 10px 12px;
    margin: 0 !important;
}

/* ── history ────────────────────────────────────────────────────────── */

body.shell .task-widget .task-retention {
    background: var(--sl-50);
    border: 1px solid var(--sl-200);
    border-radius: var(--task-radius);
    color: var(--sl-600);
    font-size: 12px;
    padding: 8px 12px;
    margin: 0 0 12px !important;
}

body.shell .task-widget .task-retention strong {
    color: var(--sl-800);
}

body.shell .task-widget .task-history-table {
    --bs-table-striped-bg: transparent;
    --bs-table-hover-bg: var(--sl-50);
}

body.shell .task-widget .task-history-table > tbody > tr > td {
    padding: 8px 12px;
    border-bottom: 1px solid var(--sl-100);
}

body.shell .task-widget .task-history-table > tbody > tr > td:first-child {
    font-variant-numeric: tabular-nums;
    color: var(--sl-500);
}

body.shell .task-widget .task-history-table .btn-link {
    padding: 0;
    font-size: 12px;
}

body.shell .task-widget .task-history-table .btn {
    white-space: nowrap;
}

/* Date/time. Without a floor a narrow screen squeezes it into a word per line; the table scrolls
   inside .table-responsive instead. */
body.shell .task-widget .task-history-table > tbody > tr > td:nth-child(5) {
    min-width: 200px;
}

/* "Toggle parameters" is a primary button on every row by default; in a table it reads as the
   page's main action repeated eight times. */
body.shell .task-widget .task-history-table .btn-primary {
    font-size: 11.5px;
    padding: 3px 9px;
    color: var(--sl-700);
    background-color: var(--sl-surface, #fff);
    border-color: var(--sl-200);
    box-shadow: none;
}

body.shell .task-widget .task-history-table .btn-primary:hover {
    background-color: var(--sl-50);
}

body.shell .task-widget .task-history-table textarea.form-control {
    min-width: 220px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 11px;
}

body.shell .task-widget .task-history-table .btn-sm + .btn-sm {
    margin-left: 6px;
}

body.shell .task-widget .task-history-table > tfoot td {
    border: 0;
    padding: 14px 0 0;
    background: transparent;
}

body.shell .task-widget .task-pagination {
    gap: 6px;
    margin: 0;
}

body.shell .task-widget .task-pagination .page-link {
    font-size: 12px;
    padding: 4px 11px;
    color: var(--sl-700);
    background: var(--sl-surface, #fff);
    border: 1px solid var(--sl-200);
    border-radius: var(--task-radius) !important;
    margin: 0;
}

body.shell .task-widget .task-pagination .page-link:hover {
    color: var(--sl-900);
    background: var(--sl-50);
}

body.shell .task-widget .task-pagination .page-link:focus {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-500) 14%, transparent);
}

body.shell .task-widget .task-pagination .page-item.disabled .page-link {
    color: var(--sl-400);
    background: var(--sl-surface, #fff);
    opacity: .7;
}

/* ── modals ─────────────────────────────────────────────────────────── */

body.shell .task-widget .task-modal {
    background-color: rgba(15, 23, 42, .45) !important;
    overflow-y: auto;
}

/* The error and result modals put bg-danger on the dialog; behind a rounded panel it only shows
   as red corners. */
body.shell .task-widget .task-modal .modal-dialog {
    max-width: 880px;
    margin: 56px auto;
    background: transparent !important;
}

body.shell .task-widget .task-modal .modal-content {
    border: 1px solid var(--sl-200);
    border-radius: var(--task-radius-lg);
    box-shadow: 0 20px 40px rgba(15, 23, 42, .18);
}

body.shell .task-widget .task-modal .modal-header {
    padding: 12px 16px;
    border-bottom: 1px solid var(--sl-200);
}

body.shell .task-widget .task-modal .modal-title {
    font-size: 14px;
    font-weight: 700;
    color: var(--sl-900);
}

body.shell .task-widget .task-modal .btn-close {
    font-size: 11px;
}

body.shell .task-widget .task-modal .modal-body {
    padding: 12px 16px 16px;
}

body.shell .task-widget .task-modal .modal-body > .btn-link {
    padding: 0;
    margin-bottom: 8px !important;
}

body.shell .task-widget .task-modal .task-log {
    background: var(--sl-50);
    border: 1px solid var(--sl-200);
    border-radius: var(--task-radius);
    padding: 10px 12px;
}

/* ── the task type picker on admin/system/tasks.html ────────────────── */

body.shell .task-type-picker {
    max-width: 560px;
    margin-bottom: var(--task-gap);
}

body.shell .task-type-picker .text-muted {
    font-size: 12px;
    margin: 0 0 8px;
}

body.shell .task-type-picker .select2-container--default .select2-selection--single {
    height: 32px;
    border: 1px solid var(--sl-200);
    border-radius: var(--task-radius);
    background: var(--sl-surface, #fff);
}

body.shell .task-type-picker .select2-container--default .select2-selection--single .select2-selection__rendered {
    line-height: 30px;
    padding-left: 10px;
    font-size: 12.5px;
    color: var(--sl-800);
}

body.shell .task-type-picker .select2-container--default .select2-selection--single .select2-selection__placeholder {
    color: var(--sl-400);
}

body.shell .task-type-picker .select2-container--default .select2-selection--single .select2-selection__arrow {
    height: 30px;
}

body.shell .task-type-picker .select2-container--default.select2-container--open .select2-selection--single,
body.shell .task-type-picker .select2-container--default.select2-container--focus .select2-selection--single {
    border-color: var(--brand-500);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-500) 14%, transparent);
}

/* ── narrow screens ─────────────────────────────────────────────────── */

@media (max-width: 767.98px) {
    body.shell .task-widget,
    body.shell .task-type-picker {
        --task-gap: 22px;
    }

    body.shell .task-widget .task-modal .modal-dialog {
        width: auto !important;
        margin: 12px;
    }

    body.shell .task-widget .task-stats {
        gap: 10px 24px;
    }
}

@media (prefers-reduced-motion: reduce) {
    body.shell .task-widget .task-status[data-status="RUNNING"]::before {
        animation: none;
    }

    body.shell .task-widget .task-progress .progress-bar {
        transition: none;
    }
}
