/* ============================================================================
 * components.css — PulseWatch shared component vocabulary
 *
 * Loaded AFTER tokens.css, BEFORE pulsewatch.css/auth.css. Every component
 * here consumes semantic tokens from tokens.css; no hardcoded colours.
 *
 * Components included:
 *   - Reset / base typography (lightweight; doesn't override site CSS)
 *   - Buttons (.btn family, all variants and sizes, including formerly
 *     undefined .btn-danger / .btn-warning / .btn-xs)
 *   - Page header (.page-header — replaces 5 legacy header components)
 *   - Status pill (.status-pill — replaces .status-badge + .badge)
 *   - Copy block (.copy-block — prominent code-with-copy artifact)
 *   - Meta chips (.meta-chip — inline metadata like "Phoned home 12s ago")
 *   - Card (.card — generic container; .dashboard-section now aliases this)
 *   - Disclosure (<details>/<summary> styled as native UI primitive)
 *   - Navbar (denser, with hamburger toggle for mobile)
 *   - Modal touch-ups (token-aware update of dialog styling)
 *   - Form refinements (.form-control, .form-group consume tokens)
 *   - Theme toggle button
 * ========================================================================= */

/* ----------------------------------------------------------------------------
 * Body baseline — applied app-wide, picks up the page surface in either theme
 * --------------------------------------------------------------------------*/
body {
    background: var(--surface-0);
    color: var(--text-primary);
    font-family: var(--font-sans);
    line-height: var(--line-height-base);
}

/* Smooth transitions when toggling themes — surfaces and text fade rather
 * than snap. Skipped for inputs/buttons that need instant feedback. */
body,
.card,
.page-header,
.status-pill,
.meta-chip,
.copy-block,
.modal {
    transition: background-color 0.18s ease, color 0.18s ease,
                border-color 0.18s ease;
}

/* ----------------------------------------------------------------------------
 * Buttons — .btn family
 *
 * Variants:  primary, secondary, outline, danger, warning, ghost (no border)
 * Sizes:     btn-xs, btn-sm, [default], btn-lg
 * Modifier:  btn-block (full width)
 * --------------------------------------------------------------------------*/
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-4);
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    background: var(--surface-2);
    color: var(--text-primary);
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    line-height: 1.2;
    cursor: pointer;
    text-decoration: none;
    transition: background-color 0.12s ease, border-color 0.12s ease,
                color 0.12s ease, transform 0.06s ease, box-shadow 0.12s ease;
    white-space: nowrap;
}
.btn:hover         { background: var(--border-subtle); }
.btn:active        { transform: translateY(1px); }
.btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--accent-focus-ring);
}
.btn:disabled,
.btn[aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
}

.btn-primary {
    background: var(--accent-primary);
    border-color: var(--accent-primary);
    color: var(--text-on-accent);
}
.btn-primary:hover {
    background: var(--accent-primary-hover);
    border-color: var(--accent-primary-hover);
}

.btn-secondary {
    background: var(--surface-2);
    border-color: var(--border-default);
    color: var(--text-primary);
}
.btn-secondary:hover { background: var(--border-subtle); }

.btn-outline {
    background: transparent;
    border-color: var(--border-default);
    color: var(--text-primary);
}
.btn-outline:hover {
    background: var(--surface-2);
    border-color: var(--border-strong);
}

/* DANGER and WARNING — formerly used in templates but never defined in CSS.
 * Defining them here closes a latent bug surfaced in the redesign audit. */
.btn-danger {
    background: var(--btn-danger);
    border-color: var(--btn-danger);
    color: var(--btn-danger-text);
}
.btn-danger:hover {
    background: var(--btn-danger-hover);
    border-color: var(--btn-danger-hover);
}

.btn-warning {
    background: var(--status-warn-bg);
    border-color: var(--status-warn-border);
    color: var(--status-warn-fg);
}
.btn-warning:hover { background: var(--status-warn-border); }

.btn-ghost {
    background: transparent;
    border-color: transparent;
    color: var(--text-secondary);
}
.btn-ghost:hover {
    background: var(--surface-2);
    color: var(--text-primary);
}

