FABLE 50 · Site 5 · Method
How this site
was made.
KŌAN is a fictional nine-seat tea house in northern Kyoto. The brief: wabi-sabi Japanese minimalism — a four-color palette, extreme asymmetric whitespace (間, ma), ink-wash image reveals, vertical text, one slow enso. The mood is a single word: stillness. Everything below is vanilla HTML, CSS and SVG. No build step, no framework.
壱Concept & art direction
The design treats emptiness as the primary material. The hero is one vertical word,
one hand-drawn circle, one bowl — everything else is Cloud Dancer #F0EEE9 paper.
The palette is locked to four values (paper, warm gray #D6D1C8, sumi ink
#171512, moss #2E4B3F) plus opacity tints via CSS
color-mix(). Type is Shippori Mincho for display and vertical columns,
Zen Kaku Gothic New (weight 300) for body. Copy is short and declarative — no filler,
because a tea house would not fill silence either.
弐The technique stack
- Ink-wash blob reveals — each photograph sits inside an inline SVG,
masked by an ellipse roughened with
feTurbulence+feDisplacementMap. The ellipse scales from 0 → 1 on scroll (IntersectionObserver adds a class), so images bloom in like ink hitting wet paper. - The enso — a single SVG
<circle>withpathLength="100", dash-drawn on load viastroke-dashoffset. The dash array stops at 93 units so the circle never closes — a proper enso leaves the gap. A high-frequency turbulence filter gives the stroke a dry-brush edge. - Vertical Japanese text —
writing-mode: vertical-rlwithtext-orientation: uprightand wide letter-spacing, used for the hero word 静けさ, section numerals and marginal columns. - Ma (間) — asymmetric whitespace is engineered with huge
clamp()-based margins that push text blocks off-axis, and figures that bleed toward one edge only. - Paper grain — a fixed full-viewport overlay whose background is a
data-URI SVG of
feTurbulencefractal noise at 6% alpha.
The signature trick, in full:
<!-- roughening filter, defined once -->
<filter id="ink-rough">
<feTurbulence type="fractalNoise" baseFrequency="0.012 0.016"
numOctaves="4" seed="7" result="n"/>
<feDisplacementMap in="SourceGraphic" in2="n" scale="90"
xChannelSelector="R" yChannelSelector="G"/>
</filter>
<!-- each photo: image masked by a displaced ellipse -->
<svg viewBox="0 0 600 800">
<mask id="m-bowl">
<ellipse class="ink-blob" cx="300" cy="400" rx="290" ry="392"
fill="#fff" filter="url(#ink-rough)"/>
</mask>
<image href="assets/bowl.jpg" mask="url(#m-bowl)" .../>
</svg>
/* CSS: the blob blooms open when scrolled into view */
.ink-blob { transform-box: fill-box; transform-origin: center;
transform: scale(.001);
transition: transform 2.2s cubic-bezier(.25,.6,.25,1); }
.is-in .ink-blob { transform: scale(1); }
参Imagery
All three photographs were generated with MiniMax image-01, then resized
and recompressed with ffmpeg to under 150 KB each. Example prompt:
still life of a single raku tea bowl on weathered grey wood,
soft diffused window light from the left, wabi-sabi aesthetic,
muted earth tones, cream and warm grey palette, film photography,
kodak portra, shallow depth of field, vast negative space above,
quiet, minimal, Kyoto tea house — aspect_ratio 3:4
Prompting for "vast negative space" and "film photography" made the images sit naturally in the paper-toned layout instead of fighting it.
肆Iteration
The site was deployed after the first draft, then refined through at least three screenshot–critique–fix passes against the live URL with a headless-Chromium script: checking type hierarchy, whitespace rhythm, mask edges, mobile at 390px, and hunting console errors. The resting state after all animations finish was treated as the primary composition — a screenshot must be beautiful even when nothing is moving.



Designed and built autonomously by Claude (Fable 5) — part of the FABLE 50 experiment.