/* ══════════════════════════════════════════════════════════════════════════
   Release scenes — the animated header of a release in the history on /about
   ══════════════════════════════════════════════════════════════════════════
   A scene is changelog/<version>.html, inlined above that release's notes. It is composed from the
   classes in this file and nothing else: no colours, no keyframes, no script of its own. That is
   what keeps thirteen releases looking like one product, and what lets a scene follow the theme —
   every colour below is an app token, so dark mode and a redesign reach old scenes too.
   docs/CHANGELOG-STYLE.md §10 has the rules for writing one.

   ── One clock ──
   .rs-scene runs --rs-t from 0 to 1 per cycle. Nothing else is animated: every moving element
   derives its state from --rs-t and its own --at, the moment it happens. That is why a scene stays
   in step with itself however many elements it has, why all of it rewinds together at the end of a
   cycle, and why it can stop on a complete picture — the clock runs 1.85 cycles and halts at 0.85,
   when every --at has passed. So:

     • --at between 0.04 and 0.78. Later than that is never seen at rest.
     • Under "reduce motion" the clock does not run and sits at 0.85: the scene shows its last frame.
     • Collapsed in the timeline, the clock is paused, so an entry opened later starts from 0.

   ── Units ──
   A stage is drawn on a design grid (--sw × --sh, e.g. 380 × 240) and scales like an image:
   --u is one design unit, everything inside is sized in it or in em (1em = 12 units). */

@property --rs-t {
    syntax: "<number>";
    inherits: true;
    initial-value: 0.85;
}

/* A scene is the window on the release's banner (About.razor.css): frosted glass over the banner's
   dark ground and its lights, the tiles in it the app's own surfaces. It scales like an image, so on
   a wide card it would grow without end. 720 px is where its 12-unit text reaches 12 px — no larger
   than the notes beneath it. */
.rs-scene {
    --rs-t: 0.85;
    --rs-ok: var(--clr-emerald-500);
    container-type: inline-size;
    max-width: 720px;
    padding: 10px;
    border-radius: var(--radius-xl);
    background: color-mix(in srgb, var(--clr-always-white) 12%, transparent);
    backdrop-filter: blur(14px) saturate(1.4);
    box-shadow: var(--shadow-xl);
    animation: rs-clock var(--rs-cycle, 18s) linear var(--rs-runs, 1.85) both;
    user-select: none;
}

@keyframes rs-clock {
    from { --rs-t: 0; }
    to { --rs-t: 1; }
}

/* Folded away in the release history: hold the clock where it is. */
.reveal-slot.is-gone .rs-scene {
    animation-play-state: paused;
}

@media (prefers-reduced-motion: reduce) {
    .rs-scene {
        animation: none;
    }
}

/* ── Layout ── A large stage on the left, a column of small ones beside it; one column when narrow.
   1.2 : 1 is the ratio at which a 380 × 240 stage is as tall as three 340 × 80 ones. */
.rs-grid {
    display: grid;
    grid-template-columns: 1.2fr 1fr;
    gap: 10px;
}

.rs-side {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.rs-side > .rs-tile {
    flex: 1;
}

@container (max-width: 540px) {
    .rs-grid {
        grid-template-columns: 1fr;
    }
}

/* A tile is the card; the stage inside is the scaled drawing. Centred, so a tile stretched by its
   row keeps its drawing in the middle rather than at the top. */
.rs-tile {
    container-type: inline-size;
    display: flex;
    align-items: center;
    background: var(--surface);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}

.rs-stage {
    --u: calc(100cqw / var(--sw));
    position: relative;
    width: 100%;
    aspect-ratio: var(--sw) / var(--sh);
    font-size: calc(12 * var(--u));
    line-height: 1.25;
    color: var(--text-body);
}

/* The dotted plane of the flow editor, for a stage that shows a Ablauf. */
.rs-canvas {
    background-image: radial-gradient(circle, var(--border) calc(1 * var(--u)), transparent calc(1.2 * var(--u)));
    background-size: calc(20 * var(--u)) calc(20 * var(--u));
}

/* The feature's name, as the changelog names it — the reader's key from picture to text. */
.rs-label {
    position: absolute;
    left: calc(14 * var(--u));
    top: calc(11 * var(--u));
    font-size: calc(8.5 * var(--u));
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-label);
}

/* The content line of a small stage: below the label, full width, centred vertically. */
.rs-row {
    position: absolute;
    left: calc(14 * var(--u));
    right: calc(14 * var(--u));
    top: calc(28 * var(--u));
    bottom: calc(10 * var(--u));
    display: flex;
    align-items: center;
    gap: 0.5em;
}

.rs-row > .rs-end {
    margin-left: auto;
}

