.exp-seq {
    --seq-border: #E5E7EB;
    --seq-ink: #111827;
    --seq-harm: #B42318;
    --seq-futile: #7C879B;
    /* the greys, named once: text, faint text, hairlines, trail default */
    --seq-dim: #98A2B3;
    --seq-fainter: #B0B7C3;
    --seq-hairline: #E1E4EA;
    --seq-trail: #7A8496;
    --seq-ship: #067647;

    /*
     * Geometry every decision rule derives from. The template overrides the
     * first three inline from config.php's $seqCol/$seqGap/$stepPx, so the px
     * it positions trails with and the values animated against here stay in
     * step. These are the standalone defaults, used if the CSS is loaded alone.
     */
    --seq-col: 50px;          /* one decision column */
    --seq-gap: 10px;          /* between columns */
    --seq-step: 60px;         /* col + gap: one column of travel */
    --seq-box-h: 34px;        /* a decision box */
    --seq-bar-h: 5px;         /* the sample bar; a settled row draws a thinner one */
    /*
     * The row template, and the inset and gutter every row shares. The design
     * column is sized to its widest label ("HYBRID / 2-TAIL"), not padded out —
     * the slack goes to the experiment name, which is the column that needs it.
     */
    --seq-grid: 84px 1fr 148px 170px;
    --seq-inset: 16px;        /* the card's left/right padding */
    --seq-gutter: 16px;       /* between columns */

    /* the texture that marks "waiting on the sample" */
    --seq-hatch: repeating-linear-gradient(
        -45deg, #FCFCFD 0 6px, #F7F8FA 6px 12px);
    /*
     * The table is wider than the 800px article column it sits in, so it breaks
     * out on both sides — the same left:50% + translateX(-50%) centring the
     * template card rows use, since auto margins cannot exceed the container.
     * Capped against the viewport so it never causes a horizontal scrollbar.
     */
    position: relative;
    left: 50%;
    transform: translateX(-50%);
    box-sizing: border-box;
    width: 920px;
    max-width: calc(100vw - 32px);
    margin: 0 0 60px;
    font-family: Arial, Helvetica, sans-serif;
    color: var(--seq-ink);
}

/* ---- header row: labels shown once ---- */
/*
 * Inside the card rather than floating above it, so the column labels read as
 * belonging to the table they name. Same grid and padding as a row, so every
 * label lines up with its column; a tinted band and the shared row border
 * separate it from the first experiment.
 */
.exp-seq-head {
    display: grid;
    grid-template-columns: var(--seq-grid);
    align-items: end;
    gap: var(--seq-gutter);
    padding: 10px var(--seq-inset) 8px;
    background: #FCFCFD;
    border-bottom: 1px solid var(--seq-border);
}
/*
 * 10.5px is as large as these go: "GIVE UP" is the longest label over the
 * narrowest column (50px) and takes ~46px of it here, so a larger size would
 * wrap it onto a second line. Tracking is tightened a little for the same
 * reason, and the grey darkened so the labels hold their own at this size.
 */
.exp-seq-head-name,
.exp-seq-head-col,
.exp-seq-head-decision {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #8A93A0;
}
.exp-seq-head-design { text-align: left; }
.exp-seq-head-decisions {
    display: flex;
    gap: 10px;
}

/*
 * Every square is sized and positioned relative to the last visit, so the table
 * states that reference once, here, rather than leaving it to the row tooltips.
 * It sits below the header rule on its own line — a note about the table, not a
 * column label — but keeps the header's grid so it lands under the decision
 * columns it actually qualifies.
 */
.exp-seq-since-row {
    display: grid;
    grid-template-columns: var(--seq-grid);
    gap: var(--seq-gutter);
    padding: 7px var(--seq-inset) 8px;
    border-bottom: 1px solid var(--seq-border);
}
.exp-seq-since {
    grid-column: 4;
    font-size: 10.5px;
    font-weight: 400;
    letter-spacing: 0.01em;
    text-transform: none;
    text-align: center;
    line-height: 1.3;
    color: var(--seq-dim);
    white-space: nowrap;
}
.exp-seq-head-decision {
    width: 50px;
    text-align: center;
    line-height: 1.2;
}
/*
 * Every element that names a decision — a header label, a completed sample bar,
 * a verdict, a decision square, an open panel's figure — wears that decision's
 * colour. The mapping is made once here as --kind-color, and each of those sites
 * below just spends it on whichever property it needs.
 */
.exp-seq [data-kind="abort"]  { --kind-color: var(--seq-harm); }
.exp-seq [data-kind="futile"] { --kind-color: var(--seq-futile); }
.exp-seq [data-kind="ship"]   { --kind-color: var(--seq-ship); }

.exp-seq-head-decision { color: var(--kind-color); }

/*
 * The card holds the header and the rows together. The border and rounding move
 * here from the list, so the labels sit inside the same white panel.
 */
.exp-seq-card {
    border: 1px solid var(--seq-border);
    border-radius: 8px;
    overflow: hidden;
    background: #fff;
}

/*
 * A loose visual reference from each numbered point above to roughly where it
 * shows up in the table. Absolutely positioned against .exp-seq (not measured
 * against any row), so this never affects the table's own layout or sizing —
 * an association, not a precise pointer. Each badge carries a small notch
 * (the ::after triangle) aimed toward the table, and a drop shadow to read as
 * sitting above the surface rather than printed on it.
 */
.exp-seq-annotations {
    position: absolute;
    inset: 0;
    z-index: 3;
    pointer-events: none;
}
.exp-seq-annotations span {
    position: absolute;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 2px solid #fff;
    background: #be65ac;
    color: #fff;
    font-family: "Oswald", Arial, Helvetica, sans-serif;
    font-size: 13px;
    font-weight: 800;
    box-shadow: 0 3px 8px rgba(17, 24, 39, 0.28);
}
.exp-seq-annotations span::after {
    content: "";
    position: absolute;
    z-index: -1;
    width: 10px;
    height: 10px;
    background: #be65ac;
    border-radius: 2px;
}

/* #1 — sticks out over the table's top-right corner */
.is-note-1 {
    top: -30px;
    right: 75px;
}
.is-note-1::after {
    bottom: -3px;
    left: 50%;
    transform: translateX(-50%) rotate(45deg);
}

/* #2 — right side, pointing in at the row whose square travelled the farthest */
.is-note-2 {
    top: 190px;
    right: -28px;
}
.is-note-2::after {
    left: -3px;
    top: 50%;
    transform: translateY(-50%) rotate(45deg);
}

/* #3 — left side, pointing in at the Design column */
.is-note-3 {
    top: 90px;
    left: -28px;
}
.is-note-3::after {
    right: -3px;
    top: 50%;
    transform: translateY(-50%) rotate(45deg);
}

/* #4 — sits just left of the "days left" badge it points at */
.is-note-4 {
    top: 365px;
    left: 490px;
}
.is-note-4::after {
    right: -3px;
    top: 50%;
    transform: translateY(-50%) rotate(45deg);
}

/* #5 — right side, pointing at a fixed-horizon row's greyed-out placeholder */
.is-note-5 {
    top: 755px;
    right: -13px;
}
.is-note-5::after {
    left: -3px;
    top: 50%;
    transform: translateY(-50%) rotate(45deg);
}
.exp-seq-list {
    list-style: none;
    margin: 0;
    padding: 0;
    background: #fff;
}
.exp-seq-item {
    display: grid;
    grid-template-columns: var(--seq-grid);
    align-items: center;
    gap: var(--seq-gutter);
    padding: 7px var(--seq-inset);
}
.exp-seq-item + .exp-seq-item { border-top: 1px solid var(--seq-border); }

.exp-seq-name {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: 1.35;
    word-break: break-word;
}

/* ---- experiment design ---- */
/*
 * Left-aligned, not centred. The column is wider than the glyph pair, so
 * centring floated the glyphs ~18px inward and made the table's left inset read
 * as twice its right one — even though the padding either side is identical.
 * Aligning to the start puts the first glyph on the card's true inset.
 */
.exp-seq-design {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    font-size: 8.5px;
    line-height: 1.3;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    text-align: left;
    color: var(--seq-dim);
}
/*
 * Abbreviated in config.php so the pair fits the 104px column on one line; this
 * keeps it there if a longer name is ever added, rather than silently wrapping.
 */
.exp-seq-design-label {
    white-space: nowrap;
}
/* the goal half of the label sits a shade back, as the design leads */
.exp-seq-design-goal {
    display: inline-block;
    color: var(--seq-fainter);
}

/* the two glyphs sit side by side: how it may stop, and what counts as a result */
.exp-seq-glyphs {
    display: flex;
    align-items: center;
    gap: 3px;
}
.exp-seq-design-icon {
    flex: 0 0 auto;
    width: 22px;
    height: 20px;
    color: #B6BDC8;
}
.exp-seq-design-icon.is-goal {
    color: #CDD3DC;
}

/* ---- sample progress + days left ---- */
/*
 * The bar always reserves the same width and position, whether or not a row
 * carries a wait — nothing beside it claims part of the column any more, so
 * a badge appearing or disappearing between visits never moves it.
 */
.exp-seq-sample {
    position: relative;
}
.exp-seq-sample-track {
    display: flex;
    align-items: center;
    height: var(--seq-bar-h);
}
.exp-seq-sample-bar {
    flex: 1 1 auto;
    min-width: 0;
    height: var(--seq-bar-h);
    border-radius: 3px;
    background: #EAECF0;
    overflow: hidden;
}
/*
 * An unfinished bar takes the same ink as the days badge beneath it: the two are
 * one statement about a row still gathering — how far it has come, and how long
 * is left. A decided row overrides this with its decision's colour below.
 */
.exp-seq-sample-fill {
    height: 100%;
    border-radius: 3px;
    background: var(--seq-ink);
    transition: width 0.3s ease, background 0.3s ease;
}
/*
 * A settled row states its result three times over: this bar, the verdict in the
 * note beneath it, and the filled decision square across the row. At 100% the
 * bar carries no ratio any more — only colour, which the other two already give
 * — so it thins to a rule. The gathering rows keep the full weight, since there
 * the bar is the only thing showing how far along they are.
 */
.exp-seq-sample-bar.is-done,
.exp-seq-sample-bar.is-done .exp-seq-sample-fill {
    height: 2px;
}
.exp-seq-sample-fill.is-complete { background: var(--kind-color); }
.exp-seq-sample-note {
    margin-top: 6px;
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 11px;
    font-variant-numeric: tabular-nums;
    color: var(--seq-dim);
    white-space: nowrap;
}

/*
 * A reached decision is named in words as well as shown as a square, so the
 * note says what to do rather than only that something was decided.
 */
.exp-seq-verdict {
    font-weight: 700;
}
.exp-seq-verdict { color: var(--kind-color); }

/* a row still far from a decision states its wait plainly */
.exp-seq-sample-note.is-waiting {
    color: var(--seq-fainter);
}
/*
 * With no decision to read yet, the time still to wait is the only thing on the
 * row worth acting on — so it is given a solid badge of its own rather than
 * being left to trail off the end of a sentence. Filled rather than outlined:
 * against a pale row an inverted chip carries further than a bordered one.
 *
 * Sits inline on the note's own line now, beside the visitor count, rather than
 * overhanging the bar above — so the bar it used to overlap never has to leave
 * room for it, and a row gaining or losing its wait never reflows the bar.
 */
.exp-seq-eta {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
}
.exp-seq-eta-badge {
    display: inline-block;
    padding: 3px 7px;
    border-radius: 6px;
    background: var(--seq-ink);
    color: #fff;
    font-size: 12px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.01em;
}
.exp-seq-sample-note.is-done {
    color: #7A828E;
}

/* ---- the three decision squares ---- */
/*
 * Fixed three-column grid at a fixed height. Every square is centred in its own
 * cell, so growing or shrinking one changes nothing outside that cell — the
 * sample bars beside it stay exactly where they are.
 */
.exp-seq-decisions {
    display: grid;
    grid-template-columns: repeat(3, var(--seq-col));
    gap: var(--seq-gap);
    place-items: center;
    position: relative;
    height: 42px;
    /* a resolving panel spans the full width rather than overflowing one cell,
       so nothing needs clipping here — see .is-resolving */
}
.exp-seq-decision {
    display: flex;
    justify-content: center;
    align-items: center;
    box-sizing: border-box;
    width: var(--seq-col);
    height: var(--seq-box-h);
    border: 1px solid var(--seq-border);
    border-radius: 6px;
    background: #FCFCFD;
    position: relative;
    z-index: 1;
    font-size: 12px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    /* probability now reads as weight rather than size */
    color: color-mix(in srgb, var(--seq-ink) calc(30% + var(--p) * 55%), #C4CAD4);
    transition: width 0.3s ease, height 0.3s ease, background 0.3s ease,
                border-color 0.3s ease, color 0.3s ease, transform 0.3s ease;
}

/* the leading decision takes on its colour */
/* holds the column position without drawing anything */
.exp-seq-decision.is-placeholder {
    border-color: transparent;
    background: none;
    box-shadow: none;
}

/* no decision yet: the leaning option shows faintly, as a hint not a verdict */
.exp-seq-decision.is-leaning {
    border-style: dashed;
    border-color: #E1E4EA;
    background: none;
    color: var(--seq-fainter);
    font-weight: 600;
}

/* a reached decision fills solid with a white figure */
.exp-seq-decision.is-leading {
    color: #fff;
    --decision-type: 13px;
    font-size: var(--decision-type);
    letter-spacing: -0.02em;
    border-color: transparent;
    box-shadow: 0 1px 3px rgba(16, 24, 40, 0.18);
    z-index: 1;
}
/* the travelling square starts on the old fill, so the name stays indirect */
.exp-seq-decision { --decision-fill: var(--kind-color); }
.exp-seq-decision.is-leading { background: var(--decision-fill); }

/* ---- changed since last visit ---- */
/*
 * The square makes one quick move from the column it held last visit into the
 * one it belongs in now. The gradient trail it leaves is the only record of
 * where it came from — it stays after the motion ends. Nothing animates until
 * the row is actually scrolled into view, and rows fire one at a time.
 */
.exp-seq-item.is-changed .exp-seq-decisions {
    position: relative;
}
/*
 * Parked at the old column, wearing last visit's state: the previous decision's
 * colour if one had been reached, or a neutral grey if it was only leaning.
 * Both the position and the fill then transition together over the same half
 * second. The .is-leaning selector below sets its own background, so these rules
 * carry an extra class to stay more specific than it.
 */
.exp-seq-decision.is-travelling.is-travelling {
    transform: translateX(var(--from-x)) scale(var(--from-scale, 1));
    background: var(--from-fill, var(--decision-fill));
    border-color: transparent;
    color: #fff;
    z-index: 2;
}
.exp-seq-decision.is-travelling.is-played {
    transform: translateX(0) scale(var(--to-scale, 1));
    background: var(--decision-fill);
    transition: transform 0.5s cubic-bezier(0.34, 1.24, 0.64, 1),
                background 0.5s ease-out,
                color 0.5s ease-out,
                border-color 0.5s ease-out;
}
/*
 * A changed row that has not reached a decision does not move columns — it just
 * grows or shrinks in place to its new effect strength. Width, height and type
 * size are animated directly rather than through a transform, so the number
 * stays crisp instead of being scaled up as a blurry bitmap.
 */
.exp-seq-decision.is-resized {
    width: calc(50px * var(--from-scale, 1));
    height: calc(var(--seq-box-h) * var(--from-scale, 1));
    font-size: calc(var(--decision-type, 12px) * max(var(--from-scale, 1), 0.97));
}
.exp-seq-decision.is-resized.is-played {
    width: calc(50px * var(--to-scale, 1));
    height: calc(var(--seq-box-h) * var(--to-scale, 1));
    font-size: calc(var(--decision-type, 12px) * max(var(--to-scale, 1), 0.97));
    transition: width 0.55s cubic-bezier(0.34, 1.18, 0.64, 1),
                height 0.55s cubic-bezier(0.34, 1.18, 0.64, 1),
                font-size 0.55s cubic-bezier(0.34, 1.18, 0.64, 1);
}

/*
 * A fixed-horizon row has no decision to draw. It spans the whole decision area
 * with the effect it is powered to detect — a stated intention, not a reading,
 * so it is set in outline rather than as one of the three decision squares.
 */
.exp-seq-mde {
    justify-self: stretch;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 11px;
    height: var(--seq-box-h);
    border: 1px dashed var(--seq-hairline);
    border-radius: 6px;
    background: var(--seq-hatch);
}
.exp-seq-mde-pair {
    display: flex;
    align-items: baseline;
    gap: 5px;
}
.exp-seq-mde-running {
    font-size: 12px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--seq-dim);
}
/*
 * Grey while the reading is not statistically significant, coloured by direction
 * once it is. This follows the p-value on its own — significance and the MDE are
 * different things, and a reading either side of the MDE can go either way.
 */
.exp-seq-mde-running[data-tone="none"]   { color: var(--seq-dim); }
.exp-seq-mde-running[data-tone="ship"]   { color: var(--seq-ship); }
.exp-seq-mde-running[data-tone="harm"]   { color: var(--seq-harm); }
/*
 * The running figure drifts like any other reading, but it is a bare number
 * rather than a square — so only its type size changes, not a box.
 */
.exp-seq-mde-running.is-resized {
    display: inline-block;
    font-size: calc(12px * max(var(--from-scale, 1), 0.97));
}
.exp-seq-mde-running.is-resized.is-played {
    font-size: calc(12px * max(var(--to-scale, 1), 0.97));
    transition: font-size 0.55s cubic-bezier(0.34, 1.18, 0.64, 1);
}

/*
 * A decision the design will not let you act on yet. It borrows the same dashed,
 * hatched treatment the fixed-horizon row uses, because it means the same thing:
 * waiting on the sample. No colour — that is reserved for decisions you can take.
 */
.exp-seq-decision.is-locked.is-locked {
    border: 1px dashed var(--seq-hairline);
    background: var(--seq-hatch);
    color: var(--seq-dim);
    font-weight: 700;
}
/* a held panel still shows which way it leans, in that outcome's colour — the
   .is-open-span rule further down already does this for locked and open alike */

/* a held panel stretches across every column still in play */
.exp-seq-decision.is-held-span,
.exp-seq-mde.is-held-span {
    grid-column: span var(--span, 1);
    justify-self: stretch;
    width: auto;
}

/*
 * Undecided: the panel holds the whole decision area open, and the figure sits
 * over whichever column currently leads. Colour says which way it leans without
 * claiming the decision has been made.
 */
.exp-seq-decision.is-open-span {
    grid-column: span var(--span, 3);
    justify-self: stretch;
    align-self: center;
    width: auto;
    height: var(--seq-box-h);
    position: relative;
    display: block;
    /* the figure is positioned against this box, so nothing may escape it */
    overflow: hidden;
    border: 1px dashed var(--seq-hairline);
    background: var(--seq-hatch);
}
.exp-seq-open-value {
    position: absolute;
    /* above the trail that runs behind it */
    z-index: 1;
    top: 50%;
    /* centre of the leading column, measured inside the panel's own box */
    left: calc(var(--lean) * var(--seq-step) + 24px);
    transform: translate(-50%, -50%);
    display: inline-block;
    font-size: 12px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    transition: left 0.45s cubic-bezier(0.34, 1.18, 0.64, 1);
}
.exp-seq-decision.is-open-span .exp-seq-open-value { color: var(--kind-color); }

/*
 * A lean that moved between columns starts over the column it held last visit
 * and slides across to the new one, so the shift is watched rather than assumed.
 */
.exp-seq-open-value.is-shifting {
    left: calc(var(--from-lean) * var(--seq-step) + 24px);
}
.exp-seq-open-value.is-shifting.is-played {
    left: calc(var(--lean) * var(--seq-step) + 24px);
}

/*
 * A lean that crossed columns leaves the same kind of trace a travelling square
 * does — drawn inside the panel, since that is the box the figure moves within.
 */
/*
 * Both trails are the same 13px band: only where they start, how wide they run
 * and how the colour ramps differ. The shared box is defined once, so the two
 * rules below carry just what actually distinguishes them.
 */
.exp-seq-decisions.has-trail::before,
.exp-seq-decision.is-open-span.has-shift::after {
    content: "";
    position: absolute;
    top: 50%;
    height: 13px;
    margin-top: -6.5px;
    border-radius: 2px;
    opacity: 0;
    pointer-events: none;
    z-index: 0;
    transition: opacity 0.45s ease-out;
}

/*
 * A lean that crossed columns. Unlike a decided row, this figure sits straight on
 * the trail rather than on an opaque square — so the band stops short of it and
 * only runs from there back to the centre of the column it came from.
 * --shift-dir is 1 when the value moved right, -1 when it moved left.
 * The ramp is densest at the origin and fades to nothing where it landed.
 */
.exp-seq-decision.is-open-span.has-shift::after {
    left: calc(
        min(var(--lean), var(--from-lean)) * var(--seq-step) + 24px
        + max(var(--shift-dir) * -1, 0) * 19px
    );
    width: calc(
        (max(var(--lean), var(--from-lean)) - min(var(--lean), var(--from-lean))) * var(--seq-step) - 19px
    );
    background: linear-gradient(
        to var(--trail-fade, left),
        color-mix(in srgb, var(--trail-color, var(--seq-trail)) 52%, transparent) 0%,
        color-mix(in srgb, var(--trail-color, var(--seq-trail)) 40%, transparent) 12%,
        color-mix(in srgb, var(--trail-color, var(--seq-trail)) 20%, transparent) 45%,
        color-mix(in srgb, var(--trail-color, var(--seq-trail)) 4%, transparent) 100%);
}
.exp-seq-decision.is-open-span.has-shift.is-played::after { opacity: 1; }
.exp-seq-decision.is-open-span.has-shift.is-settled::after { opacity: 0.7; }

/* the figure keeps the same grow/shrink step as every other reading */
.exp-seq-open-value.is-resized {
    font-size: calc(12px * max(var(--from-scale, 1), 0.97));
}
.exp-seq-open-value.is-resized.is-played {
    font-size: calc(12px * max(var(--to-scale, 1), 0.97));
    transition: font-size 0.55s cubic-bezier(0.34, 1.18, 0.64, 1),
                left 0.45s cubic-bezier(0.34, 1.18, 0.64, 1);
}

/*
 * Crossed from an open lean into a decision since the last visit. It is the
 * same open-lean panel this row showed then — .is-open-span, unchanged, so it
 * is wide, hatched and spans every live column exactly as it did before — and
 * only .is-resolving adds how it leaves that state: closing down onto its own
 * column and taking on the solid fill as the decision lands. The grid area it
 * reserves never changes, only how much of it the box actually fills, so nothing
 * needs to be visible from the start depends on JS to appear at all if playback
 * is ever skipped or fails to run — only the close is played.
 */
.exp-seq-decision.is-open-span.is-resolving.is-resolving {
    /* .is-open-span stretches to fill its whole span by default; pinning an
       explicit width here is what makes that width something to shrink */
    justify-self: start;
    width: calc(var(--span, 3) * var(--seq-col) + (var(--span, 3) - 1) * var(--seq-gap));
}
.exp-seq-decision.is-open-span.is-resolving.is-resolving.is-played {
    /* shrinks to one column and slides to sit over it, the same column its
       figure already sat above inside the open panel */
    width: var(--seq-col);
    margin-left: calc(var(--lean, 0) * var(--seq-step));
    background: var(--decision-fill);
    border-color: transparent;
    box-shadow: 0 1px 3px rgba(16, 24, 40, 0.18);
    transition: width 0.5s cubic-bezier(0.34, 1.14, 0.64, 1),
                margin-left 0.5s cubic-bezier(0.34, 1.14, 0.64, 1),
                background 0.45s ease-out 0.1s,
                border-color 0.45s ease-out 0.1s,
                box-shadow 0.45s ease-out 0.1s;
}
/*
 * The figure sits at the same on-screen spot throughout — over its own column
 * — but that spot is measured from the panel's own left edge, and that edge
 * moves as the panel shrinks and slides (see margin-left above). Its "left"
 * here has to converge on plain center (24px into a 50px box) in step with
 * that shrink, or the number would drift off-centre as the box closes in
 * under it. Only its colour then finishes the move, from the outcome's tint
 * against the open panel to solid white against the fill it lands on.
 */
.exp-seq-decision.is-open-span.is-resolving .exp-seq-open-value {
    transition: left 0.5s cubic-bezier(0.34, 1.14, 0.64, 1), color 0.35s ease-out 0.15s;
}
.exp-seq-decision.is-open-span.is-resolving.is-played .exp-seq-open-value {
    left: 24px;
    color: #fff;
}

/*
 * A fixed design's one and only decision moment: the full sample is in, and
 * the MDE panel this row showed while gathering closes down onto the outcome
 * reached, the same way the sequential open-lean panel above does — reusing
 * .exp-seq-mde's own flex-centred layout means the running figure stays
 * centred in the box through the shrink for free, with no position to track.
 */
.exp-seq-mde.is-resolving.is-resolving {
    justify-self: start;
    width: calc(var(--span, 3) * var(--seq-col) + (var(--span, 3) - 1) * var(--seq-gap));
}
.exp-seq-mde.is-resolving.is-resolving.is-played {
    width: var(--seq-col);
    margin-left: calc(var(--lean, 0) * var(--seq-step));
    /* --decision-fill is only defined on .exp-seq-decision; this panel is an
       .exp-seq-mde, so it reaches for --kind-color directly instead */
    background: var(--kind-color);
    border-color: transparent;
    box-shadow: 0 1px 3px rgba(16, 24, 40, 0.18);
    transition: width 0.5s cubic-bezier(0.34, 1.14, 0.64, 1),
                margin-left 0.5s cubic-bezier(0.34, 1.14, 0.64, 1),
                background 0.45s ease-out 0.1s,
                border-color 0.45s ease-out 0.1s,
                box-shadow 0.45s ease-out 0.1s;
}
.exp-seq-mde.is-resolving .exp-seq-mde-running {
    transition: color 0.35s ease-out 0.15s;
}
.exp-seq-mde.is-resolving.is-played .exp-seq-mde-running {
    color: #fff;
}

/* a lean that has not hardened into a decision ends pale, not filled */
.exp-seq-decision.is-travelling.is-leaning.is-played {
    background: none;
    border-color: #E1E4EA;
    color: var(--seq-fainter);
}

/*
 * The trail belongs to the row, not the square, so it stays put while the
 * square moves across it. It spans from the origin column to the destination
 * and fades in the direction of travel.
 */
/*
 * A square that travelled between columns. Runs from the edge of the landed
 * square back to the centre of the column it came from, so none of it hides
 * under the opaque square. --travel-dir is 1 when the square moved right and -1
 * when it moved left. Densest at the origin, ramping to nothing where it landed,
 * in the colour of the decision it arrived at.
 */
.exp-seq-decisions.has-trail::before {
    left: calc(
        var(--trail-left) + 25px
        + max(var(--travel-dir) * -1, 0) * 25px
    );
    width: calc(var(--trail-width) - 75px);
    background: linear-gradient(
        to var(--trail-fade, left),
        color-mix(in srgb, var(--trail-color, var(--seq-trail)) 8%, transparent) 0%,
        color-mix(in srgb, var(--trail-color, var(--seq-trail)) 45%, transparent) 55%,
        color-mix(in srgb, var(--trail-color, var(--seq-trail)) 90%, transparent) 88%,
        var(--trail-color, var(--seq-trail)) 100%);
}
.exp-seq-decisions.has-trail.is-played::before { opacity: 1; }
.exp-seq-decisions.has-trail.is-settled::before {
    opacity: 0.75;
    transition: opacity 0.9s ease-out;
}

@media (max-width: 700px) {
    .exp-seq-head { display: none; }
    .exp-seq-item {
        grid-template-columns: auto 1fr;
        gap: 10px 12px;
    }
    .exp-seq-sample { grid-column: 1 / -1; }
    .exp-seq-decisions {
        grid-column: 1 / -1;
        justify-content: flex-start;
    }
}

@media (prefers-reduced-motion: reduce) {
    .exp-seq * {
        transition: none !important;
        animation: none !important;
    }
    /* no travel — the square simply sits where it now belongs */
    .exp-seq-decision.is-travelling { transform: scale(var(--to-scale, 1)); }
    .exp-seq-decision.is-resized {
        width: calc(50px * var(--to-scale, 1));
        height: calc(var(--seq-box-h) * var(--to-scale, 1));
        font-size: calc(var(--decision-type, 12px) * max(var(--to-scale, 1), 0.97));
    }
    .exp-seq-decisions.has-trail::before { opacity: 0.42; }
}