.btn-xs {
    padding: var(--space-1) var(--space-2);
    font-size: var(--font-size-xs);
    border-radius: var(--radius-sm);
}
.btn-sm {
    padding: var(--space-1) var(--space-3);
    font-size: var(--font-size-xs);
}
.btn-lg {
    padding: var(--space-3) var(--space-5);
    font-size: var(--font-size-base);
}
.btn-block {
    display: flex;
    width: 100%;
}

/* ----------------------------------------------------------------------------
 * Page header — the unified component that replaces .dashboard-header,
 * .section-header, .page-header, .target-detail-header, .profile-header.
 *
 * Slots (see templates/components/page_header.html):
 *   .page-header__leading      → back link + title block
 *   .page-header__back         → optional "← Back" link
 *   .page-header__title        → h1/h2
 *   .page-header__subtitle     → small text under the title
 *   .page-header__meta         → inline chips (status, "12s ago" etc.)
 *   .page-header__actions      → right-side button cluster
 * --------------------------------------------------------------------------*/
.page-header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-5);
    flex-wrap: wrap;
    padding-bottom: var(--space-3);
    margin: 0 0 var(--space-5);
    border-bottom: 1px solid var(--border-subtle);
}
.page-header__leading {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-width: 0;
}
.page-header__back {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    color: var(--text-secondary);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    text-decoration: none;
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    margin-bottom: var(--space-1);
}
.page-header__back:hover { color: var(--accent-primary); }
.page-header__back::before {
    content: "←";
    font-size: var(--font-size-base);
    transition: transform 0.12s ease;
}
.page-header__back:hover::before { transform: translateX(-2px); }

.page-header__title {
    margin: 0;
    font-size: var(--font-size-2xl);
    font-weight: var(--font-weight-semibold);
    line-height: var(--line-height-tight);
    letter-spacing: -0.01em;
    color: var(--text-primary);
    word-break: break-word;
}
.page-header__subtitle {
    margin: 0;
    color: var(--text-tertiary);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-normal);
}
.page-header__subtitle code {
    background: var(--surface-2);
    padding: 0 var(--space-1);
    border-radius: var(--radius-sm);
    font-family: var(--font-mono);
    font-size: 0.85em;
    color: var(--text-secondary);
}

.page-header__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-2);
}
.page-header__actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}

/* Variant: "compact" — for section headers inside a page, no border, smaller */
.page-header--compact {
    padding-bottom: var(--space-2);
    margin-bottom: var(--space-3);
}
.page-header--compact .page-header__title { font-size: var(--font-size-xl); }

/* Legacy .section-header / .section-actions — kept for sub-section dividers
 * inside a page (e.g. the "Probe Management" / "Monitored Targets" blocks
 * on the dashboard). Use components/page_header.html for the *top* of the
 * page; .section-header for in-page sub-dividers with an h3.
 *
 * Visually aligned with .page-header--compact so they read as the same
 * family. Theme-aware via tokens. */
.section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin: 0 0 var(--space-3);
    padding-bottom: var(--space-2);
    border-bottom: 1px solid var(--border-subtle);
}
.section-header h3,
.section-header h4 {
    margin: 0;
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--text-primary);
    letter-spacing: -0.005em;
}
.section-actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}

/* ----------------------------------------------------------------------------
 * Status pill — sharp letter-spaced-caps treatment. Replaces .status-badge
 * and .badge mixed together. One signature: tone + label.
 *
 * Tones: ok, warn, crit, neutral, info
 * --------------------------------------------------------------------------*/
.status-pill {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 3px var(--space-2);
    border: 1px solid transparent;
    border-radius: 999px;
    font-size: 0.6875rem;          /* 11px — tight caps */
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    line-height: 1.2;
    white-space: nowrap;
    font-family: inherit;
}
.status-pill::before {
    content: "●";
    font-size: 0.7em;
    line-height: 1;
}
.status-pill--ok      { background: var(--status-ok-bg);      color: var(--status-ok-fg);      border-color: var(--status-ok-border); }
.status-pill--warn    { background: var(--status-warn-bg);    color: var(--status-warn-fg);    border-color: var(--status-warn-border); }
.status-pill--crit    { background: var(--status-crit-bg);    color: var(--status-crit-fg);    border-color: var(--status-crit-border); }
.status-pill--neutral { background: var(--status-neutral-bg); color: var(--status-neutral-fg); border-color: var(--status-neutral-border); }
.status-pill--info    { background: var(--status-info-bg);    color: var(--status-info-fg);    border-color: var(--status-info-border); }

