/* ==========================================================================
   Autoplay tabs
   ==========================================================================

   A set of steps that plays itself. Each step carries a title, a description, a
   thin progress bar and a media stage; the active step's bar fills over a fixed
   duration and then hands over to the next, looping. Clicking a step jumps to
   it. Pointing at the group, or tabbing into it, pauses the cycle.

   PROGRESSIVE ENHANCEMENT, TWO LAYOUTS. The base layout below is a plain
   vertical list: every step shows its own heading, copy and image, stacked. That
   is what a no-JS visitor gets, what everyone gets under the breakpoint, and it
   is a perfectly reasonable way to read a numbered sequence — nothing is hidden
   and nothing needs a control. assets/js/autoplay-tabs.js adds `.is-ready` only
   above 992px, which is where the two-column tab layout and the cycling live.

   NOTHING IS EVER HIDDEN, EVEN THERE. All three headings and descriptions stay
   on screen in the tab layout too; only the media stage swaps. The progress bar
   tells you where the cycle is, rather than the copy appearing and disappearing.
   That keeps the whole section readable at a glance and means the autoplay is
   decoration rather than a gate on the content.

   THE TIMER IS THE PROGRESS BAR. There is no setTimeout anywhere. The bar is a
   CSS animation and the JS advances on its `animationend`, so the two cannot
   drift apart, and pausing is `animation-play-state: paused` — the browser owns
   the remaining time. A timer alongside a CSS animation is two clocks that
   disagree the moment a tab is backgrounded.
   ========================================================================== */

[data-tabset] {
    /* Overwritten from the data-tabset-timing attribute by the JS, so the markup
       stays the single source of truth for the duration. */
    --tabset-timing: 6500ms;
    --tabset-gap: clamp(1.75rem, 4vw, 3.5rem);

    /* Width of the media panel in the tab layout, as a share of the group. The
       copy column takes whatever is left after this and the gap — about 40%,
       which is the split the reference layout uses. */
    --tabset-media: 56%;
}

/* --------------------------------------------------------------------------
   Base / below the breakpoint — a stacked, self-explanatory list
   -------------------------------------------------------------------------- */

.tabset-list {
    display: flex;
    flex-direction: column;
    gap: clamp(2rem, 5vw, 3rem);
    margin: 0;
    padding: 0;
    list-style: none;
}

/* The copy block. The control is a separate, absolutely positioned <button>
   INSIDE this, rather than a button wrapping the copy, for two reasons: a
   <button>'s content model is phrasing content, so an <h3> inside one is
   invalid, and a step whose heading is not a heading gives the section no
   outline for a screen reader to navigate. This way the step keeps a real h3
   and still has one large, obvious hit area. */
.tabset-head {
    position: relative;
}

.tabset-tab {
    /* Covers the copy block. Carries an aria-label of the step title, so it
       announces as a control for that step rather than as empty. */
    position: absolute;
    inset: 0;
    inline-size: 100%;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    cursor: pointer;
    /* Above the copy for hit-testing, but the copy is not interactive so nothing
       is stolen; text remains selectable outside the button's own bounds. */
    z-index: 1;
}

.tabset-track {
    /* The rail the bar runs along. Hidden in the stacked layout, where there is
       no cycle to report — it only earns its place once steps take turns. */
    display: none;
}

.tabset-progress {
    display: block;
    block-size: 100%;
    background: linear-gradient(90deg, var(--color-primary), var(--color-secondary));
    scale: 0 1;
    transform-origin: left;
}

[dir="rtl"] .tabset-progress {
    transform-origin: right;
}

.tabset-step {
    display: block;
    margin-block-end: 0.5rem;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    color: var(--color-primary);
    font-variant-numeric: tabular-nums;
}

.tabset-title {
    margin: 0 0 0.5rem;
    font-family: var(--font-family-heading);
    font-size: var(--font-size-xl);
    font-weight: var(--font-weight-semibold);
    line-height: 1.25;
    color: var(--text-primary);
}

/* An <h3> inside a <button> would be invalid, hence the overlay control above.
   Neither host's `[lang="ar"] h1, h2, h3 { font-family: 'Cairo', … }` rule is
   relied on either, because this heading level is reached by both main.css and
   landing.css with different selector lists; the component states the Arabic
   stack once for itself rather than having each host patch it. */
html[lang="ar"] .tabset-title {
    font-family: 'Cairo', var(--font-family-heading);
}

.tabset-desc {
    margin: 0;
    font-size: var(--font-size-base);
    line-height: var(--line-height-relaxed);
    color: var(--text-secondary);
}

.tabset-stage {
    position: relative;
    margin-block-start: 1.25rem;
    /* Deliberately larger than --radius-lg. The panel is the biggest object in the
       section and a 0.75rem corner on something this size reads as almost square. */
    border-radius: 1.25rem;
    overflow: hidden;
    border: 1px solid color-mix(in srgb, var(--border-color) 70%, transparent);
    background: var(--bg-secondary);
    aspect-ratio: 16 / 10;
    /* Lifts the panel off the tinted band so it reads as a screen rather than a
       hole cut in the section. */
    box-shadow:
        0 1px 2px color-mix(in srgb, var(--color-primary) 8%, transparent),
        0 18px 40px -24px color-mix(in srgb, var(--color-primary) 45%, transparent);
}

.tabset-stage img {
    inline-size: 100%;
    block-size: 100%;
    display: block;
    object-fit: cover;
}

/* A soft wash behind the image, so a stage whose art fails to load still reads
   as a deliberate panel instead of an empty bordered box. */
