/* Qi-styled stylesheet for the Preservica Sync web UI.
 *
 * Colour palette (eyeballed from a Qi 6.2 dashboard screenshot):
 *   --qi-bg      : light page background           #f2f2f2
 *   --qi-surface : card surfaces                   #ffffff
 *   --qi-ink     : primary text                    #222222
 *   --qi-muted   : secondary text                  #6b6b6b
 *   --qi-border  : hairline borders                #e2e2e2
 *   --qi-header  : top bar background              #2c2c2c
 *   --qi-accent  : primary action / brand accent   #e94e2c (orange-red)
 *   --qi-accent2 : hover / pressed state           #c93f20
 *   --qi-ok      : success badge                   #1e7e34
 *   --qi-warn    : warning badge                   #c98415
 *   --qi-err     : error badge                     #c0392b
 */

:root {
    --qi-bg:        #f2f2f2;
    --qi-surface:   #ffffff;
    --qi-ink:       #222;
    --qi-muted:     #6b6b6b;
    --qi-border:    #e2e2e2;
    --qi-header:    #5a5a5a;   /* mid-dark grey, matches Qi 6.2 admin top bar */
    --qi-header-ink:#f4f4f4;
    --qi-header-mute:#cdccc2;  /* subdued text on the dark bar (matches logo stroke) */
    --qi-accent:    #e94e2c;
    --qi-accent2:   #c93f20;
    --qi-ok:        #1e7e34;
    --qi-warn:      #c98415;
    --qi-err:       #c0392b;
    --qi-blue:      #2c6fa3;
    --qi-radius:    4px;
    --qi-mono:      "SF Mono", Menlo, Consolas, "Courier New", monospace;
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    background: var(--qi-bg);
    color: var(--qi-ink);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    font-size: 14px;
    line-height: 1.4;
}

a { color: var(--qi-blue); text-decoration: none; }
a:hover { text-decoration: underline; }

code { font-family: var(--qi-mono); font-size: 12.5px; background: #f5f5f5; padding: 1px 4px; border-radius: 3px; color: #555; }

/* ---------- header ---------- */

.qi-header {
    display: flex;
    align-items: center;
    gap: 24px;
    background: var(--qi-header);
    color: var(--qi-header-ink);
    padding: 0 20px;
    height: 48px;
    box-shadow: 0 1px 0 rgba(0,0,0,0.15);
    position: sticky;
    top: 0;
    z-index: 10;
}

.qi-header__brand {
    display: flex;
    align-items: center;
    gap: 12px;
    color: var(--qi-header-ink);
    font-weight: 600;
}
.qi-header__brand:hover { text-decoration: none; }

/* Qi monogram — inline SVG so we can recolour both fills via
 * `currentColor` (light grey on the dark header, ink on the white login
 * card). The mark itself is 74×190 (aspect ≈ 0.39, i.e. tall and slim),
 * so we drive the size from the height; width auto-derives. */
.qi-logo {
    display: inline-block;
    height: 26px;
    width: auto;
    vertical-align: middle;
    color: var(--qi-header-mute);
    flex: 0 0 auto;
}
.qi-logo--lg {
    height: 64px;
    width: auto;
    color: var(--qi-ink);
}

.qi-header__title {
    color: #ddd;
    font-weight: 500;
    font-size: 14px;
    letter-spacing: 0.2px;
}

.qi-header__nav {
    display: flex;
    gap: 0;
    margin-left: 12px;
    height: 100%;
    align-items: stretch;
}
.qi-header__nav a {
    color: var(--qi-header-mute);
    padding: 0 14px;
    display: flex;
    align-items: center;
    font-weight: 500;
    border-bottom: 2px solid transparent;
}
.qi-header__nav a:hover { color: #fff; text-decoration: none; }
.qi-header__nav a.is-active {
    color: #fff;
    border-bottom-color: var(--qi-accent);
}

.qi-header__user {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--qi-header-mute);
}
.qi-header__user-name { font-size: 13px; }

/* Logout = the red power icon in the top-right corner, matching the
 * Qi 6.2 admin UI. Always shows the accent stroke; hover fills the
 * circle with the accent so it reads as a destructive action. */
.qi-header__logout {
    background: transparent;
    border: 1px solid var(--qi-accent);
    color: var(--qi-accent);
    width: 28px;
    height: 28px;
    border-radius: 50%;
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
}
.qi-header__logout:hover { background: var(--qi-accent); color: #fff; }

/* ---------- main / footer ---------- */

.qi-main {
    max-width: 1200px;
    margin: 24px auto;
    padding: 0 20px 60px;
}

.qi-footer {
    text-align: center;
    color: var(--qi-muted);
    font-size: 12px;
    padding: 12px 0 24px;
}
.qi-footer__sep { margin: 0 8px; }

/* ---------- sections ---------- */

.qi-section {
    background: var(--qi-surface);
    border: 1px solid var(--qi-border);
    border-radius: var(--qi-radius);
    padding: 20px 24px;
    margin-bottom: 20px;
}
.qi-section + .qi-section {
    /* Slightly tighter rhythm between consecutive panels so the page
     * scans as one continuous dashboard rather than three loosely
     * stacked boxes. */
    margin-top: 0;
}
.qi-section__head {
    margin-bottom: 16px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--qi-border);
}
.qi-section__head:last-child {
    /* No trailing content under the head → no need for the divider. */
    border-bottom: 0;
    padding-bottom: 0;
    margin-bottom: 0;
}
.qi-section__head h2 {
    margin: 0 0 2px;
    font-size: 16px;
    font-weight: 600;
    letter-spacing: 0.1px;
}
.qi-section__head p {
    margin: 0;
    color: var(--qi-muted);
    font-size: 12.5px;
}
.qi-section__head--row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}