/* Solid variant — for when the pill IS the foreground, e.g. a count badge */
.status-pill--solid.status-pill--ok      { background: var(--status-ok-fg);      color: var(--surface-1); border-color: transparent; }
.status-pill--solid.status-pill--crit    { background: var(--btn-danger);        color: var(--btn-danger-text); border-color: transparent; }

/* ----------------------------------------------------------------------------
 * Meta chip — small inline metadata. Used in page headers and in rows.
 * Examples: "Phoned home 12s ago", "Local master", "3 deployments".
 *
 * Tone is optional; default is neutral.
 * --------------------------------------------------------------------------*/
.meta-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 2px var(--space-2);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    color: var(--text-secondary);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    line-height: 1.4;
    border: 1px solid transparent;
    white-space: nowrap;
}
.meta-chip__icon {
    font-size: 0.85em;
    opacity: 0.85;
    line-height: 1;
}
.meta-chip--ok   { background: var(--status-ok-bg);   color: var(--status-ok-fg);   border-color: var(--status-ok-border); }
.meta-chip--warn { background: var(--status-warn-bg); color: var(--status-warn-fg); border-color: var(--status-warn-border); }
.meta-chip--crit { background: var(--status-crit-bg); color: var(--status-crit-fg); border-color: var(--status-crit-border); }
.meta-chip--info { background: var(--status-info-bg); color: var(--status-info-fg); border-color: var(--status-info-border); }

/* Pulsing dot — for "Live" / "Waiting" / "Polling" indicators. */
.meta-chip__pulse {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: currentColor;
    box-shadow: 0 0 0 0 currentColor;
    animation: meta-chip-pulse 1.6s ease-out infinite;
}
@keyframes meta-chip-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(56, 189, 248, 0.45); }
    70%  { box-shadow: 0 0 0 6px rgba(56, 189, 248, 0); }
    100% { box-shadow: 0 0 0 0 rgba(56, 189, 248, 0); }
}

/* ----------------------------------------------------------------------------
 * Copy block — the redesigned bootstrap-one-liner / shell-command artifact.
 *
 * Structure (see templates/components/copy_block.html):
 *   .copy-block
 *     .copy-block__label    (optional: "Run this on the target host")
 *     .copy-block__body
 *       .copy-block__code   (<pre><code>)
 *       .copy-block__button (large explicit Copy button)
 *     .copy-block__hint     (optional one-liner help text)
 *
 * Behaviour:
 *   The button gets [data-copy-source="<selector>"] consumed by copy.js,
 *   which copies the source element's text and flips the button to its
 *   success state for 2 seconds.
 * --------------------------------------------------------------------------*/
.copy-block {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin: var(--space-4) 0;
}
.copy-block__label {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    color: var(--text-secondary);
}
.copy-block__body {
    position: relative;
    display: flex;
    align-items: stretch;
    gap: 0;
    background: #0f172a;
    color: #e2e8f0;
    border: 1px solid #1e293b;
    border-radius: var(--radius-lg);
    overflow: hidden;
}
[data-theme="dark"] .copy-block__body {
    background: #050a14;
    border-color: #1e2a44;
}
.copy-block__code {
    flex: 1;
    margin: 0;
    padding: var(--space-4) var(--space-5);
    font-family: var(--font-mono);
    font-size: var(--font-size-sm);
    line-height: 1.5;
    white-space: pre-wrap;
    word-break: break-all;
    overflow-x: auto;
    user-select: all;     /* triple-click selects everything anyway */
}
.copy-block__button {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: 0 var(--space-5);
    border: 0;
    border-left: 1px solid #1e293b;
    background: #1e293b;
    color: #f1f5f9;
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease;
    min-width: 88px;
    justify-content: center;
}
.copy-block__button:hover { background: #334155; }
.copy-block__button:focus-visible {
    outline: none;
    box-shadow: inset 0 0 0 2px var(--accent-primary);
}
/* When the JS toggles [data-state="copied"], the button flips to success. */
.copy-block__button[data-state="copied"] {
    background: var(--status-ok-fg);
    color: var(--status-ok-bg);
}
.copy-block__hint {
    font-size: var(--font-size-xs);
    color: var(--text-tertiary);
}

/* ----------------------------------------------------------------------------
 * Card — generic surface container. .dashboard-section, .stat-card,
 * .master-card etc. should migrate to this. For now, .card stands alongside.
 * --------------------------------------------------------------------------*/
.card {
    background: var(--surface-1);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--space-5);
    box-shadow: var(--shadow-sm);
}
.card--flush  { padding: 0; }                 /* for tables that fill the card */
.card--muted  { background: var(--surface-2); }
.card__title  {
    margin: 0 0 var(--space-3);
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--text-primary);
}

