You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/web/routes/temas/animations/panel-cascade/panel-cascade.css

158 lines
6.8 KiB

/*
* Fase 1 prototype — the cascade, as a real eidos recipe would ship it: PLAIN global
* CSS in a .css file (no Svelte `<style>` scoping/pruning), selecting on data-attrs.
* EIDOS owns 100% of this. The page (soma role) only flips data-state + retains the
* leaving node (Svelte `out:`); nobody writes a per-card variable.
*/
[data-cascade-panel] {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
gap: 0.75rem;
padding: 1rem;
border: 1px solid var(--color-border-subtle, #e5e5e5);
border-radius: var(--radius-lg, 12px);
min-block-size: 8rem;
/* rhythm tokens, set once on the container (inherited). The demo overrides the
outer one inline. */
--card-stagger-each: 70ms;
--inner-stagger-each: 45ms;
/* inner content waits for its card to SETTLE, then cascades — so the nesting
reads as a distinct second phase instead of being masked by the card's fade. */
--inner-after: var(--duration-moderate, 240ms);
}
/* the wrapper IS the grid cell + the animated box; the Card fills it */
[data-cascade-item] {
display: flex;
}
[data-cascade-item] > [data-card] {
flex: 1;
}
@keyframes card-rise {
from {
opacity: 0;
transform: translateY(14px);
}
to {
opacity: 1;
transform: none;
}
}
@keyframes card-fall {
from {
opacity: 1;
transform: none;
}
to {
opacity: 0;
transform: translateY(8px);
}
}
/* EIDOS computes the per-card index FROM STRUCTURE — nobody writes it.
nth-child → forward index (enter); nth-last-child → reverse (exit). */
[data-cascade-panel] > [data-cascade-item]:nth-child(1) { --row: 0; }
[data-cascade-panel] > [data-cascade-item]:nth-child(2) { --row: 1; }
[data-cascade-panel] > [data-cascade-item]:nth-child(3) { --row: 2; }
[data-cascade-panel] > [data-cascade-item]:nth-child(4) { --row: 3; }
[data-cascade-panel] > [data-cascade-item]:nth-child(5) { --row: 4; }
[data-cascade-panel] > [data-cascade-item]:nth-child(6) { --row: 5; }
[data-cascade-panel] > [data-cascade-item]:nth-child(7) { --row: 6; }
[data-cascade-panel] > [data-cascade-item]:nth-child(8) { --row: 7; }
[data-cascade-panel] > [data-cascade-item]:nth-child(9) { --row: 8; }
[data-cascade-panel] > [data-cascade-item]:nth-child(10) { --row: 9; }
[data-cascade-panel] > [data-cascade-item]:nth-child(11) { --row: 10; }
[data-cascade-panel] > [data-cascade-item]:nth-child(12) { --row: 11; }
[data-cascade-panel] > [data-cascade-item]:nth-child(13) { --row: 12; }
[data-cascade-panel] > [data-cascade-item]:nth-child(14) { --row: 13; }
[data-cascade-panel] > [data-cascade-item]:nth-child(15) { --row: 14; }
[data-cascade-panel] > [data-cascade-item]:nth-child(16) { --row: 15; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(1) { --row-rev: 0; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(2) { --row-rev: 1; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(3) { --row-rev: 2; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(4) { --row-rev: 3; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(5) { --row-rev: 4; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(6) { --row-rev: 5; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(7) { --row-rev: 6; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(8) { --row-rev: 7; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(9) { --row-rev: 8; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(10) { --row-rev: 9; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(11) { --row-rev: 10; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(12) { --row-rev: 11; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(13) { --row-rev: 12; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(14) { --row-rev: 13; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(15) { --row-rev: 14; }
[data-cascade-panel] > [data-cascade-item]:nth-last-child(16) { --row-rev: 15; }
/* ENTER: container open → each NON-leaving card rises, delayed by its structural index. */
[data-cascade-panel][data-state='open'] > [data-cascade-item]:not([data-leaving]) {
animation: card-rise var(--duration-moderate, 240ms) var(--ease-out, cubic-bezier(0.2, 0.8, 0.2, 1))
backwards;
animation-delay: calc(var(--row, 0) * var(--card-stagger-each));
}
/* EXIT (panel close): all cards reverse-cascade out, held forwards. */
[data-cascade-panel][data-state='closed'] > [data-cascade-item] {
animation: card-fall var(--duration-fast, 120ms) var(--ease-in, cubic-bezier(0.4, 0, 1, 1)) forwards;
animation-delay: calc(var(--row-rev, 0) * var(--card-stagger-each));
}
/* EXIT (cards removed, panel still open): each retained item plays card-fall, staggered
by its REVERSE structural index (--row-rev, from nth-last-child). A lone removal → the
last card has --row-rev 0 → delay 0 (immediate); a bulk removal → reverse cascade (the
last card leaves first). No `data-phase` needed — the structure gives both for free.
Soma's `out:` retains each node for delay + duration, then unmounts. */
[data-cascade-panel] > [data-cascade-item][data-leaving] {
animation: card-fall var(--duration-fast, 120ms) var(--ease-in, cubic-bezier(0.4, 0, 1, 1)) forwards;
animation-delay: calc(var(--row-rev, 0) * var(--card-stagger-each));
}
/* ── NESTED cascade: inner content inside each card ──────────────────────────
The nesting test. Each inner item composes TWO structural indices, both pure
CSS:
· `--row` — inherited from its ancestor [data-cascade-item] (the card's
OUTER position in the panel cascade);
· `--inner-row` — its OWN position among siblings (`:nth-child`, scoped to its
own [data-inner-list] parent — nesting is automatic).
delay = card_delay + inner_delay → the inner content enters AFTER its card.
Zero JS writes; inheritance + nth-child do the composition. */
[data-inner-list] {
display: flex;
flex-direction: column;
gap: 0.3rem;
margin-block-start: 0.5rem;
}
[data-inner-item] {
block-size: 0.55rem;
border-radius: 3px;
background: var(--color-content-muted, #8a8a8a);
}
[data-inner-list] > [data-inner-item]:nth-child(1) { --inner-row: 0; inline-size: 90%; }
[data-inner-list] > [data-inner-item]:nth-child(2) { --inner-row: 1; inline-size: 60%; }
[data-inner-list] > [data-inner-item]:nth-child(3) { --inner-row: 2; inline-size: 78%; }
@keyframes inner-rise {
from {
opacity: 0;
transform: translateX(-18px);
}
to {
opacity: 1;
transform: none;
}
}
[data-cascade-panel][data-state='open'] [data-inner-item] {
animation: inner-rise var(--duration-moderate, 240ms) var(--ease-out, cubic-bezier(0.2, 0.8, 0.2, 1))
backwards;
/* composed delay: card's outer index + the card's settle time + own inner index */
animation-delay: calc(
var(--row, 0) * var(--card-stagger-each) + var(--inner-after) + var(--inner-row, 0) *
var(--inner-stagger-each)
);
}

Powered by TurnKey Linux.