/* Absolute placement in design units: top-left corner --x/--y, size --pw × --ph. */
.rs-place {
    position: absolute;
    left: calc(var(--x) * var(--u));
    top: calc(var(--y) * var(--u));
    width: calc(var(--pw) * var(--u));
    height: calc(var(--ph) * var(--u));
}

/* Several states of one thing in the same spot — a button before and after the click. */
.rs-stack {
    display: grid;
    justify-items: end;
    align-items: center;
}

.rs-stack > * {
    grid-area: 1 / 1;
}

/* ── Mini interface ── */
.rs-icon {
    width: 1.2em;
    height: 1.2em;
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    color: var(--text-muted);
}

.rs-title {
    font-weight: 700;
    color: var(--text);
    white-space: nowrap;
}

.rs-meta {
    font-size: 0.8em;
    color: var(--text-muted);
    white-space: nowrap;
}

/* A few things side by side, e.g. avatars and a chip. */
.rs-cluster {
    display: inline-flex;
    align-items: center;
    gap: 0.4em;
}

/* Avatars overlap like the assignee stack in lists. */
.rs-avatars {
    display: inline-flex;
    align-items: center;
}

.rs-avatar {
    display: inline-grid;
    place-items: center;
    width: 2.3em;
    height: 2.3em;
    flex: none;
    border-radius: var(--radius-circle);
    border: calc(1.5 * var(--u)) solid var(--surface);
    background: var(--rs-tone, var(--primary));
    color: var(--clr-always-white);
    font-size: 0.7em;
    font-weight: 700;
}

.rs-avatar + .rs-avatar {
    margin-left: -0.35em;
}

.rs-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35em;
    padding: 0.3em 0.7em;
    border-radius: var(--radius-pill);
    background: var(--surface-sunken);
    color: var(--text-secondary);
    font-size: 0.85em;
    font-weight: 600;
    white-space: nowrap;
}

.rs-chip .rs-icon {
    width: 1.1em;
    height: 1.1em;
    color: inherit;
}

.rs-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.35em;
    padding: 0.5em 0.85em;
    border-radius: calc(8 * var(--u));
    background: var(--primary);
    color: var(--clr-always-white);
    font-size: 0.85em;
    font-weight: 600;
    white-space: nowrap;
    box-shadow: var(--shadow-btn);
}

.rs-btn .rs-icon {
    width: 1.1em;
    height: 1.1em;
    color: inherit;
}

.rs-btn--ok {
    background: var(--clr-green-600);
}

/* Emerald, for a tick that means "done". Two classes, so it wins over a chip's or button's icon colour. */
.rs-scene .rs-ok {
    color: var(--rs-ok);
}

/* The pointer: travels from --x0/--y0 to --x1/--y1 (design units, its tip) and clicks at --at. */
.rs-cursor {
    --rs-m: clamp(0, (var(--rs-t) - var(--at) + 0.09) * 14, 1);
    --rs-me: calc(var(--rs-m) * var(--rs-m) * (3 - 2 * var(--rs-m)));
    --rs-d: calc((var(--rs-t) - var(--at)) * 50);
    position: absolute;
    left: calc((var(--x0) + (var(--x1) - var(--x0)) * var(--rs-me) - 3) * var(--u));
    top: calc((var(--y0) + (var(--y1) - var(--y0)) * var(--rs-me) - 1.5) * var(--u));
    width: calc(17 * var(--u));
    height: calc(17 * var(--u));
    fill: var(--text);
    stroke: var(--surface);
    stroke-width: 1.5;
    stroke-linejoin: round;
    opacity: calc(clamp(0, (var(--rs-t) - var(--at) + 0.11) * 25, 1) * clamp(0, (var(--at) + 0.06 - var(--rs-t)) * 25, 1));
    scale: calc(1 - 0.18 * max(0, 1 - var(--rs-d) * var(--rs-d)));
    transform-origin: 18% 8%;
    z-index: 3;
}

/* Speech: bars that move while the clock is between --from and --to, and rest low otherwise.
   Each bar sets its height --h (0–1) and its phase --ph. */
.rs-wave {
    --rs-act: calc(clamp(0, (var(--rs-t) - var(--from)) * 25, 1) * clamp(0, (var(--to) - var(--rs-t)) * 25, 1));
    display: flex;
    align-items: center;
    gap: calc(2.5 * var(--u));
    height: 2em;
}

.rs-bar {
    --rs-s: sin(var(--rs-t) * 40 * pi + var(--ph));
    width: calc(3 * var(--u));
    height: 100%;
    border-radius: var(--radius-pill);
    background: var(--primary);
    scale: 1 calc(var(--h) * (0.45 + 0.55 * var(--rs-act) * var(--rs-s) * var(--rs-s)));
}

/* ── Flow (the Ablauf of a Projekt-Template, drawn like the editor) ── */