/* ----------------------------------------------------------------------------
 * Disclosure — the <details>/<summary> primitive styled to fit the UI.
 * Used in Phase 2 to replace the cascading-toggle JS in master_form.html.
 * --------------------------------------------------------------------------*/
details.disclosure {
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-1);
    margin: var(--space-3) 0;
    overflow: hidden;
}
details.disclosure > summary {
    list-style: none;
    cursor: pointer;
    padding: var(--space-3) var(--space-4);
    font-weight: var(--font-weight-semibold);
    color: var(--text-primary);
    display: flex;
    align-items: center;
    gap: var(--space-2);
}
details.disclosure > summary::-webkit-details-marker { display: none; }
details.disclosure > summary::before {
    content: "▸";
    color: var(--text-tertiary);
    transition: transform 0.15s ease;
}
details.disclosure[open] > summary::before { transform: rotate(90deg); }
details.disclosure > summary:hover { background: var(--surface-2); }
details.disclosure > .disclosure__body {
    padding: var(--space-4);
    border-top: 1px solid var(--border-subtle);
}

/* ----------------------------------------------------------------------------
 * Navbar — denser, with hamburger toggle on mobile.
 * Replaces the old .navbar rules in base.css.
 * --------------------------------------------------------------------------*/
.navbar {
    background: var(--nav-bg);
    color: var(--nav-text);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    position: sticky;
    top: 0;
    z-index: 100;
}
.navbar > .container {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    min-height: 56px;
    padding-top: var(--space-2);
    padding-bottom: var(--space-2);
}
.navbar-brand {
    display: flex;
    align-items: baseline;
    gap: var(--space-3);
    min-width: 0;
}
.navbar-brand a {
    color: var(--nav-text);
    text-decoration: none;
    display: inline-flex;
    align-items: baseline;
    gap: var(--space-2);
}
.navbar-brand h1 {
    margin: 0;
    font-size: 1.125rem;
    font-weight: var(--font-weight-semibold);
    letter-spacing: -0.01em;
}
.navbar-brand .subtitle {
    color: rgba(255, 255, 255, 0.55);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
}
.navbar-menu {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: var(--space-1);
}
.nav-link {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--nav-text);
    text-decoration: none;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-md);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    background: transparent;
    border: 0;
    cursor: pointer;
    font-family: inherit;
    transition: background 0.12s ease;
}
.nav-link:hover { background: var(--nav-link-hover); }
.nav-link[aria-current="page"] {
    background: rgba(255, 255, 255, 0.08);
}
.nav-dropdown { position: relative; }
.dropdown-toggle::after {
    content: "▾";
    margin-left: var(--space-1);
    font-size: 0.7em;
    opacity: 0.7;
}
.dropdown-menu {
    position: absolute;
    top: calc(100% + var(--space-1));
    right: 0;
    min-width: 220px;
    background: var(--surface-elevated);
    color: var(--text-primary);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    padding: var(--space-1);
    display: none;
    z-index: 110;
}
.dropdown-menu.show { display: block; }
.dropdown-menu--right { right: 0; left: auto; }
.dropdown-item {
    display: block;
    padding: var(--space-2) var(--space-3);
    color: var(--text-primary);
    text-decoration: none;
    border-radius: var(--radius-sm);
    font-size: var(--font-size-sm);
    background: transparent;
    border: 0;
    width: 100%;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
}
.dropdown-item:hover { background: var(--surface-2); }
.dropdown-item.text-muted { color: var(--text-tertiary); cursor: default; }
.dropdown-item.text-muted:hover { background: transparent; }
.dropdown-divider {
    height: 1px;
    background: var(--border-subtle);
    margin: var(--space-1) 0;
    border: 0;
}

