Something went wrong. Try again.
Monorepo for Tangled forked from tangled.org/core
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404@reference "../../../../app.css";
/* ---------- The CI visual: CiDevice (the NixOS box) and its workflow steps (CiStep.svelte) ---------- */.landing { /* ---- A workflow step: its mark and name, sized by the visual (--step-size, --step-gap). The mark spins while the step runs and pops as it ticks off. ---- */ .ci-step { display: flex; align-items: center; gap: var(--step-gap, 8px); height: var(--step-size, 17px); white-space: nowrap; } .ci-mark { display: block; flex: none; width: var(--step-size, 17px); height: var(--step-size, 17px); color: var(--hl-mid); } .ci-step:is(.run, .ok) .ci-mark { color: var(--ind-grid); } .ci-step.run .ci-mark { animation: d-spin 0.9s linear infinite; } .ci-step.ok .ci-mark { animation: d-pop 0.35s var(--ease-pop); } .ci-name { flex: 1; }
/* ---- CiDevice: the NixOS box and its slots ---- */ /* The group at 1:1, 547 × 291; every piece placed in it (.at). The device and the slots are hairline plates: opaque, so where they overlap the near one hides the far. */ .cd { position: relative; flex: none; width: 547px; height: 291px; font-size: 10.19px; font-weight: 450; line-height: 1.2; letter-spacing: -0.01em; color: var(--text); } .cd-at { display: block; max-width: none; } .cd-cable-in { --y: 86.98px; width: 145.86px; height: 59.42px; } .cd-cable-out { --x: 397.84px; --y: 228.71px; width: 148.9px; height: 61.39px; } .cd-cable-in.light-art, .cd-cable-out.light-art { display: none; } /* The cables' dots drift along them, in towards the box and out: each line is laid along its cable (18.3°), and every dot runs its length on one clock, offset to where it's drawn, fading in and out at the ends. */ .cd-flow { width: var(--len); height: 0; rotate: 18.3deg; transform-origin: 0 0; pointer-events: none; } .cd-dot { position: absolute; left: -0.83px; top: -0.83px; width: 1.67px; height: 1.67px; border-radius: 50%; background: color-mix(in srgb, var(--ink) 25%, transparent); animation: cd-flow 9s linear infinite; } /* The device: rotated 19°, skewed -43° and squashed to 73% (in that order — each piece's transform below follows it, and its box matches only that way). Its thickness is the top face copied 27px straight down the screen — a drop shadow on an untransformed box (.cd-slab), not in the tilted plane — and the box's four 1px drops draw the silhouette round the whole slab. The end caps, inside it, fill the notches a shifted copy leaves at either end. The top face's own border is the crease, dim. */ .cd-box { --x: 64.5px; --y: 86.36px; width: 406.02px; height: 167.87px; filter: drop-shadow(1px 0 0 var(--hl-edge)) drop-shadow(-1px 0 0 var(--hl-edge)) drop-shadow(0 1px 0 var(--hl-edge)) drop-shadow(0 -1px 0 var(--hl-edge)); } .cd-slab { position: absolute; inset: 0; display: grid; place-items: center; filter: drop-shadow(0 27px 0 var(--hl-side)); } .cd-top { position: relative; flex: none; box-sizing: border-box; width: 271px; height: 169.64px; border: 1px solid var(--hl-mid); border-radius: 13.59px; background: var(--hl-solid); transform: var(--iso-device); } .cd-groove { width: 7.68px; height: 140.63px; box-sizing: border-box; border: 1px solid var(--hl-edge); border-radius: 2px; background: var(--hl-side); } /* The end caps: the notch shapes, placed in .cd-box, from its corner. */ .cd-cap { background: var(--hl-side); -webkit-mask: var(--cap) center / 100% 100% no-repeat; mask: var(--cap) center / 100% 100% no-repeat; } .cd-cap-l { --x: 7.36px; --y: 79.58px; width: 24.86px; height: 32.75px; } .cd-cap-r { --x: 375.07px; --y: 89.54px; width: 23.79px; height: 32.75px; transform: scaleX(-1); } .cd-vent { --x: 82.26px; width: 59.04px; height: 21.83px; display: grid; place-items: center; } .cd-vent span { width: 62.44px; height: 1.5px; border-radius: 3px; background: var(--hl-mid); transform: rotate(19deg) skewX(19deg) scale(1, 0.95); } .cd-grill { --x: 429.08px; --y: 192.35px; width: 25.23px; height: 23.23px; } /* Two diodes on the front face, each a bead in a ring: one dark, one lit green — it flickers while a workflow runs. */ .cd-led-box { width: 5.45px; height: 8.39px; display: grid; place-items: center; } .cd-led-box.off { --x: 285.5px; --y: 251.78px; } .cd-led-box.on { --x: 294.84px; --y: 255.31px; } .cd-led { display: block; padding: 0.444px 0.444px 0.888px 0.888px; border: 0.5px solid var(--hl-mid); border-radius: 99px; transform: rotate(29deg) skewX(24deg) scale(1, 0.91); } .cd-led span { display: block; width: 3.87px; height: 3.87px; box-sizing: border-box; border: 0.5px solid var(--hl-edge); border-radius: 50%; background: var(--hl-plate); } .cd-led-box.on .cd-led { border-color: var(--color-foreground-success); } .cd-led-box.on .cd-led span { border-color: var(--color-foreground-success); background: var(--color-foreground-success); } .cd.busy .cd-led-box.on { animation: cd-blink 1.2s ease infinite; } .cd-nix { --x: 330.79px; --y: 245.14px; width: 26.61px; height: 21.08px; display: grid; place-items: center; } .cd-nix span { white-space: nowrap; color: var(--muted); transform: rotate(-28deg) skewX(-29deg) scale(1, 0.87); } .cd-slot-fx { position: absolute; inset: 0; pointer-events: none; } /* A slot: the full 161.45px card, its bottom-centre on its groove, under the slot transform (rotate -28°, skew -27°, squash to 89%). Its wrapper cuts it at the groove, so down it shows only its top 50.65px; pulling it up is a translate along the slot. The slot's own clip leaves a little below the groove, so the thickness cast from it reaches there too. */ .cd-slot { width: 135.55px; height: 161.45px; transform-origin: 50% 100%; transform: var(--iso-slot); clip-path: inset(-6px -4px -8px -6px); } .cd-card { position: absolute; inset: 0; box-sizing: border-box; overflow: hidden; border: 1px solid var(--hl-edge); border-bottom: 0; border-radius: 5px 5px 0 0; background: var(--hl-solid); box-shadow: -3.33px -3.57px 0 var(--hl-side), -4.45px -4.09px 0 var(--hl-edge), -3.31px -4.56px 0 var(--hl-edge), -4.43px -5.09px 0 var(--hl-edge); translate: 0 110.8px; /* A long ease-out both ways: it leaves quickly and settles slowly, in the groove or up. Lengths match PULL and DROP in CiDevice. */ transition: translate 0.55s var(--ease-settle); } .cd-card.up { translate: 0 0; transition-duration: 0.7s; } /* The card's foot is in the groove: its glint runs on past the clip, so no edge is lit there. */ .cd-card::after { bottom: -8px; } /* Each card is a button. Waiting in its groove, it rises a little under the pointer; the running one isn't a target. The slot's clip keeps the hit area to what shows. */ .cd-card { display: block; padding: 0; font: inherit; color: inherit; text-align: left; cursor: pointer; pointer-events: auto; } .cd-card.up { cursor: default; } .cd-card:not(.up):hover { translate: 0 104px; transition-duration: 0.2s; } .cd-card:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; } /* The content waves in, top to bottom, 60ms apart (--i: the row), rising a few px along the slot; it waves out faster and closer together. */ .cd-file, .cd-step { opacity: 0; translate: 0 5px; transition: opacity 0.16s ease calc(var(--i) * 25ms), translate 0.16s ease calc(var(--i) * 25ms); } .cd-run { display: block; } .cd-run.shown .cd-file, .cd-run.shown .cd-step { opacity: 1; translate: 0 0; transition: opacity 0.3s ease calc(var(--i) * 60ms), translate 0.4s var(--ease-out) calc(var(--i) * 60ms); } .cd-file { display: block; padding: 13.59px 10.19px; border-bottom: 1px solid var(--hl-mid); text-box: trim-both cap alphabetic; white-space: nowrap; } .cd-steps { --step-size: 14.44px; --step-gap: 6.8px; display: flex; flex-direction: column; gap: 10.19px; padding: 13.59px 8px; } @media (width < 64rem) { .cd { --z: 0.66; scale: var(--z); margin: calc((var(--z) - 1) * 291px / 2) calc((var(--z) - 1) * 547px / 2); } } /* Phones: a size up, the art having the column to itself. */ @media (width < 48rem) { .cd { --z: 0.78; } } /* Small phones: the box is wider than the column. Sized to the stage, the grid track no longer grows to fit it, so the box centres on the column and overflows both sides evenly: the slab sits in the middle, the cables run off either edge. */ @media (width < 420px) { .stage:has(> .cd) { grid-template-columns: minmax(0, 1fr); } } @media (prefers-reduced-motion: reduce) { .ci-mark, .cd-card, .cd-led-box { transition: none; animation: none; } .cd-file, .cd-step { translate: none; } /* The dots hold where they're drawn. */ .cd-dot { animation: none; translate: var(--d) 0; } }}
.landing { @variant light { .cd-grill { filter: invert(0.88); } .cd-cable-in.dark-art, .cd-cable-out.dark-art { display: none; } .cd-cable-in.light-art, .cd-cable-out.light-art { display: block; } .cd-dot { background: color-mix(in srgb, var(--ink) 30%, transparent); } }}
/* A cable's dot, along its line (see .cd-flow). */@keyframes cd-flow { from { translate: 0 0; opacity: 0; } 15%, 85% { opacity: 1; } to { translate: var(--len) 0; opacity: 0; }}
@keyframes cd-blink { 50% { opacity: 0.45; }}