/* ---------- card grid ---------- */

.qi-group__title {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: var(--qi-muted);
    margin: 0 0 12px;
    padding: 0;
    border: 0;
}
.qi-group + .qi-group {
    margin-top: 24px;
}
.qi-group__desc {
    text-transform: none;
    letter-spacing: 0;
    font-weight: 400;
    margin-left: 8px;
    color: #999;
}

.qi-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
    /* Cards size to their own content. Forcing equal-height rows looks
     * "tidy" in the abstract but leaves a giant void in cards with few
     * fields (the form gets pinned to the bottom of an over-tall card),
     * which is worse than natural variation. */
    gap: 14px;
    align-items: start;
}

.qi-card {
    border: 1px solid var(--qi-border);
    border-radius: var(--qi-radius);
    background: #fcfcfc;
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
}
.qi-card__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 6px;
}
.qi-card__head h4 {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
}
.qi-card__cmd {
    font-size: 11px;
    color: var(--qi-muted);
    background: transparent;
    padding: 0;
    /* Ellipsise long command names so the head row never wraps. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 60%;
}
.qi-card__desc {
    margin: 0 0 12px;
    color: var(--qi-muted);
    font-size: 12.5px;
    line-height: 1.45;
}
.qi-card__form {
    border-top: 1px dashed var(--qi-border);
    padding-top: 12px;
    /* Sits naturally right after the description — no auto-margin push.
     * Cards in the same row may end up different heights, which is fine
     * and reads much cleaner than a void between description and form. */
}
.qi-card__fields {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 12px;
}
.qi-card__actions {
    display: flex;
    justify-content: flex-end;
}

/* ---------- forms ---------- */

.qi-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.qi-field > span {
    font-size: 12px;
    color: var(--qi-muted);
    font-weight: 500;
}
.qi-field input[type="text"],
.qi-field input[type="number"],
.qi-field input[type="password"] {
    border: 1px solid var(--qi-border);
    border-radius: 3px;
    padding: 6px 8px;
    background: #fff;
    font-size: 13px;
    font-family: inherit;
}
.qi-field input:focus {
    outline: none;
    border-color: var(--qi-accent);
    box-shadow: 0 0 0 2px rgba(233, 78, 44, 0.15);
}
.qi-field small {
    color: #999;
    font-size: 11px;
}

/* Two-column grid: [label | input], with the help text wrapping below
 * the input on its own row. The previous flex+`flex-basis: 100%` shape
 * relied on flex-wrap which we never set, so on narrow cards the help
 * text overflowed into the gutter — visible as that ragged column of
 * vertical text outside the card body. Grid handles this natively. */