/* Hamburger — hidden on desktop, shown below 768px */
.nav-hamburger {
    display: none;
    background: transparent;
    border: 0;
    color: var(--nav-text);
    cursor: pointer;
    padding: var(--space-2);
    margin-left: auto;
    font-size: 1.25rem;
    line-height: 1;
}

/* ----------------------------------------------------------------------------
 * Theme toggle button — sun/moon icon swap.
 * --------------------------------------------------------------------------*/
.theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    color: var(--nav-text);
    cursor: pointer;
    font-size: 1rem;
    line-height: 1;
}
.theme-toggle:hover { background: var(--nav-link-hover); }
.theme-toggle .theme-toggle__moon { display: inline; }
.theme-toggle .theme-toggle__sun  { display: none; }
[data-theme="dark"] .theme-toggle .theme-toggle__moon { display: none; }
[data-theme="dark"] .theme-toggle .theme-toggle__sun  { display: inline; }

/* ----------------------------------------------------------------------------
 * Modal — sizing + token-aware colours for the global <dialog id="modal">.
 *
 * <dialog> with no width rules sizes to "tiny" by browser default — the
 * desktop dimensional rules used to live in base.css and got stripped in
 * Phase 1's audit cleanup. Restored here alongside the token-aware
 * background/border so all modal styling is in one place.
 * --------------------------------------------------------------------------*/
.modal {
    width: 600px;
    max-width: 90vw;
    max-height: calc(100vh - 4rem);
    padding: 0;
    overflow: auto;
    background: var(--surface-elevated);
    color: var(--text-primary);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xl);
}
.modal--wide   { width: 900px; }
.modal--narrow { width: 420px; }
.modal::backdrop { background: rgba(15, 23, 42, 0.55); }
[data-theme="dark"] .modal::backdrop { background: rgba(0, 0, 0, 0.72); }
.modal-header {
    border-bottom-color: var(--border-subtle);
    padding: var(--space-4) var(--space-5);
}
.modal-header h3 {
    margin: 0;
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--text-primary);
}
.modal-close { color: var(--text-tertiary); }
.modal-close:hover { color: var(--text-primary); }
.modal-body { padding: var(--space-5); }
.modal-footer {
    border-top-color: var(--border-subtle);
    padding: var(--space-4) var(--space-5);
    gap: var(--space-2);
}

/* ----------------------------------------------------------------------------
 * Form refinements — keep existing classes but make them theme-aware.
 * --------------------------------------------------------------------------*/
.form-control,
input.form-control,
textarea.form-control,
select.form-control {
    background: var(--surface-1);
    color: var(--text-primary);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    padding: var(--space-2) var(--space-3);
    font-size: var(--font-size-sm);
    font-family: inherit;
    width: 100%;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.form-control:focus,
.form-control:focus-visible {
    outline: none;
    border-color: var(--accent-primary);
    box-shadow: 0 0 0 3px var(--accent-focus-ring);
}
.form-control::placeholder { color: var(--text-tertiary); }

.form-group { display: flex; flex-direction: column; gap: var(--space-1); margin-bottom: var(--space-4); }
.form-group label { font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); color: var(--text-secondary); }
.form-text  { color: var(--text-tertiary); font-size: var(--font-size-xs); }
.form-errors { color: var(--status-crit-fg); font-size: var(--font-size-xs); }

/* Inputs in checkbox/radio rows want horizontal layout, not the column flex */
.form-group.form-check,
.form-check {
    flex-direction: row;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
}
.form-check input[type="checkbox"],
.form-check input[type="radio"] { width: auto; margin: 0; }
.form-check-input { width: auto; }

