/*
 * NetShow — perceived performance: reserved space for late content  (OPUS5-M10)
 * ---------------------------------------------------------------------------
 * The defect this file exists to remove: a container is empty (or display:none) at first paint,
 * its content arrives later from Alpine/jQuery/fetch, and every element BELOW it jumps down the
 * page. Measured on the golden-path dashboard before this file existed: the activation checklist
 * reserves exactly 0px and then occupies 450-650px in a single frame.
 *
 * Two contracts, both pure CSS. Neither needs a timer, a callback, or any teardown.
 *
 *   1. THE CLOAK HOLD — for a surface hidden behind [x-cloak] until Alpine boots.
 *      The skeleton is a sibling placed immediately AFTER the cloaked element. While the
 *      element still carries x-cloak it is display:none and the adjacent-sibling selector
 *      paints the skeleton in its place. The instant Alpine strips x-cloak the selector stops
 *      matching, so the skeleton vanishes in the very same frame the real content paints.
 *      Nothing to clean up, and if Alpine never arrives the customer keeps a calm placeholder
 *      instead of a blank page.
 *
 *   2. THE RESERVED BAND — for a container that JS clears and refills.
 *      The skeleton is the container's INITIAL content, so the band is reserved by real boxes
 *      rather than a magic number. Every site wired here clears with innerHTML = '' (or React
 *      createRoot, which clears on first render) before filling, so the skeleton is removed by
 *      the same code that delivers the content.
 *
 * Heights below are measured against the real rendered content, not guessed — see
 * staged-patches/opus5-m10-skeleton-pass-20260816/evidence/ for the before/after numbers.
 *
 * Depends on public/css/loading-states.css for the .ns-skeleton* primitives and on
 * design-system.css for every --ns-* token used here.
 */

/* ── 1. The two holds ───────────────────────────────────────────────────────────────────── */

/*
 * The RESERVED BAND is visible from first paint. It is the container's own initial content and
 * is removed by the clear-and-fill that delivers the real rows, so it must occupy space the
 * moment it renders — this is the default because it is the common case.
 *
 * (Measured the hard way: this rule started life as `display: none`, borrowed from the cloak
 * contract below. Every wired band then reserved exactly nothing and the before/after numbers
 * came back bit-for-bit identical, which is the only reason the mistake was caught.)
 */
.ns-hold {
    display: block;
}

/*
 * The CLOAK HOLD is the opposite: it must stay hidden while the surface it stands in for is
 * visible, and paint only while that surface carries [x-cloak]. Opting in by class keeps the
 * two contracts from cancelling each other out.
 */
.ns-hold--cloak {
    display: none;
}

[x-cloak] + .ns-hold--cloak {
    display: block;
}

/* ── 2. Shared shell ────────────────────────────────────────────────────────────────────── */

.ns-hold__inner {
    display: grid;
    gap: var(--ns-space-3, 0.75rem);
}

/*
 * A band dropped INSIDE a container that already lays its children out — a CSS grid, a flex row —
 * must not introduce a box of its own, or the skeleton reserves one column's worth of space while
 * the real content will fill several. `display: contents` dissolves both wrappers so the skeleton
 * cards become direct children of the host container and inherit its exact columns, widths and
 * gaps. Measured on /website-listing: without this the hold drew one 260px column against real
 * content of two 405px columns; with it the silhouette matches the content it stands in for.
 *
 * Custom properties still cascade through a display:contents element, so --ns-hold-card-h set on
 * the wrapper continues to reach the cards.
 */
.ns-hold--inline,
.ns-hold--inline > .ns-hold__inner {
    display: contents;
}

/* A hold must never be read out or focused: it is scaffolding, not content. The live region
   that announces real loading state belongs to the surface itself. */
.ns-hold [aria-hidden='true'] {
    pointer-events: none;
}

/* ── 3. Shapes ──────────────────────────────────────────────────────────────────────────── */

/* Card wall — mirrors the scheduler / check-in / topic grids. */
.ns-hold--grid .ns-hold__inner {
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: var(--ns-space-4, 1rem);
}

.ns-hold--grid .ns-skeleton-card {
    min-height: var(--ns-hold-card-h, 160px);
}

/* Row list — mirrors timeline / task / activity lists. */
.ns-hold--list .ns-hold__inner {
    gap: var(--ns-space-3, 0.75rem);
}

/* Panel — mirrors a settings card with a heading and a few fields. */
.ns-hold--panel .ns-hold__inner {
    border: 1px solid var(--ns-border-subtle, rgba(255, 255, 255, 0.08));
    border-radius: var(--ns-radius-lg, 12px);
    background: var(--ns-bg-secondary, rgba(255, 255, 255, 0.02));
    padding: var(--ns-space-4, 1rem);
    gap: var(--ns-space-3, 0.75rem);
}

/* ── 4. Calm ────────────────────────────────────────────────────────────────────────────── */

/*
 * A skeleton that shimmers forever reads as a hang rather than a wait. loading-states.css runs
 * the shimmer as an infinite animation; here it is allowed ~8 seconds of motion and then rests
 * as a flat, quiet block. If the network never delivers, the customer sees stillness instead of
 * a surface that looks permanently busy.
 */
.ns-hold .ns-skeleton-text::after,
.ns-hold .ns-skeleton-card::after,
.ns-hold .ns-skeleton-avatar::after,
.ns-hold .ns-skeleton::after {
    animation-iteration-count: 5;
}

@media (prefers-reduced-motion: reduce) {
    .ns-hold .ns-skeleton-text::after,
    .ns-hold .ns-skeleton-card::after,
    .ns-hold .ns-skeleton-avatar::after,
    .ns-hold .ns-skeleton::after {
        animation: none;
    }
}

/* ── 5. Mobile ──────────────────────────────────────────────────────────────────────────── */

@media (max-width: 640px) {
    .ns-hold--grid .ns-hold__inner {
        grid-template-columns: 1fr;
        gap: var(--ns-space-3, 0.75rem);
    }

    .ns-hold--grid .ns-skeleton-card {
        min-height: var(--ns-hold-card-h-sm, 132px);
    }
}
