Three sites, one directory each

flux.vision, tobias.raayoni-last.com and randogoth.com. They were one site until
October 2026, serving four audiences from a single dated list, which is the only
format that can hold unrelated things at once.

flux.vision is recovered from the Wayback Machine, where it had sat since being
deleted in 2021: 90 articles, closed and maintained rather than updated.
tobias.raayoni-last.com is the professional record, 97 articles back to 1999.
randogoth.com is the technical work, 41 articles across six areas, served as an
ANSI bulletin board.

History starts here deliberately. The development history, the 266-row inventory
that records why each article went where it did, the Wayback pipelines, the
pruned articles, the source archives and the full-size images are kept beside
the repo rather than in it, so a clone is the web presence and not the argument
that produced it. REFACTOR.md is gitignored for the same reason. See README.md
for where that material lives, and keep it: the sort is not reproducible from
these three directories alone.

Each site documents itself in its own README, including the traps that cost time
and look like nothing when you get them wrong.
This commit is contained in:
randogoth 2026-10-05 20:54:17 +03:00
commit 8505b7e9e0
1003 changed files with 13289 additions and 0 deletions

View file

@ -0,0 +1,290 @@
/* flux.vision — reconstruction of the 2004–2019 site
*
* Values taken verbatim from the original /theme/template.css, recovered from
* the Wayback Machine. The original used Lato from Google Fonts at weights
* 100/300/400/700; self-hosted here.
*
* body Lato 300, #1C1B1B, 1.8em/1.5em, padding-top 50px for the fixed nav
* nav #0D0C0C, no border
* links #F8F8F8, hover #999
* #bg fixed, 200% x 200%, offset -50% so it always covers
* content laid over rgba(0,0,0,.5)
*/
@font-face{font-family:Lato;font-style:normal;font-weight:100;font-display:swap;src:url(../fonts/lato-100-normal-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:Lato;font-style:normal;font-weight:100;font-display:swap;src:url(../fonts/lato-100-normal-latin-ext.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:Lato;font-style:normal;font-weight:300;font-display:swap;src:url(../fonts/lato-300-normal-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:Lato;font-style:normal;font-weight:300;font-display:swap;src:url(../fonts/lato-300-normal-latin-ext.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:Lato;font-style:normal;font-weight:400;font-display:swap;src:url(../fonts/lato-400-normal-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:Lato;font-style:normal;font-weight:400;font-display:swap;src:url(../fonts/lato-400-normal-latin-ext.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:Lato;font-style:normal;font-weight:700;font-display:swap;src:url(../fonts/lato-700-normal-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:Lato;font-style:normal;font-weight:700;font-display:swap;src:url(../fonts/lato-700-normal-latin-ext.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:Lato;font-style:normal;font-weight:900;font-display:swap;src:url(../fonts/lato-900-normal-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:Lato;font-style:normal;font-weight:900;font-display:swap;src:url(../fonts/lato-900-normal-latin-ext.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:Lato;font-style:italic;font-weight:400;font-display:swap;src:url(../fonts/lato-400-italic-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:Lato;font-style:italic;font-weight:400;font-display:swap;src:url(../fonts/lato-400-italic-latin-ext.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:Lato;font-style:italic;font-weight:700;font-display:swap;src:url(../fonts/lato-700-italic-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:Lato;font-style:italic;font-weight:700;font-display:swap;src:url(../fonts/lato-700-italic-latin-ext.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:Lato;font-style:italic;font-weight:900;font-display:swap;src:url(../fonts/lato-900-italic-latin.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:Lato;font-style:italic;font-weight:900;font-display:swap;src:url(../fonts/lato-900-italic-latin-ext.woff2) format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
*,*::before,*::after { box-sizing: border-box; }
html { overflow-y: scroll; overflow-x: clip; }
:root { --panel-w: 148px; --panel-h: 196px;
/* One gutter for everything. Never narrower than the floating panel's lane,
so content can never slide under it; wider than that it tracks the
original's 960px centred column. */
--lane: 186px; --gutter: max(26px, calc(50% - 480px)); --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; }
body {
font-family: Lato, Helvetica, Arial, Verdana, sans-serif;
font-weight: 300;
background: #1C1B1B;
color: #F8F8F8;
font-size: 1.05rem;
line-height: 1.5em;
margin: 0;
}
a, a:visited, a:active { text-decoration: none; color: #F8F8F8; }
a:hover { color: #999; }
/* the oversized fixed backdrop, exactly as the original positioned it */
#bg { position: fixed; top: -50%; left: -50%; width: 200%; height: 200%;
background-color: #1C1B1B; background-position: 50%; background-repeat: no-repeat;
background-size: cover; z-index: 0; }
#content { position: relative; z-index: 1; min-height: 100vh;
background-color: rgba(0,0,0,0.5); }
/* The hero keeps the original's half-black scrim; past it the backdrop is
pulled further down so the work, not the texture, carries the page. */
/* full-bleed: the panel sits inside the 960px column, so it has to break out
of it or the backdrop keeps running down both margins */
.timeline { background: rgba(10,10,10,.82); padding-bottom: 4rem; }
/* nav */
/* Not a bar. A full-width header spends the whole top edge of the viewport on
* four words, and on a site whose content is images that edge is the most
* valuable surface there is. This is a panel floating in the corner instead,
* the way an on-screen display sits over a picture: hairline border, backdrop
* blur, nothing behind it hidden.
*/
.navbar { position: fixed; top: 22px; left: 22px; z-index: 30;
display: flex; flex-direction: column; align-items: flex-start; gap: .1rem;
padding: .7rem .95rem .6rem;
background: rgba(8,8,8,.52); backdrop-filter: blur(16px) saturate(.9);
border: 1px solid rgba(255,255,255,.1); }
/* The logotype was a 56px JPEG that only worked on #0D0C0C. It is Lato 700
italic, so it can simply be set: scalable, crisp at any density, and it takes
currentColor so it sits on any ground. */
.navbar .brand { margin: 0 0 .55rem; font-style: italic; font-weight: 700;
font-size: 1.32rem; letter-spacing: -.01em; line-height: 1; color: #fff; }
.navbar .brand sup { font-size: .46em; font-weight: 400; vertical-align: super;
margin-left: .04em; }
.navbar .brand:hover { opacity: 1; }
.navbar a { font-weight: 300; font-size: .76rem; letter-spacing: .1em;
color: #c7c7c7; line-height: 1.75; }
.navbar a:hover { color: #fff; }
.slate { margin: .55rem 0 0; padding-top: .5rem; font-family: var(--mono);
font-size: .56rem; letter-spacing: .2em; text-transform: uppercase;
color: #7c7c7c; border-top: 1px solid rgba(255,255,255,.1);
align-self: stretch; }
/* On narrow screens it lies back down: a corner panel would cover the picture. */
@media (max-width: 760px) {
:root { --lane: 18px; --gutter: 18px; }
.navbar { top: 0; left: 0; right: 0; flex-direction: row; align-items: center;
gap: 1rem; padding: .5rem 16px; border-width: 0 0 1px; }
.navbar .brand { margin: 0; }
.slate { display: none; }
}
/* No negative margins anywhere. The bands are simply full width and pad
themselves, because `vw` counts the scrollbar that `overflow-y: scroll`
always shows, so any 50vw-based pull-out overflowed by its width and made
the page scroll sideways. */
.container { max-width: none; margin: 0; padding: 0; }
.container > * { padding-left: max(var(--lane), var(--gutter)); padding-right: var(--gutter); }
/* Direct children of .container must set padding with the -top/-bottom longhand.
A `padding:` shorthand has the same specificity as the rule above and comes
later in the file, so it silently resets the gutter to zero and the text ends
up flush against the screen edge. */
/* timeline: year bands of tiles, as the original laid them out */
.yearband { padding: 2.2rem 0 1rem; }
.yearband h1 { font-weight: 100; font-size: 5.4rem; margin: 0 0 .6rem; letter-spacing: .09em;
line-height: 1; opacity: .92; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(214px, 1fr));
grid-auto-flow: dense; gap: 1.15rem; align-items: start; }
/* Size comes from the entry itself: surviving imagery, video, how much was
written. See plugins/tileweight.py. A ten-hour festival set and a two-line
workshop note should not occupy the same rectangle. */
.art.md { grid-column: span 2; }
.art.lg { grid-column: span 2; }
.art.md .art-preview { aspect-ratio: 16 / 9; }
.art.lg .art-preview { aspect-ratio: 4 / 3; }
@media (max-width: 640px) { .art.md, .art.lg { grid-column: span 1; }
.art.md .art-preview, .art.lg .art-preview { aspect-ratio: 4 / 3; } }
.art { display: block; }
.art-preview { display: block; aspect-ratio: 4/3; border: 1px solid transparent;
background: #111; position: relative; overflow: hidden; }
/* The static, as a 12-frame sprite stepped by CSS rather than an animated GIF.
* Every url(void.gif) instance shared one decode and so ran in lockstep; a
* sprite driven by steps() takes an animation-delay, which lets each tile start
* at its own frame. The delay is negative, so they begin already diverged
* rather than staggering into life. */
.art-preview::before {
content: ""; position: absolute; left: 0; top: 0; width: 100%; height: 1200%;
background: url(../img/noise.png) 0 0 / 100% 100%;
animation: static .48s steps(12) infinite;
animation-delay: calc(var(--seed, 0) * -37ms);
}
@keyframes static { from { transform: translateY(0); } to { transform: translateY(-100%); } }
@media (prefers-reduced-motion: reduce) { .art-preview::before { animation: none; } }
/* the real image fades in over the static once it has decoded */
.art-preview.lazy::after { content: ""; position: absolute; inset: 0;
background-image: var(--src); background-size: cover; background-position: center;
opacity: 0; transition: opacity .45s ease; }
.art-preview.lazy.loaded::after { opacity: 1; }
.art:hover .art-preview { border-color: #6a6a6a; }
/* Hovering knocks the picture out of sync for a moment and lets the static
behind it show through, the way a tape head does. One gesture, 260ms. No
scanlines, no curvature, no chromatic fringing. */
.art:hover .art-preview.loaded::after { animation: tracking .26s steps(5) 1; }
@keyframes tracking {
0% { transform: translateY(0); opacity: 1; }
20% { transform: translateY(-7px); opacity: .45; }
45% { transform: translateY(5px); opacity: .85; }
70% { transform: translateY(-3px); opacity: .6; }
100% { transform: translateY(0); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
.art:hover .art-preview.loaded::after { animation: none; }
}
/* No image survived the recovery, so the static simply never resolves. That
reads as signal lost, which is truer than a typographic placeholder. */
.art-preview.empty { border-color: transparent; }
.art-title { font-size: .78rem; margin: .5rem 0 0; padding: 0; text-transform: uppercase;
letter-spacing: .08em; font-weight: 400; line-height: 1.3; }
.art-date { font-family: var(--mono); font-size: .6rem; margin-top: 3px; color: #7a7a7a;
letter-spacing: .1em; text-transform: uppercase; }
/* article */
.hero-title h1 { font-weight: 100; font-size: 4.6rem; line-height: 1.02; margin: 0; letter-spacing: .05em; }
#article-meta { font-family: var(--mono); font-size: .68rem; color: #8a8a8a;
letter-spacing: .06em; padding-bottom: 1.4rem; }
#article-meta .rel { color: #777; }
#article-meta a { color: #F8F8F8; }
#article { font-weight: 300; padding-bottom: 6rem; }
#article p { text-align: justify; hyphens: auto; margin: 0 0 1.1rem; }
/* Article bodies carry their own section headings. Unstyled they fell back to
the browser's bold default, the one piece of type on the page not set in
Lato thin. Same register as the slate and the tile titles. */
#article h1, #article h2, #article h3 {
font-weight: 300; letter-spacing: .14em; text-transform: uppercase; color: #cfcfcf;
margin: 2.8rem 0 1.1rem; padding-top: .7rem;
border-top: 1px solid rgba(255,255,255,.12); }
#article h1 { font-size: 1rem; }
#article h2 { font-size: .9rem; }
#article h3 { font-size: .8rem; }
#article ul, #article ol { margin: 0 0 1.4rem; padding-left: 1.2rem; }
#article li { line-height: 1.55; }
/* Justification needs room. In a ~350px column it opens rivers between words
wide enough to read as a column of holes, so below the tablet break the text
is simply set ragged-right. */
@media (max-width: 700px) { #article p { text-align: left; hyphens: none; } }
#article img { width: 100%; padding: 10px 0; display: block; }
#article iframe, #article embed { width: 100%; aspect-ratio: 16/9; border: 0; padding: 10px 0; }
#article a { border-bottom: 1px solid #555; }
#article a:hover { border-bottom-color: #999; }
/* listings */
.cloud { padding-top: 1rem; padding-bottom: 6rem; line-height: 2.4; }
.cloud a { margin-right: 1.2rem; text-transform: uppercase; font-size: .9rem; }
.cloud a span { color: #777; }
.rows { list-style: none; margin: 0; padding-bottom: 6rem; }
.rows li { display: flex; gap: 1.2rem; align-items: baseline; padding: .5rem 0; border-bottom: 1px solid #2a2a2a; }
.rows .yr { font-size: .75rem; color: #999; min-width: 4.2rem; }
.rows .ti { text-transform: uppercase; font-size: .95rem; }
.pagetitle { font-weight: 100; font-size: 4.4rem; padding-top: 4.5rem; padding-bottom: 1.2rem; margin: 0;
letter-spacing: .07em; line-height: 1; }
.hero-title { padding-top: 5.5rem; padding-bottom: 1rem; }
/* Views that begin at the top of the document still have to clear the panel
vertically; the gutter only handles the horizontal. */
@media (min-width: 761px) {
.pagetitle, .hero-title { padding-top: calc(var(--panel-h) + 1.5rem); }
}
.lede { color: #999; padding-bottom: 2rem; }
@media (max-width: 700px) {
.hero-title h1 { font-size: 2.4rem; }
.pagetitle { font-size: 2.1rem; }
.navbar { gap: .9rem; font-size: .8rem; }
}
/* ── the landing ──────────────────────────────────────────────────────────
* The original opened on a full-bleed hero with the wordmark, then alternating
* bands: the flux dictionary entry on dark, the bio on light. Both run the full
* width of the viewport, not the content column.
*/
.navbar .brand img { display: block; }
.landing { min-height: 368px; display: flex; align-items: flex-end;
padding-bottom: 1.6rem; }
.wordmark { font-weight: 100; font-size: 4.3rem; letter-spacing: .14em;
text-transform: uppercase; margin: 0; line-height: 1; }
.deck { padding-top: 1.6rem; padding-bottom: 2rem; font-size: 1.02rem; }
.deck p { margin: 0; }
/* The light band was a flat grey rectangle, the one unambiguously graphic-design
object on the page. It becomes a luminance step instead: the same backdrop,
blown out, as an overexposed frame rather than a swatch. */
.bio { position: relative; color: #161515; isolation: isolate; overflow: hidden;
padding-top: 2.4rem; padding-bottom: 2.4rem; }
/* Inverting the backdrop straight produced legible high-contrast texture and
the dark type sat on black streaks. Blurred hard it becomes what was wanted
in the first place: a soft blown-out field that is still the same frame,
rather than a flat swatch. */
.bio::before { content: ""; position: absolute; inset: 0; z-index: -1;
background: url(../img/bg1.jpg) center / cover;
filter: grayscale(1) invert(1) brightness(1.5) contrast(.42) blur(34px);
transform: scale(1.1); }
.bio::after { content: ""; position: absolute; inset: 0; z-index: -1;
background: rgba(226,224,220,.72); }
.bio strong { font-weight: 700; }
@media (max-width: 700px) {
.wordmark { font-size: 2.2rem; letter-spacing: .1em; }
.landing { min-height: 42vh; }
}
/* The date leads the entry meta, set like the tile dates and the slate so the
three read as one register. Works carry month precision only: the recovery
could recover "Dec 2013" and no more, so a day would be invented. */
#article-meta time { color: #cfcfcf; letter-spacing: .12em; text-transform: uppercase; }
#article-meta .sep { color: #555; margin: 0 .5rem; }
/* ── the reel ─────────────────────────────────────────────────────────────
* The original index carried a video below the bio. It is the single best
* argument the archive has, so it gets the full width of the band rather than
* sitting inside the text column.
*/
.reel { padding-top: 3.4rem; padding-bottom: 3.8rem; background: rgba(6,6,6,.88); }
.reel-frame { position: relative; aspect-ratio: 16 / 9; background: #000;
border: 1px solid rgba(255,255,255,.08); }
.reel-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.reel-cap { margin-top: .7rem; font-family: var(--mono); font-size: .58rem;
letter-spacing: .2em; text-transform: uppercase; color: #777; }
.reel-cap a { color: #aaa; }
.reel-cap a:hover { color: #fff; }
@media (max-width: 760px) { .reel { padding-top: 2rem; padding-bottom: 2.2rem; } }
/* The colophon. Set like the slate rather than like navigation: this is an
ident at the end of a closed archive, not a way out of it. Vertical padding
only, so the gutter from `.container > *` survives (see the note there). */
/* It needs its own ground. Article pages set a hero backdrop that runs the
full height of the document, so without this the text sat straight on the
photograph and vanished. Same treatment as the other full-bleed bands. */
.colophon { margin-top: 4.5rem; padding-top: 1.3rem; padding-bottom: 3.5rem;
background: rgba(6,6,6,.9);
border-top: 1px solid rgba(255,255,255,.1);
font-family: var(--mono); font-size: .62rem; letter-spacing: .13em;
text-transform: uppercase; color: #8a8a8a; line-height: 2.1; }
.colophon p { margin: 0; }
.colophon a { color: #cfcfcf; }
.colophon a:hover { color: #F8F8F8; }
@media (max-width: 700px) { .colophon { letter-spacing: .08em; line-height: 2.3; } }