/* Section panels inside forms */
.form-section {
    margin-bottom: var(--space-5);
    padding: var(--space-4);
    background: var(--surface-2);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
}
.form-section h4 {
    margin: 0 0 var(--space-3);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-caps);
    color: var(--text-secondary);
}

/* ----------------------------------------------------------------------------
 * Deployment cards (master_detail) — replaces the disconnected flex-between
 * rows where the Delete button was visually orphaned from its row.
 *
 * Grid layout: auto-fits ~280px columns. Each card stacks title → meta
 * chips → action buttons vertically with consistent spacing so the visual
 * hierarchy reads top-down rather than left-right.
 * --------------------------------------------------------------------------*/
.deployments-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: var(--space-3);
}
.deployment-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    background: var(--surface-1);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--space-4);
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.deployment-card:hover {
    border-color: var(--border-default);
    box-shadow: var(--shadow-md);
}
.deployment-card--deployed { border-left: 3px solid var(--status-ok-fg); padding-left: calc(var(--space-4) - 2px); }
.deployment-card__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-2);
}
.deployment-card__title {
    min-width: 0;
    font-weight: var(--font-weight-semibold);
    font-size: var(--font-size-base);
    line-height: 1.3;
}
.deployment-card__title a {
    color: var(--text-primary);
    text-decoration: none;
    word-break: break-word;
}
.deployment-card__title a:hover { color: var(--accent-primary); }
.deployment-card__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}
.deployment-card__actions {
    display: flex;
    gap: var(--space-2);
    margin-top: auto;       /* push to the bottom on tall cards */
    padding-top: var(--space-2);
    border-top: 1px solid var(--border-subtle);
}

/* ----------------------------------------------------------------------------
 * Probe-location card grid (probe_list). Same family as .deployment-card
 * but with a third row (.probe-card__slug) and a slightly looser layout —
 * probe locations are configuration-heavy so the card carries more meta.
 * --------------------------------------------------------------------------*/
.probes-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: var(--space-3);
}
.probe-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    background: var(--surface-1);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--space-4);
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.probe-card:hover {
    border-color: var(--border-default);
    box-shadow: var(--shadow-md);
}
.probe-card--inactive { opacity: 0.75; }
.probe-card__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-2);
}
.probe-card__title {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.probe-card__title a {
    color: var(--text-primary);
    text-decoration: none;
    font-weight: var(--font-weight-semibold);
    font-size: var(--font-size-base);
}
.probe-card__title a:hover { color: var(--accent-primary); }
.probe-card__slug code {
    font-family: var(--font-mono);
    font-size: var(--font-size-xs);
    color: var(--text-tertiary);
    background: transparent;
    padding: 0;
}
.probe-card__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
}
.probe-card__actions {
    display: flex;
    gap: var(--space-2);
    margin-top: auto;
    padding-top: var(--space-2);
    border-top: 1px solid var(--border-subtle);
}

/* ----------------------------------------------------------------------------
 * Status filter chips — sticky bar above probetask_list.
 * --------------------------------------------------------------------------*/
.filter-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
    padding: var(--space-2) 0;
    margin-bottom: var(--space-3);
    border-bottom: 1px solid var(--border-subtle);
    position: sticky;
    top: 56px;              /* matches navbar min-height */
    background: var(--surface-0);
    z-index: 10;
}
.filter-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-3);
    border: 1px solid var(--border-default);
    border-radius: 999px;
    background: var(--surface-1);
    color: var(--text-secondary);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    text-decoration: none;
    cursor: pointer;
    line-height: 1.4;
    transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.filter-chip:hover { background: var(--surface-2); }
.filter-chip[aria-pressed="true"],
.filter-chip--active {
    background: var(--accent-primary);
    color: var(--text-on-accent);
    border-color: var(--accent-primary);
}
.filter-chip__count {
    background: rgba(0,0,0,0.10);
    border-radius: 999px;
    padding: 0 6px;
    font-variant-numeric: tabular-nums;
}
.filter-chip[aria-pressed="true"] .filter-chip__count {
    background: rgba(255,255,255,0.18);
}

