diff --git a/html/crumble.tsx b/html/crumble.tsx
new file mode 100644
index 0000000..54c6a31
--- /dev/null
+++ b/html/crumble.tsx
@@ -0,0 +1,86 @@
+import { ComponentChildren } from "preact";
+import { css, render_and_copy } from "./common.tsx";
+// combine a shake with a fall
+// fall should be more delayed than shake
+// we want outliers (a few letters falling before than others)
+// exponentials should do
+
+const default_shaky_delay = (x: number) => 5 + 10 * x;
+export type DelayFn = (_: number) => number;
+
+// exporting these in case they turn out to be useful
+export const Shaky = ({
+ children,
+ delay_fn = default_shaky_delay,
+}: {
+ children: ComponentChildren;
+ delay_fn?: DelayFn;
+}) => (
+
+ {children}
+
+);
+
+const default_fall_delay = (x: number) => (3 * x) ** 4;
+export const Fall = ({
+ children,
+ delay_fn = default_fall_delay,
+}: {
+ children: ComponentChildren;
+ delay_fn?: DelayFn;
+}) => (
+
+ {children}
+
+);
+
+const msg = `
+i haven't seen this on other blogs, but some of the posts on mine seem to be kinda unstable?
+if that makes sense?
+like, sometimes i see them shake, and i swear i saw some letters fall
+
+i know i'm a (convicted?) css criminal, so i'm thinking that this might just be the w3 gods punishing me.
+
+so. yeah. if you see anything like that on any of my posts let me know
+`.trim();
+
+// should probably do it word wise so they don't break
+export const Crumble = ({
+ msg,
+ shaky_delay_fn,
+ fall_delay_fn,
+}: {
+ msg: string;
+ shaky_delay_fn?: DelayFn;
+ fall_delay_fn?: DelayFn;
+}) => (
+
+ {msg.split("").map(c =>
+ /[^\s]/.test(c) ? (
+
+ {c}
+
+ ) : c == "\n" ? (
+
+ ) : (
+ c
+ )
+ )}
+
+);
+
+render_and_copy();
diff --git a/html/diyavepeta.tsx b/html/diyavepeta.tsx
index c2cf7a8..9680e89 100644
--- a/html/diyavepeta.tsx
+++ b/html/diyavepeta.tsx
@@ -1,5 +1,6 @@
import { ToggleOnClick, render_and_copy, static_url } from "./common.tsx";
+// kind of want to do transparent (it would slick) but eh
render_and_copy(