.qi-field--inline {
    display: grid;
    grid-template-columns: 110px minmax(0, 1fr);
    align-items: center;
    column-gap: 8px;
    row-gap: 4px;
}
.qi-field--inline > span {
    margin: 0;
}
.qi-field--inline > input {
    /* `min-width: 0` is critical — grid items default to `min-width: auto`
     * which respects intrinsic input width and forces overflow on narrow
     * cards. The `minmax(0, 1fr)` on the column above is the other half. */
    min-width: 0;
    width: 100%;
}
.qi-field--inline > small {
    grid-column: 2;
    margin: 0;
    line-height: 1.35;
}

/* Vertical layout: label on top, full-width input/textarea below. Used
 * for fields where the input is too wide for the 110px-label grid (e.g.
 * a paste-list textarea). */
.qi-field--block {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.qi-field--block > span,
.qi-field--block > label { margin: 0; font-size: 12px; color: var(--qi-muted); font-weight: 500; }
.qi-field--block textarea {
    border: 1px solid var(--qi-border);
    border-radius: 3px;
    padding: 6px 8px;
    background: #fff;
    font-size: 13px;
    font-family: var(--qi-mono);
    width: 100%;
    min-width: 0;
    resize: vertical;
    line-height: 1.4;
}
.qi-field--block textarea:focus {
    outline: none;
    border-color: var(--qi-accent);
    box-shadow: 0 0 0 2px rgba(233, 78, 44, 0.15);
}
.qi-field--block > small {
    color: #999;
    font-size: 11px;
    line-height: 1.35;
}

.qi-check {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
}
.qi-check small {
    color: #999;
    font-size: 11px;
    margin-left: 4px;
}
.qi-check--inline { margin-left: 16px; }

.qi-inline-form { display: inline; margin: 0; }

/* ---------- buttons ---------- */

.qi-btn {
    appearance: none;
    -webkit-appearance: none;
    border: 1px solid var(--qi-border);
    background: #f7f7f7;
    color: var(--qi-ink);
    padding: 6px 14px;
    border-radius: 3px;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    font-family: inherit;
    line-height: 1.4;
    text-decoration: none;
    display: inline-block;
}
.qi-btn:hover { background: #ececec; text-decoration: none; }
.qi-btn--primary {
    background: var(--qi-accent);
    border-color: var(--qi-accent);
    color: #fff;
}
.qi-btn--primary:hover { background: var(--qi-accent2); border-color: var(--qi-accent2); }
.qi-btn--danger {
    background: #fff;
    border-color: var(--qi-err);
    color: var(--qi-err);
}
.qi-btn--danger:hover { background: var(--qi-err); color: #fff; }
.qi-btn--ghost {
    background: transparent;
    border-color: var(--qi-border);
    color: var(--qi-muted);
}
.qi-btn--ghost:hover { background: #f0f0f0; color: var(--qi-ink); }
.qi-btn--small { padding: 4px 10px; font-size: 12px; }
.qi-btn--block { width: 100%; margin-top: 12px; }

/* ---------- table ---------- */

.qi-table {
    width: 100%;
    border-collapse: collapse;
    border: 1px solid var(--qi-border);
    background: #fff;
}
.qi-table th,
.qi-table td {
    text-align: left;
    padding: 8px 12px;
    border-bottom: 1px solid var(--qi-border);
    font-size: 13px;
}
.qi-table th {
    background: #fafafa;
    font-weight: 600;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--qi-muted);
}
.qi-table tbody tr:last-child td { border-bottom: none; }
.qi-table tbody tr:hover { background: #fafafa; }

.qi-job__link { display: flex; flex-direction: column; }
.qi-job__label { color: var(--qi-ink); font-weight: 500; }
.qi-job__id { font-family: var(--qi-mono); font-size: 11px; color: var(--qi-muted); }

.qi-tar { text-align: right; }
.qi-dim { color: #c0c0c0; }
.qi-empty {
    padding: 30px;
    text-align: center;
    color: var(--qi-muted);
    background: #fafafa;
    border: 1px dashed var(--qi-border);
    border-radius: var(--qi-radius);
}

/* ---------- badges / pills ---------- */

.qi-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    background: #eee;
    color: #555;
}
.qi-badge--is-running  { background: #cee8ff; color: #1d4f86; }
.qi-badge--is-stopping { background: #fff3cd; color: #856404; }
.qi-badge--is-success  { background: #d4edda; color: #155724; }
.qi-badge--is-failed   { background: #f8d7da; color: #721c24; }
.qi-badge--is-stopped  { background: #e2e3e5; color: #383d41; }
.qi-badge--is-unknown  { background: #fff; color: #999; border: 1px solid var(--qi-border); }

.qi-pill {
    display: inline-block;
    padding: 1px 8px;
    border-radius: 10px;
    font-size: 11px;
    background: #eee;
    color: #555;
}

/* ---------- job page ---------- */

.qi-back {
    display: inline-block;
    margin-right: 6px;
    color: var(--qi-muted);
    font-weight: 400;
    text-decoration: none;
}
.qi-back:hover { color: var(--qi-accent); text-decoration: none; }

.qi-job-meta {
    margin: 4px 0 0;
    color: var(--qi-muted);
    font-size: 12px;
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    align-items: center;
}
.qi-job-meta__right {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 12px;
    color: var(--qi-muted);
}

.qi-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 12px;
    margin: 18px 0;
}
.qi-stat {
    background: #fafafa;
    border: 1px solid var(--qi-border);
    padding: 10px 14px;
    border-radius: var(--qi-radius);
}
.qi-stat__k { font-size: 11px; text-transform: uppercase; color: var(--qi-muted); letter-spacing: 0.5px; }
.qi-stat__v { font-size: 14px; font-weight: 500; margin-top: 4px; font-family: var(--qi-mono); }

.qi-job-actions {
    display: flex;
    gap: 10px;
    align-items: center;
    margin-bottom: 12px;
}

.qi-log {
    background: #1d1f21;
    color: #e3e3e3;
    padding: 14px 16px;
    border-radius: var(--qi-radius);
    font-family: var(--qi-mono);
    font-size: 12px;
    line-height: 1.45;
    max-height: 540px;
    overflow: auto;
    white-space: pre-wrap;
    word-break: break-word;
    margin: 0;
}

/* ---------- toast / alert ---------- */

.qi-toast-wrap {
    max-width: 1200px;
    margin: 12px auto 0;
    padding: 0 20px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.qi-toast {
    padding: 10px 14px;
    border-radius: var(--qi-radius);
    font-size: 13px;
    border: 1px solid transparent;
}
.qi-toast--ok  { background: #d4edda; color: #155724; border-color: #c3e6cb; }
.qi-toast--err { background: #f8d7da; color: #721c24; border-color: #f5c6cb; }

.qi-alert {
    padding: 10px 14px;
    border-radius: var(--qi-radius);
    font-size: 13px;
    margin-bottom: 12px;
}
.qi-alert--err { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }

/* ---------- progress bars ---------- */

.qi-progress {
    position: relative;
    height: 6px;
    width: 100%;
    background: #eee;
    border-radius: 4px;
    overflow: hidden;
    margin: 6px 0 4px;
}
.qi-progress--inline {
    height: 4px;
    margin: 2px 0 4px;
}
.qi-progress--lg {
    height: 12px;
    border-radius: 6px;
    margin: 6px 0 0;
}
.qi-progress__bar {
    height: 100%;
    background: linear-gradient(90deg, var(--qi-accent), var(--qi-accent2));
    transition: width 600ms ease-out;
}
.qi-progress__txt {
    font-size: 12px;
    color: var(--qi-muted);
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
}
.qi-progress__txt strong {
    color: var(--qi-ink);
    font-weight: 600;
}

.qi-progress-block {
    margin: 8px 0 16px;
    padding: 12px 14px;
    background: #fafafa;
    border: 1px solid var(--qi-border);
    border-radius: var(--qi-radius);
}
.qi-progress-block[hidden] { display: none; }
.qi-progress-block__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 6px;
}
.qi-progress-block__pct {
    font-size: 14px;
}
.qi-progress-block__pct strong {
    font-size: 18px;
    font-weight: 600;
    margin-right: 8px;
    color: var(--qi-ink);
    font-family: var(--qi-mono);
}

.qi-progress-cell {
    min-width: 200px;
}

.qi-table--jobs td {
    vertical-align: middle;
}

.qi-row--stalled td {
    background: #fff7e8 !important;
}
.qi-stale {
    color: var(--qi-warn) !important;
    font-weight: 500;
}

.qi-alert--warn {
    background: #fff3cd;
    color: #856404;
    border: 1px solid #ffeeba;
}
.qi-alert__detail {
    margin-top: 6px;
    font-size: 12px;
    color: #6e5400;
}
.qi-alert__detail code {
    background: rgba(0,0,0,0.04);
    color: #6e5400;
}

/* ---------- stats panel ---------- */

.qi-stats-section__meta {
    font-size: 12px;
    color: var(--qi-muted);
    display: flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}

.qi-statgrid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    /* `1fr` rows so every card in the row shares the tallest card's
     * height. Combined with `margin-top: auto` on the accessory rows
     * below, that gives us "label + value tight at the top, fine-print
     * pinned to the bottom" across the row. */
    grid-auto-rows: 1fr;
    gap: 12px;
    margin-bottom: 16px;
}
.qi-statcard {
    background: #fafafa;
    border: 1px solid var(--qi-border);
    border-left: 3px solid var(--qi-border);
    border-radius: var(--qi-radius);
    padding: 12px 14px;
    /* Plain top-anchored stack. Cards with no sub/progress just leave
     * empty space at the bottom rather than floating the big number
     * down. Accessory rows below use `margin-top: auto` to slide to
     * the bottom so fine-print aligns across the row. */
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-height: 86px;
}
.qi-statcard--ok   { border-left-color: var(--qi-ok); }
.qi-statcard--warn { border-left-color: var(--qi-warn); }
.qi-statcard--err  { border-left-color: var(--qi-err); }
.qi-statcard__k {
    font-size: 11px;
    text-transform: uppercase;
    color: var(--qi-muted);
    letter-spacing: 0.5px;
}
.qi-statcard__v {
    font-family: var(--qi-mono);
    font-size: 20px;
    font-weight: 600;
    color: var(--qi-ink);
    line-height: 1.15;
    /* Keep value tight against its label — overrides the 4px flex gap.
     * Without this the headline number drifts down slightly which
     * reads as misaligned between cards that have a sub line and
     * those that don't. */
    margin-top: 2px;
}
.qi-statcard__v small {
    font-family: inherit;
    font-size: 11px;
    color: var(--qi-muted);
    font-weight: 400;
    margin-left: 4px;
    white-space: nowrap;
}
.qi-statcard__sub {
    font-size: 11px;
    color: var(--qi-muted);
    line-height: 1.4;
    /* Pin accessory rows to the bottom of an equal-height card so the
     * fine-print line is horizontally aligned across the whole grid. */
    margin-top: auto;
}
.qi-statcard__link {
    display: inline-block;
    font-size: 11px;
    font-weight: 500;
}
.qi-statcard .qi-progress {
    margin-top: auto;
}

/* ----------------------------------------------------------------------
 *  Bulk-select tables (Logs, etc.)
 * --------------------------------------------------------------------*/

.qi-bulk-form { margin: 0; }
.qi-hidden-form { display: none; }

.qi-bulk-col {
    width: 28px;
    padding-left: 12px !important;
    padding-right: 4px !important;
    text-align: center;
}
.qi-bulk-col input[type="checkbox"] {
    vertical-align: middle;
    margin: 0;
    cursor: pointer;
}

.qi-table--logs tbody tr.is-selected,
[data-bulk-table] tbody tr.is-selected {
    background: #fff5ee;
}
.qi-table--logs tbody tr.is-selected:hover,
[data-bulk-table] tbody tr.is-selected:hover {
    background: #ffe9d8;
}

.qi-bulk-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding: 8px 14px;
    margin: 0 0 10px;
    background: #fff5ee;
    border: 1px solid #f5c6a8;
    border-radius: var(--qi-radius);
    font-size: 13px;
}
.qi-bulk-bar[hidden] { display: none; }
.qi-bulk-bar__count { margin-right: auto; }
.qi-bulk-bar__count strong { color: var(--qi-accent); }
.qi-bulk-bar__hint {
    font-size: 11px;
    flex-basis: 100%;
}
.qi-bulk-bar__hint kbd {
    background: #fff;
    border: 1px solid var(--qi-border);
    border-radius: 3px;
    padding: 1px 5px;
    font-family: var(--qi-mono);
    font-size: 10px;
}

/* ----------------------------------------------------------------------
 *  Diagnostics
 * --------------------------------------------------------------------*/

.qi-diag-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    margin: 10px 0 14px;
    background: #fafafa;
    border: 1px solid var(--qi-border);
    border-radius: var(--qi-radius);
    font-size: 13px;
}
.qi-diag-summary > div { margin-right: auto; }

.qi-table--diag td { vertical-align: top; }
.qi-table--diag .qi-small { font-size: 11px; }

.qi-charts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    grid-auto-rows: 1fr;
    gap: 16px;
}
.qi-chart {
    border: 1px solid var(--qi-border);
    border-radius: var(--qi-radius);
    background: #fff;
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
}
.qi-chart__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 6px;
}
.qi-chart__head h4 {
    margin: 0;
    font-size: 13px;
    font-weight: 600;
    color: var(--qi-ink);
}
.qi-chart__sub {
    font-size: 11px;
    color: var(--qi-muted);
}
.qi-spark {
    width: 100%;
    height: 80px;
    display: block;
    flex-grow: 1;
}
.qi-spark__line {
    fill: none;
    stroke: var(--qi-accent);
    stroke-width: 1.5;
    stroke-linejoin: round;
    stroke-linecap: round;
}
.qi-spark__area {
    fill: var(--qi-accent);
    opacity: 0.10;
}
.qi-spark__dot {
    fill: var(--qi-accent);
    opacity: 0;
}
.qi-spark__dot:hover {
    opacity: 1;
}
.qi-spark__last {
    fill: var(--qi-accent2);
    stroke: #fff;
    stroke-width: 1.5;
}

/* ---------- login page ---------- */

.qi-login-body {
    background: var(--qi-header);
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--qi-header-ink);
}
.qi-login {
    width: 360px;
}
.qi-login__card {
    background: var(--qi-surface);
    color: var(--qi-ink);
    border-radius: 6px;
    padding: 28px 28px 24px;
    box-shadow: 0 20px 50px rgba(0,0,0,0.35);
}
.qi-login__brand { text-align: center; margin-bottom: 18px; }
.qi-login__brand .qi-logo { color: var(--qi-ink); }
.qi-login__sub {
    margin-top: 4px;
    color: var(--qi-muted);
    font-size: 13px;
    letter-spacing: 0.5px;
}
.qi-login__hint {
    margin-top: 14px;
    text-align: center;
    color: #aaa;
    font-size: 12px;
}
.qi-login__hint code { background: rgba(255,255,255,0.08); color: #ddd; }

/* ----------------------------------------------------------------------
 *  Schedules
 * --------------------------------------------------------------------*/

.qi-table--schedules td { vertical-align: top; }
.qi-table--schedules .qi-small { font-size: 11px; }
.qi-mono { font-family: var(--qi-mono); }
.qi-table__actions {
    text-align: right;
    white-space: nowrap;
}
.qi-table__actions .qi-inline-form { display: inline-block; margin-left: 4px; }
.qi-table__actions .qi-btn { margin-left: 4px; }

.qi-row--disabled { opacity: 0.55; }

.qi-pill--ok    { background: #d4edda; color: #155724; }
.qi-pill--err   { background: #f8d7da; color: #721c24; }
.qi-pill--mute  { background: #eee;    color: #777;    }

.qi-help {
    margin-top: 24px;
    padding: 16px 18px;
    background: #fafafa;
    border: 1px solid var(--qi-border);
    border-radius: var(--qi-radius);
    font-size: 13px;
    color: var(--qi-muted);
}
.qi-help h4 { margin: 0 0 6px; color: var(--qi-ink); font-size: 13px; }
.qi-code {
    display: block;
    margin: 8px 0;
    padding: 10px 12px;
    background: #1f1f1f;
    color: #eee;
    border-radius: 4px;
    font-family: var(--qi-mono);
    font-size: 12px;
    overflow-x: auto;
    white-space: pre;
}

/* ---------- schedule form ---------- */

.qi-schedule-form { max-width: 720px; }
.qi-schedule-form .qi-field { margin-bottom: 18px; }

.qi-freq {
    display: flex;
    gap: 18px;
    flex-wrap: wrap;
    align-items: center;
}
.qi-radio {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    font-size: 13px;
}
.qi-radio input { margin: 0; }

.qi-freq-block,
.qi-args-block {
    border: 1px solid var(--qi-border);
    border-radius: var(--qi-radius);
    padding: 14px 16px;
    margin: 0 0 14px;
    background: #fafafa;
}
.qi-freq-block[hidden],
.qi-args-block[hidden] { display: none; }

.qi-form__actions {
    display: flex;
    gap: 10px;
    align-items: center;
    margin-top: 6px;
}

.qi-alert--err { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
