201 lines
51 KiB
HTML
201 lines
51 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>House Hand</title>
|
||
<meta name="description" content="A drawing hand for agents. Characters, mascots and scenes in one consistent style, drawn in Python and handed back as SVG, PNG, or a drawing that draws itself.">
|
||
<link rel="canonical" href="https://househand.yolopreneur.lol/">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:title" content="House Hand">
|
||
<meta property="og:description" content="A drawing hand for agents. Characters, mascots and scenes in one consistent style, drawn in Python and handed back as SVG, PNG, or a drawing that draws itself.">
|
||
<meta property="og:url" content="https://househand.yolopreneur.lol/">
|
||
<meta property="og:image" content="https://househand.yolopreneur.lol/shots/og.png">
|
||
<meta property="og:image:width" content="1200">
|
||
<meta property="og:image:height" content="630">
|
||
<meta name="twitter:card" content="summary_large_image">
|
||
<link rel="icon" href="favicon.svg" type="image/svg+xml">
|
||
<link rel="alternate" type="text/plain" href="llms.txt" title="For agents">
|
||
<link rel="preload" href="fonts/fredoka.woff2" as="font" type="font/woff2" crossorigin>
|
||
<style>
|
||
@font-face { font-family: "Fredoka"; src: url("fonts/fredoka.woff2") format("woff2"); font-weight: 300 700;
|
||
font-display: swap; }
|
||
:root {
|
||
--paper: #FFEAD2; /* the house cream: every sheet's own background, so the plates sit on the page unframed */
|
||
--ink: #2B2135; /* the house line */
|
||
--muted: #6A5672;
|
||
--rule: #E9CFB2;
|
||
--pink: #FF8FD6;
|
||
--focus: #2B2135;
|
||
}
|
||
* { box-sizing: border-box; }
|
||
html { color-scheme: light; }
|
||
body { margin: 0; background: var(--paper); color: var(--ink);
|
||
font: 400 1.125rem/1.6 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }
|
||
h1, h2, h3, .hero ul, .thumbs span { font-family: "Fredoka", ui-rounded, "SF Pro Rounded", system-ui, sans-serif; }
|
||
a { color: var(--ink); text-decoration-line: underline; text-decoration-color: var(--pink);
|
||
text-decoration-thickness: 3px; text-underline-offset: 0.22em; }
|
||
a:hover { text-decoration-color: var(--ink); }
|
||
:focus-visible { outline: 3px solid var(--focus); outline-offset: 4px; border-radius: 8px; }
|
||
.wrap { max-width: 1240px; margin: 0 auto; padding: 0 clamp(16px, 4vw, 44px); }
|
||
|
||
.hero { display: grid; grid-template-columns: minmax(200px, 380px) 1fr; gap: clamp(20px, 5vw, 72px);
|
||
align-items: center; padding: clamp(28px, 6vw, 80px) 0 clamp(24px, 4vw, 48px); }
|
||
.emblem { display: block; width: 100%; height: auto; overflow: visible; }
|
||
.hero h1 { margin: 0 0 0.12em; font-weight: 600; letter-spacing: -0.02em; font-size: clamp(3.6rem, 11vw, 8.2rem);
|
||
line-height: 0.9; }
|
||
.hero p { margin: 0 0 1.3em; max-width: 34ch; font-size: clamp(1.15rem, 2.1vw, 1.4rem); line-height: 1.45; }
|
||
.hero ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.5em 1.6em; font-size: 1.2rem;
|
||
font-weight: 500; }
|
||
|
||
section { border-top: 3px solid var(--rule); margin-top: clamp(36px, 6vw, 64px); padding-top: clamp(26px, 4vw, 40px); }
|
||
h2 { margin: 0; font-weight: 500; font-size: clamp(1.75rem, 3.4vw, 2.4rem); line-height: 1.15; display: flex;
|
||
align-items: center; gap: 0.45em; }
|
||
.dot { flex: none; width: 0.72em; height: 0.72em; border-radius: 50%; border: 3px solid var(--ink); }
|
||
.sub { margin: 0.3em 0 0; color: var(--muted); font-size: 1.2rem; }
|
||
.intro p { max-width: 66ch; margin: 1em 0 0; }
|
||
code { font: 0.88em/1 ui-monospace, "SF Mono", Menlo, monospace; background: rgba(43, 33, 53, 0.07); padding: 0.1em 0.3em;
|
||
border-radius: 5px; }
|
||
|
||
.thumbs { list-style: none; margin: 26px 0 0; padding: 0; display: grid; gap: 22px 16px;
|
||
grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); }
|
||
.thumbs a { display: block; color: var(--ink); text-decoration: none; border-radius: 10px; }
|
||
.thumbs img { display: block; width: 100%; height: auto; aspect-ratio: 8 / 5; object-fit: contain; }
|
||
.thumbs span { display: block; margin-top: 6px; font-size: 1rem; line-height: 1.25; }
|
||
.thumbs b { font-weight: 500; color: var(--muted); margin-right: 0.35em; }
|
||
.thumbs a:hover span, .thumbs a:focus-visible span { text-decoration: underline; text-decoration-color: var(--pink);
|
||
text-decoration-thickness: 3px; text-underline-offset: 0.2em; }
|
||
|
||
.plate { margin: clamp(36px, 6vw, 64px) 0 0; scroll-margin-top: 24px; }
|
||
.plate > a { display: block; width: fit-content; max-width: 100%; border-radius: 6px; }
|
||
.plate img { display: block; max-width: 100%; height: auto; }
|
||
.plate figcaption { max-width: 66ch; margin-top: 14px; }
|
||
.plate h3 { margin: 0 0 0.15em; font-weight: 500; font-size: clamp(1.35rem, 2.4vw, 1.6rem); line-height: 1.25; }
|
||
.plate h3 b { font-weight: 500; color: var(--muted); margin-right: 0.45em; }
|
||
.plate p { margin: 0; }
|
||
.plate .meta { color: var(--muted); margin-top: 0.25em; font-size: 1rem; }
|
||
|
||
footer { border-top: 3px solid var(--rule); margin-top: 88px; padding: 26px 0 64px; color: var(--muted); font-size: 1rem; }
|
||
footer p { margin: 0 0 0.6em; max-width: 72ch; }
|
||
|
||
@media (max-width: 760px) {
|
||
.hero { grid-template-columns: 1fr; }
|
||
.emblem { max-width: 260px; }
|
||
}
|
||
.redraw { margin-top: 0.55em; padding: 0; border: 0; background: none; color: var(--ink); cursor: pointer;
|
||
font: 500 1rem/1.3 "Fredoka", ui-rounded, system-ui, sans-serif; text-decoration: underline;
|
||
text-decoration-color: var(--pink); text-decoration-thickness: 3px; text-underline-offset: 0.22em; }
|
||
.redraw:hover { text-decoration-color: var(--ink); }
|
||
.redraw[hidden] { display: none; }
|
||
@media (prefers-reduced-motion: no-preference) {
|
||
.emblem .wave { transform-box: view-box; transform-origin: 255px 262px; animation: hello 1.7s ease-in-out 3.63s 1 both; }
|
||
}
|
||
@keyframes hello { 0%, 100% { transform: rotate(0); } 20% { transform: rotate(14deg); } 45% { transform: rotate(-9deg); }
|
||
70% { transform: rotate(9deg); } }
|
||
|
||
/* the venture: what to paste into an agent, and what comes back */
|
||
.use .lead { max-width: 62ch; margin: 0.6em 0 0; }
|
||
.prompt { margin: 24px 0 0; max-width: 74ch; border: 3px solid var(--ink); border-radius: 24px; background: #FFF6EC; }
|
||
.prompt pre { margin: 0; padding: 20px 24px 4px; white-space: pre-wrap; overflow-wrap: anywhere; color: var(--ink);
|
||
font: 0.98rem/1.6 ui-monospace, "SF Mono", Menlo, Consolas, monospace; }
|
||
.prompt .bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; padding: 14px 24px 20px; }
|
||
.copy { font: 600 1.05rem/1 "Fredoka", ui-rounded, system-ui, sans-serif; color: var(--ink); background: var(--pink);
|
||
border: 3px solid var(--ink); border-radius: 999px; padding: 0.62em 1.3em; cursor: pointer; }
|
||
.copy:hover { background: #FFA9E0; }
|
||
.copy:active { transform: translateY(1px); }
|
||
.copy[hidden] { display: none; }
|
||
.hint { color: var(--muted); font-size: 1rem; }
|
||
.use h3 { margin: 40px 0 0; font-weight: 500; font-size: clamp(1.35rem, 2.4vw, 1.6rem); }
|
||
.formats { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 20px 40px; max-width: 840px;
|
||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
|
||
.formats b { display: block; font: 500 1.2rem/1.3 "Fredoka", ui-rounded, system-ui, sans-serif; margin-bottom: 0.15em; }
|
||
.next, .files { max-width: 66ch; margin: 1.1em 0 0; }
|
||
.next { margin-top: 32px; }
|
||
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="wrap">
|
||
<header class="hero">
|
||
<svg xmlns="http://www.w3.org/2000/svg" class="emblem" viewBox="0 0 420 570" role="img" aria-label="The house hand waving: three fingers and a thumb, coming out of a mint sleeve" data-duration="3.53"><path fill="none" stroke="#2B2135" stroke-width="84" stroke-linecap="round" stroke-linejoin="round" d="M150.0 520.0 C170.0 430.0 215.0 330.0 250.0 250.0" stroke-dasharray="296.14 596.29" stroke-dashoffset="297.14"><animate attributeName="stroke-dashoffset" values="297.14;0" begin="0.300s" dur="0.192s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /></path><path fill="none" stroke="#FFEAD2" stroke-width="64" stroke-linecap="round" stroke-linejoin="round" d="M150.0 520.0 C170.0 430.0 215.0 330.0 250.0 250.0" stroke-dasharray="296.14 596.29" stroke-dashoffset="297.14"><animate attributeName="stroke-dashoffset" values="297.14;0" begin="0.300s" dur="0.192s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /><animate attributeName="stroke" values="#FFEAD2;#FFD0B8" begin="1.908s" dur="0.220s" fill="freeze" /></path><path fill="none" stroke="#2B2135" stroke-width="128.8" stroke-linecap="round" stroke-linejoin="round" d="M150.0 520.0 C160.0 475.0 176.2 427.5 194.4 381.2" stroke-dasharray="150.79 305.58" stroke-dashoffset="151.79"><animate attributeName="stroke-dashoffset" values="151.79;0" begin="0.513s" dur="0.097s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /></path><path fill="none" stroke="#FFEAD2" stroke-width="108.8" stroke-linecap="round" stroke-linejoin="round" d="M150.0 520.0 C160.0 475.0 176.2 427.5 194.4 381.2" stroke-dasharray="150.79 305.58" stroke-dashoffset="151.79"><animate attributeName="stroke-dashoffset" values="151.79;0" begin="0.513s" dur="0.097s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /><animate attributeName="stroke" values="#FFEAD2;#B3FFC7" begin="1.953s" dur="0.220s" fill="freeze" /></path><path class="s" fill="#61E684" opacity="0" d="M200.6 523.4 L202.5 515.5 L204.6 507.5 L206.8 499.5 L209.1 491.4 L211.5 483.2 L214.1 474.9 L216.7 466.6 L219.5 458.2 L222.3 449.8 L225.3 441.4 L228.3 433.0 L231.4 424.5 L234.6 416.1 L237.8 407.6 L199.3 392.7 L195.9 401.4 L192.7 410.1 L189.5 418.9 L186.3 427.6 L183.3 436.4 L180.3 445.1 L177.4 453.8 L174.6 462.5 L172.0 471.1 L169.4 479.8 L166.9 488.4 L164.6 496.9 L162.4 505.4 L160.3 513.9 Z"><animate attributeName="opacity" values="0;1" begin="2.698s" dur="0.300s" fill="freeze" /></path><path fill="#FFEAD2" stroke="#2B2135" stroke-width="10" stroke-linecap="round" stroke-linejoin="round" d="M140.0 359.9 C147.9 339.8 178.6 333.0 208.7 344.8 C238.7 356.6 256.6 382.4 248.7 402.6 C240.9 422.7 210.1 429.5 180.1 417.7 C150.1 405.9 132.1 380.1 140.0 359.9 Z" stroke-dasharray="317.64 639.27" stroke-dashoffset="318.64" fill-opacity="0"><animate attributeName="stroke-dashoffset" values="318.64;0" begin="0.641s" dur="0.206s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /><animate attributeName="fill-opacity" values="0;1" begin="0.847s" dur="0.060s" fill="freeze" /><animate attributeName="fill" values="#FFEAD2;#61E684" begin="1.998s" dur="0.220s" fill="freeze" /></path><path fill="none" stroke="#2B2135" stroke-width="10" stroke-linecap="round" stroke-linejoin="round" d="M155.2 365.9 C164.9 392.8 208.1 409.8 233.5 396.6" stroke-dasharray="96.58 197.16" stroke-dashoffset="97.58"><animate attributeName="stroke-dashoffset" values="97.58;0" begin="0.866s" dur="0.070s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /></path><g class="wave">
|
||
<path fill="none" stroke="#2B2135" stroke-width="60.0" stroke-linecap="round" stroke-linejoin="round" d="M256.8 184.8 Q256.1 136.1 240.2 90.2" stroke-dasharray="100.39 204.77" stroke-dashoffset="101.39"><animate attributeName="stroke-dashoffset" values="101.39;0" begin="0.969s" dur="0.070s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /></path><path fill="none" stroke="#2B2135" stroke-width="60.0" stroke-linecap="round" stroke-linejoin="round" d="M271.2 185.8 Q293.3 142.5 300.8 94.5" stroke-dasharray="100.31 204.62" stroke-dashoffset="101.31"><animate attributeName="stroke-dashoffset" values="101.31;0" begin="1.072s" dur="0.070s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /></path><path fill="none" stroke="#2B2135" stroke-width="60.0" stroke-linecap="round" stroke-linejoin="round" d="M283.4 193.4 Q323.2 165.5 352.4 126.7" stroke-dasharray="100.29 204.59" stroke-dashoffset="101.29"><animate attributeName="stroke-dashoffset" values="101.29;0" begin="1.175s" dur="0.070s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /></path><path fill="none" stroke="#2B2135" stroke-width="66.0" stroke-linecap="round" stroke-linejoin="round" d="M291.7 214.0 Q323.7 214.0 355.7 214.0" stroke-dasharray="67.28 138.56" stroke-dashoffset="68.28"><animate attributeName="stroke-dashoffset" values="68.28;0" begin="1.278s" dur="0.070s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /></path>
|
||
<path fill="none" stroke="#FFEAD2" stroke-width="40.0" stroke-linecap="round" stroke-linejoin="round" d="M256.8 184.8 Q256.1 136.1 240.2 90.2" stroke-dasharray="100.39 204.77" stroke-dashoffset="101.39"><animate attributeName="stroke-dashoffset" values="101.39;0" begin="0.969s" dur="0.070s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /><animate attributeName="stroke" values="#FFEAD2;#FFD0B8" begin="2.043s" dur="0.220s" fill="freeze" /></path><path fill="none" stroke="#FFEAD2" stroke-width="40.0" stroke-linecap="round" stroke-linejoin="round" d="M271.2 185.8 Q293.3 142.5 300.8 94.5" stroke-dasharray="100.31 204.62" stroke-dashoffset="101.31"><animate attributeName="stroke-dashoffset" values="101.31;0" begin="1.072s" dur="0.070s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /><animate attributeName="stroke" values="#FFEAD2;#FFD0B8" begin="2.088s" dur="0.220s" fill="freeze" /></path><path fill="none" stroke="#FFEAD2" stroke-width="40.0" stroke-linecap="round" stroke-linejoin="round" d="M283.4 193.4 Q323.2 165.5 352.4 126.7" stroke-dasharray="100.29 204.59" stroke-dashoffset="101.29"><animate attributeName="stroke-dashoffset" values="101.29;0" begin="1.175s" dur="0.070s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /><animate attributeName="stroke" values="#FFEAD2;#FFD0B8" begin="2.133s" dur="0.220s" fill="freeze" /></path><path fill="none" stroke="#FFEAD2" stroke-width="46.0" stroke-linecap="round" stroke-linejoin="round" d="M291.7 214.0 Q323.7 214.0 355.7 214.0" stroke-dasharray="67.28 138.56" stroke-dashoffset="68.28"><animate attributeName="stroke-dashoffset" values="68.28;0" begin="1.278s" dur="0.070s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /><animate attributeName="stroke" values="#FFEAD2;#FFD0B8" begin="2.178s" dur="0.220s" fill="freeze" /></path>
|
||
<path fill="#FFEAD2" stroke="#2B2135" stroke-width="10" stroke-linecap="round" stroke-linejoin="round" d="M216.1 214.0 C216.1 184.8 236.6 161.2 262.0 161.2 C287.4 161.2 307.9 184.8 307.9 214.0 C307.9 243.2 287.4 266.8 262.0 266.8 C236.6 266.8 216.1 243.2 216.1 214.0 Z" stroke-dasharray="318.74 641.47" stroke-dashoffset="319.74" fill-opacity="0"><animate attributeName="stroke-dashoffset" values="319.74;0" begin="1.381s" dur="0.207s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /><animate attributeName="fill-opacity" values="0;1" begin="1.588s" dur="0.060s" fill="freeze" /><animate attributeName="fill" values="#FFEAD2;#FFD0B8" begin="2.223s" dur="0.220s" fill="freeze" /></path>
|
||
<path fill="none" stroke="#FFEAD2" stroke-width="40.0" stroke-linecap="round" stroke-linejoin="round" d="M256.8 184.8 Q256.1 136.1 240.2 90.2" stroke-dasharray="100.39 204.77" stroke-dashoffset="101.39"><animate attributeName="stroke-dashoffset" values="101.39;0" begin="0.969s" dur="0.070s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /><animate attributeName="stroke" values="#FFEAD2;#FFD0B8" begin="2.268s" dur="0.220s" fill="freeze" /></path><path fill="none" stroke="#FFEAD2" stroke-width="40.0" stroke-linecap="round" stroke-linejoin="round" d="M271.2 185.8 Q293.3 142.5 300.8 94.5" stroke-dasharray="100.31 204.62" stroke-dashoffset="101.31"><animate attributeName="stroke-dashoffset" values="101.31;0" begin="1.072s" dur="0.070s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /><animate attributeName="stroke" values="#FFEAD2;#FFD0B8" begin="2.313s" dur="0.220s" fill="freeze" /></path><path fill="none" stroke="#FFEAD2" stroke-width="40.0" stroke-linecap="round" stroke-linejoin="round" d="M283.4 193.4 Q323.2 165.5 352.4 126.7" stroke-dasharray="100.29 204.59" stroke-dashoffset="101.29"><animate attributeName="stroke-dashoffset" values="101.29;0" begin="1.175s" dur="0.070s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /><animate attributeName="stroke" values="#FFEAD2;#FFD0B8" begin="2.358s" dur="0.220s" fill="freeze" /></path><path fill="none" stroke="#FFEAD2" stroke-width="46.0" stroke-linecap="round" stroke-linejoin="round" d="M291.7 214.0 Q323.7 214.0 355.7 214.0" stroke-dasharray="67.28 138.56" stroke-dashoffset="68.28"><animate attributeName="stroke-dashoffset" values="68.28;0" begin="1.278s" dur="0.070s" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.45 0 0.55 1" /><animate attributeName="stroke" values="#FFEAD2;#FFD0B8" begin="2.403s" dur="0.220s" fill="freeze" /></path></g><g class="spark"><path class="fx" fill="#FFE780" opacity="0" d="M368.0 70.0 Q372.0 88.0 390.0 92.0 Q372.0 96.0 368.0 114.0 Q364.0 96.0 346.0 92.0 Q364.0 88.0 368.0 70.0 Z"><animate attributeName="opacity" values="0;1" begin="2.958s" dur="0.250s" fill="freeze" /></path><path class="fx" fill="#FFFFFF" opacity="0" d="M368.0 82.0 Q369.8 90.2 378.0 92.0 Q369.8 93.8 368.0 102.0 Q366.2 93.8 358.0 92.0 Q366.2 90.2 368.0 82.0 Z"><animate attributeName="opacity" values="0;1" begin="3.038s" dur="0.250s" fill="freeze" /></path><path class="fx" fill="#FFE780" opacity="0" d="M120.0 136.0 Q122.5 147.5 134.0 150.0 Q122.5 152.5 120.0 164.0 Q117.5 152.5 106.0 150.0 Q117.5 147.5 120.0 136.0 Z"><animate attributeName="opacity" values="0;1" begin="3.118s" dur="0.250s" fill="freeze" /></path><path class="fx" fill="#FFFFFF" opacity="0" d="M120.0 144.0 Q121.1 148.9 126.0 150.0 Q121.1 151.1 120.0 156.0 Q118.9 151.1 114.0 150.0 Q118.9 148.9 120.0 144.0 Z"><animate attributeName="opacity" values="0;1" begin="3.198s" dur="0.250s" fill="freeze" /></path></g></svg>
|
||
<div>
|
||
<h1>house hand</h1>
|
||
<p>A drawing hand for agents. Characters, mascots and scenes in one consistent style, drawn in Python and handed back as SVG, PNG, or a drawing that draws itself.</p>
|
||
<ul><li><a href="#use">Use it with your agent</a></li><li><a href="#plates">See the plates</a></li>
|
||
<li><a href="#how">How the drawings were made</a></li></ul>
|
||
</div>
|
||
</header>
|
||
<main>
|
||
<section id="use" class="use" aria-labelledby="use-h"><h2 id="use-h">Use it with your agent</h2>
|
||
<p class="lead">Copy this prompt into any agent that can run Python. It reads the skill, draws with house.py, and hands
|
||
back the files.</p>
|
||
<div class="prompt"><pre id="prompt">Draw a gardener with a watering can, waving hello, in the House Hand style.
|
||
|
||
First read https://househand.yolopreneur.lol/skill.md and follow it. Download house.py from the same site and draw with it in Python, keeping its rules: three fingers and a thumb, four toes, limbs as round tubes, one ink line weight, flat colours from its palette.
|
||
|
||
Give me the SVG and a PNG. Then run drawon.py on the SVG so I also get a version that draws itself.</pre>
|
||
<div class="bar"><button class="copy" type="button" hidden>Copy prompt</button><span class="hint" id="copy-hint">Change
|
||
the first line to what you want drawn.</span><span class="sr" id="copied" aria-live="polite"></span></div></div>
|
||
<h3>What comes back</h3>
|
||
<ul class="formats"><li><b>SVG</b>The drawing as one file: flat colours, one ink line, nothing linked from outside.</li><li><b>PNG</b>Rendered from the SVG at whatever size you need.</li><li><b>A drawing that draws itself</b>drawon.py replays the drawing stroke by stroke, head first. It plays in any browser, and in an ordinals explorer once inscribed.</li><li><b>Video</b>An MP4 or GIF of the drawing being made, for posts and previews.</li></ul>
|
||
<p class="next">Coming next: an API and an MCP server, so an agent can ask for a drawing and get these files back
|
||
without running any code, and Lottie files for apps.</p>
|
||
<p class="files">The files: <a href="skill.md">skill.md</a> (how to draw in the hand), <a href="house.py">house.py</a> (the drawing library), <a href="drawon.py">drawon.py</a> (the replay), <a href="rig.py">rig.py</a> (the animation rig), <a href="llms.txt">llms.txt</a> (this list, for agents).</p>
|
||
</section>
|
||
<section id="plates" aria-labelledby="plates-h"><h2 id="plates-h">Plates</h2><p class="sub">32 drawings, in the order they
|
||
were drawn. Each one draws itself when you scroll to it. Click a thumbnail to jump there.</p>
|
||
<ol class="thumbs"><li><a href="#01-inflated-cube"><img src="plates/thumbs/01-inflated-cube.webp" width="420" height="263" alt="" loading="lazy"><span><b>1</b>Inflated cube</span></a></li><li><a href="#02-smooth-bean"><img src="plates/thumbs/02-smooth-bean.webp" width="420" height="263" alt="" loading="lazy"><span><b>2</b>Smooth bean</span></a></li><li><a href="#03-tube-discipline"><img src="plates/thumbs/03-tube-discipline.webp" width="420" height="263" alt="" loading="lazy"><span><b>3</b>Tube discipline</span></a></li><li><a href="#04-reduce-by-half"><img src="plates/thumbs/04-reduce-by-half.webp" width="420" height="263" alt="" loading="lazy"><span><b>4</b>Reduce by half</span></a></li><li><a href="#05-edgy-not-eggy"><img src="plates/thumbs/05-edgy-not-eggy.webp" width="420" height="263" alt="" loading="lazy"><span><b>5</b>Edgy, not eggy</span></a></li><li><a href="#06-face-grid"><img src="plates/thumbs/06-face-grid.webp" width="420" height="263" alt="" loading="lazy"><span><b>6</b>The face grid</span></a></li><li><a href="#07-expressions"><img src="plates/thumbs/07-expressions.webp" width="420" height="263" alt="" loading="lazy"><span><b>7</b>Expressions</span></a></li><li><a href="#08-turnaround"><img src="plates/thumbs/08-turnaround.webp" width="420" height="263" alt="" loading="lazy"><span><b>8</b>Head turnaround, five views</span></a></li><li><a href="#09-five-bodies"><img src="plates/thumbs/09-five-bodies.webp" width="420" height="263" alt="" loading="lazy"><span><b>9</b>Five bodies</span></a></li><li><a href="#10-noodle-limbs"><img src="plates/thumbs/10-noodle-limbs.webp" width="420" height="263" alt="" loading="lazy"><span><b>10</b>Noodle limbs</span></a></li><li><a href="#11-hand-library"><img src="plates/thumbs/11-hand-library.webp" width="420" height="263" alt="" loading="lazy"><span><b>11</b>The hand library</span></a></li><li><a href="#12-feet-footwear"><img src="plates/thumbs/12-feet-footwear.webp" width="420" height="263" alt="" loading="lazy"><span><b>12</b>Feet and footwear</span></a></li><li><a href="#13-cuffs-lips"><img src="plates/thumbs/13-cuffs-lips.webp" width="420" height="263" alt="" loading="lazy"><span><b>13</b>Cuffs and lips</span></a></li><li><a href="#14-saturated-shadows"><img src="plates/thumbs/14-saturated-shadows.webp" width="420" height="263" alt="" loading="lazy"><span><b>14</b>Saturated shadows</span></a></li><li><a href="#15-strokeless-matter"><img src="plates/thumbs/15-strokeless-matter.webp" width="420" height="263" alt="" loading="lazy"><span><b>15</b>Strokeless matter</span></a></li><li><a href="#16-attitude-lineup"><img src="plates/thumbs/16-attitude-lineup.webp" width="420" height="263" alt="" loading="lazy"><span><b>16</b>Attitude line-up</span></a></li><li><a href="#17-pose-sheet"><img src="plates/thumbs/17-pose-sheet.webp" width="420" height="263" alt="" loading="lazy"><span><b>17</b>Pose sheet, twelve up</span></a></li><li><a href="#18-full-turnaround"><img src="plates/thumbs/18-full-turnaround.webp" width="420" height="263" alt="" loading="lazy"><span><b>18</b>Full turnaround, eight views and a hero</span></a></li><li><a href="#19-depth-without-blur"><img src="plates/thumbs/19-depth-without-blur.webp" width="420" height="263" alt="" loading="lazy"><span><b>19</b>Depth without blur</span></a></li><li><a href="#20-dark-key"><img src="plates/thumbs/20-dark-key.webp" width="420" height="263" alt="" loading="lazy"><span><b>20</b>Dark-key inversion</span></a></li><li><a href="#21-twelve-frame-loop"><img src="plates/thumbs/21-twelve-frame-loop.webp" width="420" height="263" alt="" loading="lazy"><span><b>21</b>Twelve-frame loop, contact sheet</span></a></li><li><a href="#loop"><img src="plates/thumbs/loop.webp" width="336" height="420" alt="" loading="lazy"><span><b>22</b>The loop itself</span></a></li><li><a href="#phly-sheet"><img src="plates/thumbs/phly-sheet.webp" width="420" height="263" alt="" loading="lazy"><span><b>23</b>Phly's character sheet</span></a></li><li><a href="#phly-hero"><img src="plates/thumbs/phly-hero.webp" width="420" height="336" alt="" loading="lazy"><span><b>24</b>Phly, hero</span></a></li><li><a href="#phly-mark"><img src="plates/thumbs/phly-mark.webp" width="420" height="420" alt="" loading="lazy"><span><b>25</b>Phly's mark</span></a></li><li><a href="#phly-mug"><img src="plates/thumbs/phly-mug.webp" width="420" height="263" alt="" loading="lazy"><span><b>26</b>Phly on the mug</span></a></li><li><a href="#garden-still"><img src="plates/thumbs/garden-still.webp" width="420" height="263" alt="" loading="lazy"><span><b>27</b>The tea garden</span></a></li><li><a href="#garden"><img src="plates/thumbs/garden.webp" width="420" height="263" alt="" loading="lazy"><span><b>28</b>The tea garden assembles</span></a></li><li><a href="#bunny-sheet"><img src="plates/thumbs/bunny-sheet.webp" width="420" height="263" alt="" loading="lazy"><span><b>29</b>Bunny</span></a></li><li><a href="#unicorn-sheet"><img src="plates/thumbs/unicorn-sheet.webp" width="420" height="263" alt="" loading="lazy"><span><b>30</b>Unicorn</span></a></li><li><a href="#dance-still"><img src="plates/thumbs/dance-still.webp" width="420" height="263" alt="" loading="lazy"><span><b>31</b>Bunny and Unicorn dance</span></a></li><li><a href="#dance"><img src="plates/thumbs/dance.webp" width="420" height="263" alt="" loading="lazy"><span><b>32</b>The dance loop</span></a></li></ol></section>
|
||
<section id="how" aria-labelledby="how-h"><h2 id="how-h">How the drawings were made</h2><div class="intro"><p>The studio had a published style guide it loved and no hand that could draw in it. So the guide was read front to back and turned into twenty-one katas, about four to a belt, each with pass conditions written as things a reviewer could see. Every drawing on this page comes out of one Python file, house.py, which grew a function per belt: head, bean, tubes, hands, feet, garments, shadows, FX, and finally figure().</p><p>Two graders, and neither of them draws. svg_lint.py checks the mechanical rules on the SVG itself: one line weight, round caps and joins, palette colours only, no gradients or filters. Cloudflare's Clef model looks at the rendered picture and answers each rule as a probability. A sheet clears its kata at 1.8 out of 3 with no single check under 0.4. When a sheet stalled, the move was to ask the grader one claim at a time and fix whichever came back weakest, never to argue with the number.</p><p>The plates replay their own making. drawon.py traces every ink line at one steady pen speed, lets each shape fill with paper as it closes, then floods in the flat colours, the shadows and the effects. house.py marks the parts of each character as it draws them, so the replay goes the way an artist works: head first, feet last.</p></div></section>
|
||
<section id="white" aria-labelledby="white-h"><h2 id="white-h"><span class="dot" style="background:#FFFFFF"></span>White belt</h2><p class=sub>One form at a time</p><div class="intro"><p>Four katas on single forms: the inflated cube, the smooth bean, tube discipline, reduce-by-half. This is where the lint grader was written: constant stroke width, round caps and joins, palette-only fills, no gradients or filters. Every later sheet has to pass it before a reviewer ever sees it.</p><p>The first lesson was cheap and permanent: the producer never grades its own work. The lint is deterministic; the visual judgement goes to a separate model.</p></div><figure class="plate" id="01-inflated-cube"><a href="plates/01-inflated-cube.webp" aria-label="Plate 1, Inflated cube: full-size image"><img src="plates/01-inflated-cube.webp" width="1600" height="1000" alt="Inflated cube. Corners 9% of edge, every edge bowed, interior lines stopping short of the centre." loading="lazy" data-drawn="plates/01-inflated-cube.svg" data-paper="#FFEAD2"></a><figcaption><h3><b>1</b>Inflated cube</h3><p>Corners 9% of edge, every edge bowed, interior lines stopping short of the centre.</p><p class="meta">Kata 1</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="02-smooth-bean"><a href="plates/02-smooth-bean.webp" aria-label="Plate 2, Smooth bean: full-size image"><img src="plates/02-smooth-bean.webp" width="1600" height="1000" alt="Smooth bean. Seven anchors, one arced back, a belly circle at ~60% of the height." loading="lazy" data-drawn="plates/02-smooth-bean.svg" data-paper="#B3FFC7"></a><figcaption><h3><b>2</b>Smooth bean</h3><p>Seven anchors, one arced back, a belly circle at ~60% of the height.</p><p class="meta">Kata 2</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="03-tube-discipline"><a href="plates/03-tube-discipline.webp" aria-label="Plate 3, Tube discipline: full-size image"><img src="plates/03-tube-discipline.webp" width="1600" height="1000" alt="Tube discipline. Constant-width tubes, loop radius never below the width, round ends." loading="lazy" data-drawn="plates/03-tube-discipline.svg" data-paper="#FEFEFE"></a><figcaption><h3><b>3</b>Tube discipline</h3><p>Constant-width tubes, loop radius never below the width, round ends.</p><p class="meta">Kata 3</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="04-reduce-by-half"><a href="plates/04-reduce-by-half.webp" aria-label="Plate 4, Reduce by half: full-size image"><img src="plates/04-reduce-by-half.webp" width="1600" height="1000" alt="Reduce by half. The same object at half the line count; features deleted, not shrunk." loading="lazy" data-drawn="plates/04-reduce-by-half.svg" data-paper="#FFEAD2"></a><figcaption><h3><b>4</b>Reduce by half</h3><p>The same object at half the line count; features deleted, not shrunk.</p><p class="meta">Kata 4</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure></section><section id="yellow" aria-labelledby="yellow-h"><h2 id="yellow-h"><span class="dot" style="background:#FFE780"></span>Yellow belt</h2><p class=sub>The head</p><div class="intro"><p>The head is an oblong, not an egg: 1.2× taller than wide, flattened top and bottom. Eyes sit on the upper third, the mouth just below them. Kata 8 (the turnaround) took seven attempts; the breakthrough came from asking the grader one claim at a time — closed-lobe ears and a compressed far eye lifted it from 1.77 to 1.80.</p></div><figure class="plate" id="05-edgy-not-eggy"><a href="plates/05-edgy-not-eggy.webp" aria-label="Plate 5, Edgy, not eggy: full-size image"><img src="plates/05-edgy-not-eggy.webp" width="1600" height="1000" alt="Edgy, not eggy." loading="lazy" data-drawn="plates/05-edgy-not-eggy.svg" data-paper="#FFEAD2"></a><figcaption><h3><b>5</b>Edgy, not eggy</h3><p class="meta">Kata 5, Clef 2.07</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="06-face-grid"><a href="plates/06-face-grid.webp" aria-label="Plate 6, The face grid: full-size image"><img src="plates/06-face-grid.webp" width="1600" height="1000" alt="The face grid." loading="lazy" data-drawn="plates/06-face-grid.svg" data-paper="#B3FFC7"></a><figcaption><h3><b>6</b>The face grid</h3><p class="meta">Kata 6, Clef 1.85</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="07-expressions"><a href="plates/07-expressions.webp" aria-label="Plate 7, Expressions: full-size image"><img src="plates/07-expressions.webp" width="1600" height="1000" alt="Expressions. Only the eyes and mouth change." loading="lazy" data-drawn="plates/07-expressions.svg" data-paper="#FFE780"></a><figcaption><h3><b>7</b>Expressions</h3><p>Only the eyes and mouth change.</p><p class="meta">Kata 7, Clef 2.08</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="08-turnaround"><a href="plates/08-turnaround.webp" aria-label="Plate 8, Head turnaround, five views: full-size image"><img src="plates/08-turnaround.webp" width="1600" height="1000" alt="Head turnaround, five views." loading="lazy" data-drawn="plates/08-turnaround.svg" data-paper="#A1E9FF"></a><figcaption><h3><b>8</b>Head turnaround, five views</h3><p class="meta">Kata 8, Clef 1.80</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure></section><section id="green" aria-labelledby="green-h"><h2 id="green-h"><span class="dot" style="background:#B3FFC7"></span>Green belt</h2><p class=sub>Bodies, limbs, hands, feet</p><div class="intro"><p>Beans for torsos, tubes for limbs, and the two house rules the creative director set over the field guide: hands are three fingers plus a thumb (thumb 1.15×, not oversized), feet have four toes. Kata 9 needed the bean on the hip line and shoulders at 0.72× before it cleared.</p></div><figure class="plate" id="09-five-bodies"><a href="plates/09-five-bodies.webp" aria-label="Plate 9, Five bodies: full-size image"><img src="plates/09-five-bodies.webp" width="1600" height="1000" alt="Five bodies." loading="lazy" data-drawn="plates/09-five-bodies.svg" data-paper="#FFEAD2"></a><figcaption><h3><b>9</b>Five bodies</h3><p class="meta">Kata 9, Clef 1.85</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="10-noodle-limbs"><a href="plates/10-noodle-limbs.webp" aria-label="Plate 10, Noodle limbs: full-size image"><img src="plates/10-noodle-limbs.webp" width="1600" height="1000" alt="Noodle limbs. Constant width, single curves, no elbows." loading="lazy" data-drawn="plates/10-noodle-limbs.svg" data-paper="#B3FFC7"></a><figcaption><h3><b>10</b>Noodle limbs</h3><p>Constant width, single curves, no elbows.</p><p class="meta">Kata 10, Clef 2.17</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="11-hand-library"><a href="plates/11-hand-library.webp" aria-label="Plate 11, The hand library: full-size image"><img src="plates/11-hand-library.webp" width="1600" height="1000" alt="The hand library." loading="lazy" data-drawn="plates/11-hand-library.svg" data-paper="#FFE780"></a><figcaption><h3><b>11</b>The hand library</h3><p class="meta">Kata 11, Clef 2.06</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="12-feet-footwear"><a href="plates/12-feet-footwear.webp" aria-label="Plate 12, Feet and footwear: full-size image"><img src="plates/12-feet-footwear.webp" width="1600" height="1000" alt="Feet and footwear." loading="lazy" data-drawn="plates/12-feet-footwear.svg" data-paper="#A1E9FF"></a><figcaption><h3><b>12</b>Feet and footwear</h3><p class="meta">Kata 12, Clef 2.01</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure></section><section id="blue" aria-labelledby="blue-h"><h2 id="blue-h"><span class="dot" style="background:#A1E9FF"></span>Blue belt</h2><p class=sub>Garments, shadows, matter</p><div class="intro"><p>Every opening is an ellipse with a lip; sleeves and trouser legs are 1.6–1.7× the limb. Every shadow is a more saturated version of its base hue, one hard-edged strokeless shape per form. FX — steam, sparkles, liquid, fire — carry no outline at all. The lint learned the saturated-shadow rule here (hue ±5°, saturation up, value down by at most 0.12).</p></div><figure class="plate" id="13-cuffs-lips"><a href="plates/13-cuffs-lips.webp" aria-label="Plate 13, Cuffs and lips: full-size image"><img src="plates/13-cuffs-lips.webp" width="1600" height="1000" alt="Cuffs and lips." loading="lazy" data-drawn="plates/13-cuffs-lips.svg" data-paper="#FFEAD2"></a><figcaption><h3><b>13</b>Cuffs and lips</h3><p class="meta">Kata 13, Clef 1.94</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="14-saturated-shadows"><a href="plates/14-saturated-shadows.webp" aria-label="Plate 14, Saturated shadows: full-size image"><img src="plates/14-saturated-shadows.webp" width="1600" height="1000" alt="Saturated shadows." loading="lazy" data-drawn="plates/14-saturated-shadows.svg" data-paper="#FFEAD2"></a><figcaption><h3><b>14</b>Saturated shadows</h3><p class="meta">Kata 14, Clef 2.27</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="15-strokeless-matter"><a href="plates/15-strokeless-matter.webp" aria-label="Plate 15, Strokeless matter: full-size image"><img src="plates/15-strokeless-matter.webp" width="1600" height="1000" alt="Strokeless matter." loading="lazy" data-drawn="plates/15-strokeless-matter.svg" data-paper="#5467EF"></a><figcaption><h3><b>15</b>Strokeless matter</h3><p class="meta">Kata 15, Clef 2.09</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure></section><section id="brown" aria-labelledby="brown-h"><h2 id="brown-h"><span class="dot" style="background:#FFC897"></span>Brown belt</h2><p class=sub>Whole figures</p><div class="intro"><p>The full-figure taste test. One library call, <code>figure()</code>, draws an on-model character from a view, a lean, arm and leg targets, hands, props and accessories. Kata 17 cleared once the sitting pose actually sat (hips at bench height); kata 18 cleared once the figures were drawn big enough for the grader to see cuffs and shadows at all — a rule the dojo now keeps: nothing under about 70px of head height on a graded sheet.</p></div><figure class="plate" id="16-attitude-lineup"><a href="plates/16-attitude-lineup.webp" aria-label="Plate 16, Attitude line-up: full-size image"><img src="plates/16-attitude-lineup.webp" width="1600" height="1000" alt="Attitude line-up. Four characters, one ground shadow." loading="lazy" data-drawn="plates/16-attitude-lineup.svg" data-paper="#FFEAD2"></a><figcaption><h3><b>16</b>Attitude line-up</h3><p>Four characters, one ground shadow.</p><p class="meta">Kata 16, Clef 1.83</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="17-pose-sheet"><a href="plates/17-pose-sheet.webp" aria-label="Plate 17, Pose sheet, twelve up: full-size image"><img src="plates/17-pose-sheet.webp" width="1600" height="1000" alt="Pose sheet, twelve up." loading="lazy" data-drawn="plates/17-pose-sheet.svg" data-paper="#D9F3FF"></a><figcaption><h3><b>17</b>Pose sheet, twelve up</h3><p class="meta">Kata 17, Clef 1.83</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="18-full-turnaround"><a href="plates/18-full-turnaround.webp" aria-label="Plate 18, Full turnaround, eight views and a hero: full-size image"><img src="plates/18-full-turnaround.webp" width="1600" height="1000" alt="Full turnaround, eight views and a hero." loading="lazy" data-drawn="plates/18-full-turnaround.svg" data-paper="#FFEAD2"></a><figcaption><h3><b>18</b>Full turnaround, eight views and a hero</h3><p class="meta">Kata 18, Clef 1.81</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure></section><section id="black" aria-labelledby="black-h"><h2 id="black-h"><span class="dot" style="background:#2B2135"></span>Black belt</h2><p class=sub>Depth, dark key, motion</p><div class="intro"><p>Depth without blur: overlap, scale and value only. The dark-key inversion swaps the shadow family in as the base and lights the scene with a strokeless halo. The twelve-frame loop exposed a real bug — <code>figure()</code> had a fixed ink width, so a half-scale figure drew with double-weight line — and taught the reviewer-facing trick of putting the seam on the sheet: frames 1 and 2 repeated, ghosted, after 12.</p></div><figure class="plate" id="19-depth-without-blur"><a href="plates/19-depth-without-blur.webp" aria-label="Plate 19, Depth without blur: full-size image"><img src="plates/19-depth-without-blur.webp" width="1600" height="1000" alt="Depth without blur." loading="lazy" data-drawn="plates/19-depth-without-blur.svg" data-paper="#D9F3FF"></a><figcaption><h3><b>19</b>Depth without blur</h3><p class="meta">Kata 19, Clef 1.94</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="20-dark-key"><a href="plates/20-dark-key.webp" aria-label="Plate 20, Dark-key inversion: full-size image"><img src="plates/20-dark-key.webp" width="1600" height="1000" alt="Dark-key inversion." loading="lazy" data-drawn="plates/20-dark-key.svg" data-paper="#FFEAD2"></a><figcaption><h3><b>20</b>Dark-key inversion</h3><p class="meta">Kata 20, Clef 1.91</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="21-twelve-frame-loop"><a href="plates/21-twelve-frame-loop.webp" aria-label="Plate 21, Twelve-frame loop, contact sheet: full-size image"><img src="plates/21-twelve-frame-loop.webp" width="1600" height="1000" alt="Twelve-frame loop, contact sheet." loading="lazy" data-drawn="plates/21-twelve-frame-loop.svg" data-paper="#D9F3FF"></a><figcaption><h3><b>21</b>Twelve-frame loop, contact sheet</h3><p class="meta">Kata 21, Clef 1.85</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="loop"><a href="plates/loop.gif" aria-label="Plate 22, The loop itself: full-size image"><img src="plates/loop.gif" width="400" height="500" alt="The loop itself. Twelve frames, a second long." loading="lazy"></a><figcaption><h3><b>22</b>The loop itself</h3><p>Twelve frames, a second long.</p></figcaption></figure></section><section id="final" aria-labelledby="final-h"><h2 id="final-h"><span class="dot" style="background:#FFB3E6"></span>After the ladder</h2><p class=sub>Phly, the mug, the garden</p><div class="intro"><p>With the hand locked in, the real work: the phly.cloud mascot rebuilt as one closed silhouette with wings, cap, goggles and scarf (2.00 first time); the old mug scene redrawn with <code>figure()</code>; and the maths.teahub.xyz title card remade as a frame-by-frame animation from the same drawing library.</p><p>Two of those three never cleared the tangent check (0.36 against a 0.4 gate). The probe named the same thing every time: a figure or object resting on a horizontal set line. That's the rule the next version of the dojo gets — break the line with a clear overlap, or lift the thing off it.</p></div><figure class="plate" id="phly-sheet"><a href="plates/phly-sheet.webp" aria-label="Plate 23, Phly's character sheet: full-size image"><img src="plates/phly-sheet.webp" width="1600" height="1000" alt="Phly's character sheet. Hero, three expressions and the mark." loading="lazy" data-drawn="plates/phly-sheet.svg" data-paper="#D9F3FF"></a><figcaption><h3><b>23</b>Phly's character sheet</h3><p>Hero, three expressions and the mark.</p><p class="meta">Clef 2.00</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="phly-hero"><a href="plates/phly-hero.webp" aria-label="Plate 24, Phly, hero: full-size image"><img src="plates/phly-hero.webp" width="1000" height="800" alt="Phly, hero." loading="lazy" data-drawn="plates/phly-hero.svg" data-paper="#D9F3FF"></a><figcaption><h3><b>24</b>Phly, hero</h3><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="phly-mark"><a href="plates/phly-mark.webp" aria-label="Plate 25, Phly's mark: full-size image"><img src="plates/phly-mark.webp" width="512" height="512" alt="Phly's mark. Drawn to work as a favicon." loading="lazy" data-drawn="plates/phly-mark.svg" data-paper="#D9F3FF"></a><figcaption><h3><b>25</b>Phly's mark</h3><p>Drawn to work as a favicon.</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="phly-mug"><a href="plates/phly-mug.webp" aria-label="Plate 26, Phly on the mug: full-size image"><img src="plates/phly-mug.webp" width="1600" height="1000" alt="Phly on the mug. The old scene, house hand. Tangents 0.36." loading="lazy" data-drawn="plates/phly-mug.svg" data-paper="#A1E9FF"></a><figcaption><h3><b>26</b>Phly on the mug</h3><p>The old scene, house hand. Tangents 0.36.</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="garden-still"><a href="plates/garden-still.webp" aria-label="Plate 27, The tea garden: full-size image"><img src="plates/garden-still.webp" width="1600" height="1000" alt="The tea garden. End frame. Tangents 0.36." loading="lazy" data-drawn="plates/garden-still.svg" data-paper="#D9F3FF"></a><figcaption><h3><b>27</b>The tea garden</h3><p>End frame. Tangents 0.36.</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="garden"><a href="plates/garden.gif" aria-label="Plate 28, The tea garden assembles: full-size image"><img src="plates/garden.gif" width="640" height="400" alt="The tea garden assembles. Nine seconds, ending on the frame above." loading="lazy"></a><figcaption><h3><b>28</b>The tea garden assembles</h3><p>Nine seconds, ending on the frame above.</p></figcaption></figure></section><section id="cast" aria-labelledby="cast-h"><h2 id="cast-h"><span class="dot" style="background:#C5C5FF"></span>New cast</h2><p class=sub>Bunny, Unicorn, and a dance</p><div class="intro"><p>Two new cast members, each with a card of her own: Bunny (kata 23) — long lilac ears, the right one flopping, a pink dress with puff sleeves and a cotton tail — and Unicorn (kata 24) — a gold spiral horn, pony ears, a lavender mane with one pink streak, white hoof boots. The library grew a little for each: hooks to draw parts behind, between and over the body, a palm that stays wrist-wide on big hands, and opt-in fixes for small figures, where the constant 10px line closes cuffs, soles and collars up into solid ink.</p><p>Bunny cleared at 1.81. Unicorn plateaued at 1.65 over seven grades and is committed ungated, with her scores. Then the two of them got a scene. The first version held hands, and every clasp — fingers under a fist, one fist hiding both hands — came back as the worst tangent on the page; a high five with a clear gap passed every check.</p><p>Posing them in the rig showed what the sheets hid: arms that grew from under the chin, a three-quarter view that put the far shoulder over the chest so they looked hunched, and a skirt drawn as if from below, with the legs behind its opening. Redrawn with the shoulders below the chin, each limb layered whole and the skirt seen from a little above, Bunny held at 1.81, Unicorn rose to 1.70, and the dance kept every check above 0.4.</p></div><figure class="plate" id="bunny-sheet"><a href="plates/bunny-sheet.webp" aria-label="Plate 29, Bunny: full-size image"><img src="plates/bunny-sheet.webp" width="1600" height="1000" alt="Bunny. Hero, turnaround, ear moods, colour chips and the mark." loading="lazy" data-drawn="plates/bunny-sheet.svg" data-paper="#FFEAD2"></a><figcaption><h3><b>29</b>Bunny</h3><p>Hero, turnaround, ear moods, colour chips and the mark.</p><p class="meta">Clef 1.81</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="unicorn-sheet"><a href="plates/unicorn-sheet.webp" aria-label="Plate 30, Unicorn: full-size image"><img src="plates/unicorn-sheet.webp" width="1600" height="1000" alt="Unicorn. Hero, turnaround, moods carried by the ears and the horn's sparkles, the mark. Ungated (gate 1.8)." loading="lazy" data-drawn="plates/unicorn-sheet.svg" data-paper="#FFEAD2"></a><figcaption><h3><b>30</b>Unicorn</h3><p>Hero, turnaround, moods carried by the ears and the horn's sparkles, the mark. Ungated (gate 1.8).</p><p class="meta">Clef 1.70</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="dance-still"><a href="plates/dance-still.webp" aria-label="Plate 31, Bunny and Unicorn dance: full-size image"><img src="plates/dance-still.webp" width="1600" height="1000" alt="Bunny and Unicorn dance. The still. Every check at least 0.4; tangents 0.41." loading="lazy" data-drawn="plates/dance-still.svg" data-paper="#FFEAD2"></a><figcaption><h3><b>31</b>Bunny and Unicorn dance</h3><p>The still. Every check at least 0.4; tangents 0.41.</p><button class="redraw" type="button" hidden>Draw it again</button></figcaption></figure><figure class="plate" id="dance"><a href="plates/dance.gif" aria-label="Plate 32, The dance loop: full-size image"><img src="plates/dance.gif" width="800" height="500" alt="The dance loop. Two seconds: two hops, and a clap on the second landing." loading="lazy"></a><figcaption><h3><b>32</b>The dance loop</h3><p>Two seconds: two hops, and a clap on the second landing.</p></figcaption></figure></section>
|
||
</main>
|
||
<footer><p>House Hand is a venture on <a href="https://yolopreneur.lol/">yolopreneur.lol</a>. Every drawing here was drawn
|
||
by Claude in Python with house.py and graded by svg_lint and Cloudflare's Clef, October 2026.</p>
|
||
<p>Headings are set in Fredoka, under the <a href="fonts/OFL.txt">SIL Open Font License</a>.</p></footer>
|
||
</div>
|
||
<script>
|
||
(() => {
|
||
const still = matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||
if (still) for (const s of document.querySelectorAll("svg.emblem")) { s.pauseAnimations(); s.setCurrentTime(60); }
|
||
let n = 0;
|
||
const draw = img => { img.src = img.dataset.drawn + "?" + (++n); };
|
||
const io = "IntersectionObserver" in window && new IntersectionObserver(es => {
|
||
for (const e of es) if (e.isIntersecting) { io.unobserve(e.target); draw(e.target); }
|
||
}, { threshold: 0.35 });
|
||
for (const img of document.querySelectorAll("img[data-drawn]")) {
|
||
const b = img.closest("figure").querySelector(".redraw");
|
||
b.hidden = false;
|
||
b.textContent = still ? "Watch it being drawn" : "Draw it again";
|
||
b.addEventListener("click", () => draw(img));
|
||
if (still || !io) continue;
|
||
const w = img.getAttribute("width"), h = img.getAttribute("height");
|
||
img.src = "data:image/svg+xml," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="' + w +
|
||
'" height="' + h + '"><rect width="100%" height="100%" fill="' + img.dataset.paper + '"/></svg>');
|
||
io.observe(img);
|
||
}
|
||
})();
|
||
(() => {
|
||
const b = document.querySelector("button.copy"), pre = document.getElementById("prompt"), said = document.getElementById("copied");
|
||
if (!b || !pre) return;
|
||
b.hidden = false;
|
||
document.getElementById("copy-hint").textContent = "Then change the first line to what you want drawn.";
|
||
let t = 0;
|
||
b.addEventListener("click", async () => {
|
||
let ok = false;
|
||
try { await navigator.clipboard.writeText(pre.textContent); ok = true; } catch (e) {
|
||
const r = document.createRange(); r.selectNodeContents(pre);
|
||
const s = getSelection(); s.removeAllRanges(); s.addRange(r);
|
||
try { ok = document.execCommand("copy"); } catch (e2) {}
|
||
}
|
||
b.textContent = ok ? "Copied" : "Selected: press ⌘C or Ctrl+C";
|
||
said.textContent = ok ? "Prompt copied to the clipboard." : "";
|
||
clearTimeout(t); t = setTimeout(() => { b.textContent = "Copy prompt"; }, 2200);
|
||
});
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|