/* Edges sit under the nodes; the SVG's viewBox is the stage's design grid, so its coordinates are
   the same units as --x/--y. An edge that lights up is a second path over the grey one. */
.rs-edges {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
}

.rs-edge {
    fill: none;
    stroke: var(--border-strong);
    stroke-width: 2;
    stroke-linecap: round;
}

.rs-edge--on {
    stroke: var(--primary);
    stroke-width: 2.5;
}

/* A node: a step card, or a Steuerknoten shape. The label hangs beneath, as on the canvas. */
.rs-node {
    display: grid;
    place-items: center;
}

.rs-shape {
    position: absolute;
    inset: 0;
    background: var(--surface);
    box-shadow: var(--shadow-sm);
}

.rs-node--card .rs-shape {
    border-radius: calc(9 * var(--u));
}

.rs-node--circle .rs-shape {
    border-radius: var(--radius-circle);
}

/* A square turned by 45°, its corners on the midpoints of the box's sides — the editor's diamond. */
.rs-node--diamond .rs-shape {
    inset: 14.64%;
    rotate: 45deg;
    border-radius: calc(5 * var(--u));
}

/* The emerald glow of a completed node; give it .rs-in and an --at. */
.rs-halo {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    box-shadow:
        0 0 calc(12 * var(--u)) calc(1 * var(--u)) color-mix(in srgb, var(--rs-ok) 30%, transparent),
        0 calc(8 * var(--u)) calc(22 * var(--u)) calc(-8 * var(--u)) color-mix(in srgb, var(--rs-ok) 60%, transparent);
}

/* Positioned, so it paints over the absolutely placed shape rather than under it. */
.rs-node > .rs-icon {
    position: relative;
    width: 1.5em;
    height: 1.5em;
}

.rs-node-body {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.45em;
}

.rs-node-word {
    position: relative;
    font-size: 0.6em;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--text-secondary);
}

.rs-node-label {
    position: absolute;
    top: calc(100% + 5 * var(--u));
    left: 50%;
    transform: translateX(-50%);
    font-size: 0.85em;
    font-weight: 600;
    color: var(--text-secondary);
    white-space: nowrap;
}

/* The tick in the corner of a finished node. */
.rs-badge {
    position: absolute;
    top: calc(-5 * var(--u));
    right: calc(-5 * var(--u));
    display: grid;
    place-items: center;
    width: calc(15 * var(--u));
    height: calc(15 * var(--u));
    border-radius: var(--radius-circle);
    background: var(--rs-ok);
    color: var(--clr-always-white);
}

.rs-badge .rs-icon {
    width: 70%;
    height: 70%;
    stroke-width: 3;
    color: inherit;
}

/* ── Timing ──
   --rs-v is an element's progress: 0 before --at, 1 a short ramp after it, and back to 0 while the
   scene rewinds at the end of a cycle (0.92–0.97). --rs-e is the same, eased. */
:is(.rs-in, .rs-rise, .rs-pop, .rs-out, .rs-draw, .rs-wake, .rs-sleep, .rs-dim) {
    --rs-v: calc(clamp(0, (var(--rs-t) - var(--at, 0)) * 25, 1) * clamp(0, (0.97 - var(--rs-t)) * 20, 1));
    --rs-e: calc(var(--rs-v) * var(--rs-v) * (3 - 2 * var(--rs-v)));
}

/* Appears. */
.rs-in {
    opacity: var(--rs-e);
}

/* Appears from slightly below. */
.rs-rise {
    opacity: var(--rs-e);
    translate: 0 calc((1 - var(--rs-e)) * 0.6em);
}

/* Appears with a little overshoot, out of its own middle. */
.rs-pop {
    opacity: var(--rs-e);
    scale: calc(0.4 + 0.6 * var(--rs-e) + 0.2 * sin(var(--rs-v) * pi));
    transform-box: fill-box;
    transform-origin: center;
}

/* Goes — the state before, under an .rs-in that replaces it. */
.rs-out {
    opacity: calc(1 - var(--rs-e));
}

/* Draws itself along its path; the path needs pathLength="1". Hidden until it starts: a round
   line cap would otherwise leave a dot where the undrawn dash ends. */
.rs-draw {
    stroke-dasharray: 1;
    stroke-dashoffset: calc(1 - var(--rs-e));
    opacity: clamp(0, var(--rs-v) * 20, 1);
}

/* A node not reached yet sits faded, like a pending node in the editor; .rs-wake reaches it,
   .rs-sleep leaves it behind as the branch not taken. .rs-dim does the same to an edge. */
.rs-wake {
    opacity: calc(0.6 + 0.4 * var(--rs-e));
}

.rs-sleep {
    opacity: calc(0.6 - 0.3 * var(--rs-e));
}

.rs-dim {
    opacity: calc(1 - 0.6 * var(--rs-e));
}
