<div class="exfiltrate-animated-svg-with-css">
<div class="cpu-exfiltrator">
<output class="cpu-phase-cycle-request0r"></output>
<output class="svg-animation-current-state-reporter"></output>
<div class="xfl-presentation">
The final embeded data will be hosted on cpu-exfiltrator - and presenting
here will allow me to show the internal states as the algorithm executes.
</div>
</div>
</div>
/* Markup specifically in this structure:
<div class="exfiltrate-animated-svg-with-css">
<div class="cpu-exfiltrator">
<output class="cpu-phase-cycle-request0r"></output>
<output class="svg-animation-current-state-reporter"></output>
<div class="xfl-presentation">
The final embeded data will be hosted on cpu-exfiltrator - and presenting
here will allow me to show the internal states as the algorithm executes.
</div>
</div>
</div>
*/
@property --xfl-cpu-phase { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl-raw-data { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl-data-type { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl-data-value { syntax: "<integer>"; initial-value: 0; inherits: true; }
@keyframes --xfl-cpu-phase { 0% { --xfl-cpu-phase: 4; } 100% { --xfl-cpu-phase: 0; } }
@keyframes --xfl-raw-data {
0% { --xfl-raw-data: var(--xfl-max); } 100% { --xfl-raw-data: 0; }
}
@keyframes --xfl-data-type {
0% { --xfl-data-type: 34; } 100% { --xfl-data-type: 0; }
}
@keyframes --xfl-data-value {
0% { --xfl-data-value: var(--xfl-max); } 100% { --xfl-data-value: 0; }
}
@property --cpu-phase-next { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl-data-length { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl-checksum { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl-complete { syntax: "<integer>"; initial-value: 0; inherits: true; }
/* Hosts 4 timeline values and their animations */
.exfiltrate-animated-svg-with-css {
--xfl-max: 100000;
--xfl-tl: --xfl-cpu-phase, --xfl-raw-data, --xfl-data-type, --xfl-data-value;
animation:
--xfl-cpu-phase 1ms linear,
--xfl-raw-data 1ms linear,
--xfl-data-type 1ms linear,
--xfl-data-value 1ms linear;
animation-timeline: var(--xfl-tl);
animation-range: entry 100% exit 100%;
timeline-scope: var(--xfl-tl);
*, &, ::before, ::after {
box-sizing: border-box; padding: 0px; margin: 0px;
}
}
/* Hosts the 2 animations of the CSS CPU Hack, no timelines */
.cpu-exfiltrator {
/* The CPU Hack's frame cycler has a 5 tick sequence now, first 4 are the same.
// 0: ready - capture phase
// 1: capture lock phase
// 2: saving - hoist phase
// 3: hoist lock phase
// 4: CPU Frame Complete (new) helps w/sequencing stability and safe signaling.
// In this case, 4 stays active until data-type is 0, then will become 0 again.
// When data-type is reset, data-value is also reset.
*/
/* CPU Hack will request capture lock phase (1) when data is ready.
// Data ready = data-type > 0 && raw-frame-data - 35 === data-value
*/
/* data-type values - baked into the server-side script that generates the SVG:
// 0: local signaling in CSS here, as described above
// 1-32: data frames. Since the SVG Animation requires 1D transmition expressed
// over animation time, we won't know if we're repeating values on purpose or
// what we're looking at in general without sentinels before each data frame.
// 33: Data length, even if data length is 1.
// 34: Checksum of data and length. Both PHP and CSS run the same checksum alg,
// if the server's checksum value matches the CSS result, we have a degree of
// certainty that it was successful. The SVG Animation can easily skip frames
// which can cause all sorts of false reads. The exfiltrator will continue to
// run until the checksum matches, overwritting whenever the animation loops.
*/
animation: capture 1ms infinite, hoist 1ms infinite;
animation-play-state: paused, paused;
--cpu-next-phase: 0;
--xfl-data-is-ready: calc(
min(1, var(--xfl-data-type, 0)) *
(1 - min(1, max(
(var(--xfl-raw-data, 0) - 35) - var(--xfl-data-value, 0),
var(--xfl-data-value, 0) - (var(--xfl-raw-data, 0) - 35)
)))
);
@container style(--xfl-cpu-phase: 0) {
animation-play-state: running, paused;
--cpu-next-phase: var(--xfl-data-is-ready);
}
@container style(--xfl-cpu-phase: 1) {
animation-play-state: paused, paused;
--cpu-next-phase: 2;
}
@container style(--xfl-cpu-phase: 2) {
animation-play-state: paused, running;
--cpu-next-phase: 3;
}
@container style(--xfl-cpu-phase: 3) {
animation-play-state: paused, paused;
--cpu-next-phase: 4;
}
@container style(--xfl-cpu-phase: 4) {
animation-play-state: paused, paused;
--cpu-next-phase: calc(
min(1, var(--xfl-data-type)) * 4
);
}
--xfl\\1: calc(
var(--xfl\\1-hoist, 0) + 1
);
}
/* Sources the timeline controlling the CPU Hack's 5 tick sequence / CPU frame */
.cpu-phase-cycle-request0r {
display: block;
position: absolute;
overflow: hidden;
background: hotpink;
width: 100px;
height: 10px;
bottom: 100vh;
&::before {
content: "";
position: absolute;
left: 0px;
top: 0px;
height: 100%;
width: calc(25px * var(--cpu-next-phase));
background: lime;
view-timeline: --xfl-cpu-phase inline;
}
}
/* Sources 3 timelines to read & report the Animated SVG's current indicated data
// WARN: There is 1 frame between raw & type, and 1 SVG step between type & value
// raw-frame-data: the data reported by reading the SVG Animation's current frame
// data-type: Indicates what the next SVG Animation step's data represents & will
// hold on to it THROUGH the next step - keeping in in scope for the data-value
// data-value: 0 if typing step, else the 16 bit data value indicated by raw - 35
*/
.svg-animation-current-state-reporter { display: none; }
/* the container style condition is "if not complete" */
@container style(--xfl-complete: 0) {
.svg-animation-current-state-reporter {
/* The CPU Hack's cycler phase also indicates the timing of what to do here. */
/* Phase 0 indicates we are to move forward with reading SVG Animation data. */
/* Phase 4 signals resetting data type and value to 0, which causes phase 0. */
/* WARN: SVG may skip steps rendering, so rewrite & checksum helps accuracy. */
display: block;
position: absolute;
background: rgba(255, 0, 0, 0.5);
width: 34px; /* --xfl-data-type keyframes are 34 to 0 b/c max data-type = 34 */
height: calc(var(--xfl-max) * 1px);
bottom: calc(var(--xfl-max) * 1px + 100vh);
left: calc(-100vw - 100px);
overflow: hidden;
font-size: 0px!important;
line-height: 0px!important;
margin: 0px;
padding: 0px;
/* --xfl-raw-data, --xfl-data-type, --xfl-data-value */
&::before {
content: //url('http://css-api.propjockey.io/api.svg.php?');
position: absolute;
background: lime;
left: 0px;
top: 0px;
width: 10px!important;
--height: 2135px;
font-size: 0px!important;
line-height: 0px!important;
view-timeline: --xfl-raw-data block;
}
&::after {
content: "";
position: absolute;
width: 1px;
height: 1px;
/* there's 4 stages here
// 1) cpu tells us to reset to 0s
// 2) cpu is in phase 0 (capture running) and stays until these stages finish
// a. if svg animation frame (based on raw) is type, set type else use prev
// 3. if svg animation frame (based on raw) is data, set data else use prev
// 4) CPU is executing, our job is to hold prev values and ignore the SVG ani
*/
--xfl-reset: (1 - max(0, var(--cpu-next-phase, 0) - 3)); /* reset:0 else:1 */
--xfl-cpu-awaits-us: (1 - min(1, var(--cpu-next-phase, 0))); /* true:1 f:0 */
--xfl-svg-step-type: clamp(0, var(--xfl-raw-data, 0) - 34, 1); /* data = 1 */
--xfl-maybe-next-type: calc(
(1 - var(--xfl-svg-step-type)) * var(--xfl-raw-data, 0) +
var(--xfl-svg-step-type) * var(--xfl-data-type, 0)
);
--xfl-maybe-next-value: calc(
var(--xfl-svg-step-type) * (var(--xfl-raw-data) - 35) +
(1 - var(--xfl-svg-step-type)) * (var(--xfl-data-value))
);
--xfl-next-type: calc(
var(--xfl-cpu-awaits-us) * var(--xfl-maybe-next-type) +
(1 - var(--xfl-cpu-awaits-us)) * var(--xfl-data-type, 0)
);
--xfl-next-value: calc(
min(1, var(--xfl-next-type)) * (
var(--xfl-cpu-awaits-us) * var(--xfl-maybe-next-value) +
(1 - var(--xfl-cpu-awaits-us)) * var(--xfl-data-value, 0)
)
);
left: calc(
var(--xfl-reset) * var(--xfl-next-type, 0) * 1px - 1px
);
top: calc(
var(--xfl-reset) * var(--xfl-next-value, 0) * 1px - 1px
);
background: black;
view-timeline: --xfl-data-type inline, --xfl-data-value block;
}
}
}
@property --xfl\\1 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\2 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\3 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\4 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\5 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\6 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\7 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\8 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\9 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\10 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\11 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\12 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\13 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\14 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\15 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\16 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\17 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\18 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\19 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\20 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\21 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\22 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\23 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\24 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\25 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\26 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\27 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\28 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\29 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\30 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\31 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@property --xfl\\32 { syntax: "<integer>"; initial-value: 0; inherits: true; }
@keyframes capture {
0%, 100% {
--xfl-data-length-captured: var(--xfl-data-length);
--xfl-checksum-captured: var(--xfl-checksum);
--xfl\\1-captured: var(--xfl\\1);
--xfl\\2-captured: var(--xfl\\2);
--xfl\\3-captured: var(--xfl\\3);
--xfl\\4-captured: var(--xfl\\4);
--xfl\\5-captured: var(--xfl\\5);
--xfl\\6-captured: var(--xfl\\6);
--xfl\\7-captured: var(--xfl\\7);
--xfl\\8-captured: var(--xfl\\8);
--xfl\\9-captured: var(--xfl\\9);
--xfl\\10-captured: var(--xfl\\10);
--xfl\\11-captured: var(--xfl\\11);
--xfl\\12-captured: var(--xfl\\12);
--xfl\\13-captured: var(--xfl\\13);
--xfl\\14-captured: var(--xfl\\14);
--xfl\\15-captured: var(--xfl\\15);
--xfl\\16-captured: var(--xfl\\16);
--xfl\\17-captured: var(--xfl\\17);
--xfl\\18-captured: var(--xfl\\18);
--xfl\\19-captured: var(--xfl\\19);
--xfl\\20-captured: var(--xfl\\20);
--xfl\\21-captured: var(--xfl\\21);
--xfl\\22-captured: var(--xfl\\22);
--xfl\\23-captured: var(--xfl\\23);
--xfl\\24-captured: var(--xfl\\24);
--xfl\\25-captured: var(--xfl\\25);
--xfl\\26-captured: var(--xfl\\26);
--xfl\\27-captured: var(--xfl\\27);
--xfl\\28-captured: var(--xfl\\28);
--xfl\\29-captured: var(--xfl\\29);
--xfl\\30-captured: var(--xfl\\30);
--xfl\\31-captured: var(--xfl\\31);
--xfl\\32-captured: var(--xfl\\32);
}
}
@keyframes hoist {
0%, 100% {
--xfl-data-length-hoist: var(--xfl-data-length-captured, 0);
--xfl-checksum-hoist: var(--xfl-checksum-captured, 0);
--xfl\\1-hoist: var(--xfl\\1-captured, 0);
--xfl\\2-hoist: var(--xfl\\2-captured, 0);
--xfl\\3-hoist: var(--xfl\\3-captured, 0);
--xfl\\4-hoist: var(--xfl\\4-captured, 0);
--xfl\\5-hoist: var(--xfl\\5-captured, 0);
--xfl\\6-hoist: var(--xfl\\6-captured, 0);
--xfl\\7-hoist: var(--xfl\\7-captured, 0);
--xfl\\8-hoist: var(--xfl\\8-captured, 0);
--xfl\\9-hoist: var(--xfl\\9-captured, 0);
--xfl\\10-hoist: var(--xfl\\10-captured, 0);
--xfl\\11-hoist: var(--xfl\\11-captured, 0);
--xfl\\12-hoist: var(--xfl\\12-captured, 0);
--xfl\\13-hoist: var(--xfl\\13-captured, 0);
--xfl\\14-hoist: var(--xfl\\14-captured, 0);
--xfl\\15-hoist: var(--xfl\\15-captured, 0);
--xfl\\16-hoist: var(--xfl\\16-captured, 0);
--xfl\\17-hoist: var(--xfl\\17-captured, 0);
--xfl\\18-hoist: var(--xfl\\18-captured, 0);
--xfl\\19-hoist: var(--xfl\\19-captured, 0);
--xfl\\20-hoist: var(--xfl\\20-captured, 0);
--xfl\\21-hoist: var(--xfl\\21-captured, 0);
--xfl\\22-hoist: var(--xfl\\22-captured, 0);
--xfl\\23-hoist: var(--xfl\\23-captured, 0);
--xfl\\24-hoist: var(--xfl\\24-captured, 0);
--xfl\\25-hoist: var(--xfl\\25-captured, 0);
--xfl\\26-hoist: var(--xfl\\26-captured, 0);
--xfl\\27-hoist: var(--xfl\\27-captured, 0);
--xfl\\28-hoist: var(--xfl\\28-captured, 0);
--xfl\\29-hoist: var(--xfl\\29-captured, 0);
--xfl\\30-hoist: var(--xfl\\30-captured, 0);
--xfl\\31-hoist: var(--xfl\\31-captured, 0);
--xfl\\32-hoist: var(--xfl\\32-captured, 0);
}
}
.xfl-presentation {
/* The final embeded data will be hosted on cpu-exfiltrator - and presenting
// here will allow me to show the internal states as the algorithm executes.
*/
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.