.tabset-stage::before {
    content: '';
    position: absolute;
    inset: 0;
    background:
        radial-gradient(80% 70% at 20% 15%, color-mix(in srgb, var(--color-primary) 22%, transparent), transparent 70%),
        radial-gradient(70% 70% at 85% 85%, color-mix(in srgb, var(--color-secondary) 20%, transparent), transparent 70%);
}

.tabset-tab:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 4px;
    border-radius: var(--radius-sm);
}

/* --------------------------------------------------------------------------
   Tab layout — above the breakpoint, once the JS is in
   -------------------------------------------------------------------------- */

@media (min-width: 992px) {

    /* TWO COLUMNS WITHOUT A GRID, deliberately.
    
       Each stage lives INSIDE its own step in the DOM — that is what lets the
       stacked layout put every image directly under its own heading. Showing them
       all in one shared media column therefore means one cell spanning every
       step's row, and that needs a row count the stylesheet cannot know: the
       walkthrough has three steps on the platform but two on an instance that
       shipped without the AI modules.
    
       The first attempt was a grid with `display: contents` on the step and
       `grid-row: 1 / -1` on the stage. With no EXPLICIT rows declared, `-1`
       resolves to the first grid line, so the span collapsed to row one and the
       remaining steps were auto-placed into whatever cells were left — steps two
       and three ended up side by side under the image instead of stacked beside
       it.
    
       So: the list reserves a gutter as wide as the media panel and each stage is
       absolutely positioned into it, against the list itself. Any number of steps
       works with no count anywhere, and `inset-block: 0` makes the panel exactly
       as tall as the copy beside it, which is what makes the two columns balance
       instead of one dangling below the other. */
    [data-tabset].is-ready .tabset-list {
        position: relative;
        display: flex;
        flex-direction: column;
        /* Centres the copy against the panel when the steps are shorter than the
           minimum panel height. */
        justify-content: center;
        gap: clamp(1.5rem, 2.6vw, 2.5rem);
        padding-inline-end: calc(var(--tabset-media) + var(--tabset-gap));
        min-block-size: 22rem;
    }

    [data-tabset].is-ready .tabset-head {
        /* Inactive steps recede rather than disappear: the copy stays readable,
           which is the point of showing every step at once. 0.5 was too far — the
           steps read as disabled — so the dimming is gentler here and the heading
           is held back further still, below. */
        opacity: 0.68;
        transition: opacity 0.45s ease;
    }

    [data-tabset].is-ready .tabset-item.is-active .tabset-head,
    [data-tabset].is-ready .tabset-head:hover,
    [data-tabset].is-ready .tabset-head:focus-within {
        opacity: 1;
    }

    [data-tabset].is-ready .tabset-track {
        display: block;
        block-size: 3px;
        margin-block-end: 1.125rem;
        border-radius: 999px;
        overflow: hidden;
        /* Mixed rather than the raw token: --border-color is tuned for card edges
           on the page background and disappears entirely against this tinted band,
           which left the inactive steps looking like they had no rail at all. */
        background: color-mix(in srgb, var(--text-primary) 14%, transparent);
    }

    /* The heading carries the emphasis; dimming it as hard as the body copy made
       the inactive steps look disabled rather than simply not-current. */
    [data-tabset].is-ready .tabset-head .tabset-title {
        transition: color 0.45s ease;
    }

    [data-tabset].is-ready .tabset-item:not(.is-active) .tabset-title {
        color: color-mix(in srgb, var(--text-primary) 82%, transparent);
    }

    [data-tabset].is-ready .tabset-stage {
        /* Positioned against .tabset-list, since the step wrapper is static. All
           the stages therefore land in exactly the same box and cross-fade in
           place. */
        position: absolute;
        inset-block: 0;
        inset-inline-end: 0;
        inline-size: var(--tabset-media);
        margin: 0;
        /* Height now comes from the insets, so the ratio has to stand down or the
           two would fight. The image covers, so a panel taller or shorter than
           16:10 still fills without letterboxing. */
        aspect-ratio: auto;
        /* `visibility` as well as opacity, so an inactive panel is out of hit
           testing and the tab order rather than merely transparent. */
        opacity: 0;
        visibility: hidden;
        transition: opacity 0.5s ease, visibility 0.5s;
    }

    [data-tabset].is-ready .tabset-item.is-active .tabset-stage {
        opacity: 1;
        visibility: visible;
    }

    /* The fill. Attached to `.is-active`, so moving that class to another step
       restarts the animation on the new bar and resets the old one to zero —
       no manual restart, and no state to keep in sync.

       `.is-auto` is absent when autoplay is off (reduced motion, a single step,
       or the group being off screen has never yet been resumed), in which case
       the bar simply sits empty and the steps stay clickable. */
    [data-tabset].is-ready.is-auto .tabset-item.is-active .tabset-progress {
        animation: tabsetProgress var(--tabset-timing) linear forwards;
    }

    /* Pointer over the group, or focus inside it, or the group scrolled out of
       view. The browser holds the remaining time for us. */
    [data-tabset].is-ready.is-auto.is-paused .tabset-item.is-active .tabset-progress {
        animation-play-state: paused;
    }
}

@keyframes tabsetProgress {
    from { scale: 0 1; }
    to   { scale: 1 1; }
}

/* --------------------------------------------------------------------------
   Reduced motion
   --------------------------------------------------------------------------
   The JS declines to add `.is-auto`, so nothing cycles and no `animationend`
   ever fires. The bar would sit permanently empty and read as a broken control,
   so it is removed instead, and the first stage is simply the one on show until
   a step is clicked. */

@media (prefers-reduced-motion: reduce) {

    [data-tabset].is-ready .tabset-track {
        display: none;
    }

    [data-tabset].is-ready .tabset-stage,
    [data-tabset].is-ready .tabset-head {
        transition: none;
    }
}
