/* ===================================================================================================
   PreemptiveScheduler utilities (feature K) — the curated helper set, opt-in by .ps-* class so the
   sheet is inert until markup asks for it. Layered after ps-base (see base.css for the layer order);
   per-knob custom properties (--ps-stack-gap, …) let a consumer tune an instance without new classes.
   Deliberately small: layout composition (stack/cluster/auto-grid/center), overflow discipline
   (scroll-x/truncate/clamp-2/min-0), text/measure helpers, and element resets for list/button-shaped
   components. Anything richer is a Ui/ component, not a utility.
   =================================================================================================== */

@layer ps-utilities {
    /* Vertical flow with a consistent gap. */
    .ps-stack {
        display: flex;
        flex-direction: column;
        gap: var(--ps-stack-gap, var(--ps-space-4));
    }

    /* A tighter vertical flow — same axis as .ps-stack but a denser default gap, for closely-related rows
       (a label and its value, a heading and its note). Still tunable per-instance via --ps-stack-gap. */
    .ps-stack-tight {
        display: flex;
        flex-direction: column;
        gap: var(--ps-stack-gap, var(--ps-space-2));
    }

    /* Horizontal grouping that wraps (toolbars, tag rows, action clusters). */
    .ps-cluster {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: var(--ps-cluster-gap, var(--ps-space-2));
    }

    /* The RAM grid: packs as many ≥--ps-auto-grid-min columns as fit — 1-up on phones, more at 4K,
       no media queries; min() prevents overflow when the container is narrower than the basis. */
    .ps-auto-grid {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(min(var(--ps-auto-grid-min, var(--ps-tile-min)), 100%), 1fr));
        gap: var(--ps-auto-grid-gap, var(--ps-space-4));
    }

    /* Centered content column capped at a readable width. */
    .ps-center {
        margin-inline: auto;
        max-inline-size: var(--ps-center-max, var(--ps-content-max));
    }

    /* List/table-page content sizing: at the 4xl wall-display tier a list/settings page FILLS the fluid shell column
       UP TO a readable table cap (inline-size:100% bounded by --ps-table-max ≈ 1920px) and CENTERS it (the shell's
       large-screen composition rule — surplus becomes symmetric gutters; see MainLayout.razor.css), so an ultrawide
       screen renders a ~1920px-wide table in TABLE mode, balanced in the column — neither stretched edge-to-edge
       across the fluid shell nor (the v3 fit-content regression) shrunk to its natural width, which dropped a
       few-column table BELOW the DataTable container-query card-collapse threshold (28rem) and forced phone-style
       card mode on a 4K display. The 100% fill keeps the table container at the cap width — far above 28rem — so the
       table always renders in table mode. Inert below 4xl (≤1920 unchanged) and on width-hungry pages that simply do
       not carry the class (the dashboard and usage pages fill the full fluid column). The 160rem literal mirrors
       tokens.css (var() is illegal in @media conditions). */
    @media (min-width: 160rem) {
        .ps-content--list {
            inline-size: 100%;
            max-inline-size: var(--ps-table-max);
            margin-inline: auto;
        }

        /* The LOW-COLUMN variant of the same rule, worn BESIDE .ps-content--list (it overrides only the cap; the
           fill and the centering come from the base class, and the two selectors have equal specificity so this one
           wins by source order). What decides whether a page wears it is the COLUMN DENSITY of the table it holds,
           not which page it is: auto table layout spreads a wall display's surplus across however many cells the row
           has, so a four-column row at 2560+ turns into four islands with dead field between them while a
           nine-column row genuinely uses that width. The same jobs page therefore wears this for the normal user's
           four-column occupancy view and NOT for the administrator's nine-column operator table. Inert below 4xl. */
        .ps-content--list-narrow {
            max-inline-size: var(--ps-table-max-narrow);
        }

        /* Detail-page content sizing (same composition rule): the whole page — masthead, alerts, DetailLayout —
           caps at --ps-detail-max and CENTERS, so the h1 and its header badge align with the centered detail pair
           instead of clinging to the far shell edges. Inert below 4xl. */
        .ps-content--detail {
            inline-size: 100%;
            max-inline-size: var(--ps-detail-max);
            margin-inline: auto;
        }

        /* Form-page content sizing (same composition rule): the page caps at the readable form column + the docked
           context rail + their gap, centered, keeping the masthead aligned with the form pair. Inert below 4xl. */
        .ps-content--form {
            inline-size: 100%;
            max-inline-size: calc(var(--ps-form-max) + var(--ps-detail-rail-width-wide) + var(--ps-space-8));
            margin-inline: auto;
        }
    }

    /* A declared horizontal scroll container (the layout probes treat overflow outside one as a bug). */
    .ps-scroll-x {
        overflow-x: auto;
        scrollbar-gutter: stable;
    }

    /* Single-line ellipsis truncation. min-inline-size releases the flex/grid min-content floor. */
    .ps-truncate {
        min-inline-size: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* Two-line clamp for secondary prose (descriptions, status reasons). */
    .ps-clamp-2 {
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        overflow: hidden;
    }

    /* Lets a flex/grid child shrink below its content (the companion of ps-truncate on wrappers). */
    .ps-min-0 {
        min-inline-size: 0;
    }

    /* Readable line length for prose, including on 4K (never stretch text columns). */
    .ps-measure {
        max-inline-size: var(--ps-measure);
    }

    /* THE shared user-text rule: every cell/label that renders a USER-SUPPLIED string (job name, remark,
       member role, progress, command/env values, error/output excerpts) wears this class. User text can be
       one long token with no break opportunity — default wrapping only breaks at whitespace, so a single
       such token widens a table/page past its container. Anywhere-wrap breaks it at any point AND collapses
       its min-content contribution, so no user string can ever blow a layout. Inherited, so one class on a
       wrapping element covers its text descendants. */
    .ps-user-text {
        overflow-wrap: anywhere;
    }

    /* An icon-led note: a leading icon beside prose that may run to several lines. The icon tracks the FIRST
       line's box (the Alert recipe — block-size: one body line) and centers against it, instead of centering
       against the whole wrapped block, which parks the icon halfway down a three-line warning. The icon never
       shrinks; the prose takes the remaining width. */
    .ps-icon-lede {
        display: flex;
        align-items: flex-start;
        gap: var(--ps-space-1);
        min-inline-size: 0;
    }

    .ps-icon-lede > :first-child {
        display: inline-flex;
        align-items: center;
        flex: none;
        block-size: calc(1em * var(--ps-line-body));
    }

    .ps-mono {
        font-family: var(--ps-font-mono);
    }

    /* Lining figures that align in columns — durations, counters, table numerics. */
    .ps-nums {
        font-variant-numeric: tabular-nums;
    }

    .ps-muted {
        color: var(--ps-color-text-muted);
    }

    /* Guarantees the WCAG 2.5.8 minimum interactive target around small visuals (icon buttons). */
    .ps-target {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-inline-size: var(--ps-target-min);
        min-block-size: var(--ps-target-min);
    }

    /* Semantic <ul>/<ol> rendered as a non-list (nav rails, card collections). */
    .ps-reset-list {
        margin: 0;
        padding: 0;
        list-style: none;
    }

    /* A <button> that looks like its content — for icon buttons and clickable tiles to style up from. */
    .ps-reset-button {
        padding: 0;
        border: 0;
        background: none;
        color: inherit;
        font: inherit;
        text-align: inherit;
        cursor: pointer;
    }
}