/* ----------------------------------------------------------------------------
 * Timeline (probetask_detail) — horizontal stepper showing the four
 * lifecycle events: created → sent → started → finished. Each step is a
 * dot + label + relative time, connected by a thin rule. Below 640px,
 * the layout flips to vertical.
 * --------------------------------------------------------------------------*/
.timeline {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 0;
    align-items: stretch;
    position: relative;
    padding: var(--space-3) 0;
}
.timeline__step {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    align-items: flex-start;
    padding: 0 var(--space-3) 0 var(--space-4);
    position: relative;
    min-width: 0;
}
.timeline__step::before {
    content: "";
    position: absolute;
    left: 0;
    top: 8px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--surface-2);
    border: 2px solid var(--border-default);
    z-index: 1;
}
.timeline__step::after {
    content: "";
    position: absolute;
    left: 12px;
    top: 13px;
    right: 0;
    height: 2px;
    background: var(--border-subtle);
}
.timeline__step:last-child::after { display: none; }
.timeline__step--done::before {
    background: var(--status-ok-fg);
    border-color: var(--status-ok-fg);
}
.timeline__step--current::before {
    background: var(--accent-primary);
    border-color: var(--accent-primary);
    box-shadow: 0 0 0 4px var(--accent-focus-ring);
}
.timeline__step--error::before {
    background: var(--status-crit-fg);
    border-color: var(--status-crit-fg);
}
.timeline__step--done + .timeline__step--done::after,
.timeline__step--done + .timeline__step--current::after {
    background: var(--status-ok-fg);
}
.timeline__label {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    color: var(--text-secondary);
}
.timeline__time {
    font-family: var(--font-mono);
    font-size: var(--font-size-xs);
    color: var(--text-primary);
}
.timeline__duration {
    font-size: 0.6875rem;
    color: var(--text-tertiary);
}

@media (max-width: 640px) {
    .timeline {
        grid-template-columns: 1fr;
        gap: var(--space-3);
    }
    .timeline__step {
        flex-direction: row;
        align-items: center;
        gap: var(--space-3);
        padding-left: var(--space-4);
    }
    .timeline__step::after { display: none; }
}

/* ----------------------------------------------------------------------------
 * Responsive — hamburger swap below 768px
 * --------------------------------------------------------------------------*/
@media (max-width: 768px) {
    .nav-hamburger { display: inline-flex; }

    .navbar > .container { flex-wrap: wrap; }
    .navbar-menu {
        flex-basis: 100%;
        flex-direction: column;
        align-items: stretch;
        gap: var(--space-1);
        margin-left: 0;
        padding: var(--space-2) 0 var(--space-3);
        display: none;
    }
    .navbar-menu.navbar-menu--open { display: flex; }
    .nav-link { width: 100%; }
    .nav-dropdown,
    .nav-dropdown .dropdown-menu {
        position: static;
        width: 100%;
        box-shadow: none;
        border: 0;
        background: transparent;
    }
    .nav-dropdown .dropdown-menu {
        padding-left: var(--space-3);
    }
    /* Theme toggle stays visible outside the hamburger so users can switch
     * themes without unfolding the menu. */
    .theme-toggle { order: -1; }
}

/* ============================================================================
 * Wizard shell — progress strip + step header + body + footer
 *
 * Used by the slave-deployment wizard (apps/pulsewatch/wizards/). Every step
 * partial wraps its content in `.wizard-shell` and includes the shared
 * `components/wizard_shell.html` header at the top. Step body and footer
 * are laid out directly inside the partial.
 * ========================================================================= */
.wizard-shell {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4) var(--space-4);
}
.wizard-shell__head {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    border-bottom: 1px solid var(--border-subtle);
    padding-bottom: var(--space-3);
}
.wizard-shell__title {
    margin: var(--space-1) 0 0;
    font-size: 1.375rem;
    letter-spacing: -0.01em;
}
.wizard-shell__subtitle {
    margin: 0;
    color: var(--text-secondary);
    line-height: 1.5;
}

.wizard-progress {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    gap: var(--space-1);
    align-items: center;
}
.wizard-progress__step {
    flex: 1;
    height: 0.25rem;
    background: var(--border-subtle);
    border-radius: 9999px;
    position: relative;
    transition: background 0.2s ease;
}
.wizard-progress__step.is-complete,
.wizard-progress__step.is-current { background: var(--accent-primary); }
.wizard-progress__dot {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 9999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    font-weight: 600;
    background: var(--surface-1);
    color: var(--text-tertiary);
    border: 2px solid var(--border-subtle);
}
.wizard-progress__step.is-complete .wizard-progress__dot {
    background: var(--accent-primary);
    color: var(--text-on-accent, #fff);
    border-color: var(--accent-primary);
}
.wizard-progress__step.is-current .wizard-progress__dot {
    background: var(--surface-1);
    color: var(--accent-primary);
    border-color: var(--accent-primary);
}
.wizard-progress__label {
    margin: var(--space-1) 0 0;
    font-size: 0.75rem;
    color: var(--text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

/* ----- Step 1: radio-card choice + form fields ----- */
.wizard-choice {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    border: 0;
    padding: 0;
    margin: 0;
}
.wizard-choice__option {
    display: flex;
    gap: var(--space-2);
    align-items: flex-start;
    padding: var(--space-3);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease;
}
.wizard-choice__option:hover { border-color: var(--accent-primary); }
.wizard-choice__option:has(input:checked) {
    border-color: var(--accent-primary);
    background: var(--accent-soft, var(--surface-2));
}
.wizard-choice__option input[type=radio] { margin-top: 0.25rem; }
.wizard-choice__body { display: flex; flex-direction: column; gap: 0.125rem; }
.wizard-choice__body strong { font-size: 0.9375rem; }
.wizard-choice__body small { color: var(--text-secondary); line-height: 1.45; }

/* ----- Footer button row ----- */
.wizard-footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2);
    margin-top: var(--space-3);
    padding-top: var(--space-3);
    border-top: 1px solid var(--border-subtle);
}

/* ----- Status indicator block on step 3 ----- */
.wizard-status {
    margin-top: var(--space-3);
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}
.wizard-status__chip {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-3);
    border-radius: var(--radius-md);
    border: 1px solid var(--border-subtle);
}
.wizard-status__chip strong { display: block; font-size: 0.9375rem; }
.wizard-status__chip small { color: var(--text-secondary); }
.wizard-status__chip--ok {
    background: var(--status-ok-bg, var(--surface-2));
    color: var(--status-ok-fg, inherit);
    border-color: var(--status-ok-border, var(--border-default));
}
.wizard-status__chip--waiting {
    background: var(--surface-2);
    color: var(--text-primary);
}
.wizard-status__icon {
    font-size: 1.25rem;
    line-height: 1;
    flex-shrink: 0;
}
.wizard-status__icon--pulse {
    color: var(--accent-primary);
    animation: wizardPulse 1.4s ease-in-out infinite;
}
@keyframes wizardPulse {
    0%, 100% { opacity: 0.4; }
    50%      { opacity: 1.0; }
}

/* ----- Step 4: done screen ----- */
.wizard-done { display: flex; flex-direction: column; gap: var(--space-4); }
.wizard-done__hero {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-3);
    background: var(--status-ok-bg, var(--surface-2));
    border-radius: var(--radius-md);
}
.wizard-done__hero strong { display: block; font-size: 1.0625rem; }
.wizard-done__hero small { color: var(--text-secondary); }
.wizard-done__icon {
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 9999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--status-ok-border, var(--accent-primary));
    color: #fff;
    font-size: 1.25rem;
    font-weight: bold;
    flex-shrink: 0;
}
.wizard-done__next {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}
.wizard-done__next li {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) 0;
}
.wizard-done__next .btn { flex-shrink: 0; min-width: 14rem; }
.wizard-done__next small { color: var(--text-secondary); line-height: 1.45; }

/* ----- Modal eyebrow (small caps caption above wizard title) ----- */
.modal-eyebrow {
    display: inline-block;
    font-size: 0.6875rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-tertiary);
    font-weight: 600;
}
