/* =============================================================================
   stimpunks.world — one street, no two rooms alike, and a campground off the end of it.

   The organising idea: this site has NO single design system, on purpose. Every
   other Stimpunks site applies one consistent look across many pages. Here the
   STREET is the system and the ROOMS refuse to share one. So this file is a
   small shared base (§1–§4) followed by one self-contained world per room
   (§5 onward), each free to contradict the others.

   The one thing every room DOES share is §3, the intensity dial. Danny the
   Street rearranges themselves for whoever walks down it, so loudness is a
   control the visitor holds, never a fixed property of the page. Who Danny is,
   and why they/them, is §33 and danny-the-street.html.
   ============================================================================= */


/* §1 ── The faces ────────────────────────────────────────────────────────────
   Self-hosted, so reading a page here makes no third-party request — the same
   rule queering.earth and starstuff.earth follow. MOST of these families are
   under the SIL Open Font License and FOUR ARE UNDER APACHE 2.0 — Permanent
   Marker, Rock Salt, Special Elite and Ultra. This comment said "every family
   here is OFL-licensed" until tools/pull-foundry.py read each family's own
   record and found otherwise, which is what that tool is for: a licence nobody
   has checked since the file was added is a claim rather than a fact.
   fonts/_sources.json records where each file came from, and
   data/foundry-faces.json records who drew it and under what.
   @font-face is lazy: a room only downloads the faces it actually sets. */

@font-face { font-family: 'Bungee';          src: url('fonts/bungee-400.woff2') format('woff2');           font-weight: 400; font-display: swap; }
@font-face { font-family: 'Bungee Shade';    src: url('fonts/bungee-shade-400.woff2') format('woff2');     font-weight: 400; font-display: swap; }
@font-face { font-family: 'Shrikhand';       src: url('fonts/shrikhand-400.woff2') format('woff2');        font-weight: 400; font-display: swap; }
@font-face { font-family: 'Monoton';         src: url('fonts/monoton-400.woff2') format('woff2');          font-weight: 400; font-display: swap; }
@font-face { font-family: 'Rock Salt';       src: url('fonts/rock-salt-400.woff2') format('woff2');        font-weight: 400; font-display: swap; }
@font-face { font-family: 'Archivo Black';   src: url('fonts/archivo-black-400.woff2') format('woff2');    font-weight: 400; font-display: swap; }
@font-face { font-family: 'VT323';           src: url('fonts/vt323-400.woff2') format('woff2');            font-weight: 400; font-display: swap; }
@font-face { font-family: 'Special Elite';   src: url('fonts/special-elite-400.woff2') format('woff2');    font-weight: 400; font-display: swap; }
@font-face { font-family: 'Titan One';       src: url('fonts/titan-one-400.woff2') format('woff2');        font-weight: 400; font-display: swap; }
/* Space Grotesk ships as a variable font, so Google serves ONE file for 400,
   500 and 700 — it is downloaded once and declared three times against the
   weight axis, rather than stored three times under three names. It WAS stored
   three times, byte for byte, until tools/pull-foundry.py hashed the shelf and
   said so; on the shared base that EVERY page on the street loads that cost
   about 45KB. The axis is real and all three declarations earn their place —
   rendered out of the one file, 700 lays down 41% more ink than 400, which is
   the same arrangement Nunito, Cabin and Karla are in below. Do not read
   identical bytes as an absent bold. See fonts/_sources.json. */
@font-face { font-family: 'Space Grotesk';   src: url('fonts/space-grotesk-400.woff2') format('woff2');    font-weight: 400; font-display: swap; }
@font-face { font-family: 'Space Grotesk';   src: url('fonts/space-grotesk-400.woff2') format('woff2');    font-weight: 500; font-display: swap; }
@font-face { font-family: 'Space Grotesk';   src: url('fonts/space-grotesk-400.woff2') format('woff2');    font-weight: 700; font-display: swap; }
@font-face { font-family: 'Courier Prime';   src: url('fonts/courier-prime-400.woff2') format('woff2');    font-weight: 400; font-display: swap; }
@font-face { font-family: 'Courier Prime';   src: url('fonts/courier-prime-700.woff2') format('woff2');    font-weight: 700; font-display: swap; }
@font-face { font-family: 'Instrument Serif';src: url('fonts/instrument-serif-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Instrument Serif';src: url('fonts/instrument-serif-400-italic.woff2') format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }

/* The campgrounds (§13) and the Faery Yurt (§14). Five families arriving at
   once, which is what it costs to open an area whose two pages are allowed to
   share nothing — with the street, or with each other. Alfa Slab One and Bitter
   are the campground's routed sign and its field-guide body; the other three are
   Helen's, named in her own mockup, and taking them is how the yurt stays hers.
   Bitter ships as a variable font, so its bold was byte-identical to its
   regular; the campground sets emphasis in Alfa Slab One rather than serve the
   same 34KB twice. See fonts/_sources.json. */
@font-face { font-family: 'Alfa Slab One';  src: url('fonts/alfa-slab-one-400.woff2') format('woff2');  font-weight: 400; font-display: swap; }
@font-face { font-family: 'Bitter';         src: url('fonts/bitter-400.woff2') format('woff2');         font-weight: 400; font-display: swap; }
@font-face { font-family: 'Cormorant Garamond'; src: url('fonts/cormorant-garamond-600.woff2') format('woff2');        font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: 'Cormorant Garamond'; src: url('fonts/cormorant-garamond-600-italic.woff2') format('woff2'); font-weight: 600; font-style: italic; font-display: swap; }
@font-face { font-family: 'Crimson Pro';    src: url('fonts/crimson-pro-400.woff2') format('woff2');        font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Crimson Pro';    src: url('fonts/crimson-pro-400-italic.woff2') format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Caveat';         src: url('fonts/caveat-600.woff2') format('woff2');         font-weight: 600; font-display: swap; }

/* The Arcade (§15), and the only face it sets. A pixel face is the one thing
   no other room on this street could borrow without turning into the arcade,
   which is what its own family is for. 4.7KB, latin only, and nothing
   else here loads it. */
@font-face { font-family: 'Press Start 2P'; src: url('fonts/press-start-2p-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }

/* The Latibulum (§16). A soft slab and a rounded sans, which is the pair that
   keeps a warm brown burrow from reading like the warm brown tent two pages
   away: the yurt is high-contrast italic serif, this is planed and round.
   Nunito ships as a variable font, so Google serves ONE file for 400 and for
   700 — it is downloaded once and declared twice against the weight axis,
   rather than stored twice under two names. See fonts/_sources.json. */
@font-face { font-family: 'Bree Serif'; src: url('fonts/bree-serif-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Nunito';     src: url('fonts/nunito-400.woff2') format('woff2');     font-weight: 400; font-display: swap; }
@font-face { font-family: 'Nunito';     src: url('fonts/nunito-400.woff2') format('woff2');     font-weight: 700; font-display: swap; }

/* The Jungle Room (§17). A swollen, high-contrast display face and a humanist
   sans — a botanical plate and the caption under it. Yeseva One is the one
   face on this street whose strokes THICKEN as they curve, which is the
   closest type gets to something grown rather than built, and it is why this
   room does not sound like the two brown rooms or the cold field. Cabin ships
   as a variable font, so Google serves ONE file for 400 and 700; it is stored
   once and declared twice against the weight axis, the same as Nunito above.
   See fonts/_sources.json. */
@font-face { font-family: 'Yeseva One'; src: url('fonts/yeseva-one-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Cabin';      src: url('fonts/cabin-400.woff2') format('woff2');      font-weight: 400; font-display: swap; }
@font-face { font-family: 'Cabin';      src: url('fonts/cabin-400.woff2') format('woff2');      font-weight: 700; font-display: swap; }

/* The Den (§18), the subroom behind the Jungle Room. A FAT 1970s SLAB and a
   grotesque — the weight a record sleeve was set in the year those sessions
   happened. It is the single thing that stops a green room reading as its own
   parent: upstairs sets a high-contrast serif whose strokes swell as they
   curve, and this sets a slab with no contrast in it at all. Karla ships as a
   variable font, so one file serves 400 and 700, the same as Cabin above. */
/* The Solarpunk Hermitage (§19). An organic serif and a technical sans, which
   is the room's whole thesis set in type: Fraunces' strokes swell and its
   terminals curl like something grown, and Sora is drawn on a grid with flat
   ends. Tech AND nature, not one of them in fancy dress. It is also the only
   pairing here that has to work at SIZE ON A LIGHT GROUND all the way down —
   every other serif on this street is cream on something dark. */
/* Club Chronic (§20). A CONDENSED display face, a marker, and a grotesque —
   which is a gig flyer's three voices and nothing else on this street sets any
   of them. Anton is condensed because a flyer crams a bill onto one sheet of
   A4; Permanent Marker is the pen somebody actually had on them. THE ZINE
   TABLE IS THE COLLISION TO WATCH and this is how they stay apart: that room
   is a photocopier's black on white, cut up with scissors, in Special Elite
   and Rock Salt. This is paste-up on a black wall — layered, not scattered —
   and the marker is written OVER the paper rather than being the paper. */
@font-face { font-family: 'Anton';            src: url('fonts/anton-400.woff2') format('woff2');            font-weight: 400; font-display: swap; }
@font-face { font-family: 'Permanent Marker'; src: url('fonts/permanent-marker-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Barlow';           src: url('fonts/barlow-400.woff2') format('woff2');           font-weight: 400; font-display: swap; }
@font-face { font-family: 'Barlow';           src: url('fonts/barlow-600.woff2') format('woff2');           font-weight: 600; font-display: swap; }

@font-face { font-family: 'Fraunces'; src: url('fonts/fraunces-700.woff2') format('woff2'); font-weight: 700; font-display: swap; }
@font-face { font-family: 'Sora';     src: url('fonts/sora-400.woff2') format('woff2');     font-weight: 400; font-display: swap; }

@font-face { font-family: 'Ultra'; src: url('fonts/ultra-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Karla'; src: url('fonts/karla-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Karla'; src: url('fonts/karla-400.woff2') format('woff2'); font-weight: 700; font-display: swap; }

/* The Pebble Board (§21). Norah Hobbs's three, with two of them substituted.
   ATKINSON HYPERLEGIBLE IS HERS AND STAYS: it is the Braille Institute's
   low-vision face, so swapping the body text would be an access regression
   rather than a style choice, and it is the only face on this street chosen
   for legibility before looks. Her other two had to go, because both were
   already taken -- Caveat is the Faery Yurt's glimmer hint and Special Elite
   is the Zine Table's typewriter. A punk-paper noticeboard set in the zine's
   own typewriter is the collapse this street exists to refuse, and the zine
   is the room it would have collapsed into. Gloria Hallelujah is a felt pen
   rather than Caveat's brush; Josefin Sans is a filing label rather than a
   struck key, and nothing else here is geometric. See _typefaces in
   data/pebble-board.json, where the substitution is written up. */
@font-face { font-family: 'Atkinson Hyperlegible'; src: url('fonts/atkinson-hyperlegible-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Atkinson Hyperlegible'; src: url('fonts/atkinson-hyperlegible-700.woff2') format('woff2'); font-weight: 700; font-display: swap; }
@font-face { font-family: 'Gloria Hallelujah';     src: url('fonts/gloria-hallelujah-400.woff2') format('woff2');     font-weight: 400; font-display: swap; }
@font-face { font-family: 'Josefin Sans';          src: url('fonts/josefin-sans-600.woff2') format('woff2');          font-weight: 600; font-display: swap; }


/* The Mopery (§22), and its Raven nook. AN IMPRESSED FACE AND A DRAWN ONE.
   IM Fell English is Igino Marini's digitisation of the types John Fell gave
   the Oxford University Press in the 1670s, ink spread and battered counters
   left in, which makes it the only face on this street that looks STAMPED
   rather than drafted — an eldritch tome wants a punch, not a curve. THE
   FAERY YURT IS THE COLLISION TO WATCH, because that room is also serif, also
   warm, also candlelit: it sets Cormorant Garamond, which is high-contrast,
   clean and modern-cut. These two rooms are kept apart at the stroke rather
   than at the palette, which is the only place it holds. Spectral is the
   reading face — low contrast, drawn for screens, sturdy at length — because
   the library asks somebody to read eighteen stanzas in it and the tome face
   does not survive that. It is the default the Raven nook's picker starts on;
   every other face on this street is in that list too, which is the one place
   here where borrowing them all is the joke rather than the failure. */
@font-face { font-family: 'IM Fell English'; src: url('fonts/im-fell-english-400.woff2') format('woff2');        font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'IM Fell English'; src: url('fonts/im-fell-english-400-italic.woff2') format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Spectral';        src: url('fonts/spectral-400.woff2') format('woff2');               font-weight: 400; font-display: swap; }
@font-face { font-family: 'Spectral';        src: url('fonts/spectral-600.woff2') format('woff2');               font-weight: 600; font-display: swap; }

/* The Oracle Deck (§23), the subroom behind the Mopery's parlour. CUT RATHER
   THAN PRINTED, which is the whole distance between a deck and the library it
   is kept in: Cinzel is inscriptional Roman capitals — letters chiselled into
   stone, no lowercase worth the name, all of it monumental — where IM Fell is
   a page that has been through a press. Cardo is the commentary underneath,
   David Perry's type for classicists, and a card whose back is an argument
   needs a face that expects footnotes. Cinzel ships variable, so ONE file
   serves 400 and 700, the same arrangement as Nunito, Cabin and Karla. */
@font-face { font-family: 'Cinzel'; src: url('fonts/cinzel-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Cinzel'; src: url('fonts/cinzel-400.woff2') format('woff2'); font-weight: 700; font-display: swap; }
@font-face { font-family: 'Cardo';  src: url('fonts/cardo-400.woff2') format('woff2');        font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Cardo';  src: url('fonts/cardo-400-italic.woff2') format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }

/* Swaying Sweetgrass (§25). A FLARED SERIF AND A HUMANIST SANS, and the pair
   is chosen against the two rooms this one is most likely to collapse into.
   Eczar's stems are narrow and its serifs flare out like a blade opening at
   the tip — it is the only face here that looks grown rather than built, which
   is why the meadow sets it and why it could not be the Faery Yurt's Cormorant
   (cut yesterday, high contrast, calligraphic) or the Jungle Room's Fraunces
   (strokes that swell as they turn). Alegreya Sans is a sans with a
   handwriting skeleton still in it, warm without being round; the burrow's
   Nunito is round and the campground's Bitter is squared, and neither of them
   leans. Two faces, both OFL, neither set anywhere else. See
   fonts/_sources.json. */
@font-face { font-family: 'Eczar';         src: url('fonts/eczar-600.woff2') format('woff2');         font-weight: 600; font-display: swap; }
@font-face { font-family: 'Alegreya Sans'; src: url('fonts/alegreya-sans-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Alegreya Sans'; src: url('fonts/alegreya-sans-500.woff2') format('woff2'); font-weight: 500; font-display: swap; }

/* The Doomscroll (§24). BLACKLETTER LIVES HERE AND NOT IN THE LIBRARY, which
   is deliberate and is what keeps the dark academia room off the obvious peg:
   the gothic cliche is spent here, on a broadside of bad news, where it is a
   joke about mastheads rather than a costume. UnifrakturMaguntia is DISPLAY
   ONLY — the masthead and the odd single word, never a line of a poem, because
   eighteen lines of blackletter is an access failure wearing atmosphere. The
   poems are set in Vollkorn, which Friedrich Althausen drew for small text on
   cheap paper, which is what a broadside is. Vollkorn ships variable: one file,
   two weights declared against the axis. */
@font-face { font-family: 'UnifrakturMaguntia'; src: url('fonts/unifraktur-maguntia-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Vollkorn'; src: url('fonts/vollkorn-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Vollkorn'; src: url('fonts/vollkorn-400.woff2') format('woff2'); font-weight: 600; font-display: swap; }


/* The Adventurer's Guild (§26). A WOODTYPE FACE AND A CIVIC FORM FACE, which is
   the whole joke of that room set twice. Rye is the kind of type a posted bill
   was printed in -- cut, spurred, meant to be read off a wall -- and Public Sans
   is the typeface of the United States Web Design System, drawn for government
   forms. The guild is the one TIDY room on a street whose architecture is that
   nothing matches, so it is set in the type of a bill nailed up by a functioning
   bureaucracy. Neither family is anywhere else here; every other face on this
   street was already claimed by a room before this one opened. */
@font-face { font-family: 'Rye';         src: url('fonts/rye-400.woff2') format('woff2');         font-weight: 400; font-display: swap; }
@font-face { font-family: 'Public Sans'; src: url('fonts/public-sans-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Public Sans'; src: url('fonts/public-sans-700.woff2') format('woff2'); font-weight: 700; font-display: swap; }

/* THE FEED (§27). Michroma is the nameboards and the h1 and NOTHING ELSE: it is
   a very wide squared face, which is what machined signage looks like and what
   a paragraph of text must never be -- the Doomscroll's blackletter lesson, in
   a room whose whole subject is lettering in cells. Space Mono is the rows, the
   dates and the plates, because a split-flap board is a grid of cells with one
   character in each and a monospace is that grid. It is the FOURTH mono here
   and the first squared one: Courier Prime is the zine's typewriter, Special
   Elite is its battered cousin, VT323 is the quantum room's phosphor. The
   room's prose is Space Grotesk, which is Space Mono's own relative and is
   already this file's --sans, so the reading voice in here is the street's
   ordinary one and only the MACHINE has an accent. */
@font-face { font-family: 'Michroma';   src: url('fonts/michroma-400.woff2') format('woff2');   font-weight: 400; font-display: swap; }
@font-face { font-family: 'Space Mono'; src: url('fonts/space-mono-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Space Mono'; src: url('fonts/space-mono-700.woff2') format('woff2'); font-weight: 700; font-display: swap; }

/* The Garden (§28). TWO TEXT FACES AND NO DISPLAY FACE AT ALL, which is this
   room's one structural claim about type: every other world on this street has
   something that shouts -- a woodtype, a condensed grotesque, a fat slab, a
   blackletter, a pixel face -- and a garden has no signage in it. It has
   LABELS. So Faustina sets the garden's own name at size and the label on
   every bed in the same breath, because a nursery writes both with the pen it
   has, and the loud things in this room are the plants. Faustina ships as a
   variable font, so one file serves 400 and 600 against the weight axis, the
   same as Nunito and Cabin above; its italic is a second file because a
   slanted variable axis is not an italic. Mulish carries the notes -- round,
   open, tall-x, which is what a bright day does to letters. Neither face is
   set anywhere else. See fonts/_sources.json. */
@font-face { font-family: 'Faustina'; src: url('fonts/faustina-400.woff2') format('woff2');        font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Faustina'; src: url('fonts/faustina-400.woff2') format('woff2');        font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: 'Faustina'; src: url('fonts/faustina-400-italic.woff2') format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Mulish';   src: url('fonts/mulish-400.woff2') format('woff2');          font-weight: 400; font-display: swap; }
@font-face { font-family: 'Mulish';   src: url('fonts/mulish-400.woff2') format('woff2');          font-weight: 700; font-display: swap; }

/* The Zibaldone (§29). THREE TEXT FACES AND ONE HAND, and the division between
   them is enforced by tools/make-zibaldone.py rather than left to taste: the
   hand writes margins, labels and the keeper's asides, and NEVER a quotation.
   A passage set in a handwriting face is an access failure wearing atmosphere,
   which is the lesson The Doomscroll already carries one room over, where
   blackletter sets the masthead and not one line of a poem. A quote bank is
   where that mistake would look most charming.

   The three are chosen by era, because that is what a commonplace book looks
   like: lines copied out of books that were set at different times. EB Garamond
   for the oldest, Newsreader for the nineteenth century, Lora for the living.
   EB Garamond ships as a variable font, so one file serves 400 and 600 against
   the weight axis -- Faustina's arrangement, and the reason there is no second
   44KB on disk. Kalam is the hand. None of the four is set anywhere else on the
   street. See fonts/_sources.json. */
@font-face { font-family: 'EB Garamond'; src: url('fonts/eb-garamond-400.woff2') format('woff2');        font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'EB Garamond'; src: url('fonts/eb-garamond-400.woff2') format('woff2');        font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: 'EB Garamond'; src: url('fonts/eb-garamond-400-italic.woff2') format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Newsreader';  src: url('fonts/newsreader-400.woff2') format('woff2');         font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Newsreader';  src: url('fonts/newsreader-400-italic.woff2') format('woff2');  font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Lora';        src: url('fonts/lora-400.woff2') format('woff2');               font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Lora';        src: url('fonts/lora-400-italic.woff2') format('woff2');        font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Kalam';       src: url('fonts/kalam-400.woff2') format('woff2');              font-weight: 400; font-display: swap; }
@font-face { font-family: 'Kalam';       src: url('fonts/kalam-700.woff2') format('woff2');              font-weight: 700; font-display: swap; }

/* The Rabbit Hole (§30). A DIDONE AND A GEOMETRIC SANS, which is a pair nobody
   else on this street sets, and the two halves of what this room is about.

   Playfair Display is the 1865 book: high contrast, hairline serifs, the
   register a Victorian title page was cut in -- so it sits with Tenniel's wood
   engravings instead of fighting them. THIS IS NOT THE MOPERY'S SERIF AND THE
   DIFFERENCE IS THE STROKE. IM Fell English was PUNCHED, with the ink spread
   and the counters battered; this was DRAWN, with a mechanical thin and a
   clean joint. One is a book that was beaten into paper and the other is a
   book that was engraved, which is the only place two warm-serif rooms on one
   street can be kept apart.

   Jost is the wiki rabbit hole: a geometric sans, circles and straight lines,
   the face a node-and-arrow diagram is labelled in. Our own glossary entry
   illustrates the thing with a network diagram of linked topics, and this is
   what that drawing sounds like. Josefin Sans one room over is also geometric
   and is the Pebble Board's -- it is set there only as small letter-spaced
   caps, with a tiny x-height and a very high waist; this is a reading face at
   reading size. Neither of these two is set anywhere else. See
   fonts/_sources.json. */
@font-face { font-family: 'Playfair Display'; src: url('fonts/playfair-display-700.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Jost';             src: url('fonts/jost-400.woff2') format('woff2');             font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Jost';             src: url('fonts/jost-500.woff2') format('woff2');             font-weight: 500; font-style: normal; font-display: swap; }

/* The Healing Checkpoint (§31). TWO ROUNDED FACES, because it is the only room
   on this street with no hard edge in it -- and the crowding is real enough to
   be written down rather than hoped about.

   Quicksand is DISPLAY ONLY and is set nowhere at reading size: the plaque, the
   headings, the tagline, the slip labels and the buttons. It is the third
   geometric sans here and the other two are one section apart, so the division
   has to be a job rather than a shape. Jost is The Rabbit Hole's READING face,
   at reading size, doing the work Rubik does here; Josefin Sans is the Pebble
   Board's and is set only as small letter-spaced caps with a tiny x-height.
   What separates Quicksand from either is the terminal: its strokes end in true
   semicircles, which is why it can carry a room whose every border is a
   gradient and whose every corner is a long radius. Neither of the others
   could, and nothing else here is round.

   Rubik is the text face. THE LATIBULUM IS THE COLLISION TO WATCH, because that
   room also sets a rounded sans -- but Nunito is a HUMANIST face with soft,
   nearly drawn terminals, paired there with a slab, and this is a GROTESQUE
   whose corners are eased and whose terminals are cut flat. Two warm-shaped
   text faces kept apart at the stroke, which is the only place they could be,
   the way IM Fell English and Cormorant Garamond are. The rooms themselves have
   nothing in common: one is brown lit plaster and this is green-black wet
   stone. See fonts/_sources.json. */
@font-face { font-family: 'Quicksand'; src: url('fonts/quicksand-700.woff2') format('woff2'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Quicksand'; src: url('fonts/quicksand-700.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Rubik';     src: url('fonts/rubik-400.woff2') format('woff2');     font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Rubik';     src: url('fonts/rubik-400.woff2') format('woff2');     font-weight: 500; font-style: normal; font-display: swap; }

/* The Foundry (§32). A STENCIL AND A WORKHORSE, which is the one pairing a room
   full of other people's typefaces is allowed: its own voice has to be quiet
   enough not to argue with what is in the window.

   Stardos Stencil sets the nameplate and the headings and nothing else. A
   stencil is THE ONE LETTERFORM ON THIS STREET THAT IS A HOLE RATHER THAN A
   MARK -- a shape cut out of metal so it can be used again, which is the whole
   idea of type -- and it is what gets painted on a workshop's crates and
   machinery. Anton is the street's other condensed display face and belongs to
   Club Chronic: that one is solid, on a black wall, pasted up under a marker.

   Work Sans is the prose, and it is a workhorse on purpose. Two files, two real
   weights -- where many of the families on the shelves in that room are
   variable fonts declared twice against one file, which is a different way of
   holding two real weights and NOT a lesser one. This comment used to say that
   was exactly why the bench offered a weight only where the bytes differ; the
   bytes were the wrong thing to ask about, since the browser instances the
   file's own axis at every declaration. The bench offers both, and
   tools/check-weights.py renders them to be sure they differ. See
   fonts/_sources.json. */
@font-face { font-family: 'Stardos Stencil'; src: url('fonts/stardos-stencil-700.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Work Sans';       src: url('fonts/work-sans-400.woff2') format('woff2');       font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Work Sans';       src: url('fonts/work-sans-600.woff2') format('woff2');       font-weight: 600; font-style: normal; font-display: swap; }

/* Danny the Street (§33). ONE FACE, AND IT IS THE ROAD'S OWN. Overpass is drawn
   from the lettering on American highway signs -- the FHWA series, which exists
   to be read at speed, from a long way off, by somebody who is doing something
   else at the time -- so it is the only family on this street whose whole
   reason for existing is being painted onto or bolted above a road. It sets the
   nameplate, the road legends and the dates, and nothing else.

   THE PROSE IN THAT ROOM IS THE BASE'S SPACE GROTESK, which makes it the only
   room here that sets a display face and no text face of its own. The Garden is
   the exact inverse -- two text faces and no display face at all, because a
   garden has labels and no signage -- and the pair of them is the whole range
   this street's type play has in it. Under the SIL Open Font License. See
   fonts/_sources.json. */
@font-face { font-family: 'Overpass'; src: url('fonts/overpass-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Overpass'; src: url('fonts/overpass-700.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

/* The Outskirts (§34). ONE FACE, AND THE SHARED BASE UNDER IT, which is Danny
   the Street's arrangement arriving in an area rather than a room -- and for a
   related reason, since both are about a road. Bowlby One SC is fat, rounded,
   slightly irregular small capitals, and it is here because that is what
   lettering looks like when somebody has painted it onto a board by hand, at
   size, to be read from a moving car. It sets the turning boards, the numbers
   and the h1. Everything else out there is the base's Space Grotesk.

   IT IS NOT THE CAMPGROUNDS' ALFA SLAB, and the difference is the whole
   separation between this street's two areas: a campground sign is ROUTED --
   cut into wood by a machine, even-weighted, official, maintained by somebody.
   A sign out here is PAINTED, by whoever owned the premises, once, a while ago.
   Under the SIL Open Font License. See fonts/_sources.json. */
@font-face { font-family: 'Bowlby One SC'; src: url('fonts/bowlby-one-sc-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }

/* Black Leather Lagoon (§35). A DRIPPING POSTER FACE AND A PLAIN GROTESQUE, and
   the rule between them is the one the Doomscroll already wrote down: Creepster
   sets the h1 and the bill and NOTHING ELSE. A drippy horror face is an access
   failure the moment it carries a sentence, and this is the room most likely to
   talk itself into one, because every inch of the subject matter is asking for
   it. Eighteen lines of it would be atmosphere paid for out of somebody else's
   ability to read the page.

   CHIVO IS A NORMAL-WIDTH GROTESQUE ON PURPOSE. The obvious face for the small
   print on a monster-movie bill is a CONDENSED gothic, and Club Chronic has set
   Anton three doors up since it opened -- so the obvious choice would have
   borrowed the face of the one room on this street that this one must not
   collapse into. Both are music rooms with a rack of records in them; the
   separation has to start at the type and hold all the way down. Chivo is drawn
   for newspaper text, which is what a cinema listing actually was. Under the
   SIL Open Font License. See fonts/_sources.json. */
@font-face { font-family: 'Creepster'; src: url('fonts/creepster-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Chivo'; src: url('fonts/chivo-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Chivo'; src: url('fonts/chivo-700.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

/* Sithen (§36). A THIN FACE AND A PLAIN ONE, which is a pairing this street has
   never had. Italiana is very light and very high-contrast, and it is here
   because EVERY OTHER DISPLAY FACE WE HOLD IS HEAVY -- a woodtype, a fat slab,
   a condensed grotesque, a pixel face, a dripping poster face, a rounded
   painted capital. The one room on the street that is cold, thin and made of
   frost and thorn had nothing to set itself in. It takes the h1 and the
   headings and nothing else.

   LITERATA IS DELIBERATELY WITHOUT ATMOSPHERE. It is a serif drawn for reading
   on screens, and this room is mostly a LIST OF RULES -- the argument being
   that rules of this kind are never written down plainly, so the one place they
   ARE written down plainly ought to look like it means it. A fae room is under
   constant pressure to set its body copy in something uncial and unreadable;
   that is the Doomscroll's blackletter problem arriving in a hill. Under the
   SIL Open Font License. See fonts/_sources.json. */
@font-face { font-family: 'Italiana'; src: url('fonts/italiana-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Literata'; src: url('fonts/literata-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Literata'; src: url('fonts/literata-700.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

/* Covenstead (§37). TWO PLAIN FACES AND NOTHING THAT SHOUTS, which is an
   argument rather than a shortage. The Discworld witches this room is partly
   built on are practical, domestic and unglamorous -- the work is boots, tea
   and going to the people nobody else goes to -- so a room about that which set
   itself in something gothic, uncial or carved would be contradicting its own
   page in the typeface. Petrona is a workhorse text serif with a little
   roughness left in it, pushed up to display size for the headings; Asap
   carries everything else and has no mystique in it at all.

   IT IS NOT THE GARDEN'S MOVE. That room sets no display face whatsoever
   because a garden has labels and no signage. This one HAS a display face and
   has deliberately chosen an ordinary one, which is a different claim: not
   "there is no signage here" but "the sign is the same as everybody else's".
   Under the SIL Open Font License. See fonts/_sources.json. */
@font-face { font-family: 'Petrona'; src: url('fonts/petrona-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Petrona'; src: url('fonts/petrona-700.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Asap'; src: url('fonts/asap-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Asap'; src: url('fonts/asap-700.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

/* Looming Rocks Amphitheatre (§38). A PAINTED SLAB AND A PLAIN GROTESQUE. Bevan
   has the weight of a board bolted to a rock face and repainted every few
   years, which is what the signage at an outdoor venue actually is. It is the
   FOURTH heavy slab this street holds and they are told apart by era and by
   making rather than by weight: the campgrounds' Alfa Slab One is ROUTED into
   wood by a machine and maintained by somebody; The Den's Ultra is a 1970s
   record sleeve; The Latibulum's Bree Serif is soft carpentry in a burrow. This
   one is paint on a board out in the weather.

   Archivo carries everything else and is deliberately ordinary, because most of
   this room is a RUNNING ORDER -- names, dates and runtimes, at small sizes, in
   the dark. A face with character in it would be fighting the rocks, which are
   the only thing here that is allowed to be monumental. Under the SIL Open Font
   License. See fonts/_sources.json. */
@font-face { font-family: 'Bevan'; src: url('fonts/bevan-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Archivo'; src: url('fonts/archivo-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Archivo'; src: url('fonts/archivo-700.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

/* Dead Tired Society (§40). A CHARTER FACE AND A FACE BUILT AGAINST FATIGUE.
   Sorts Mill Goudy sets the society's name and its headings and nothing at
   reading size: a revival of Goudy's Oldstyle, which reads like a founding
   charter, and that is the joke -- the grandest name on the street, set like an
   institution's, for a society whose members are lying on the floor. THE MOPERY
   IS THE COLLISION THE NAME INVITES, because Dead Poets Society is the film dark
   academia is named after, so the division is the stroke and the job: IM Fell
   is punched and battered and carries that room's whole text; this is smooth,
   soft and American, and is never set as a paragraph. Its italic is kept for the
   society's one line of Latin-flavoured pomp and for nothing else, because the
   yurt owns high-contrast italic serifs and this must not start looking like it.

   Lexend carries every word that is read. It was drawn to reduce visual stress
   and ease reading fatigue, which is the whole reason a room for the dead tired
   sets it: the face does some of the work so the reader does not have to. One
   variable file, declared twice against the weight axis. Under the SIL Open
   Font License. See fonts/_sources.json. */
@font-face { font-family: 'Sorts Mill Goudy'; src: url('fonts/sorts-mill-goudy-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Sorts Mill Goudy'; src: url('fonts/sorts-mill-goudy-400-italic.woff2') format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Lexend'; src: url('fonts/lexend-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Lexend'; src: url('fonts/lexend-400.woff2') format('woff2'); font-weight: 600; font-style: normal; font-display: swap; }

/* Laughingstock (§41). A SIGN-WRITER'S SCRIPT AND A GROTESQUE MADE OF ODDMENTS.
   Yellowtail is the letterform a neon tube is bent into, and it sets the club's
   name, the comics' names and nothing you have to read: a script carrying a
   sentence is an access failure wearing atmosphere, which is the Doomscroll's
   blackletter rule arriving at a comedy club, where every inch of the subject
   is asking for a script. Monoton is the Chappell's and Shrikhand is the
   dancefloor's; this is neither a tube face nor a fat one, it is a HAND, which
   is what a neon sign is copied from. Under the Apache License 2.0.
   Bricolage Grotesque carries everything that is read. Mathieu Triay drew it
   out of the mismatched grotesques in old French specimen books, and bricolage
   is making do with whatever is to hand -- which is most of a disabled
   person's day and a good deal of what that room's comedy is about. One
   variable file, declared twice against the weight axis. Under the SIL Open
   Font License. See fonts/_sources.json. */
@font-face { font-family: 'Yellowtail'; src: url('fonts/yellowtail-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Bricolage Grotesque'; src: url('fonts/bricolage-grotesque-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Bricolage Grotesque'; src: url('fonts/bricolage-grotesque-400.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

/* The Lightbulb Picture House (§42). A FASCIA FACE AND AN EVEN ONE. Limelight
   is the Art Deco display letter cut into a 1930s picture house's front, and it
   sets the house's name, the screen numbers, the headings and the running
   numbers on the rack -- nothing at reading size. It is not the Chappell's
   Monoton, which is a neon tube, nor Laughingstock's script, which is a sign-
   writer's hand: it is carved. Outfit carries everything that is read: open,
   even and unfussy, because a relaxed screening is for people who came to
   understand something and the face should not be one more thing to get past.
   One variable file, declared twice. Both under the SIL Open Font License. See
   fonts/_sources.json. */
@font-face { font-family: 'Limelight'; src: url('fonts/limelight-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Outfit'; src: url('fonts/outfit-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Outfit'; src: url('fonts/outfit-400.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

/* Dance, Punks (§43). A WIDE FACE AND A PLAIN ONE. Unbounded sets the name, the
   headings and the channel labels: very wide, round-shouldered and heavy, which
   is what gets printed on a wristband or a headset's own casing, and nothing at
   reading size. It is not Club Chronic's condensed face -- a flyer crams a bill
   onto a sheet, and this is the opposite shape: a lot of room, and the letters
   taking it. Manrope carries everything that is read. One variable file each,
   declared at both weights, as Outfit and Lexend already are here. Both under
   the SIL Open Font License. See fonts/_sources.json. */
@font-face { font-family: 'Unbounded'; src: url('fonts/unbounded-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Unbounded'; src: url('fonts/unbounded-400.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Manrope'; src: url('fonts/manrope-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Manrope'; src: url('fonts/manrope-400.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

/* The Small Hours (§44). A ROADSIDE SIGN AND A MENU BOARD. Righteous is the
   rounded, streamlined lettering bolted along the top of a mid-century diner,
   and it sets the name, the sign and the headings, nothing at reading size.
   Libre Franklin carries everything that is read: a plain American gothic, the
   letter a menu board and a till receipt have always been set in. Righteous is
   one weight; Libre Franklin is one variable file declared at two. Both under
   the SIL Open Font License. See fonts/_sources.json. */
@font-face { font-family: 'Righteous'; src: url('fonts/righteous-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Libre Franklin'; src: url('fonts/libre-franklin-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Libre Franklin'; src: url('fonts/libre-franklin-400.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

/* The Repeater (§45). A CALL SIGN AND A MANUAL. Syncopate is a wide geometric
   face drawn in capitals only, which is how a call sign is printed across the
   top of the card radio operators send each other to confirm a contact; it sets
   the name, the headings and the call on each card, nothing at reading size.
   IBM Plex Sans carries everything that is read: an engineer's sans, the letter
   of a well-made equipment manual. Syncopate is two static files, under the
   Apache License 2.0 -- read off its own record, not assumed; the first draft of
   this comment said OFL. Plex Sans is one variable file declared at two weights,
   under the SIL Open Font License. See fonts/_sources.json. */
@font-face { font-family: 'Syncopate'; src: url('fonts/syncopate-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Syncopate'; src: url('fonts/syncopate-700.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'IBM Plex Sans'; src: url('fonts/ibm-plex-sans-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'IBM Plex Sans'; src: url('fonts/ibm-plex-sans-400.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

/* Nothing For Sale (§46). A MARKER ON CARDBOARD AND A PLAIN BODY. Patrick Hand
   is the neat capitals somebody writes on a cardboard sign propped against a
   table, and it sets the name, the headings and the sign on each table: short
   labels, never a sentence, because a passage in a handwriting face is an
   access failure (the Zibaldone's rule about Kalam). It is not Club Chronic's
   marker, which is scrawled over a wall of paper; this is careful, one sign
   each. Figtree carries everything that is read. Patrick Hand is one weight;
   Figtree is one variable file declared at two. Both under the SIL Open Font
   License, read off their records rather than assumed. See fonts/_sources.json. */
@font-face { font-family: 'Patrick Hand'; src: url('fonts/patrick-hand-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Figtree'; src: url('fonts/figtree-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Figtree'; src: url('fonts/figtree-400.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

/* Samefood Cafe (§47). A FACE CUT FROM ONE MOULD AND A FACE WITH NOTHING HIDDEN
   IN IT. Fredoka sets the cafe's name, its headings, the specials line and the
   names on the regulars' trays, and nothing at reading size: round, fat, soft,
   and every stroke ends in the same curve, which is what a melamine plate looks
   like when every one of them came out of the same mould. It is NOT the
   Healing Checkpoint's rounded sans (Rubik is squared-off and game-like) and it
   is not a hand -- nothing in this room was written by anybody in a hurry.

   Inclusive Sans carries every word that is read. Olivia King drew it for
   legibility, so that no letter can be taken for another -- a capital I, a
   lower l and a 1 all differ -- which is this room's one rule arriving at the
   level of the alphabet: nothing on the plate is hidden in anything else, and
   nothing on the page is either. ITS ITALIC IS NOT SHIPPED: it is a sloped roman,
   the same drawings leaned, and check-weights.py refused it as a style that does
   nothing -- correctly, since a slant has the roman's ink and advance. So the
   room sets titles upright and turns font-synthesis off, rather than letting the
   browser invent a slant the Foundry would then be lying about. Both faces are
   one variable file declared against more than one weight. Under the SIL Open Font License. See fonts/_sources.json. */
@font-face { font-family: 'Fredoka'; src: url('fonts/fredoka-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Fredoka'; src: url('fonts/fredoka-400.woff2') format('woff2'); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: 'Inclusive Sans'; src: url('fonts/inclusive-sans-400.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Inclusive Sans'; src: url('fonts/inclusive-sans-400.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

/* §2 ── Ground rules ─────────────────────────────────────────────────────────
   Deliberately thin. Anything that belongs to a room belongs in that room. */

:root {
  --ink:    #15121f;   --ink-2:  #241d33;   --ink-3:  #4a3f67;
  --pink:   #FF2D95;   --hot:    #FF3D9A;   --orange: #FF8A00;
  --yellow: #FFE100;   --green:  #22E06A;   --cyan:   #00D4FF;
  --violet: #AC5BFF;   --red:    #C4002B;
  --blue:   #1770C2;   --violet-deep: #7B28DD;
  --cream:  #FFF3E6;   --paper:  #EDEAE2;   --chalk:  #c8bfe0;
  --sans: 'Space Grotesk', ui-sans-serif, system-ui, sans-serif;

  /* The Chappell (§12). Its own five, because a subroom that borrowed the
     dancefloor's palette would be the harmonising instinct getting in through
     the side door it was told not to use. --nave is the ground; the glass
     colours are decorative only and never carry text. */
  --nave: #1A0A33;  --niche: #170A2B;  --glass: #0E0520;  --leaf: #F0C453;
  --ruby: #8B0E33;  --sapphire: #14406E;  --emerald: #0E5C3A;  --amethyst: #5B2A8F;

  /* The Campgrounds (§13). Cold dusk: spruce dark, bone, lichen, one moon. The
     street is night-black under neon; this is night-blue under nothing. */
  --dusk: #0E1A18;  --spruce: #13241F;  --bark: #2A3A31;
  --bone: #EFE9DC;  --lichen: #C6D2C4;  --moss: #8FAE88;  --moon: #E7D9A8;

  /* The Faery Yurt (§14), Helen's, and warm on purpose where the campground it
     is pitched on is cold — you walk in out of the night air. --tallow-3 is the
     ONE value of hers this file changed: her #8a7462 measured 4.30 on the tent
     ground and 3.61 on the canvas, and it carries the eyebrow, the shelf note,
     the window hint, the pet cards and the footer. See check-contrast.py. */
  --hearth: #150F0E;  --tent: #1B1310;  --canvas: #241A16;  --canvas-2: #2C1F19;
  --timber: #3A2A20;  --tallow: #F2E6D4;  --tallow-2: #C2AC91;  --tallow-3: #A4907B;
  --ember: #E0904A;   --ember-2: #F2B673;  --ivy: #6D8A56;  --ivy-2: #38491F;
  --candle: #E9C874;

  /* The Arcade (§15). Coin-op at midnight, and the only room here lit by a
     screen rather than by a sky, a candle or a strip light. --crt-lit is not a
     colour anybody chose: it is what --crt becomes under the scanlines, and it
     is the ground the playfield's own type actually sits on. The cabinet's
     spill over the carpet makes a second one. Both are in check-contrast.py,
     because a flat background is never what the text is on. */
  --carpet: #160A26;  --cab: #241038;  --crt: #06171C;
  --coin: #FFC21A;  --mint: #4BF0C6;  --zap: #FF6BE4;
  --tube: #B9C6D6;  --tube-2: #9AA7BA;

  /* The Arcade's second screen: a kelp bay, and the only water on this street.
     Two grounds, because the shoal is lighter than the deep, and everything is
     measured against what the scanline makes of the LIGHTER one -- #133947 --
     since that is the harder of the two. --pelt is the otter you steer and is
     held to the body threshold rather than the 3:1 graphics one: a thing you
     drive is not decoration. See check-contrast.py. */
  --bay: #06202A;  --shoal: #0A3240;
  --pelt: #D29A6B;  --whiskers: #F0D6B4;
  --kelp: #6FB050;  --kelp-2: #7ABF5A;
  --fishy: #CFE2F2;  --cobble: #A9BAC6;  --shelly: #E8D6B6;  --urchin: #B79AE0;

  /* The Arcade's third screen: a shore under overcast, and the only PALE screen
     in the room. Which is a different contrast problem from the other two --
     everything on a shingle beach is a mid-tone, including the shingle, so the
     objects here are carried by their OUTLINE rather than by their fill. That
     is what --pen-dark is: it draws every pebble, every penguin and every nest,
     and it is what check-contrast.py measures against the three grounds. A fill
     is then checked against the outline that surrounds it. See the note there;
     it is the honest reading of WCAG 1.4.11, which asks about adjacent colours
     rather than about fills. */
  /* The Latibulum (§16). Under the hill: an earth ground with a lamplit
     PLASTER wall on it, which is the one structural difference that stops a
     warm brown burrow from becoming the Faery Yurt. The yurt reads cream on
     dark all the way down; here almost every word sits dark on a lit wall, and
     the dark ground is what is left over around it. --glow-lamp is not a colour
     anybody chose: it is --lamp at .16 over --loam, the brightest the lamp pool
     gets, and it is the ground the copy on the earth actually sits on.
     check-contrast.py holds every ink against it as well as against the flat
     colour, the same way the Chappell is held against its rose window. */
  --loam: #241B12;  --burrow: #2E2317;  --recess: #17120C;
  --plaster: #E8D8BC;  --plaster-2: #D8C5A3;
  --umber: #3A2A1C;  --umber-2: #5A4230;
  --oat: #EFE4D2;  --oat-2: #C9B99F;
  --lamp: #F0C36B;  --door: #2F5A3C;  --rust: #8A3A1E;
  --beam: #7A5330;  --brass: #E3BB6A;

  --sky: #D6DFE4;  --sea: #8FA9B8;  --shingle: #B4AEA5;
  --pen-dark: #1E2833;  --pen-light: #F7FAFB;  --beak: #E07B1F;
  /* WHAT IS LEFT OF A PALETTE THE ROOM OUTGREW. The pebbling cabinet once kept
     its six carryable things here; then the room decided every fill had to
     clear 4.5 against the outline that draws it, which squeezed them all light,
     and the new values went into pebbling.js beside the shapes they fill. The
     dark originals sat on in :root afterwards, declared and painted nowhere —
     a palette that looked like the source of truth and had not been true since.
     They are gone. The colours the game actually paints are every one of them
     in check-contrast.py, measured against that outline.
     --peb-press is the survivor, and it was misnamed: it is the START button's
     hover ground, NOT the sea glass, which is a different green in the game. */
  --peb-press: #1F6B55;

  /* The Jungle Room (§17). Wet, warm, closed over the top. The campgrounds is
     night-BLUE under nothing; this is night-GREEN under a roof of leaves, and
     that difference is the whole reason the two can stand on the same street.
     --shaft is not a colour anybody chose: it is --sun at .12 over --canopy,
     which is the brightest a light shaft gets, and it is the ground every word
     on the forest floor actually sits on. --shaft-2 is the same light falling
     on an --understory panel. Both are in check-contrast.py, because the flat
     background is never what the type is on. --palm draws leaves and nothing
     else, so it is held to the 3:1 graphics bar rather than the body one. */
  --canopy: #06180F;  --understory: #0B2415;  --buttress: #143A24;  --litter: #1C2A14;
  --daylight: #EDF6E2;  --sap: #BFD6AC;
  --palm: #57A05C;  --heliconia: #FF8557;  --sun: #F5D06B;  --orchid: #E98AD2;

  /* The Den (§18). Graceland's Jungle Room, which is a den panelled in dark
     wood with a bright green shag carpet in it — and THE GREEN IS THE LIGHT
     HERE rather than the dark, which is the one structural thing keeping this
     off its own parent. Upstairs the green IS the darkness and the light comes
     down from above; down here the room is brown, the carpet is the brightest
     thing in it, and it is underfoot. --glow-lamp-den is nobody's choice
     either: --tiki at .14 over the panelling, the brightest a low lamp gets,
     and every ink on the wall is held against it. --rum and --stone carry no
     text; they are the red corner lamp and the fieldstone, and they are
     measured at the graphics bar because a room is not decoration. */
  --panel: #241508;  --teak: #3C2412;  --stone: #A06A4E;
  --shag: #63B441;  --shag-2: #57A438;
  --coconut: #F6ECD9;  --rattan: #CBB392;
  --cocoa: #1E1107;  --cocoa-2: #35210F;
  --tiki: #F0B040;  --jade: #37C9A4;  --rum: #F2705A;

  /* The Solarpunk Hermitage (§19). NAMES NOT SHARED WITH ANYBODY: --sprout and
     --daysky rather than the obvious --leaf and --sky, because both of those
     were ALREADY DECLARED in this block -- --leaf is The Chappell's gold leaf
     and --sky is the pebbling shore's overcast. A custom property declared
     twice in one :root is last-wins and silent, so for as long as this room
     used those names it was repainting a gold room green and a grey sky blue,
     in two rooms nobody was looking at. check-classes.py refuses a duplicate
     now. THE FIRST DAYLIT ROOM ON THIS STREET, and
     that is the whole of its separation from everything else here: every other
     world is a dark ground with light put on it, and this one is a lit ground
     with things standing in it. --noon is sunlight on a lime-plastered wall.
     --furrow is the ink, a green-black rather than a black, because nothing
     outdoors is actually black.

     AND THE CAVE INSIDE IT IS THE HARD PART. A deep red reading room is the
     fourth warm enclosed space on this street, after the yurt, the burrow and
     the den, and the three of those are each lit by ONE flickering source in
     the dark. This one is EVENLY LIT — that is what the panels on the roof are
     for — and the candles are decoration rather than the supply. It is also
     made of textile where the others are made of canvas, earth and panelling:
     no wood, no carpentry, no straight edge but the shelves. --velvet-lit is
     nobody's choice: it is --wick at .05 over the velvet, the brightest the
     even light makes it, and every ink down there is held against it as well
     as against the flat colour. See check-contrast.py. */
  --noon: #F7F3E6;  --noon-2: #ECE6D2;  --daysky: #BCDDEA;  --daysky-2: #E4F0F1;
  --furrow: #16291C;  --furrow-2: #34483A;
  --sprout: #2C6B45;  --sprout-2: #1D4D30;  --bloom: #B5760A;
  --cedar: #9A6A3C;  --cell: #12323C;
  /* Club Chronic (§20). A BLACK WALL WITH PAPER STUCK TO IT, which is the one
     shape nothing else here has: every other room is a ground with things
     drawn on it, and this is a ground with things GLUED on, overlapping, in
     layers, going back years. --brick is the wall; --paste is flyer stock and
     is the room's second ground, carrying dark type the way the Latibulum's
     plaster does — but that burrow is a lit wall you stand inside and this is
     a hundred small rectangles pasted onto a dark one, which is a collage and
     not a room. --marker is the pen that went over the top of all of it, and
     is the only colour here that is not either black or paper.
     --stage-lit is nobody's choice: --marker at .07 over --brick, which is the
     wash the one working bulb puts on the wall, and what the type near the
     stage actually sits on. */
  --brick: #131113;  --brick-2: #1E1B1E;  --grime: #2A262A;
  --paste: #E9E4D6;  --paste-2: #CFC8B6;  --newsprint: #A8A296;
  --marker: #D8FF3A;  --siren: #FF5A5A;  --bootblack: #0B0A0B;  --staple: #6E6A60;
  --stage-lit: #212216;

  --velvet: #4A1220;  --velvet-2: #5E1A2B;  --velvet-3: #380C18;
  /* The campfire's furniture. THE BAGS ARE BRIGHT AND THEREFORE CANNOT CARRY
     THEMSELVES: every one of them measured under 2.3 against the rug, which is
     a chair you cannot pick out of the carpet. So EVERY OBJECT IN THIS SCENE IS
     CARRIED BY ITS OUTLINE — --furrow, against the rug on one side and against
     the fill on the other — which is the pebbling cabinet's reading of WCAG
     1.4.11 arriving in a room with furniture in it. The one exception is the
     television, which is dark enough to separate from the rug on its own and
     would only be muddied by a dark line around it. */
  --turf: #3F8E4C;
  /* The three chairs' colours are NOT here: each bag carries its own hex
     inline, out of data/hermitage.json, and `.bag` reads `var(--bag)`
     singular, which only ever exists on the element. Three --bag-N
     properties sat here referenced by nothing until 2026-09-21, and they
     were lighter than the colours the page uses — which is how
     check-contrast.py came to be testing a palette that has never
     rendered, and passing. A dead declaration is not harmless when
     something else is checking against it. */
  --bakelite: #2A2621;  --bakelite-2: #7E7466;
  --bigscreen-off: #0C1110;  --bigscreen-lit: #F1EFE4;  --bigscreen-dim: #A9B4AB;
  --wick: #F6E8D0;  --wick-2: #DCC49C;  --gilt: #E9C270;

  /* The Pebble Board (§21). TWO PALETTES IN ONE ROOM ON PURPOSE, and the seam
     between them is the whole object: the street's night on the outside of the
     glass, and NORAH HOBBS'S PAPER on the inside, lit by one lamp. The fixture
     is ours and stays across every edition; the paper is hers and is replaced
     whole. Her values are carried over unmeasured-by-us and then measured --
     every one clears the body threshold, and the only pair that does not is
     the cover slug, which is 18px of Gloria Hallelujah at 4.41 and is
     registered as large text with its size written into the entry rather than
     nudged darker. See the note beside it in check-contrast.py. */
  --pbnight: #14120F;  --pbframe: #2E4640;  --pbframe-lit: #486A61;
  --pbcork: #6B4F35;   --pblamp: #F6E3B8;   --pbchalk: #C9C2B4;
  --pbplate: #B99B55;  --pbplate-ink: #1B1509;
  --pbpaper: #EDE3CC;  --pbpaper-deep: #E3D6B8;  --pbcard: #FBF8F1;
  --pbink: #2B2621;    --pbink-soft: #574F46;    --pbline: rgba(43,38,33,0.16);
  /* #8A6D2F until 2026-09-21, which measured 4.41 on --pbgold-bg and was the
     closest thing on this street to a pass: nine hundredths short at 18px,
     and invisible to a pair list that had rounded it the friendly way.
     Darkened until it clears, hue and saturation untouched. */
  --pbgold: #866A2E;   --pbgold-bg: #FFF3D0;
  --pbmem: #322D27;    --pbmem-card: #3D3730;    --pbmem-ink: #DED6C6;
  --pbmem-head: #F3EDDF;  --pbmem-credit: #C7BEB0;
  --pbmem-gold: #C9A227;  --pbmem-link: #D4AF37;

  /* The Mopery (§22). A COLD ROOM WITH WARM POINTS IN IT, and that sentence is
     the entire separation from the four warm enclosed rooms this street
     already has. The Faery Yurt, The Latibulum, The Den and the Hermitage's
     cave are each lit THROUGHOUT by one warm source; the light reaches the
     walls and the walls go amber. Here the ground is blue-black stone all the
     way to the skirting and the candlelight stops about an inch from each
     wick. Dark academia is not cosy. It is a cold building somebody has been
     let into after hours, and if this palette ever warms up at the edges it
     has turned into the yurt.
     --mop-flame is the only warm value that touches anything, and mostly it
     touches nothing: see ORNAMENT in check-contrast.py for the wax and the
     halo, which carry no words. */
  --mop-night: #10141A;  --mop-stone: #1A2027;  --mop-shelf: #232B34;  --mop-deep: #080B0E;
  --mop-bone: #EAE4D6;   --mop-dim: #A7AFB9;    --mop-gilt: #D3AB58;   --mop-flame: #F3B95F;
  --mop-wax: #6A4A2A;    --mop-rule: #3A434E;
  /* Nine spines, nine measured pairs. A shelf where one title is a guess is a
     shelf with an unreadable book on it, and the reader cannot tell which. */
  --mop-oxblood: #6B2028;  --mop-sugar: #D8BCC6;  --mop-inkspine: #232A42;
  --mop-graphite: #474D55; --mop-tar: #15181C;    --mop-wine: #5C2033;
  --mop-vellum: #D8CBA6;   --mop-dust: #8C8271;   --mop-moss: #44523D;

  /* The Oracle Deck (§23), behind the Mopery's parlour. ASH AND VERMILION, and
     not one blue in it, because the library it is kept in is blue-black all
     over and a subroom that borrowed its parent's ground would be the oldest
     mistake on this street wearing its newest costume. The other reason is the
     art: every card front is a warm paper engraving, so the room around them
     is the one cold thing and the prints are the only paper in it.
     NO GOLD AND NO INDIGO: that pair is The Chappell's, one subroom over. */
  --orc-slate: #23201E;  --orc-deep: #131110;  --orc-cut: #F2EDE4;
  --orc-dim: #B0A69B;    --orc-red: #E8724A;   --orc-brass: #B99154;
  --orc-edge: #3A342F;

  /* The Doomscroll (§24). THE ONLY PALE ROOM ON THIS SIDE OF THE STREET and the
     second pale room on the site, which is the whole reason it can sit behind a
     library that is nearly black: you come up out of the dark and somebody
     hands you a paper. THE ZINE TABLE IS THE COLLISION TO WATCH, because that
     is also ink on paper -- and it is a photocopier's stark white with pure
     black on it, cut up with scissors and scattered. This is foxed newsprint,
     warm and grey, in one unbroken roll with nothing cut and nothing at an
     angle, lying on a dark desk. If this paper ever goes white, the two rooms
     have become one room.
     --dsc-rule carries no text and is measured in ORNAMENT. */
  --dsc-desk: #211D18;   --dsc-paper: #DCD7CC;  --dsc-paper-2: #CFC8BA;
  --dsc-ink: #1A1714;    --dsc-ink-2: #4A423A;  --dsc-rule: #8A8073;
  --dsc-red: #8C1D18;    --dsc-bone: #EAE4D6;

  /* Swaying Sweetgrass (§25), pitch 02 in the campgrounds. A MEADOW LIT FROM
     BEHIND, which is the one thing keeping it out of the warm-enclosed family
     it otherwise joins — the Faery Yurt, The Latibulum, The Den, the
     Hermitage's cave and the Mopery's shelves are every one of them lit by a
     flame you could put your hand over. THIS LIGHT IS THE SUN, LOW, A HUNDRED
     FEET AWAY, AND BEHIND THE GRASS. Nothing in here is lit from the front:
     the blades glow because the light is coming THROUGH them, so the greens
     go yellow and the ground stays dark. That is also what keeps it off the
     Jungle Room, where the light falls DOWN through a roof and lands in
     patches, and off the campground it is pitched on, which is night-blue
     with no light in it at all.

     --sedge and --stem are the drawn blades and carry no words; both are
     measured in ORNAMENT with what they came out at, because the Jungle
     Room's canopy taught this file that a plant nobody can make out is not a
     plant. --band is the purple-white where the stems meet the ground, which
     is Kimmerer's own description and the only cool colour in the room — it
     sits at the FOOT of things, never at the top, because that is where it is
     on the plant. */
  --soil: #141A0C;       --shade: #1D2612;      --straw: #EFE6C6;
  --awn: #C4C08E;        --glow: #D7E06A;       --seed: #E3C85C;
  --band: #D9C6E8;       --sedge: #8FA05A;      --stem: #4E6B2E;

  /* THE ADVENTURER'S GUILD (§26). THE ONE TIDY ROOM, and every value here is
     doing that one job. Manila, printer's ink, hairline rules, a vermilion
     stamp and a clerk's blue: the palette of a form rather than of a place.

     IT IS THE SECOND DAYLIT-LOOKING ROOM AND IT HAS NO LIGHT IN IT AT ALL,
     which is the distinction that keeps it off the Solarpunk Hermitage. That
     cabin has a SUN in it -- a direction, a warmth, shadows falling away from
     it, sunflowers. This room is lit the way a photocopy of a document is lit:
     evenly, from nowhere, with nothing casting anything. So there is no
     gradient in this section, no shadow in it, no rounded corner in it and no
     ambient layer at any dial setting. A form does not move; if it did you
     would be worried about it. If anything in here ever picks up a glow, a
     soft edge or a drop shadow, the room has stopped being a printed sheet and
     started being a place, and the hermitage already is one.

     IT IS ALSO THE SECOND PALE GROUND ON A DARK STREET, and the Doomscroll is
     the one to watch. That room is FOXED NEWSPRINT -- warm, grey, one unbroken
     roll with nothing cut and nothing rotated, lying on a dark desk you can see
     the edges of. This is MANILA, ruled: boxes, columns, a class in the margin,
     a stamp. The doomscroll has no rule on it anywhere and this room is made of
     them. If this paper ever goes grey, the two have become one.

     --gu-rule carries no text and is in check-contrast.py's ORNAMENT at 2.22,
     which is what a hairline printed rule measures and is the whole reason it
     reads as a hairline. --gu-stamp and --gu-file are both held against both
     papers, because the alternating cells mean either can sit on either. */
  --gu-paper: #E8E1CF;   --gu-paper-2: #D8CFB6; --gu-ink: #1E241F;
  --gu-ink-2: #4C5349;   --gu-rule: #A2977E;    --gu-stamp: #9E2B1B;
  --gu-file: #1C3B6E;

  /* The Feed (§27). A dark concourse with lit machines standing in it, and the
     one room here whose FURNITURE IS DARKER THAN THE ROOM: --fd-hall is the
     concourse and --fd-enamel is a board's carcass, and the carcass is the
     darkest thing in the hall and the brightest thing in it at once -- dead
     enamel with a light behind the letters. Every other dark room on this
     street puts furniture lighter than its ground.

     --fd-girder IS AN OBJECT'S OUTLINE AND IS MEASURED AS ONE, on all four
     grounds, the Hermitage's chairs rule. It was a much darker grey first and
     measured 1.02 against the pool of light the boards throw on the floor,
     which is to say the board's own edge vanished exactly where the light was
     brightest. It is 3.07 there now and clears 3:1 on the hall, the enamel and
     a flap as well.

     A FLAP IS TWO HALVES, WHICH IS WHY THERE ARE TWO FLAP COLOURS. The first
     version drew the seam as one near-black hairline straight through the
     middle of the letters -- which is what the real machine does, and which on
     the share card read as a STRIKETHROUGH: the row lettered NEVER looked
     deleted rather than printed, at the size a card is actually seen. So the
     lower half of every flap is its own slightly darker face (--fd-flap-lo)
     with a lit fold along its top edge (--fd-fold), which is both what a folded
     flap looks like and a thing nobody can mistake for a line through a word.
     Both halves are grounds and both are measured; --fd-fold carries no text
     and is in check-contrast.py's ORNAMENT with its numbers. --fd-split is the
     hard dark line between the flaps in this room's DOOR awning on the street,
     the one place a flat seam still reads as a seam. */
  --fd-hall: #1D2124;    --fd-enamel: #0B0E10;  --fd-flap: #141A1D;
  --fd-flap-lo: #0F1417; --fd-fold: #313A3F;
  --fd-girder: #6B7479;  --fd-split: #04070A;
  --fd-lamp: #EFEAE0;    --fd-dim: #9AA4A9;     --fd-amber: #F0B542;
  --fd-signal: #63CBA2;

  /* The Garden (§28). MIDDAY, AND THE LIGHT HAS BEEN THROUGH A LEAF ON ITS WAY
     DOWN, which is the whole of its separation from the two rooms on this
     street it would otherwise collapse into.

       · THE SOLARPUNK HERMITAGE is the other room the sun is up in, and its
         light LANDS ON A WALL: --noon is warm lime plaster, everything stands
         in front of it, and the shadows fall sideways off a low sun. There is
         no wall here and nothing to stand in front of. The sun is overhead and
         it has come down through foliage, so every pale surface in this room is
         tinted GREEN and every shadow is small, hard and directly underneath
         the thing that made it.
       · THE ADVENTURER'S GUILD is the other pale ground, and it has no light
         source in it at all -- lit like a photocopy, evenly, from nowhere, with
         nothing casting anything. This room is nothing but light.

     AND THE PALEST THING HERE IS NOT THE GROUND. --gd-day is the path you are
     standing on and --gd-board is a limewashed plank laid on it, BRIGHTER than
     the ground it sits on -- where the hermitage's panels are darker than its
     plaster and the guild's are darker than its manila. A board separates from
     the path by 1.07, which is to say not at all, so it is carried by its edge
     and by the hard shadow under it, the way every object in the Hermitage's
     campfire is carried by its outline.

     --gd-dapple IS PAINTED AND NOT LAYERED, which makes this the one room on
     the street with no composite ground in it. The Chappell has a rose window
     over its type, the burrow a lamp pool, the arcade a scanline, the meadow a
     sun wash: in every one of those the colour the text actually sits on is a
     thing nobody declared, and check-contrast.py has to reconstruct it. Leaf
     shadow is an opaque colour here -- the second ground, measured as itself,
     with nothing to guess about.

     --gd-edge never fills anything and --gd-dapple never draws a line.
     --gd-leaf-2 is the lit face of a drawn leaf and is held to the 3:1 graphics
     bar on all three grounds, the Jungle Room's canopy rule: a leaf nobody can
     make out is not a leaf. --gd-bloom is the one flower colour and started at
     #C2470E, which measured 4.12 on a limewashed board -- a garden's brightest
     colour failing on its brightest surface, found before it shipped rather
     than after. GD- PREFIXED THROUGHOUT, because `leaf` is already The
     Chappell's gold, and `shade`, `bloom` and `day` are the kind of plain word
     a stylesheet fills up with: a custom property declared twice in one :root
     is last-wins and silent, so this is the --leaf collision pre-empted rather
     than discovered. */
  --gd-day: #F2F7E9;    --gd-dapple: #EBF2DF;  --gd-board: #FCFDF6;
  --gd-edge: #9DB183;
  --gd-loam: #2B2013;   --gd-loam-2: #5A462C;
  --gd-leaf: #2F6B1E;   --gd-leaf-2: #55893A;  --gd-bloom: #A8390B;

  /* The Zibaldone (§29). A BOOK LYING ON A DESK, LIT FROM ONE SIDE, and that
     sentence is the whole of its separation from every other paper room on
     this street, and there is already a great deal of ink on paper here.

       · THE MOPERY is a cold BUILDING you are let into after hours: blue-black
         stone walls, an institution's books, and type that was PUNCHED into
         the page by a press. You stand up in it. This is one object at arm's
         length, seen from directly above, warm, and written into by hand --
         and it is nobody's property but the keeper's. Printed against written
         is the separation, and it holds at the stroke rather than at the
         palette, which is the only place these two could ever have been kept
         apart.
       · THE DOOMSCROLL is the closest call, because it is also pale paper on a
         dark desk. It is ONE UNBROKEN ROLL -- machine-set, nothing cut,
         nothing rotated, cold grey newsprint. This is BOUND LEAVES: --zb-gutter
         is a fold, there is a verso and a recto, and everything on it was
         pasted down at whatever angle the hand was holding. Newsprint is grey
         and cheap; laid paper is warm and has a tooth. If this paper ever goes
         grey the two rooms have become one.
       · THE ZINE TABLE is photocopied -- stark white, pure black, cut with
         scissors, made in a hundred copies to be given away. This is ONE COPY,
         warm, and nothing in it was cut out: it was written in. A zine is for
         strangers and a commonplace book is for its keeper.
       · THE GARDEN and THE ADVENTURER'S GUILD are the other pale grounds. The
         garden's light came down through leaves, so everything in it is tinted
         green and every shadow is small, hard and directly underneath. The
         guild has NO LIGHT SOURCE AT ALL and casts nothing. Here the light
         RAKES ACROSS FROM ONE SIDE at desk height -- which is why the paper has
         a tooth you can see, why the fold has a shadow in it, and why this is
         the only room on the street lit by something in the room with you.

     ZB- PREFIXED THROUGHOUT, on the Garden's precedent rather than after this
     room's own accident: `desk`, `paper`, `tape`, `iron` and `gutter` are
     exactly the plain words a stylesheet fills up with, and a custom property
     declared twice in one :root is last-wins and silent -- which is how a gold
     room once rendered green. --zb-tape and --zb-gutter never carry text and
     are in check-contrast.py's ORNAMENT list with their measurements. Every
     ink is held against BOTH papers, because a leaf is a slip laid on a page
     and half the type in the room sits on the slip. */
  --zb-desk: #2A211A;   --zb-desk-2: #3A2E24;
  --zb-laid: #F2E8D5;   --zb-laid-2: #E9DCC3;  --zb-gutter: #C9B693;
  --zb-oak: #3A2A18;    --zb-iron: #2B3348;    --zb-aniline: #5B2E6E;
  --zb-rubric: #8C2B18; --zb-pencil: #635A4B;  --zb-tape: #DFCDA8;

  /* The Rabbit Hole (§30). A SHAFT, LOOKING BACK UP AT THE DAYLIGHT YOU CAME
     IN BY, and the separation from its neighbours is physical rather than a
     matter of taste, because two of them are very close indeed.

       · THE LATIBULUM IS THE HARDEST COLLAPSE ON THIS STREET SO FAR, harder
         than any subroom, because these two rooms are LITERALLY both holes in
         the ground -- and every earlier version of this temptation had a
         structural excuse attached (it is only a subroom; an area should look
         like an area; they are both cosy). This one needs no excuse at all:
         the two rooms have the same floor plan. What keeps them apart is that
         the burrow is somewhere you ARRIVE and the hole is somewhere you keep
         GOING. The burrow has a floor, walls, furniture, a lamp at knee
         height and a shelf, it is horizontal, it is at rest, and almost every
         word in it sits DARK ON LIT PLASTER. This has no floor, no walls you
         could lean on and no furniture whatsoever; it is vertical, the light
         is ABOVE AND BEHIND YOU and there is less of it the further down you
         read, and every word is PALE ON THE DARK. The burrow is earth and is
         BROWN. THERE IS NO BROWN IN HERE AT ALL -- it is wet slate -- and if
         any of these greys ever warms up, the two rooms have become one and it
         is this one that moves.
       · THE MOPERY is cold blue-black stone too, and is the other close call.
         It is a BUILDING: candles the length of every top shelf, a floor, a
         ceiling, an institution's books, and you stand up in it. There is no
         flame anywhere in this room and no building around it. Its only light
         source is DAYLIGHT, arriving from one end of a hole, and a candle lights
         a foot of a large room while this lights less of one the further in
         you go.
       · THE DOOMSCROLL is the closest on MOTION rather than on colour: both
         rooms are long vertical scrolls and both are about going down. That one
         is PALE -- one unbroken roll of foxed newsprint -- and its
         downwardness is dread. This DARKENS as it goes, it is not paper, and
         its downwardness is the pleasure the room is arguing for. A pale scroll
         about despair and a darkening scroll about delight.

     RH- PREFIXED THROUGHOUT, because `slate`, `deep`, `chalk`, `paper` and
     `ink` are precisely the plain words a stylesheet fills up with, and a
     custom property declared twice in one :root is last-wins and silent.
     --rh-slate IS THE FLAT BODY GROUND AND IT IS THE LIGHTEST END OF THE
     GRADIENT, which inverts the Zibaldone's arrangement on purpose: that room
     sets dark type on pale paper, so its flat colour is the DARKER end, and
     this room sets pale type on a dark wall, so the honest flat colour is the
     LIGHTEST. In both cases the flat colour is the worse case for the type
     standing on it, which is the actual rule and is what makes
     check-contrast-live.py's answer the pessimistic one rather than the
     flattering one. --rh-graphite and --rh-root carry no text and are in
     check-contrast.py's ORNAMENT list with their measurements. --rh-brass is
     6.74 and up on all three dark grounds and only 1.83 on the paper mats, so
     the mats have a link colour of their own: see --rh-brass-dark. */
  --rh-slate: #262C35;     --rh-slate-2: #171C23;   --rh-deep: #0B0E13;
  --rh-chalk: #DEDCD4;     --rh-dim: #A2ABB6;       --rh-daylight: #BFC6CC;
  --rh-brass: #D9AE3A;     --rh-brass-dark: #6B4A0E;
  --rh-paper: #F3F0E7;     --rh-ink: #15181C;
  --rh-graphite: #4E5865;  --rh-root: #3A3026;

  /* The Healing Checkpoint (§31), room 429. A SAVE ROOM LIT FROM THE FLOOR, and
     the section below says at length why that one fact is the whole separation
     from five warm enclosed rooms, a manila job board and two cold stone ones.

     --hc-chamber IS THE FLAT BODY GROUND AND IT IS THE LIGHTEST OF THE THREE
     DARKS, The Rabbit Hole's arrangement: a room setting pale type on a dark
     wall has to take the lightest ground as its honest flat colour, because
     that is the worse case for the type standing on it.
     --hc-lit IS NOBODY'S CHOICE -- it is --hc-glim at .10 over --hc-chamber,
     which is the brightest the pool in the floor makes the room, and it is what
     the header's type actually sits on once anything has been scrolled. It is
     in check-contrast.py beside the flat colour, because a flat background is
     never what the text is on.
     --hc-clay IS THE ONLY WARM VALUE IN THE ROOM AND IT IS AN INK, never a
     ground. Every other warm enclosed room on this street is warm underfoot;
     the moment a surface in here goes warm this is the yurt with a spring in
     it. It is what pale stone looks like with a cold light on it.
     HC- PREFIXED THROUGHOUT, on the Garden's and the Zibaldone's precedent
     rather than after an accident of this room's own: `pool`, `chamber`,
     `steam`, `spring` and `clay` are exactly the plain words a stylesheet fills
     up with, and a custom property declared twice in one :root is last-wins and
     silent -- which is how a gold room once rendered green. */
  --hc-chamber: #131E20;  --hc-alcove: #0E1719;  --hc-vault: #0A1112;
  --hc-lit: #1D3131;      --hc-spring: #0C3B40;
  --hc-steam: #EAF2F0;    --hc-dim: #A6BAB8;
  --hc-glim: #79DCCE;     --hc-clay: #DDB49B;

  /* The Foundry (§32). IRON, AND IT IS THE FIRST MID-GREY GROUND ON THE STREET.
     Every other world here is a night ground with light put on it or a sheet of
     paper with the room cropped away; this is the colour of the metal, halfway
     between the two, and the separation from both families lives in that one
     value. --fo-floor is the workshop, --fo-bench is the iron of everything
     standing on it, and the only pale thing anywhere in the room is one proof.
     --fo-brass IS THE ONLY WARM VALUE AND IT IS A METAL RATHER THAN A LIGHT.
     A foundry lit by a furnace would have been the obvious build and would have
     made this the seventh warm room on a street that already has six; north
     light is what a workshop was actually built for, because the glazing faces
     away from the sun so the work has no glare on it. Nothing in here has a lit
     face.
     --fo-lead IS ORNAMENT AND CARRIES NO TEXT: 3.66 on the floor, which is
     under the bar, so it rules and borders and never says anything. It is in
     check-contrast.py's ORNAMENT list with that number written beside it.
     --fo-paper AND --fo-ink ARE THE DEFAULT PAIR ON THE BENCH and the other
     three pairs live in data/foundry.json with their measured ratios, because
     this is the one room where the visitor picks the colour of the text.
     FO- PREFIXED THROUGHOUT, on the Healing Checkpoint's precedent rather than
     after an accident of this room's own: `floor`, `bench`, `lead`, `paper` and
     `ink` are exactly the plain words a stylesheet fills up with, and `ink` is
     already the zine's. A custom property declared twice in one :root is
     last-wins and silent. */
  --fo-floor: #3F4548;    --fo-bench: #2E3335;
  --fo-bone:  #EDEAE3;    --fo-oil:   #B9BFBD;
  --fo-brass: #DCB262;    --fo-lead:  #98A0A3;
  --fo-roof:  #6E7A80;
  --fo-paper: #E8EAE9;    --fo-ink:   #16181A;

  /* Danny the Street (§33). ONE HUE AND NOTHING ELSE, which is not a taste and
     cannot be loosened: low-pressure sodium is effectively a single wavelength,
     so under a street lamp nothing has a colour of its own -- only a
     brightness. Every value here is on one warm line from the tar up to the
     lamp, and a second hue in this room would be a different kind of lamp.
     --dn-tar is the road, --dn-paint is the road marking and every word in the
     room, --dn-chalk is the fine print, --dn-sodium is the lamp and every link.
     --dn-kerb IS ORNAMENT AND CARRIES NO TEXT: 3.08 on the tar and 2.62 inside
     the lamp's pool, both under the bar, so it kerbs, rules and joints and
     never says anything. It is in check-contrast.py's ORNAMENT list with those
     numbers beside it.
     DN- PREFIXED THROUGHOUT, the Foundry's precedent: `tar`, `paint`, `chalk`
     and `kerb` are exactly the plain words this file fills up with, and `chalk`
     is already the base's. A custom property declared twice in one :root is
     last-wins and silent. */
  --dn-tar:    #1A1917;   --dn-paint:  #F1EADA;
  --dn-chalk:  #C0B8A6;   --dn-sodium: #F0A73F;
  --dn-kerb:   #6B665D;

  /* The Outskirts (§34). HEADLIGHTS, WHICH IS A LIGHT NOTHING ELSE HERE USES.
     Every other world is lit from above through leaves, from one side at desk
     height, from behind at a hundred feet, through a mask, from directly
     overhead, from under the floor, or from nowhere at all. This is lit from
     OFF THE PAGE, low and level and close, so a thing out here has one bright
     face and no back, and everything an inch past the beam is --osk-night.
     --osk-beam is what the light lands on and every word in the area;
     --osk-dim is the fine print; --osk-rust is the paint on the boards and
     every link; --osk-board is the sign face.
     --osk-weed IS ORNAMENT AND CARRIES NO TEXT: 4.04 on the night and 3.51 on
     a board, both under the bar, so it draws grass and nothing else. It is in
     check-contrast.py's ORNAMENT list with those numbers beside it.
     OSK- PREFIXED THROUGHOUT, the Foundry's and Danny's precedent: `beam`,
     `board`, `dim` and `weed` are exactly the plain words this file fills up
     with. A custom property declared twice in one :root is last-wins and
     silent, and it has already shipped once. */
  --osk-night: #08090B;   --osk-board: #1A1B17;
  --osk-beam:  #EDE7D6;   --osk-dim:   #A9A491;
  --osk-rust:  #D96A3C;   --osk-weed:  #6E7358;

  /* Black Leather Lagoon (§35). ONE LIT RECTANGLE AT A DISTANCE, and that is
     the whole separation from Club Chronic. That room is a WALL -- flat,
     pasted, layered paper, no light source anywhere in it and no depth. This
     has a horizon, standing water and one bright screen out in it, so every
     object has a face turned towards the screen and goes black behind. Two
     music rooms with a rack of records in them, kept apart by the fact that one
     of them is lit.
     --lag-water is the ground; --lag-screen is the light and every word;
     --lag-dim is the fine print; --lag-card is the face of a lobby card out in
     the shallows; --lag-acid is every link and the title; --lag-poster is the
     red that carries text.
     --lag-blood IS ORNAMENT AND CARRIES NO TEXT: 3.35 on the water and 3.05 on
     a card, both under the bar. It frames and rules and never says anything,
     and --lag-poster exists precisely so the room is not tempted to let it.
     Both are in check-contrast.py, one measured in ORNAMENT and one as a pair.
     LAG- PREFIXED THROUGHOUT: `water`, `card`, `screen` and `blood` are plain
     words, and `screen` is already three other rooms'. */
  --lag-water: #07090A;   --lag-card:   #12161A;
  --lag-screen:#E6E2D2;   --lag-dim:    #A7AFA0;
  --lag-acid:  #8CC63F;   --lag-poster: #E4564A;
  --lag-blood: #B6342F;

  /* Sithen (§36). MOONLIGHT, WHICH IS HIGH, COLD, DIFFUSE AND FROM ABOVE --
     the opposite of the road it turns off, where a headlight is low, level and
     from one side. Out there a thing has a bright face and no back; here
     everything is evenly silvered and the shadows go straight down.
     AND THERE IS NO GREEN IN IT AT ALL, which is what keeps it off the
     campgrounds -- the other cold night ground on this site, which is
     blue-green spruce, lichen and moss. Grass under a full moon has no colour,
     only a brightness, and every value here is on one grey-violet line.
     --sth-night is the field, --sth-bank is the earth of the ring and every
     panel, --sth-bone is the blossom and every word, --sth-dim is the fine
     print, --sth-moon is every link.
     --sth-thorn IS ORNAMENT AND CARRIES NO TEXT: 3.69 on the field and 3.30 on
     the bank, under the bar both ways. It draws thorns, branches and rules and
     says nothing. It is in check-contrast.py's ORNAMENT list with those
     numbers beside it.
     STH- PREFIXED THROUGHOUT, the Foundry's precedent: `bank`, `bone`, `moon`
     and `thorn` are exactly the plain words this file fills up with, and
     `moon` is already the campgrounds' link colour. A custom property declared
     twice in one :root is last-wins and silent, and it has shipped once. */
  --sth-night: #0C0B12;   --sth-bank:  #1A1822;
  --sth-bone:  #EDEAF2;   --sth-dim:   #A7A2B8;
  --sth-moon:  #BDB0DE;   --sth-thorn: #6E6880;

  /* Covenstead (§37). ONE WINDOW, IN THE AFTERNOON, INDOORS. The room moved
     off the road out of town and onto the street, and it changed worlds when it
     moved: Ryan's call, 2026-09-22. A covenstead is a group that meets
     regularly, which is neither solitude in nature (the campgrounds) nor
     revelry at a distance (The Outskirts) -- it is a premises, so it has a
     shopfront.
     THE LIGHT IS THE SEPARATION AND IT HAS TO STAY. Three pale rooms already
     exist here and every one is lit differently: the Hermitage is a LANDSCAPE
     under low morning sun with the shadows falling away from it, the Garden is
     MIDDAY from overhead through leaves, and the Guild has NO LIGHT SOURCE AT
     ALL and is lit like a photocopy. This is an INTERIOR with one window in the
     side of it, mid-afternoon, so the light arrives from one side and lands in
     a patch -- --cov-sun is where it falls and --cov-wash is the rest of the
     limewash. The two are 1.12 apart, which is what an ordinary room actually
     looks like and why both are safe grounds for text rather than one being an
     effect over the other.
     AND THERE IS NO GREEN GROUND IN IT, which is what keeps it off the other
     two daylit rooms, both of whose papers are green-white. This wall is warm
     and slightly pink, the colour of old distemper.
     --cov-ink is every word, --cov-ink-2 the fine print, and the three glazes
     are the mismatched china: --cov-delft, --cov-sage and --cov-rose. ALL THREE
     CARRY TEXT, so there is no ornament entry for this room and all ten pairs
     are measured in check-contrast.py.
     COV- PREFIXED THROUGHOUT: `wash`, `sun`, `ink` and `rose` are exactly the
     plain words this file fills up with, and `ink` is already the zine's. */
  --cov-wash:  #F3E9E1;   --cov-sun:   #FCF7EF;
  --cov-ink:   #2A211C;   --cov-ink-2: #5E5048;
  --cov-delft: #2F5E86;   --cov-sage:  #41643A;
  --cov-rose:  #A1384A;

  /* Looming Rocks Amphitheatre (§38). THE LIGHT IS THROWN UPWARD, which no
     other world on this street does. Floods stand on the ground and point UP
     the rock faces, so a rock is bright at its foot and goes dark towards the
     top, and there is nothing overhead at all -- the opposite of Sithen two
     turnings back, where a full moon lights everything from directly above.
     AND WHAT GLOWS IS NOT THE LAMP. The lichen fluoresces: a surface taking
     invisible light and giving back visible, which is emission rather than
     reflection and is the third kind of transmitted light this street has
     (Swaying Sweetgrass is lit THROUGH bodies, The Feed through an aperture).
     --lr-rock is unlit stone and the ground; --lr-face is a rock face with a
     flood on it and every panel; --lr-bone is every word; --lr-dim the fine
     print; --lr-uv is the violet of the lamps and every link; --lr-lichen is
     what the lichen gives back.
     --lr-lichen IS A CYAN-GREEN AND THE LAGOON'S ACID IS A YELLOW-GREEN, one
     turning along the same road. They are far apart in blue (200 against 63)
     and the rooms differ in everything else, but this is the pair to watch: if
     this ever warms towards yellow the two music rooms on this road have
     started sharing a colour.
     BOTH ACCENTS CARRY TEXT, so this room has no ornament entry either.
     LR- PREFIXED THROUGHOUT: `rock`, `face`, `bone` and `dim` are exactly the
     plain words this file fills up with, and `bone` is already the
     campgrounds'. */
  --lr-rock:   #15120F;   --lr-face:   #241E18;
  --lr-bone:   #EDE7DC;   --lr-dim:    #ABA196;
  --lr-uv:     #A579F0;   --lr-lichen: #4FD8C8;

  /* The address that is not on the street (§39), which is the 404. FOG, AND
     FOG IS LIT FROM EVERYWHERE. Water in the air scatters light until it
     arrives from every direction at once, so nothing casts a shadow, nothing
     has a lit face, and the only thing that tells near from far is how pale a
     thing has gone. --fg-fog is the ground and the air; --fg-ink is every word;
     --fg-dim the fine print; --fg-link every link, which is underlined because
     it is 1.55 from the ink and colour is never the only channel here;
     --fg-plate and --fg-enamel are the house-number plate on its post, which
     is the one near thing in the room.
     --fg-far, --fg-mid, --fg-halo AND --fg-post ARE ORNAMENT AND CARRY NO TEXT:
     the rooftops going back into the fog at 1.22 and 1.53, the halo round a
     distant lamp, and the post under the plate at 3.86. A rooftop that measured
     4.5 would be close enough to knock on, which is the one thing nothing in
     this room is. All four are in check-contrast.py's ORNAMENT list.
     FG- PREFIXED THROUGHOUT: `ink`, `dim`, `link` and `plate` are exactly the
     plain words this file fills up with, and `ink` is already the base's. */
  --fg-fog:    #D3D9DA;   --fg-ink:    #1C2428;
  --fg-dim:    #3D4A50;   --fg-link:   #16465C;
  --fg-plate:  #1D3557;   --fg-enamel: #F3F4EF;
  --fg-far:    #BEC6C8;   --fg-mid:    #A7B1B4;
  --fg-halo:   #E6EAEA;   --fg-post:   #5E6B70;

  /* Dead Tired Society (§40). A BORROWED ROOM AFTER HOURS WITH THE BIG LIGHTS
     OFF AND THE DOOR LEFT AJAR, and the light is the whole separation. It comes
     from OUTSIDE the room -- a corridor's strip lights, through a gap -- and it
     lies on the floor as one hard-edged wedge that NOBODY IS SITTING IN.
     --dts-hall is that light and NOTHING IS EVER SET IN IT, which is the room's
     one rule about colour and the reason it is in check-contrast.py's ORNAMENT
     list despite measuring 14.8: masking is performing under a light, and this
     is the one room on the street whose words all stay in the shade on purpose.
     COVENSTEAD IS THE ROOM TO WATCH, because a group meets there too and its
     light also comes in from one side and lands in a patch. That room is daylit
     all over, its patch is 1.12 from its wall, and it sets its words IN the
     patch. This one is dark, its patch is fourteen times brighter than anything
     around it, and it keeps every word out of it.
     THE GROUND IS PLUM AND NOT VIOLET, which holds it off Sithen's grey-violet
     night and the Chappell's votive purple: it is the colour of a dark room seen
     through half-shut eyes. --dts-exit is every link and it is the corridor's
     own green, because a link is a way out through the door. --dts-edge draws
     everything standing in the shade and carries no word.
     DTS- PREFIXED THROUGHOUT: `room`, `hall`, `edge` and `exit` are exactly the
     plain words this file fills up with, and a custom property declared twice
     in one :root is last-wins and silent. */
  --dts-room:  #22151F;   --dts-deep:  #170E15;
  --dts-pale:  #EFE7EE;   --dts-text:  #DCD1DA;   --dts-dim:   #B7A8B5;
  --dts-exit:  #A6D6B3;   --dts-hall:  #E4EFE2;   --dts-edge:  #8B7889;

  /* Laughingstock (§41). A COMEDY CELLAR SEEN FROM THE BACK OF THE HOUSE, and
     the light is the whole separation: ONE FOLLOW SPOT, FROM BEHIND YOU. It
     sits in the lighting box over the audience's heads and throws one hard-
     edged pool onto a brick wall, so the only lit things in the room are in
     front of you and every shadow falls straight back onto the brick.
     --ls-spot is that light, and THE ONLY THING EVER SET IN IT IS WHAT A COMIC
     SAID. That is Dead Tired Society's rule turned inside out, one door along:
     there nobody sits in the light because masking is performing under one;
     here exactly one person stands in it, because they chose to and they are
     holding the mic, and controlling the frame is the whole of the argument.
     Everything of ours -- the write-up, the notes, the house rules -- is out in
     the dark with the audience: --ls-house, with --ls-cream, --ls-text and
     --ls-dim on it. --ls-ink and --ls-ink-2 are the only inks in the light.
     --ls-neon is the sign over the stage and every link in the house.
     THE BRICK IS RED AND NOT BROWN. --ls-brick is the lit face of a brick and
     --ls-wall is the same brick out of the light; neither carries a word. If
     those ever drift towards brown, this has become The Den with a microphone
     in it, and it is this room that moves.
     LS- PREFIXED THROUGHOUT: `wall`, `brick`, `edge`, `spot` and `ink` are the
     plain words this file fills up with, and a custom property declared twice
     in one :root is last-wins and silent. */
  --ls-house:  #140F10;   --ls-deep:   #0B0808;
  --ls-cream:  #F4E8D8;   --ls-text:   #D8C9BB;   --ls-dim:    #B09F92;
  --ls-neon:   #86DCFF;   --ls-edge:   #7D6A60;
  --ls-spot:   #FBF0DC;   --ls-ink:    #1F1513;   --ls-ink-2:  #5B3B2F;
  --ls-brick:  #8E3526;   --ls-wall:   #3A1713;
  --ls-joint:  #231513;   --ls-joint-lit: #C9A48E;

  /* The Lightbulb Picture House (§42). AN AUDITORIUM WITH THE HOUSE LIGHTS UP,
     and that is the whole separation from every dark room on this street with a
     bright rectangle in it. The room is lit ALL OVER, by bare bulbs in brass
     sconces down both walls, so the ground is lit velvet -- red, not black --
     and there is no beam, because a projector's beam only shows in the dark.
     NOTHING HERE IS BLUE, and make-picture-house.py refuses a blue --lph-
     colour: a lightbulb theater in a neurodiversity room, lit blue, is Light It
     Up Blue. The bulbs are warm and the ornament is the gold infinity, Autistic
     UK's, from Au. --lph-velvet is the room and carries every word of ours;
     --lph-deep is the rack's cards and the seats; --lph-screen is the one pale
     thing, and every press-to-play plate is a small screen in it, dark ink on
     the light. --lph-gold is every link and heading accent. The brass, the bulbs
     and the curtain's folds draw and carry nothing.
     LAUGHINGSTOCK IS THE ROOM TO WATCH, one door along and also red, also a
     room you sit in and face something lit. That room is a DARK house with one
     spot from behind you onto brick; this is a LIT house with no spot at all and
     many small sources, velvet rather than brick, and nothing in it standing in
     a pool. If the house lights here ever go down, it has become that room with
     a screen in it, and it is this one that moves.
     LPH- PREFIXED THROUGHOUT: a custom property declared twice in one :root is
     last-wins and silent. */
  --lph-velvet: #7A1C2B;   --lph-deep:  #551220;   --lph-fold:  #9A2A3A;
  --lph-cream:  #FFF4E2;   --lph-text:  #F7E3D0;   --lph-dim:   #EDC9B0;
  --lph-gold:   #F6C95A;   --lph-bulb:  #FFE3A0;   --lph-brass: #C9953C;
  --lph-screen: #FFF6E8;   --lph-ink:   #2A0A10;   --lph-ink-2: #6B2230;

  /* Dance, Punks (§43). A SILENT DISCO LIT BY THE HEADSETS AND NOTHING ELSE. The
     light is WORN: every dancer carries a small glow at head height in the
     colour of the channel they are on, and it lights them and whoever is next
     to them. Nothing else on the runway is lit -- no rig, no runway lights, no
     moon -- so --dp-tarmac is the dark between people, and the markings,
     the runway surface and the dancers' own bodies (--dp-paint, --dp-strip,
     --dp-body) are ornament that carries no word.
     THE THREE CHANNEL INKS ARE CHOSEN BY BRIGHTNESS AS WELL AS HUE. Blue,
     orange and white, at least 1.5:1 apart from each other, so they stay three
     headsets in greyscale; the obvious red, green and blue fail that for the
     commonest colour blindness. make-dance-punks.py reads these values from
     here, measures them, and refuses a pair under the bar. Each one also sets
     its channel's name, so each is held to 4.5 on the tarmac and on --dp-deep.
     --dp-text, --dp-dim and --dp-pale carry every word of ours.
     DP- PREFIXED THROUGHOUT: a custom property declared twice in one :root is
     last-wins and silent. */
  --dp-tarmac: #0B0A0D;   --dp-deep:   #17151C;   --dp-strip:  #121116;
  --dp-paint:  #3B3842;   --dp-body:   #1E1B24;
  --dp-pale:   #F7F4FA;   --dp-text:   #E6E2EC;   --dp-dim:    #ADA7B6;
  --dp-blue:   #4F7FF5;   --dp-orange: #FF9A3C;   --dp-white:  #F4EFE6;

  /* The Small Hours (§44). A LIT BOX SEEN FROM THE DARK, which is the whole
     separation. You stand in the car park at night looking in through a band
     of plate glass at a room lit evenly all over by tubes, and every word that
     belongs to the diner is IN a window: --sh-glass, with --sh-ink,
     --sh-ink-2 and --sh-teal on it. Out on the lot you have --sh-lot, with
     --sh-pale, --sh-text, --sh-dim and the one steady neon, --sh-neon, which
     is the OPEN sign and every link outside. The wall, the kerb, the chrome,
     the formica and the booth vinyl draw and carry nothing (--sh-wall,
     --sh-line, --sh-chrome, --sh-aqua, --sh-cherry).
     DEAD TIRED SOCIETY IS THE ROOM TO WATCH, because that room's light is also
     tubes and also lies on the floor in a shape. It is the exact inverse: you
     sit in a dark room and the light is outside it, in a corridor, and nobody
     stands in it. Here the light is inside and you are the one outside. If the
     words ever come out of the windows onto the dark, this has become that
     room with a menu.
     SH- PREFIXED THROUGHOUT: a custom property declared twice in one :root is
     last-wins and silent. */
  --sh-lot:    #0F1116;   --sh-wall:   #2A2E38;
  --sh-line:   #3A3F4A;   --sh-chrome: #C7CBD3;
  --sh-pale:   #EEF0F3;   --sh-text:   #D5D9E0;   --sh-dim:    #A7ADB8;
  --sh-neon:   #FF6B6F;
  --sh-glass:  #F2F4F7;   --sh-ink:    #1A1D26;   --sh-ink-2:  #4A4F5E;
  --sh-teal:   #0F6E68;   --sh-aqua:   #1F8A84;   --sh-cherry: #B8323C;

  /* The Repeater (§45). EVERYTHING IS A SILHOUETTE, which is the whole
     separation. Nothing on the ridge is lit -- not the mast, not the hut, not
     the hill -- and the only light is the glow every other lit thing on the
     road throws up onto the underside of the cloud, so every object is a black
     shape against a sky the colour of somewhere else's light. --rp-cloud is that
     sky overhead and carries every word; --rp-glow is the band of it along the
     horizon and --rp-ridge is the black of everything standing against it, and
     neither carries a word. --rp-lamp is the two steady red lamps on the mast,
     ornament. --rp-deep is the panel the open line sits on; --rp-card,
     --rp-ink, --rp-ink-2 and --rp-call are the cards in the log.
     THE CLOUD IS WARM AND NOT BLUE. A navy night sky would be the campgrounds,
     which is cold and has the sky on it, lit by nothing. This is overcast lit
     from below by a town, which is a dull warm grey in life too.
     RP- PREFIXED THROUGHOUT: a custom property declared twice in one :root is
     last-wins and silent. */
  --rp-cloud:  #1A1517;   --rp-deep:   #241D20;   --rp-glow:   #5A4038;
  --rp-ridge:  #070606;   --rp-lamp:   #FF3B30;
  --rp-pale:   #F1ECE8;   --rp-text:   #D9D1CD;   --rp-dim:    #AEA39F;
  --rp-amber:  #F2B880;
  --rp-card:   #EFE8D8;   --rp-ink:    #1B1A22;   --rp-ink-2:  #4E4A58;
  --rp-call:   #9C1F18;

  /* Nothing For Sale (§46). LIT BY EVERYBODY'S HEADLIGHTS AT ONCE, which is the
     whole separation. The road into The Outskirts is lit by YOUR headlights, one
     low beam from behind you; this lay-by is a ring of cars pulled up nose-in
     with their lamps left on, so the middle is lit from every side and every
     object in it throws a fan of shadows, one for every car. NO TWO LAMPS
     MATCH: --nfs-halogen, --nfs-led and --nfs-fog are three different cars'
     light, and make-nothing-for-sale.py refuses two beams of one colour. Each
     table's top edge is lit by one of them; --nfs-fog is also every link.
     --nfs-gravel is the lay-by and --nfs-table the tables, and both carry
     words; --nfs-lit (the lit middle in the drawing), --nfs-car and
     --nfs-shadow draw and carry nothing.
     THE 404 IS THE ROOM TO WATCH, because that fog is also lit from every side
     at once. There, nothing casts a shadow at all. Here everything casts
     several, hard, and that is the picture: nobody brought enough light alone.
     NFS- PREFIXED THROUGHOUT: a custom property declared twice in one :root is
     last-wins and silent. */
  --nfs-gravel: #12110E;   --nfs-table:  #221F1A;   --nfs-lit:    #2A2721;
  --nfs-car:    #1F1D19;   --nfs-shadow: #070706;
  --nfs-pale:   #F3EFE6;   --nfs-text:   #DAD4C6;   --nfs-dim:    #AFA897;
  --nfs-halogen: #FFE1A1;  --nfs-led:    #E4ECFF;   --nfs-fog:    #FFD23F;

  /* Samefood Cafe (§47). A CAFE SEEN FROM DIRECTLY ABOVE THE TABLE, UNDER ONE
     EVEN LIGHT THAT DOES NOT CHANGE WITH THE HOUR, and nothing on any plate
     touches anything else. --sf-table is the laminate every word in the room
     stands on, and it is a lilac grey BECAUSE ALMOST NOTHING ON THE MENU IS
     THAT COLOUR: nothing on the table can be mistaken for the table. --sf-plate
     is the plate, and EVERY PLATE HERE IS THE SAME PLATE -- one colour, one
     mould, which is COVENSTEAD INVERTED, one door along: there nobody's cup is
     anybody else's and that is its subject; here the sameness is. --sf-well is
     the recess of each compartment on it, and words sit in those too.
     --sf-ink is every word, --sf-ink-2 the fine print, --sf-sauce every link
     (the one red on a pale table), and --sf-cress draws the job marker.
     --sf-rim and --sf-shade draw and carry nothing: the rim of the plate and
     the soft ring of shade the overhead light puts round every object, which
     is the light drawing a gap round each thing. The food colours are
     ornament, each carried by an --sf-ink-2 outline, and are measured in
     check-contrast.py's ORNAMENT list with their numbers. --sf-apple and
     --sf-ketchup are the red ones; red matters only to somebody who has asked
     about it, and Ronan has, for his own food. NO BLUE: a lilac is
     the closest this room comes, on purpose -- see the Lightbulb Picture
     House for why a neurodiversity room lit blue is a campaign we refuse.
     SF- PREFIXED THROUGHOUT: `plate`, `rim` and `shade` are exactly the plain
     words this file fills up with, and a custom property declared twice in one
     :root is last-wins and silent. */
  --sf-table:  #E6E0EB;   --sf-plate:  #FCFAF6;   --sf-well:   #F3EEE7;
  --sf-ink:    #2A1F30;   --sf-ink-2:  #5A4B60;
  --sf-sauce:  #9C2F1E;   --sf-cress:  #3E5C22;
  --sf-rim:    #B3A7BD;   --sf-shade:  #D4CBDC;
  --sf-pop:    #EFC75E;   --sf-pesto:  #7C9A45;   --sf-apple:  #C0463B;
  --sf-nut:    #B57A3E;   --sf-coffee: #6B4430;   --sf-cheese: #F29B38;
  --sf-ketchup: #B3261E;  --sf-broth:  #EBCF93;   --sf-noodle: #F7EBC0;
  --sf-onion:  #4F8F35;   --sf-nugget: #D9A04E;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.55;
  background: var(--ink);
  color: #fff;
  overflow-x: hidden;
}

img, svg { max-width: 100%; height: auto; }

/* THE HIDDEN ATTRIBUTE IS A STATEMENT ABOUT THE DOCUMENT, NOT A STYLE, and the
   browser's own rule for it is `[hidden] { display: none }` at specificity
   (0,1,0) — which any ordinary class rule setting `display` ties with and then
   WINS, because it comes later in this file. Nothing warns. An element that a
   script has switched off stays on the screen, and the script looks broken
   while the stylesheet is the one lying.

   IT HAPPENED THREE TIMES IN ONE ROOM before this rule existed: the Hermitage's
   way-out link, its play button and then its whole OFF PANEL, which sat beside
   the running video as a column of stale text announcing that the set was off
   while the set was plainly on. Two of those were patched one selector at a
   time, which is how a third one was still waiting to be found. */
[hidden] { display: none !important; }

/* Focus is never removed and never subtle. A site made of buttons has to be
   navigable by keyboard or it is a diorama. */
:focus-visible {
  outline: 4px solid var(--yellow);
  outline-offset: 3px;
  border-radius: 2px;
}

/* THE FIRST CONTROL A KEYBOARD USER MEETS, AND IT WAS UNREADABLE IN TWENTY-ONE
   ROOMS. This carries its own yellow ground and its own near-black ink at
   (0,1,0) — and every room on the street sets `.room-x a { color: … }` at
   (0,2,0), which reaches straight through to it. So the skip link took each
   room's link colour on a yellow box: gold on yellow at 1.26 in the chapel,
   mint at 1.10 in the arcade, and YELLOW ON YELLOW at 1.00 on every plain room.
   Nothing had ever seen it, because it sits at left:-9999px until it is focused
   and nobody screenshots a focused skip link.

   `!important` here for the reason §2 already carries one on [hidden]: this is
   shared furniture that every room's own rules out-specify by accident, the
   guard has to hold in a room nobody is thinking about, and patching it room by
   room is the thing that file's note tells you not to do. Rooms restyle the
   backlink on purpose; the skip link is the one piece they must not reach. */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--yellow); color: var(--ink) !important;
  font-family: 'Bungee', var(--sans); font-size: 14px;
  padding: 14px 20px; text-decoration: none;
}
.skip:focus { left: 0; }

.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.wrap { width: min(1180px, 100% - 44px); margin-inline: auto; }

/* Touch targets. 44px is the floor everywhere, toys included. */
button, .btn, a.door, .tile { min-height: 44px; }


/* §3 ── The intensity dial ───────────────────────────────────────────────────
   THE most important 40 lines in this file.

   Three levels on <html data-intensity>. The default is read from the visitor's
   own device (prefers-reduced-motion → gentle) by the inline snippet in each
   page's head, which runs BEFORE first paint so nobody gets flashed the loud
   version on the way to the quiet one. A stored choice always wins, INCLUDING
   a choice to turn it up past what the OS asked for — that is the whole point.
   The visitor is the authority on their own tolerance, not the media query.

   gentle  — no rotation, no ambient motion, no sparkle. Same rooms, same
             colours, same content. Nothing is hidden at this level; a "lite"
             version that drops content would be a worse site wearing a
             politer name.
   regular — full colour and full type play. Motion on hover/focus only.
   max     — ambient motion as well: the marquee scrolls, the sparkle twinkles,
             the toys wobble. Nobody arrives here by default.                   */

.tilt-a { transform: rotate(-2deg); }
.tilt-b { transform: rotate(1.5deg); }
.tilt-c { transform: rotate(-1deg); }
.tilt-d { transform: rotate(2.5deg); }

html[data-intensity="gentle"] .tilt-a,
html[data-intensity="gentle"] .tilt-b,
html[data-intensity="gentle"] .tilt-c,
html[data-intensity="gentle"] .tilt-d { transform: none; }

html[data-intensity="gentle"] .sparkle,
html[data-intensity="gentle"] .glow { display: none; }

html[data-intensity="gentle"] *,
html[data-intensity="gentle"] *::before,
html[data-intensity="gentle"] *::after {
  animation: none !important;
  transition: none !important;
}

html[data-intensity="regular"] .sparkle { opacity: 0.55; }
html[data-intensity="max"]     .sparkle { opacity: 1; animation: twinkle 4s steps(2) infinite; }
html[data-intensity="max"]     .marquee__inner { animation: slide 38s linear infinite; }
html[data-intensity="max"]     .toy:hover  { transform: rotate(-2deg) scale(1.03); }
html[data-intensity="max"]     .door:hover { transform: translateY(-6px) rotate(-1deg); }

@keyframes twinkle { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }
@keyframes slide   { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* The dial itself. Present in every room, always in the same corner, because a
   control you have to hunt for is not really offered. */
.dial {
  background: var(--ink-2);
  border: 3px solid #fff;
  border-radius: 18px;
  padding: 15px 17px;
}
.dial__label { font-family: 'Bungee', var(--sans); font-size: 13px; color: var(--yellow); letter-spacing: 1px; }
.dial__row   { display: flex; gap: 8px; margin-top: 11px; }
.dial__btn {
  flex: 1 1 0; cursor: pointer;
  font-family: 'Bungee', var(--sans); font-size: 11px; letter-spacing: 0.5px;
  padding: 11px 6px; border-radius: 9px;
  border: 3px solid var(--ink-3); background: var(--ink); color: var(--chalk);
}
.dial__btn:hover { border-color: #fff; color: #fff; }
.dial__btn[aria-pressed="true"] { border-color: #fff; color: var(--ink); }
.dial__btn[data-level="gentle"][aria-pressed="true"]  { background: var(--green); }
.dial__btn[data-level="regular"][aria-pressed="true"] { background: var(--cyan); }
.dial__btn[data-level="max"][aria-pressed="true"]     { background: var(--pink); }
/* THE DIAL KEEPS THE YELLOW RING IN EVERY ROOM, because it is always a dark
   box and its buttons' rings land inside it. The pale rooms set their own ring
   for their own ground (check-focus.py found yellow at 1.01 on manila), and a
   room's ring written for its paper reached straight into the dial on the
   Zibaldone, where the dial sits on a sheet. !important for the reason the
   skip link and §2's [hidden] carry it: shared furniture that rooms
   out-specify by accident, in rooms nobody is thinking about at the time. */
.dial .dial__btn:focus-visible { outline-color: var(--yellow) !important; }
.dial__note { margin-top: 11px; font-size: 13.5px; line-height: 1.45; color: #fff; }
.dial__fine {
  margin-top: 9px; padding-top: 9px; font-size: 12px; color: var(--chalk);
  border-top: 1px solid var(--ink-3);
}


/* §4 ── Shared furniture ─────────────────────────────────────────────────────
   The three things every room needs so a visitor is never stranded: a way back
   to the street, a marquee rail, and the press-to-play facade. */

.backlink {
  display: inline-block; font-family: 'Bungee', var(--sans);
  font-size: 12px; letter-spacing: 1px; text-decoration: none;
  padding: 10px 0;
}

/* THE SIGN-OFF, on every page but the front one, written by tools/make-signoff.py.
   It is layout and nothing else: NO colour, NO typeface, NO ground. It takes the
   room's own ink, face and link colour the way a job marker does, so that it
   reads as the room signing off rather than the street's pavement turning up in
   a world that has its own -- the Guild's section says why that line is held.
   A room whose floor is not the ground its links were chosen for dresses it in
   its own section, beside its other decisions; that is what §4 is for.
   Centred at its own measure because it sits in <body> after <main>, and rooms
   give their mains every width there is. */
.signoff {
  width: min(840px, calc(100% - 32px));
  margin: 0 auto;
  padding: 30px 0 44px;
  font-size: 14px;
  line-height: 1.7;
  text-align: center;
}
.signoff__line { margin: 0; }

/* The margin hand. It was written inside the zine table, and then Enid's room
   and issue #2 started wearing it too — three rooms on one class, which makes
   it furniture whichever section it was typed in. It is here now because
   check-classes.py refuses a page wearing a name another room has claimed, and
   the honest answer to that was not to rename it in two rooms but to admit what
   it had become. Every room that uses it overrides the colour inline. */
.scrawl { font-family: 'Rock Salt', var(--sans); font-size: 12px; color: var(--red); }

.marquee {
  background: var(--yellow); border-bottom: 4px solid var(--ink);
  overflow: hidden; white-space: nowrap;
}
.marquee__inner {
  display: inline-block; padding: 15px 0;
  font-family: 'Bungee', var(--sans); font-size: 18px;
  color: var(--ink); letter-spacing: 1px;
}
.marquee__inner span { padding-right: 2.5em; }

/* The embed facade. NOTHING from youtube is loaded until the visitor presses
   the button — no iframe, no cookie, no request. This is the mechanism behind
   the room rule "nothing plays until you press play", and it is why the site
   can promise it rather than merely intend it. See love-embed.js. */
.facade {
  position: relative; display: block; width: 100%;
  aspect-ratio: 16 / 9; cursor: pointer;
  border: 3px solid var(--ink); border-radius: 12px;
  background: var(--ink-2); color: var(--cream);
  font-family: var(--sans); text-align: left;
  padding: 16px 18px;
}
.facade:hover { background: var(--ink-3); }
.facade__play {
  position: absolute; inset: auto auto 16px 18px;
  font-family: 'Bungee', var(--sans); font-size: 13px; letter-spacing: 1px;
  color: var(--yellow);
}
.facade iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; border-radius: 9px; }
/* AN AUDIO FACADE IS A STRIP, NOT A SCREEN. love-embed.js builds an <audio> in a
   shell carrying this class, because the button's own classes evaporate on the
   press. Layout only: no colour, no face, no ground, so it arrives in the room's
   own clothes -- the room dresses the button, and the player is the browser's. */
.facade--audio { aspect-ratio: auto; padding: 0; }
div.facade--audio { border: 0; background: none; }
.facade--audio audio { display: block; width: 100%; }

/* THE JOB MARKER. Furniture rather than a room, for the facade's reason: every
   room on the street wears one, so it belongs to §1–§4 where a name is allowed
   to be global. What is NOT shared is the drawing inside it -- make-guild.py
   holds one per room and refuses a room it has no drawing for, exactly as
   make-og.py refuses a room it has no card for, and for the same reason. A
   single glyph repeated in every room would be one shared component on a street
   whose whole architecture is that the rooms share nothing, arriving through a
   mechanism, which is how it always arrives.

   THE PANEL BORROWS THE ROOM'S OWN INK AND GROUND rather than bringing colours
   with it: every border, rule and control in here is `currentColor` on whatever
   the room is already painted. So a marker cannot be illegible anywhere the
   room's own body copy is legible, and opening one introduces no pair the
   contrast checker has not already measured. A room may still dress it, the way
   rooms dress `.facade`.

   IT IS A NATIVE <details>. Not a scripted popup: it opens, explains itself and
   gives up its code with scripts off. And DISCREET MEANS VISUALLY QUIET AND
   NOTHING ELSE -- the mark is a full-size target in the tab order with a real
   accessible name, which is The Den's door rule. On a Disabled people's site a
   secret only a sighted mouse user can find is not a secret, it is an
   exclusion. */
.quest { display: inline-block; max-width: 100%; vertical-align: middle; }
.quest__mark {
  display: inline-flex; align-items: center; gap: 8px;
  min-width: 44px; min-height: 44px; padding: 6px;
  cursor: pointer; list-style: none; opacity: .72;
}
.quest__mark::-webkit-details-marker { display: none; }
.quest__mark:hover, .quest__mark:focus-visible, .quest[open] .quest__mark { opacity: 1; }
.quest__draw { width: 32px; height: 32px; flex: none; display: block; }
/* The name is there for everybody; it is only drawn when somebody is looking
   for it. Never display:none — that would take it off the accessibility tree
   and make the marker an unlabelled box. */
.quest__label {
  font-family: var(--sans); font-size: 12px; line-height: 1.3;
  letter-spacing: .04em; max-width: 26ch;
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}
.quest__mark:hover .quest__label,
.quest__mark:focus-visible .quest__label,
.quest[open] .quest__label {
  position: static; width: auto; height: auto; overflow: visible;
  clip: auto; white-space: normal;
}
.quest__panel {
  border: 2px solid currentColor; padding: 16px 18px; margin-top: 6px;
  max-width: 62ch; font-family: var(--sans); font-size: 15px; line-height: 1.55;
}
.quest__panel > * { margin: 0 0 10px; }
.quest__panel > :last-child { margin-bottom: 0; }
.quest__code { font-size: 16px; }
.quest__word {
  display: inline-block; border: 2px solid currentColor;
  padding: 3px 10px; letter-spacing: .18em; font-weight: 700;
}
.quest__lab { display: block; font-size: 13px; letter-spacing: .04em; margin-bottom: 5px; }
.quest__row { display: flex; flex-wrap: wrap; gap: 8px; align-items: stretch; }
.quest__in {
  flex: 1 1 11em; min-width: 0; min-height: 44px; padding: 6px 10px;
  border: 2px solid currentColor; background: transparent;
  color: inherit; font: inherit; letter-spacing: .06em;
}
.quest__check {
  min-height: 44px; padding: 6px 16px; cursor: pointer;
  border: 2px solid currentColor; background: transparent;
  color: inherit; font: inherit; font-weight: 700; letter-spacing: .06em;
}
.quest__check[disabled] { cursor: default; opacity: .6; }
.quest__said:empty { display: none; }
.quest__hint, .quest__out { border-top: 1px solid currentColor; padding-top: 8px; }
.quest__hint > summary, .quest__out > summary {
  cursor: pointer; min-height: 44px; display: flex; align-items: center;
  font-size: 13px; letter-spacing: .06em; font-weight: 700;
}
.quest__free, .quest__yes { font-size: 14px; }
.quest__yes { font-weight: 700; }


/* §5 ── THE STREET (index) ───────────────────────────────────────────────────
   Night asphalt, shopfronts, bunting. The only page that has to hold every one
   of those worlds side by side without letting any of them win. */

.street { background: var(--ink); min-height: 100vh; position: relative; }

.street .sparkle {
  position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background-image:
    radial-gradient(circle at 12% 18%, rgba(255,225,0,.5)  0 2px, transparent 3px),
    radial-gradient(circle at 78% 12%, rgba(255,45,149,.6) 0 3px, transparent 4px),
    radial-gradient(circle at 42%  8%, rgba(0,212,255,.5)  0 2px, transparent 3px),
    radial-gradient(circle at 88% 42%, rgba(34,224,106,.5) 0 3px, transparent 4px),
    radial-gradient(circle at 24% 62%, rgba(163,77,255,.5) 0 2px, transparent 3px),
    radial-gradient(circle at 62% 30%, rgba(255,138,0,.5)  0 2px, transparent 3px),
    radial-gradient(circle at  6% 88%, rgba(0,212,255,.45) 0 2px, transparent 3px),
    radial-gradient(circle at 94% 76%, rgba(255,225,0,.45) 0 2px, transparent 3px);
}

.street > * { position: relative; z-index: 1; }

.masthead { display: flex; flex-wrap: wrap; gap: 30px; align-items: flex-start; padding: 34px 0 0; }
.masthead__names { flex: 1 1 420px; }
.masthead__dial  { flex: 0 1 400px; }

/* THE NAME OF THE THING THE WHOLE SITE WAS TAKEN FROM, said in text under the
   dial. The marquee across the top of the page says DANNY IS THE STREET and is
   `aria-hidden`, because it scrolls and is decoration — so until this paragraph
   existed, the credit for the architecture was available only to somebody who
   could see it, on a site whose one surviving careful habit is attribution.
   IT DECLARES ITS OWN LINK COLOUR. The street has no base link rule of its own,
   which is the hole the Doomscroll and the Playhouse both fell down; yellow on
   the night ground is in check-contrast.py, and so is the chalk it is set in. */
.masthead__who {
  margin: 14px 0 0;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--chalk);
}
.masthead__who b { color: #fff; }
.masthead__who a { color: var(--yellow); text-underline-offset: 3px; }

.wordmark   { font-family: 'Bungee', var(--sans); font-size: clamp(46px, 8.5vw, 92px); line-height: .92; color: #fff; text-shadow: 4px 0 0 var(--pink), 8px 0 0 var(--cyan); letter-spacing: -1px; margin: 0; }
.wordmark b { font-family: 'Shrikhand', var(--sans); font-weight: 400; color: var(--pink); text-shadow: none; display: block; font-size: .78em; margin-top: -.06em; }

/* The tagline is the font-play thesis statement: six phrases, six faces, six
   colours, one sentence. Every colour here clears 4.5:1 on the night ground —
   clashing is not the same as illegible. */
.tagline { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: baseline; margin: 26px 0 0; max-width: 940px; padding: 0; list-style: none; }
.tagline li { display: inline-block; }
.tagline .t1 { font-family: 'Archivo Black', var(--sans);  font-size: 25px; color: var(--pink); }
.tagline .t2 { font-family: 'Shrikhand', var(--sans);      font-size: 25px; color: var(--orange); }
.tagline .t3 { font-family: 'Bungee', var(--sans);         font-size: 21px; color: var(--green); }
.tagline .t4 { font-family: 'Monoton', var(--sans);        font-size: 27px; color: var(--cyan); }
.tagline .t5 { font-family: 'Rock Salt', var(--sans);      font-size: 16px; color: var(--yellow); }
.tagline .t6 { font-family: 'VT323', monospace;            font-size: 30px; color: var(--violet); }

/* FOUR UP, NOT SIX ACROSS, and the Arcade is why. At minmax(172px) a 1180px
   street fits exactly six columns, so adding the Arcade left Your Room stranded
   alone on a second row at a sixth of the width — which reads as a wrapping
   accident rather than as a street. Four and three is a block of shopfronts,
   the empty storefront still comes last, and the doors got wider rather than
   thinner in the process. */
.doors { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 16px; margin: 36px 0 0; padding: 0; list-style: none; }

.door {
  display: flex; flex-direction: column; text-decoration: none;
  border: 3px solid #fff; border-radius: 12px 12px 5px 5px; overflow: hidden;
  min-height: 284px; transition: transform .18s ease;
}
.door:hover { transform: translateY(-5px); }
.door__awning { height: 36px; border-bottom: 3px solid #fff; }
.door__body   { flex: 1; display: flex; flex-direction: column; justify-content: space-between; gap: 12px; padding: 17px 15px; }
.door__body > span:first-child { display: block; }
.door__name   { display: block; font-size: 26px; line-height: 1.05; margin: 0; }
.door__blurb  { display: block; margin: 10px 0 0; font-size: 13.5px; line-height: 1.42; }
.door__knock  { display: block; }
.door__knock  { font-family: 'Bungee', var(--sans); font-size: 12px; letter-spacing: 1px; }

.door--pony  { background: var(--hot); }
.door--pony  .door__awning { background-image: repeating-linear-gradient(90deg, var(--cream) 0 14px, var(--pink) 14px 28px); }
.door--pony  .door__name  { font-family: 'Shrikhand', var(--sans); color: var(--cream); }
.door--pony  .door__blurb { color: #2b0a1c; font-weight: 500; }
.door--pony  .door__knock { color: #2b0a1c; }

.door--zine  { background: var(--paper); }
.door--zine  .door__awning { background-image: repeating-linear-gradient(90deg, var(--ink) 0 14px, var(--paper) 14px 28px); }
.door--zine  .door__name  { font-family: 'Archivo Black', var(--sans); color: var(--ink); text-transform: uppercase; font-size: 24px; }
.door--zine  .door__blurb { color: #2e2a22; font-weight: 500; }
.door--zine  .door__knock { font-family: 'Rock Salt', var(--sans); font-size: 11px; letter-spacing: 0; color: var(--ink); }

.door--quantum { background: #0a0d22; }
.door--quantum .door__awning { background-image: repeating-linear-gradient(90deg, var(--cyan) 0 14px, var(--violet) 14px 28px); }
.door--quantum .door__name  { font-family: 'VT323', monospace; color: var(--cyan); font-size: 34px; }
.door--quantum .door__blurb { color: #d8d4ff; }
.door--quantum .door__knock { font-family: 'VT323', monospace; font-size: 17px; letter-spacing: 0; color: var(--green); }

.door--enid  { background: #101014; }
.door--enid  .door__awning { background-image: repeating-linear-gradient(90deg, var(--violet) 0 14px, var(--green) 14px 28px); }
.door--enid  .door__name  { font-family: 'Bungee', var(--sans); color: var(--green); font-size: 23px; }
.door--enid  .door__blurb { color: #ece8f5; }
.door--enid  .door__knock { font-family: 'Rock Salt', var(--sans); font-size: 11px; letter-spacing: 0; color: var(--pink); }

.door--play  { background: var(--blue); }
.door--play  .door__awning { background-image: repeating-linear-gradient(90deg, var(--red) 0 14px, var(--yellow) 14px 28px); }
.door--play  .door__name  { font-family: 'Bungee', var(--sans); color: var(--yellow); font-size: 25px; }
.door--play  .door__blurb { color: #fff; font-weight: 500; }
.door--play  .door__knock { color: #fff; }

/* The Arcade's shopfront. A pixel face at shopfront size is wide enough that
   the name has to be set smaller than every other door's and still reads as
   the loudest thing in the row, which is what an arcade front does in a real
   street. */
.door--arcade { background: var(--carpet); }
.door--arcade .door__awning { background-image: repeating-linear-gradient(90deg, var(--coin) 0 14px, var(--zap) 14px 28px); }
.door--arcade .door__name  { font-family: 'Press Start 2P', monospace; color: var(--coin); font-size: 15px; line-height: 1.35; }
.door--arcade .door__blurb { color: var(--tube); }
.door--arcade .door__knock { font-family: 'Press Start 2P', monospace; font-size: 11px; letter-spacing: 0; color: var(--mint); }

/* The Latibulum's shopfront, and the only door on this street that opens onto
   a hill. It is the quietest front in the row on purpose — no clashing awning
   stripe, just earth and lamplight — because a shopfront that shouted about a
   burrow would be misdescribing what is behind it before anybody pressed it. */
.door--burrow { background: var(--loam); }
.door--burrow .door__awning { background-image: repeating-linear-gradient(90deg, var(--beam) 0 14px, var(--door) 14px 28px); }
.door--burrow .door__name  { font-family: 'Bree Serif', Georgia, serif; color: var(--lamp); font-size: 27px; }
.door--burrow .door__blurb { color: var(--oat); }
.door--burrow .door__knock { font-family: 'Bree Serif', Georgia, serif; font-size: 12px; letter-spacing: .08em; color: var(--oat-2); }

/* The Mopery's shopfront. The only front in the row lit from INSIDE rather than
   painted on the outside: a cold blue-black window with a warm rectangle in it,
   which is what a second-hand bookshop looks like from the pavement after dark.
   The awning is candle wax and tarnished gilt rather than a two-colour stripe,
   because the stripe is a seaside awning and this shop does not have one. */
.door--mopery { background: var(--mop-night); }
.door--mopery .door__awning { background-image: repeating-linear-gradient(90deg, var(--mop-wax) 0 12px, var(--mop-gilt) 12px 18px, var(--mop-stone) 18px 34px); }
.door--mopery .door__name  { font-family: 'IM Fell English', Georgia, serif; color: var(--mop-gilt); font-size: 30px; }
.door--mopery .door__blurb { color: var(--mop-bone); }
.door--mopery .door__knock { font-family: 'IM Fell English', Georgia, serif; font-size: 13px; letter-spacing: .08em; color: var(--mop-flame); }

/* The Healing Checkpoint (§31). The awning is the one on this street with no
   stripe in it: a gradient rising from the foot, because the light in that room
   comes out of the floor and the shopfront should say so before you go in. */
.door--checkpoint { background: var(--hc-chamber); }
.door--checkpoint .door__awning { background-image: linear-gradient(to top, var(--hc-glim) 0%, var(--hc-spring) 52%, var(--hc-vault) 100%); }
.door--checkpoint .door__name  { font-family: 'Quicksand', var(--sans); font-weight: 700; color: var(--hc-clay); font-size: 27px; }
.door--checkpoint .door__blurb { color: var(--hc-steam); }
.door--checkpoint .door__knock { font-family: 'Quicksand', var(--sans); font-weight: 700; font-size: 12px; letter-spacing: .1em; color: var(--hc-glim); }

/* The Jungle Room's shopfront. Leaves over the awning rather than a stripe,
   because every other front in this row is signwriting and this one is a thing
   growing over a door. The name is set in the room's own swelling serif and
   the blurb in its own sans, which is the whole convention: a door tells you
   what it is like in there before you push it. */
.door--jungle { background: var(--canopy); }
.door--jungle .door__awning { background-image: repeating-linear-gradient(90deg, var(--buttress) 0 9px, var(--palm) 9px 18px, var(--understory) 18px 30px); }
/* Club Chronic's awning is the one on the street with no colour in it: a black
   box with the name on it, which is what a venue awning actually is and what
   CBGB's was. The stripe is the flyers pasted along the bottom of it. */
.door--club .door__awning { background-image: repeating-linear-gradient(90deg, var(--bootblack) 0 16px, var(--paste) 16px 20px, var(--bootblack) 20px 34px); }
.door--club .door__name { font-family: 'Anton', Impact, sans-serif; text-transform: uppercase; letter-spacing: 1px; color: var(--paste); }
.door--jungle .door__name  { font-family: 'Yeseva One', Georgia, serif; color: var(--daylight); font-size: 28px; }
.door--jungle .door__blurb { font-family: 'Cabin', system-ui, sans-serif; color: var(--sap); }
.door--jungle .door__knock { font-family: 'Cabin', system-ui, sans-serif; font-weight: 700; font-size: 12px; letter-spacing: .12em; text-transform: uppercase; color: var(--sun); }

/* The Adventurer's Guild's shopfront, and the only front in the row that is not
   PAINTED. Every other door here is signwriting, a canopy or a lit window --
   somebody selling you a feeling from the pavement. This one is a notice with a
   docket number on it, screwed to the wall, because what is behind it is a
   filing system with a board in it. The awning stripe is a printed rule rather
   than a seaside two-tone, for the same reason. */
.door--guild { background: var(--gu-paper); border-color: var(--gu-ink); }
.door--guild .door__awning { background-image: repeating-linear-gradient(90deg, var(--gu-ink) 0 3px, var(--gu-paper) 3px 11px); border-bottom-color: var(--gu-ink); }
.door--guild .door__name  { font-family: 'Rye', var(--sans); color: var(--gu-ink); font-size: 25px; }
.door--guild .door__blurb { font-family: 'Public Sans', var(--sans); color: var(--gu-ink-2); }
.door--guild .door__knock { font-family: 'Public Sans', var(--sans); font-weight: 700; font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--gu-file); }

/* THE FEED'S DOOR IS A SMALL BOARD IN A SHOPFRONT, and its awning is the one on
   this street made of flap seams rather than stripes, scallops or bunting. The
   name is Michroma at door size and no larger: the widest face in the building
   on the shortest string in the room. */
/* The Foundry's shopfront, and the only MID-GREY front in the row. Every other
   door here is either a dark ground with a bright thing painted on it or a pale
   one; this is the colour of the metal and sits between them, which is what
   makes it findable at a glance without shouting. The awning is corrugated iron
   rather than a stripe, because a workshop has a roof over its door and not a
   canopy, and the name is the only stencil on the street. */
.door--foundry { background: var(--fo-floor); border-color: var(--fo-lead); }
.door--foundry .door__awning { background-image: repeating-linear-gradient(90deg, var(--fo-lead) 0 5px, var(--fo-bench) 5px 11px); border-bottom-color: var(--fo-lead); }
.door--foundry .door__name  { font-family: 'Stardos Stencil', var(--sans); font-weight: 700; color: var(--fo-bone); font-size: 27px; letter-spacing: .02em; }
.door--foundry .door__blurb { color: var(--fo-oil); }
.door--foundry .door__knock { font-family: 'Work Sans', var(--sans); font-weight: 600; font-size: 12px; letter-spacing: .12em; text-transform: uppercase; color: var(--fo-brass); }

/* Covenstead (§37). THE ONE LIT DOOR IN THE ROW, and that is the room showing
   through rather than a flourish: this is the only shopfront on a near-black
   street whose window is pale, because the room behind it is a kitchen in the
   afternoon. The awning is three bands of the three glazes, which is the
   mismatched china arriving on the street before you have opened the door.
   Every ink here is on --cov-wash and is already measured in check-contrast.py
   against that ground. */
.door--covenstead { background: var(--cov-wash); border-color: var(--cov-ink-2); }
.door--covenstead .door__awning { background-image: linear-gradient(90deg, var(--cov-delft) 0 34%, var(--cov-sage) 34% 67%, var(--cov-rose) 67% 100%); border-bottom-color: var(--cov-ink-2); }
.door--covenstead .door__name  { font-family: 'Petrona', Georgia, serif; font-weight: 700; color: var(--cov-ink); font-size: 27px; }
.door--covenstead .door__blurb { color: var(--cov-ink-2); }
.door--covenstead .door__knock { font-family: 'Asap', var(--sans); font-weight: 700; font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--cov-rose); }

/* Dead Tired Society (§40). THE ONE AWNING IN THE ROW WITH A GAP OF LIGHT IN
   IT, and nothing else lit: a dark front with the corridor showing through one
   narrow sliver, which is the door left ajar arriving on the street before you
   have pushed it. The name is the society's charter face and the knock is in
   the corridor's green, because a link on that room is a way out through the
   door. Every ink here is on --dts-room and is measured in check-contrast.py. */
.door--dead-tired { background: var(--dts-room); border-color: var(--dts-edge); }
.door--dead-tired .door__awning { background-image: linear-gradient(90deg, var(--dts-deep) 0 71%, var(--dts-hall) 71% 75%, var(--dts-deep) 75% 100%); border-bottom-color: var(--dts-edge); }
.door--dead-tired .door__name  { font-family: 'Sorts Mill Goudy', Georgia, serif; font-weight: 400; color: var(--dts-pale); font-size: 30px; }
.door--dead-tired .door__blurb { font-family: 'Lexend', var(--sans); color: var(--dts-text); }
.door--dead-tired .door__knock { font-family: 'Lexend', var(--sans); font-weight: 600; font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--dts-exit); }

/* Laughingstock (§41). THE ONE FRONT IN THE ROW WITH A NEON SIGN IN THE WINDOW,
   and the one whose awning is a course of brick: a club front on a night street,
   the name bent in blue tube over a red wall. The sign does not flicker -- no
   neon on this street does, at any setting, for Club Chronic's reason -- and its
   glow is a static shadow. Every ink here is on --ls-house and is measured in
   check-contrast.py. */
.door--laughingstock { background: var(--ls-house); border-color: var(--ls-edge); }
.door--laughingstock .door__awning { background-color: var(--ls-wall); background-image: repeating-linear-gradient(90deg, var(--ls-brick) 0 22px, var(--ls-joint) 22px 25px); border-bottom-color: var(--ls-edge); }
.door--laughingstock .door__name  { font-family: 'Yellowtail', cursive; font-weight: 400; color: var(--ls-neon); font-size: 36px; line-height: 1.05; text-shadow: 0 0 10px rgba(134, 220, 255, .45); }
.door--laughingstock .door__blurb { font-family: 'Bricolage Grotesque', var(--sans); color: var(--ls-text); }
.door--laughingstock .door__knock { font-family: 'Bricolage Grotesque', var(--sans); font-weight: 700; font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--ls-neon); }

/* The Lightbulb Picture House (§42). THE ONE FRONT IN THE ROW WITH ITS LIGHTS ON
   AND NONE OF THEM BLUE: lit velvet under a canopy of warm bulbs, and the name
   in a carved Deco fascia face. The bulbs in the awning are a static row -- they
   do not chase, which is the Arcade's marquee and a flicker by another name.
   Every ink here is on --lph-velvet and is measured in check-contrast.py. */
.door--picture-house { background: var(--lph-velvet); border-color: var(--lph-brass); }
.door--picture-house .door__awning { background-color: var(--lph-deep); background-image: radial-gradient(circle, var(--lph-bulb) 0 4px, transparent 5px); background-size: 22px 100%; background-position: 11px 50%; border-bottom-color: var(--lph-brass); }
.door--picture-house .door__name  { font-family: 'Limelight', Georgia, serif; font-weight: 400; color: var(--lph-cream); font-size: 25px; line-height: 1.15; }
.door--picture-house .door__blurb { font-family: 'Outfit', var(--sans); color: var(--lph-text); }
.door--picture-house .door__knock { font-family: 'Outfit', var(--sans); font-weight: 700; font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--lph-gold); }

/* Samefood Cafe (§47). THE ONE FRONT IN THE ROW WHOSE AWNING IS A TRAY: a grid
   of little wells with a gap of table round every one of them, so that nothing
   in it touches anything else before you have even come in. The name is the
   cafe's own moulded face and the knock is the sauce. Every ink here is on
   --sf-table and is measured in check-contrast.py. */
.door--samefood { background: var(--sf-table); border-color: var(--sf-ink-2); }
.door--samefood .door__awning { background-color: var(--sf-table); background-image: linear-gradient(90deg, var(--sf-table) 0 5px, transparent 5px), linear-gradient(0deg, var(--sf-table) 0 5px, transparent 5px), linear-gradient(var(--sf-plate), var(--sf-plate)); background-size: 26px 100%, 100% 16px, 100% 100%; background-position: 0 0, 0 0, 0 0; border-bottom-color: var(--sf-ink-2); }
.door--samefood .door__name  { font-family: 'Fredoka', var(--sans); font-weight: 600; color: var(--sf-ink); font-size: 30px; line-height: 1.1; }
.door--samefood .door__blurb { font-family: 'Inclusive Sans', var(--sans); color: var(--sf-ink-2); }
.door--samefood .door__knock { font-family: 'Fredoka', var(--sans); font-weight: 600; font-size: 13px; letter-spacing: .08em; text-transform: uppercase; color: var(--sf-sauce); }

.door--feed { background: var(--fd-enamel); border-color: var(--fd-girder); }
.door--feed .door__awning { background-image: repeating-linear-gradient(180deg, var(--fd-flap) 0 6px, var(--fd-split) 6px 7px); border-bottom-color: var(--fd-girder); }
.door--feed .door__name  { font-family: 'Michroma', var(--sans); color: var(--fd-lamp); font-size: 15px; letter-spacing: .1em; text-transform: uppercase; }
.door--feed .door__blurb { color: var(--fd-dim); }
.door--feed .door__knock { font-family: 'Space Mono', ui-monospace, monospace; font-weight: 700; font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--fd-signal); }

/* THE ZIBALDONE'S DOOR IS THE ONLY PALE SHOPFRONT IN THE ROW, which is what a
   commonplace book looks like from the street: a cream page in a dark window.
   Its awning is the fold of a bound gathering rather than a stripe, and the
   name is the oldstyle serif the book's own title is set in. */
.door--zibaldone { background: var(--zb-laid); border-color: var(--zb-oak); }
.door--zibaldone .door__awning { background-image: repeating-linear-gradient(90deg, var(--zb-gutter) 0 2px, var(--zb-laid-2) 2px 9px, var(--zb-tape) 9px 11px); border-bottom-color: var(--zb-oak); }
.door--zibaldone .door__name  { font-family: 'EB Garamond', Georgia, serif; font-weight: 600; color: var(--zb-oak); font-size: 30px; }
.door--zibaldone .door__blurb { font-family: 'Lora', Georgia, serif; color: var(--zb-pencil); }
.door--zibaldone .door__knock { font-family: 'Kalam', cursive; font-weight: 700; font-size: 13px; letter-spacing: 0; color: var(--zb-rubric); }

.door--empty { background: var(--ink-2); border-style: dashed; border-color: #7c6ba8; }
.door--empty .door__awning { background-image: repeating-linear-gradient(90deg, var(--ink-3) 0 14px, var(--ink-2) 14px 28px); border-bottom-style: dashed; border-bottom-color: #7c6ba8; }
.door--empty .door__name  { font-family: 'Bungee', var(--sans); color: var(--chalk); font-size: 23px; }
.door--empty .door__blurb { color: var(--chalk); }
.door--empty .door__knock { font-family: 'Rock Salt', var(--sans); font-size: 11px; letter-spacing: 0; color: #9d8cc8; }

/* The signpost at the end of the shopfronts. NOT A DOOR AT ALL, and the grid
   above is why: a door on this street is a storefront you walk into, and the
   campgrounds is not a storefront — it is where the street stops. So it is one
   plank pointing off the end, the full width of the row, shaped like a
   fingerpost rather than boxed like a shop. It wears the street's Bungee and
   the street's green because it is a street object; what it points at is
   nothing like it.

   PAINTED, NOT OUTLINED — every door in the grid is an outlined box, and a border
   cannot survive the clip-path that cuts the point anyway: it came out as a
   bordered plank with a borderless triangle stuck on the end. A solid plank
   takes the cut cleanly, and dark-on-green is a pair this street already
   holds. */
/* The noticeboard on the pavement, and the SECOND thing here that is not a
   door. A storefront is permanent and singular; the Pebble Board is defined by
   being replaced, edition after edition, with the old ones kept. A shop whose
   entire stock is swapped out every gathering is a periodical, and giving it a
   shopfront would quietly make every other shopfront look temporary.

   It also could not be a door for a second reason: Your Room already holds the
   "the community gets a storefront" slot, and that one means something exact --
   ONE person decorates ONE room. The board is everybody at once. Two community
   doors on one street makes both of them vaguer about which to knock on.

   A STREET OBJECT IN THE STREET'S CLOTHES, like the signpost: the street's
   Bungee, the street's green, a case on two legs. What is inside the glass
   looks nothing like it, which is the whole arrangement. */
.noticeboard { display: block; margin: 26px 0 0; text-decoration: none; }
/* BLOCK, and the first version was not. A <span> is inline, so the border drew
   itself once per line-box -- three ragged green brackets down the left of the
   text -- and the padding pushed nothing. An inline box cannot be a case with
   something inside it, which is the whole picture here. */
.noticeboard__case {
  display: block;
  border: 3px solid var(--green); border-radius: 10px 10px 4px 4px;
  background: var(--ink-2); padding: 14px 18px 15px;
  box-shadow: inset 0 3px 0 var(--green);
}
.noticeboard:hover .noticeboard__case { background: var(--ink-3); }
.noticeboard__what {
  display: block; font-family: 'Bungee', var(--sans); font-size: 17px;
  letter-spacing: 1px; color: var(--green);
}
.noticeboard__why { display: block; margin-top: 7px; font-size: 14.5px; max-width: 62ch; color: var(--chalk); }
/* space-between rather than a percentage gap: a % gap resolves against the
   container and put both legs in the middle of the pavement. */
.noticeboard__legs { display: flex; justify-content: space-between; margin: 0 26px; }
.noticeboard__legs::before, .noticeboard__legs::after {
  content: ""; width: 10px; height: 16px; background: var(--ink-3); border-radius: 0 0 3px 3px;
}

.signpost { display: flex; align-items: stretch; margin: 26px 0 0; text-decoration: none; }
.signpost__post { flex: 0 0 14px; background: var(--ink-3); border-radius: 3px 3px 0 0; }
.signpost__arm {
  flex: 1 1 auto; display: flex; flex-wrap: wrap; gap: 4px 20px;
  align-items: baseline; justify-content: space-between;
  margin: 14px 0; padding: 15px 52px 15px 18px;
  background: var(--green); color: var(--ink);
  clip-path: polygon(0 0, calc(100% - 30px) 0, 100% 50%, calc(100% - 30px) 100%, 0 100%);
}
.signpost:hover .signpost__arm { background: var(--cyan); }
.signpost__to { font-family: 'Bungee', var(--sans); font-size: 17px; letter-spacing: 1px; }
.signpost__why { font-size: 14.5px; max-width: 62ch; }

/* THE OTHER END OF THE STREET, and the fourth thing here that is not a door.
   The signpost points off the end at a field; this points off the other end at a
   road. They are deliberately opposite objects: a signpost is a thing somebody
   put up FOR you, painted, maintained, with an arrow on it. This is the LAST
   STREETLIGHT — the last piece of the town's own kit before there is none, so
   the pool of light under it fades out to the right and the words carry on into
   the dark. Nothing out there is signposted. That is the area's whole premise,
   and the furniture on this page should already say so before you leave.

   THE WASH IS DECORATION AND THE WORDS DO NOT STAND ON IT. It is on the lamp's
   own strip, which carries nothing — the Rabbit Hole's rule about a gradient
   under type, applied by keeping the two apart rather than by measuring a
   gradient nobody can measure. */
.roadout { display: flex; align-items: stretch; margin: 26px 0 0; text-decoration: none; }
.roadout__lamp {
  flex: 0 0 18px; border-radius: 3px 3px 0 0;
  background: linear-gradient(to bottom, var(--yellow) 0 26px, var(--ink-3) 26px);
}
.roadout__arm {
  flex: 1 1 auto; display: flex; flex-wrap: wrap; gap: 4px 20px;
  align-items: baseline; justify-content: space-between;
  margin: 14px 0; padding: 15px 20px 15px 22px;
  background: var(--ink-2); color: var(--cream);
  border-top: 3px solid var(--ink-3); border-bottom: 3px solid var(--ink-3);
}
.roadout:hover .roadout__arm { background: var(--ink-3); }
.roadout__to { font-family: 'Bungee', var(--sans); font-size: 17px; letter-spacing: 1px; color: var(--yellow); }
.roadout__why { font-size: 14.5px; max-width: 62ch; }

/* THE GATE IN THE WALL, and the THIRD thing on this street that is not a door.
   The signpost points off the end of the street at a field; the noticeboard is
   a case bolted to the pavement; this is a HOLE IN THE WALL between two
   shopfronts, with daylight coming through it.

   It could not be a door in the grid for the plainest reason yet: the garden is
   not a room of ours at all. Every bed in it links out to a different site we
   publish, and a shopfront promising a room you never arrive in would be the
   street telling a lie about its own architecture. So it is an opening rather
   than a premises -- you go through it and out.

   AND IT IS THE ONE PLACE ON A NIGHT STREET WHERE THE SUN IS UP. The doors
   each carry their own room's colours, which is this street's oldest grammar,
   and what is behind this one is midday: the opening is filled with the
   garden's own daylight, the words in it are dark on that light, and the wall
   around it stays the street's. Arched and centred, because an arch is
   symmetrical and the other two street objects are neither. */
.gardengate { display: block; margin: 26px 0 0; text-decoration: none; }
.gardengate__arch {
  display: block; text-align: center;
  background: var(--gd-day); color: var(--gd-loam);
  border: 5px solid var(--ink-3);
  border-radius: 170px 170px 5px 5px;
  padding: 42px 38px 20px;
}
.gardengate:hover .gardengate__arch { background: var(--gd-board); }
.gardengate__to {
  display: block; font-family: 'Bungee', var(--sans); font-size: 17px;
  letter-spacing: 1px; color: var(--gd-leaf);
}
.gardengate__why {
  display: block; margin: 8px auto 0; font-size: 14.5px; max-width: 58ch;
  color: var(--gd-loam-2);
}

.pavement {
  margin-top: 40px; border-top: 3px solid var(--ink-3); background: var(--ink-2);
  padding: 22px 0 34px;
}
.pavement a { color: var(--yellow); }
.pavement .chalk { font-family: 'Rock Salt', var(--sans); font-size: 12.5px; color: var(--yellow); }


/* §6 ── ROOM: Pink Pony Club ─────────────────────────────────────────────────
   The dancefloor. Hot pink ground, cream ink, a mirrorball made of conic
   gradients. The jukebox is ten facades — press to play, nothing before. */

.room-pony { background: var(--hot); color: #2b0a1c; }
.room-pony .backlink { color: #2b0a1c; }
.room-pony .glow {
  position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background-image: repeating-conic-gradient(from 0deg at 26% 20%, rgba(255,243,230,.16) 0deg 9deg, rgba(255,61,154,0) 9deg 18deg);
}
.room-pony > * { position: relative; z-index: 1; }
.room-pony h1 { font-family: 'Shrikhand', var(--sans); font-size: clamp(54px, 9vw, 92px); line-height: .9; color: var(--cream); text-shadow: 5px 5px 0 #2b0a1c; margin: 18px 0 0; }
.room-pony .lede { font-size: 19px; line-height: 1.5; font-weight: 500; max-width: 46ch; margin: 22px 0 0; }
.room-pony h2 { font-family: 'Bungee', var(--sans); font-size: 20px; color: var(--cream); letter-spacing: 1px; }
.room-pony a { color: #2b0a1c; }
/* The ring is the room's ink. Yellow was 2.51 on the hot pink and 1.31 round
   a white jukebox card; the ink is 5.49 and 18.06. check-focus.py. */
.room-pony :focus-visible { outline-color: #2b0a1c; }
/* The two dark plates below the decks are the ink as a ground, so they take
   the yellow back: 13.78 there, where the ink would be 1.00. */
.room-pony .pony-dark :focus-visible { outline-color: var(--yellow); }

.mirrorball { width: 74px; height: 74px; border-radius: 50%; border: 4px solid var(--cream); background-image: repeating-conic-gradient(from 0deg, var(--cream) 0deg 12deg, #c9a9be 12deg 24deg); flex: none; }

.consent {
  background: #2b0a1c; border: 4px solid var(--cream); border-radius: 20px;
  padding: 22px 24px; color: #ffd9ec; margin: 28px 0 0;
}
.consent strong { display: block; font-family: 'Bungee', var(--sans); font-weight: 400; font-size: clamp(19px,2.6vw,23px); line-height: 1.15; color: var(--yellow); margin-bottom: 11px; }

.jukebox { list-style: none; margin: 18px 0 0; padding: 16px; background: var(--cream); border: 4px solid #2b0a1c; border-radius: 16px; display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); }
.track { background: #fff; border: 2px solid #e0a9c6; border-radius: 12px; padding: 13px 14px; }
.track h3 { margin: 0; font-size: 18px; color: #2b0a1c; }
.track p  { margin: 3px 0 11px; font-size: 13px; color: #6b3a55; }
.track .facade { aspect-ratio: 16/9; }

/* THE DECKS — the room's other tray, and not a second jukebox. The jukebox is
   a grid of narrow cards, one song each, picked off our own published page;
   this is one wide record at a time, a whole playlist we keep on our own
   channel, put on and left running.

   SAME MATERIALS ON PURPOSE, DIFFERENT PROPORTION. Cream tray, white card,
   dark red rule, the same small plum for the credit line — every colour here
   is a pair check-contrast.py already holds for a .track, so the decks
   introduced nothing to measure. What separates them is that the jukebox packs
   its cards into columns and this one never has more than one across: a record
   on the deck is a thing you put on, not a thing you scan. If these ever grow
   a second column they have become the jukebox with longer titles in it.

   NO RUNTIME ON THESE BUTTONS, and make-jukebox.py refuses one. A playlist is
   a list we keep adding to; today's total is wrong the next time it changes. */
.decks { list-style: none; margin: 18px 0 0; padding: 16px; background: var(--cream); border: 4px solid #2b0a1c; border-radius: 16px; display: grid; gap: 14px; grid-template-columns: 1fr; }
.decks__rec { background: #fff; border: 2px solid #e0a9c6; border-left: 9px solid #2b0a1c; border-radius: 12px; padding: 14px 16px; }
.decks__rec h3 { margin: 0; font-size: 20px; color: #2b0a1c; }
.decks__rec p  { margin: 3px 0 11px; font-size: 13.5px; color: #6b3a55; }
.decks__rec .facade { aspect-ratio: 16/9; }
/* Scoped rather than !important: .decks__rec p sets the margin above and would
   out-rank a bare .decks__via. This room's furniture is not shared, so there is
   nothing here that earns the hammer §2's [hidden] guard needs. */
.decks__rec .decks__via { margin: 9px 0 0; font-size: 12px; color: #6b3a55; line-height: 1.5; }


/* §7 ── ROOM: The Zine Table ─────────────────────────────────────────────────
   Photocopier grain, ransom-note headline, two columns of typewriter.
   Already black-on-white, so gentle mode costs this room the least. */

.room-zine { background: var(--paper); color: var(--ink); font-family: 'Courier Prime', monospace; }
.room-zine .backlink { font-family: 'Courier Prime', monospace; color: var(--ink); text-decoration: underline; letter-spacing: 0; }
/* Photocopier black, 15.35 on the paper, where yellow was 1.09. */
.room-zine :focus-visible { outline-color: var(--ink); }
/* The pull quote and the black box in the foot row are the ink as a ground,
   and take the yellow the zine's own links there are already set in. */
.room-zine :is(.pullquote, .zine-black) :focus-visible { outline-color: var(--yellow); }
.room-zine .grain {
  position: fixed; inset: 0; pointer-events: none; opacity: .16; z-index: 0;
  background-image:
    repeating-linear-gradient(0deg,  rgba(21,18,31,.5)  0 1px, transparent 1px 3px),
    repeating-linear-gradient(90deg, rgba(21,18,31,.35) 0 1px, transparent 1px 4px);
}
.room-zine > * { position: relative; z-index: 1; }

.ransom { display: flex; flex-wrap: wrap; gap: 6px 11px; align-items: baseline; margin: 16px 0 0; }
.ransom span { display: inline-block; line-height: .9; padding: 2px 9px; }
.ransom .r1 { font-family: 'Archivo Black', var(--sans); font-size: clamp(42px,7vw,72px); color: var(--ink);  background: var(--yellow); transform: rotate(-2.5deg); }
.ransom .r2 { font-family: 'Special Elite', var(--sans); font-size: clamp(38px,6.2vw,62px); color: var(--paper); background: var(--ink); transform: rotate(1.5deg); }
.ransom .r3 { font-family: 'Shrikhand', var(--sans);     font-size: clamp(40px,6.6vw,66px); color: var(--red); background: none; transform: rotate(-1deg); }
.ransom .r4 { font-family: 'Bungee', var(--sans);        font-size: clamp(34px,5.8vw,58px); color: var(--ink);  background: var(--cyan); transform: rotate(2deg); }
.ransom .r5 { font-family: 'Archivo Black', var(--sans); font-size: clamp(41px,7vw,70px); color: var(--paper); background: var(--red); transform: rotate(-1.5deg); }
html[data-intensity="gentle"] .ransom span { transform: none; }

.zine-cols { columns: 2 260px; column-gap: 28px; column-rule: 1px solid #b9b2a3; margin-top: 12px; }
.zine-cols p { margin: 0 0 13px; font-size: 14.5px; line-height: 1.62; }
.zine-cols .shout { font-family: 'Special Elite', var(--sans); font-size: 16px; color: var(--red); }

.pullquote { background: var(--ink); color: var(--paper); padding: 22px 24px; position: relative; }
.pullquote blockquote { margin: 0; font-family: 'Special Elite', var(--sans); font-size: clamp(21px,3vw,26px); line-height: 1.26; }
.pullquote cite { display: block; margin-top: 13px; font-family: 'Courier Prime', monospace; font-size: 12.5px; font-style: normal; color: #b9b2a3; }
.pullquote .tape { position: absolute; top: -12px; left: 28px; width: 108px; height: 26px; background: rgba(237,234,226,.72); border: 1px solid rgba(21,18,31,.25); transform: rotate(-3deg); }
html[data-intensity="gentle"] .pullquote .tape { transform: none; }

.keeps { background: var(--yellow); border: 3px solid var(--ink); padding: 18px 20px; }
.keeps h2 { font-family: 'Archivo Black', var(--sans); font-size: 17px; margin: 0 0 12px; }
.keeps dl { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px,1fr)); gap: 16px; margin: 0; }
.keeps dt { font-weight: 700; }
.keeps dd { margin: 3px 0 0; font-size: 13.5px; line-height: 1.5; }



/* §8 ── ROOM: Hear Queer Here ────────────────────────────────────────────────
   Deep space, interference fringes, a mono face and a serif arguing. */

.room-quantum { background: #05060f; color: #d8d4ff; }
.room-quantum .backlink { font-family: 'VT323', monospace; font-size: 19px; letter-spacing: 0; color: var(--green); }
.room-quantum .glow {
  position: fixed; inset: 0; pointer-events: none; z-index: 0; opacity: .5;
  background-image:
    repeating-linear-gradient(90deg, rgba(0,212,255,.22) 0 2px, transparent 2px 26px),
    repeating-linear-gradient(90deg, rgba(163,77,255,.16) 0 3px, transparent 3px 41px);
}
.room-quantum > * { position: relative; z-index: 1; }
.room-quantum h1 { font-family: 'VT323', monospace; font-size: clamp(56px,10vw,108px); line-height: .82; color: var(--cyan); text-shadow: 3px 0 0 rgba(255,45,149,.8), -3px 0 0 rgba(34,224,106,.8); margin: 14px 0 0; }
.room-quantum .lede { font-family: 'Instrument Serif', serif; font-style: italic; font-size: clamp(22px,3.4vw,30px); line-height: 1.3; color: #d8d4ff; max-width: 40ch; margin: 16px 0 0; }
.room-quantum a { color: var(--cyan); }

.qcard { border: 2px solid #2a2d5c; border-radius: 16px; padding: 22px 24px; }
.qcard blockquote { margin: 0; font-family: 'Instrument Serif', serif; font-size: clamp(22px,3vw,30px); line-height: 1.24; color: #fff; }
.qcard cite { display: block; margin-top: 14px; font-family: var(--sans); font-size: 13px; font-style: normal; line-height: 1.5; color: #a6a1d4; }
.qcard--barad { background: rgba(0,212,255,.05); }
.qcard--helen { background: rgba(34,224,106,.05); }
.qcard--helen a { color: var(--green); }

.fringe { position: relative; height: 210px; border-radius: 12px; overflow: hidden; background: #0a0d22; border: 1px solid #2a2d5c; }
.fringe::before, .fringe::after { content: ""; position: absolute; inset: 0; }
.fringe::before { background-image: repeating-linear-gradient(90deg, rgba(0,212,255,.55) 0 4px, transparent 4px 22px); }
.fringe::after  { background-image: repeating-linear-gradient(90deg, rgba(255,45,149,.45) 0 4px, transparent 4px 29px); }
.fringe span { position: absolute; left: 0; right: 0; bottom: 14px; text-align: center; font-family: 'VT323', monospace; font-size: 21px; color: #fff; z-index: 1; }

.collapse { display: flex; gap: 10px; flex-wrap: wrap; }
.collapse button { flex: 1 1 140px; cursor: pointer; font-family: 'VT323', monospace; font-size: 20px; padding: 12px 8px; border-radius: 10px; background: transparent; }
.collapse .a { border: 2px solid var(--cyan);  color: var(--cyan); }
.collapse .b { border: 2px solid var(--pink);  color: var(--pink); }
.collapse .c { border: 2px solid var(--green); color: var(--green); background: rgba(34,224,106,.14); }
.collapse button[aria-pressed="true"] { background: currentColor; }
.collapse button[aria-pressed="true"] span { color: #05060f; }

.term { font-family: 'VT323', monospace; font-size: 22px; color: var(--pink); margin: 0; }


/* The audio room. The words are always present; the player arrives when the
   file does. A passage tied to a panel state lifts when that button is pressed
   — highlight only, because nothing on this street plays without a press. */
.readings h2 { font-family: 'Bungee', var(--sans); font-size: 15px; color: var(--cyan); letter-spacing: 1px; margin: 0 0 14px; }
.readings__lead { margin: 0 0 18px; font-size: 14px; line-height: 1.6; color: #a6a1d4; }
.reading { border-top: 1px solid #2a2d5c; padding: 16px 0 16px 14px; border-left: 3px solid transparent; }
/* NOT .term -- that is already the terminal-style line further up this section,
   and reusing it put a border between "the instrument decides what it can see"
   and the line that finishes the sentence. */
.readset { margin-top: 6px; }
.readset + .readset { margin-top: 26px; border-top: 2px solid #2a2d5c; padding-top: 18px; }
.readset__name { margin: 0 0 6px; font-family: 'Bungee', var(--sans); font-size: 14px; letter-spacing: 1px; color: var(--pink); }
.readset__lead { margin: 0 0 14px; font-size: 13.5px; line-height: 1.6; color: #a6a1d4; }
.reading h4 { margin: 0 0 8px; font-family: 'VT323', monospace; font-size: 21px; letter-spacing: .5px; color: var(--cyan); }
.measuring { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 12px; }
.measuring__label { font-family: 'VT323', monospace; font-size: 18px; color: #8c87bd; }
.measuring__btn { cursor: pointer; font-family: 'VT323', monospace; font-size: 18px; padding: 5px 11px; border-radius: 8px; background: transparent; border: 2px solid #3a3d72; color: #d8d4ff; }
.measuring__btn[aria-pressed="true"] { border-color: var(--violet); color: var(--violet); }
.reading__text { margin: 0; font-family: 'Instrument Serif', serif; font-size: 19px; line-height: 1.45; color: #d8d4ff; }
.reading__empty { margin: 12px 0 0; font-size: 13px; line-height: 1.5; color: #8c87bd; }
.reading__player { margin-top: 12px; width: 100%; max-width: 420px; }

.seqplay { margin-top: 14px; }
.seqplay__btn { width: 100%; cursor: pointer; font-family: 'VT323', monospace; font-size: 19px; line-height: 1.25; padding: 11px 10px; border-radius: 10px; background: transparent; border: 2px solid var(--green); color: var(--green); }
.seqplay__btn[disabled] { cursor: default; border-color: #3a3d72; color: #8c87bd; }
.seqplay__btn[data-mode="stop"] { background: var(--green); color: #05060f; }
.seqplay__now { margin: 10px 0 0; font-size: 13px; line-height: 1.5; color: #a6a1d4; min-height: 1.3em; }
.reading--playing { border-left-color: var(--green) !important; background: rgba(34,224,106,.07) !important; }

/* The three that answer to the panel. Pressed state lifts one; the others stay
   legible rather than dimming, because Gentle hides nothing and neither does this. */
/* Marked by love.js rather than by a descendant selector, because with more
   than one term the match depends on BOTH which term is being measured and
   which way it was collapsed, and static CSS cannot name a term it has not
   met yet. */
.reading--collapsed[data-reading-state="a"]    { border-left-color: var(--cyan);  background: rgba(0,212,255,.05); }
.reading--collapsed[data-reading-state="b"]    { border-left-color: var(--pink);  background: rgba(255,45,149,.05); }
.reading--collapsed[data-reading-state="open"] { border-left-color: var(--green); background: rgba(34,224,106,.05); }

/* The fringe's three states, driven by the superposition panel in love.js.
   "open" is the default and shows both patterns at once. */
.fringe[data-state="a"]::after  { display: none; }
.fringe[data-state="b"]::before { display: none; }

/* §9 ── ROOM: Enid's Room ────────────────────────────────────────────────────
   Black walls, technicolour everything else. The room for the one who does not
   match the house — and the template the empty storefront is built from. */

.room-enid { background: #101014; color: #ece8f5; }
.room-enid .backlink { font-family: 'Special Elite', var(--sans); font-size: 14px; letter-spacing: 0; color: var(--pink); }
.room-enid .glow {
  position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background-image:
    radial-gradient(ellipse at 84%  8%, rgba(172,91,255,.24) 0%, rgba(16,16,20,0) 55%),
    radial-gradient(ellipse at  6% 92%, rgba(34,224,106,.18) 0%, rgba(16,16,20,0) 55%);
}
.room-enid > * { position: relative; z-index: 1; }
.room-enid h1 { font-family: 'Bungee Shade', var(--sans); font-size: clamp(42px,7.5vw,76px); line-height: .96; color: var(--green); margin: 12px 0 0; }
.room-enid h2 { font-family: 'Bungee', var(--sans); font-size: 15px; letter-spacing: 1px; margin: 0; }
.room-enid a { color: var(--green); }

.panel { border: 3px solid #2a2a34; border-radius: 18px; padding: 22px 24px; background: #16161d; }
.panel--pink { border-color: var(--pink); }

.stickers { list-style: none; display: flex; flex-wrap: wrap; gap: 11px; margin: 16px 0 0; padding: 0; }
.stickers a { display: inline-block; color: #101014; text-decoration: none; padding: 9px 15px; font-size: 15px; }
.stickers a:hover { text-decoration: underline; }
.stickers .s1 { font-family: 'Bungee', var(--sans);        background: var(--pink);   border-radius: 24px; transform: rotate(-3deg); }
.stickers .s2 { font-family: 'Bungee', var(--sans);        background: var(--green);  border-radius: 6px;  transform: rotate(2deg); }
.stickers .s3 { font-family: 'Special Elite', var(--sans); background: var(--yellow); border-radius: 24px; transform: rotate(-1deg); font-size: 17px; }
.stickers .s4 { font-family: 'Bungee', var(--sans);        background: var(--cyan);   border-radius: 6px;  transform: rotate(3deg); }
.stickers .s5 { font-family: 'Rock Salt', var(--sans);     background: var(--violet); border-radius: 24px; transform: rotate(-2deg); font-size: 13px; }
.stickers .s6 { font-family: 'Bungee', var(--sans);        background: var(--orange); border-radius: 6px;  transform: rotate(1.5deg); }
.stickers .s7 { font-family: 'Special Elite', var(--sans); background: var(--red);    border-radius: 24px; transform: rotate(-2.5deg); color: #fff; font-size: 17px; }
html[data-intensity="gentle"] .stickers a { transform: none; }

/* The wall is a wall, not a stack. Polaroids are all one size -- real ones are
   -- and they pack across and wrap, so the tenth photograph widens the wall
   instead of lengthening the page under it. Heights stay ragged because the
   frame adapts to each picture, which is the no-crop promise showing its work.
   The note is a flex item too, since make-polaroids.py writes it last inside
   the markers, so it is given a line of its own rather than left to squeeze
   into whatever gap the final photo happened to leave. */
.polaroid-wall { display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-start; }
.polaroid-wall .polaroid { flex: 0 0 auto; width: 232px; }
.polaroid-wall .polaroid__note { flex: 1 1 100%; }

.polaroid { background: #ece8f5; border-radius: 4px; padding: 11px 11px 0; transform: rotate(-2deg); }
/* Three photos in a row all leaning the same way reads as one skewed strip
   rather than three separately pinned pictures, so every other one leans back.
   :where() is load-bearing: it contributes no specificity, which keeps this at
   (0,2,0). The obvious `.polaroid-wall .polaroid:nth-child(even)` would be
   (0,3,0) and would OUT-SPECIFY the Gentle reset further down -- leaving the
   wobble switched on for exactly the people who asked for it to stop. The dial
   outranks the decoration, and the selector has to be written so it cannot
   quietly stop being true. */
:where(.polaroid-wall) .polaroid:nth-child(even) { transform: rotate(1.5deg); }
.polaroid__plate { aspect-ratio: 1; background: #2a2a34; border-radius: 2px; }
.polaroid figcaption { font-family: 'Rock Salt', var(--sans); font-size: 11px; color: #3a3644; padding: 14px 0; line-height: 1.4; }
/* A real photo keeps its own shape. The plate is square for the grey
   placeholder, but forcing a photograph into it means object-fit: cover, and
   cover crops -- which polaroids.html explicitly promises we will not do to
   anybody. The frame adapts to the picture instead of the other way round. */
img.polaroid__plate { display: block; width: 100%; height: auto; aspect-ratio: auto; }
.polaroid__credit { display: block; margin-top: 7px; font-family: var(--sans); font-size: 10.5px; letter-spacing: .2px; }
.polaroid__note { margin: 0; background: #16161d; border: 3px solid #2a2a34; border-radius: 14px; padding: 14px 15px; font-size: 13px; line-height: 1.45; color: #b9b5c9; }
.polaroid__note a { color: var(--green); }
html[data-intensity="gentle"] .polaroid { transform: none; }

.boombox { border: 2px solid #2a2a34; border-radius: 12px; padding: 15px; display: flex; gap: 11px; align-items: center; }
.boombox .cone { width: 44px; height: 44px; border-radius: 50%; border: 3px solid #6d6a7a; flex: none; }


/* §10 ── ROOM: The Playhouse ─────────────────────────────────────────────────
   Saturated primaries, checkerboard floor, everything is a real button. */

.room-play { background: var(--blue); color: #fff; }
.room-play .backlink { color: #fff; }
.room-play h1 { font-family: 'Titan One', var(--sans); font-size: clamp(44px,8vw,78px); line-height: .95; color: var(--yellow); text-shadow: 5px 5px 0 #101014; margin: 12px 0 0; }
.room-play .lede { font-size: 19px; font-weight: 500; max-width: 46ch; }
/* THREE LINKS IN THIS ROOM WERE 1.31:1 AND THE CHECKER COULD NOT SEE THEM.
   `.room-play a` was yellow, which is the room's colour and is right on the
   near-black boxes — and the only links on this page are on the blue ground and
   inside the WHITE house-rules cards. Yellow on that white measures 1.31; the
   quest marker's hand-in link measured 3.88 on the blue at 15px. Nothing held a
   pair for either, because check-contrast.py holds a pair for every colour
   somebody DECIDED on and an inherited one was never decided — the exact hole
   the Doomscroll left, in a room that has been published since the street
   opened. Ryan found it by looking at the page; so did the Doomscroll's.

   So the room decides, at each ground it actually has. White on the blue is
   5.08 and the room's own blue on the white cards is 5.08. The yellow stays
   where it was always legible: the h1, which is large, and the near-black
   boxes. */
.room-play a { color: #fff; }
.room-play .rules a { color: var(--blue); }
/* The blue ground keeps the yellow ring. The two grounds it does not reach are
   the white house rules (1.31) and the pink telephone tile (2.64), so those
   decide their own: the room's blue at 5.08 and the near-black at 5.33. */
.room-play .rules :focus-visible { outline-color: var(--blue); }
.room-play .toy--pink :focus-visible { outline-color: var(--ink); }

.bunting { height: 40px; border-bottom: 5px solid #101014; background-image: repeating-linear-gradient(90deg, var(--red) 0 44px, var(--yellow) 44px 88px, var(--green) 88px 132px, var(--violet) 132px 176px); }

.secret { background: var(--red); border: 5px solid #101014; border-radius: 20px; padding: 18px 20px; transform: rotate(2deg); }
html[data-intensity="gentle"] .secret { transform: none; }
.secret h2 { font-family: 'Bungee', var(--sans); font-size: 13px; letter-spacing: 1px; color: var(--yellow); margin: 0; }
.secret p  { font-family: 'Titan One', var(--sans); font-size: clamp(30px,4.6vw,42px); line-height: 1; color: #fff; margin: 7px 0 8px; }
.secret small { font-size: 13px; color: #ffe0e2; font-weight: 500; }

.toys { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 16px; margin: 0; padding: 0; list-style: none; }
@media (max-width: 620px) { .toys { grid-template-columns: 1fr; } }
.toy {
  width: 100%; cursor: pointer; text-align: left; font-family: var(--sans);
  border: 5px solid #101014; border-radius: 24px; padding: 20px 18px;
  display: flex; flex-direction: column; gap: 12px; min-height: 168px;
  transition: transform .15s ease;
}
.toy strong { font-family: 'Titan One', var(--sans); font-weight: 400; font-size: 27px; line-height: 1.05; }
.toy__what  { font-size: 13.5px; line-height: 1.45; font-weight: 500; }
.toy--yellow { background: var(--yellow); color: #101014; } .toy--yellow .toy__what { color: #3a3200; }
.toy--green  { background: var(--green);  color: #101014; } .toy--green  .toy__what { color: #0a3a1c; }
.toy--violet { background: var(--violet-deep); color: #fff; }    .toy--violet .toy__what { color: #efe2ff; }
.toy--orange { background: var(--orange); color: #101014; } .toy--orange .toy__what { color: #3d2100; }

/* SIX MORE TOYS, SIX MORE FILLS, AND NO TWO THE SAME. That is the street's own
   rule holding at the size of one object, and it is the only thing keeping a
   wall of ten boxes from reading as a grid of one box — make-toys.py refuses a
   fill claimed twice. The four above tint their blurb; these bright ones set the
   room's flat near-black for both the title and the blurb, because a tint per
   fill is four more grounds nobody measured for the sake of a shade. Every pair
   here is in check-contrast.py. */
.toy--cyan   { background: var(--cyan);   color: #101014; } .toy--cyan .toy__what   { color: #101014; }
.toy--pink   { background: var(--pink);   color: #101014; } .toy--pink .toy__what   { color: #101014; }
.toy--lilac  { background: var(--violet); color: #101014; } .toy--lilac .toy__what  { color: #101014; }
.toy--white  { background: #ffffff;       color: #101014; } .toy--white .toy__what  { color: #101014; }
/* Red carries white at display size and the room's pale pink below it: white on
   this red is 6.21 and passes at any size, but the 13.5px blurb is exactly where
   a near-white is the one to measure rather than assume — 5.03. */
.toy--red    { background: var(--red); color: #ffffff; } .toy--red .toy__what { color: #ffe0e2; }
/* The off switch is the only unlit tile on a wall of lit ones. It is the toy
   that takes something away, and it looks like it. */
.toy--night  { background: #101014; color: var(--yellow); border-color: #ffffff; }
.toy--night .toy__what { color: var(--cream); }

/* THE TILE IS NOT ALWAYS THE BUTTON. The telephone has two controls in it, so
   its tile is a <div> and the handsets are the buttons — a button cannot be
   nested inside a button, and the alternative was one control pretending to be
   two. It is the only toy on this wall with more than one thing to press. */
.toy--pair { cursor: default; }
.handsets { display: flex; flex-wrap: wrap; gap: 8px; margin-top: auto; }
.handset {
  flex: 1 1 auto; cursor: pointer; font-family: 'Bungee', var(--sans);
  font-size: 12px; letter-spacing: .5px; line-height: 1.1;
  background: #101014; color: var(--cream);
  border: 3px solid #101014; border-radius: 12px; padding: 10px 12px;
  transition: transform .12s ease;
}
.handset:hover { transform: translateY(-2px); }
.handset:active { transform: translateY(2px); }

/* EVERY TOY IS AN IDEA WEARING A COSTUME, AND THE LINE UNDER THE TILE SAYS
   WHICH IDEA. It sits outside the button because an <a> cannot live inside one,
   which turns out to be the right shape anyway: the tile does the thing and the
   line says where the thing came from. Two toys have no single glossary term
   behind them and get no line, because a uniform row of links would mean
   inventing one for them. */
.toys li { display: flex; flex-direction: column; }
.toys .toy { flex: 1 1 auto; }
.toy__idea { margin: 7px 0 0; font-size: 12.5px; line-height: 1.4; font-weight: 500; color: #ffffff; }
.toy__idea a { color: #ffffff; text-decoration-thickness: 2px; text-underline-offset: 3px; }

/* THE ANSWER COMES BACK ON THE THING YOU PRESSED, which this room did not do
   until the person who asked for it said the buttons looked broken. The live
   region is at the top of the page and is off the screen by the time anybody
   has scrolled to the toys, so every press was landing somewhere the presser
   could not see. A control that gives no sign of having worked IS broken,
   whatever the markup says — and it was invisible to us because we had been
   testing by reading the box.

   Near-black with cream on every tile, which is one measured pair for ten
   fills rather than ten. The unlit tile gets an edge, because a near-black
   panel on a near-black tile is no panel at all. It ships hidden, so a page
   with no JavaScript shows no empty box; §2's [hidden] guard is what makes
   that stick against the display rule here. */
.toy__said {
  display: block; margin-top: 10px; padding: 9px 11px;
  background: #101014; color: var(--cream);
  border-radius: 10px;
  font-size: 12.5px; line-height: 1.45; font-weight: 500;
}
.toy--night .toy__said { border: 2px solid var(--cream); }

/* The board answers once, under the keys: a key is about a hundred pixels wide
   and a sentence does not fit on one. */
.stimboard__said {
  margin: 14px 0 0; padding: 11px 13px;
  border: 2px solid var(--cream); border-radius: 10px;
  color: var(--cream); font-size: 14px; line-height: 1.5; font-weight: 500;
}

.rules { background: #fff; border: 5px solid #101014; border-radius: 24px; padding: 20px 22px; color: #101014; }
.rules h2 { font-family: 'Bungee', var(--sans); font-size: 14px; letter-spacing: 1px; color: var(--red); margin: 0 0 12px; }
.rules p { margin: 0 0 12px; font-size: 14.5px; line-height: 1.55; }

/* THE SOUND BOARD. A black slab with nine lit keys bolted to it, which is a
   different object from the toys above it on purpose: the toys are four big
   soft-cornered tiles you read, and this is an instrument you play. The slab is
   the same near-black and white edge as the says-box, because it is the same
   kind of thing — a piece of equipment in a room made of cardboard and paint.

   NINE KEYS, SIX COLOURS AND ONE NIGHT. The top rows are bright keys with the
   room's own near-black ink on them; the bottom row is the mood row and is
   black with a white edge, so which row you are in is carried by the key itself
   rather than only by where it sits. Every one of those seven grounds is in
   check-contrast.py.

   AND THERE ARE NO FACES ON IT. The moods are a word, a drawn line and a sound.
   A row of happy/sad/angry faces on a Disabled people's site is the emotion
   flashcard, and it is the kind of thing that arrives by accident from somebody
   drawing a friendly icon — see the note in data/soundboard.json. */

.stimboard {
  margin: 26px 0 0; padding: 20px 20px 22px;
  background: #101014; border: 5px solid #fff; border-radius: 22px;
}
.stimboard h2 {
  margin: 0; font-family: 'Titan One', var(--sans); font-weight: 400;
  font-size: clamp(26px, 4.6vw, 40px); line-height: 1; color: var(--yellow);
}
.stimboard__note { margin: 11px 0 0; max-width: 64ch; font-size: 14.5px; line-height: 1.55; font-weight: 500; color: #fff; }

/* THREE ACROSS, AND ON A PHONE ONE. The first draft held three columns at
   every width on the argument that the bottom row IS the mood row — and a
   third of 375px is about seventy pixels of text column, which set every
   blurb one word to a line and made each key a tower. Hiding the words to
   keep the grid would have been the lite-version mistake arriving through a
   breakpoint, so the grid gives way instead: below 620px each key is a wide
   short row, name and mood on one line and the wave under it. The moods are
   still the last three keys, which is what the room's copy says. */
.stimboard__grid {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px; margin: 16px 0 0; padding: 0; list-style: none;
}

.stimpad {
  --pad-lit: #101014;
  position: relative; overflow: hidden;
  width: 100%; height: 100%; cursor: pointer; text-align: left;
  font-family: var(--sans); color: #101014;
  border: 4px solid #101014; border-radius: 16px;
  padding: 12px 11px 13px;
  display: flex; flex-direction: column; gap: 7px; min-height: 148px;
  transition: transform .12s ease;
}
.stimpad:hover { transform: translateY(-2px); }
.stimpad:active { transform: translateY(2px); }
.stimpad__name { font-family: 'Titan One', var(--sans); font-weight: 400; font-size: clamp(14px, 2.3vw, 19px); line-height: 1.05; }
.stimpad__mood { font-family: 'Bungee', var(--sans); font-size: clamp(11px, 1.5vw, 13px); letter-spacing: 1px; line-height: 1; }
.stimpad__wave { display: block; width: 100%; height: auto; }
.stimpad__what { margin-top: auto; font-size: clamp(11px, 1.5vw, 12.5px); line-height: 1.4; font-weight: 500; }

.stimpad--yellow { background: var(--yellow); }
.stimpad--green  { background: var(--green); }
.stimpad--cyan   { background: var(--cyan); }
.stimpad--orange { background: var(--orange); }
.stimpad--pink   { background: var(--pink); }
.stimpad--violet { background: var(--violet); }
.stimpad--night  { background: #101014; border-color: #fff; color: var(--cream); --pad-lit: var(--cream); }

/* The mood, in its own colour on the black key, on the word AND on the line —
   two channels for one fact, and the word is the one that survives a screen
   reader. These are the three brightest inks this site has that clear the body
   threshold on near-black; see check-contrast.py. */
.stimpad--mood[data-mood="happy"] .stimpad__mood,
.stimpad--mood[data-mood="happy"] .stimpad__wave { color: var(--yellow); }
.stimpad--mood[data-mood="sad"] .stimpad__mood,
.stimpad--mood[data-mood="sad"] .stimpad__wave { color: var(--cyan); }
.stimpad--mood[data-mood="angry"] .stimpad__mood,
.stimpad--mood[data-mood="angry"] .stimpad__wave { color: var(--orange); }

/* `data-lit` is the mood that JUST PLAYED and `data-mood` is the one the key is
   now offering, which is why they are two attributes rather than one. The
   flourish belongs to the noise that happened; the label belongs to the one
   that has not. One attribute doing both jobs would repaint a running burst the
   moment the label moved on. */
.stimpad--night[data-lit="happy"] { --pad-lit: var(--yellow); }
.stimpad--night[data-lit="sad"]   { --pad-lit: var(--cyan); }
.stimpad--night[data-lit="angry"] { --pad-lit: var(--orange); }

/* ── The flourishes, one per key and no two alike ─────────────────────────────
   MAX GLITTER only, and love.js builds no elements at all below it — the CSS
   gate here is the second lock rather than the only one. Everything moves with
   a translate or a scale and NOTHING ROTATES, which is the call arcade.js and
   quest.js both made: rotation and skew are all check-gentle.py can read, and a
   checker must not be asked to take a room's word for something else. NOTHING
   FLASHES OR STROBES either — Club Chronic's rule, holding in the loudest room
   on the street. Each one rises, or falls, or opens out, once, and goes.

   They are clipped to their own key, so the flourish is attached to the button
   that made the noise rather than to the room. Each takes the key's ink, and
   the mood keys take the colour of the mood they just played, so a burst can
   never introduce a pair nobody measured. */
.burst { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.burst span { position: absolute; opacity: 0; background: var(--pad-lit); }

.burst--ring span { left: 50%; top: 50%; width: 26px; height: 26px; margin: -13px 0 0 -13px; border-radius: 50%; background: none; border: 3px solid var(--pad-lit); }
html[data-intensity="max"] .burst--ring span { animation: pb-ring 1.1s ease-out forwards; }
@keyframes pb-ring { 0% { opacity: 0; transform: scale(.25); } 18% { opacity: 1; } 100% { opacity: 0; transform: scale(5); } }

.burst--bubble span { bottom: -16px; width: 14px; height: 14px; border-radius: 50%; }
html[data-intensity="max"] .burst--bubble span { animation: pb-bubble 1.3s ease-out forwards; }
@keyframes pb-bubble { 0% { opacity: 0; transform: translateY(0) scale(.5); } 20% { opacity: .95; } 100% { opacity: 0; transform: translateY(-170px) scale(1.3); } }

.burst--drops span { top: -30px; width: 3px; height: 26px; border-radius: 2px; }
html[data-intensity="max"] .burst--drops span { animation: pb-drops 1.2s linear forwards; }
@keyframes pb-drops { 0% { opacity: 0; transform: translateY(0); } 12% { opacity: 1; } 100% { opacity: 0; transform: translateY(220px); } }

.burst--star span { left: 50%; top: 50%; width: 9px; height: 9px; margin: -4px 0 0 -4px; }
html[data-intensity="max"] .burst--star span { animation: pb-star 1s ease-out forwards; }
@keyframes pb-star { 0% { opacity: 0; transform: translate(0, 0) scale(.4); } 14% { opacity: 1; } 100% { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(1); } }

.burst--ripple span { left: 0; right: 0; height: 6px; border-radius: 3px; }
html[data-intensity="max"] .burst--ripple span { animation: pb-ripple 1.2s ease-out forwards; }
@keyframes pb-ripple { 0% { opacity: 0; transform: scaleX(.08); } 25% { opacity: .9; } 100% { opacity: 0; transform: scaleX(1); } }

.burst--dart span { left: -26px; width: 22px; height: 4px; border-radius: 2px; }
html[data-intensity="max"] .burst--dart span { animation: pb-dart .9s ease-in forwards; }
@keyframes pb-dart { 0% { opacity: 0; transform: translateX(0); } 20% { opacity: 1; } 100% { opacity: 0; transform: translateX(240px); } }

.burst--arc span { left: 50%; bottom: -12px; width: 44px; height: 24px; margin-left: -22px; border-radius: 50%; background: none; border: 3px solid var(--pad-lit); }
html[data-intensity="max"] .burst--arc span { animation: pb-arc 1.4s ease-out forwards; }
@keyframes pb-arc { 0% { opacity: 0; transform: scale(.3); } 22% { opacity: 1; } 100% { opacity: 0; transform: scale(4.2); } }

.burst--coil span { left: 12%; right: 12%; top: 0; height: 5px; border-radius: 3px; }
html[data-intensity="max"] .burst--coil span { animation: pb-coil 1.1s ease-in-out forwards; }
@keyframes pb-coil { 0% { opacity: 0; transform: translateY(0) scaleX(.4); } 15% { opacity: 1; } 55% { transform: translateY(var(--dy)) scaleX(1); } 100% { opacity: 0; transform: translateY(calc(var(--dy) * .5)) scaleX(.55); } }

.burst--confetti span { top: -16px; width: 11px; height: 11px; }
html[data-intensity="max"] .burst--confetti span { animation: pb-confetti 1.5s ease-in forwards; }
@keyframes pb-confetti { 0% { opacity: 0; transform: translate(0, 0); } 12% { opacity: 1; } 100% { opacity: 0; transform: translate(var(--dx), 200px); } }

/* THE PHONE. Last in the section because every rule here overrides one above
   it, and written higher up it lost exactly the declarations the base rule
   also sets while the two it alone sets went through — a half-applied media
   block, which renders as a layout nobody wrote. */
@media (max-width: 620px) {
  .stimboard__grid { grid-template-columns: 1fr; gap: 10px; }
  .stimpad { min-height: 0; flex-flow: row wrap; align-items: center; gap: 5px 12px; padding: 12px 14px 13px; }
  .stimpad__name { font-size: 19px; }
  .stimpad__mood { margin-left: auto; font-size: 13px; }
  .stimpad__wave { flex: 1 1 100%; max-width: 230px; }
  .stimpad__what { flex: 1 1 100%; margin-top: 0; font-size: 13px; }
}

.floor { height: 84px; border-top: 5px solid #101014; background-image: repeating-conic-gradient(#101014 0deg 90deg, #fff 90deg 180deg); background-size: 44px 44px; display: flex; align-items: center; justify-content: center; }
.floor span { background: #101014; padding: 9px 22px; border-radius: 30px; font-family: 'Bungee', var(--sans); font-size: 14px; color: var(--yellow); letter-spacing: 1px; }


/* §11 ── The plain rooms: Your Room, Liner Notes, Changelog ──────────────────
   Three pages that have a job rather than a vibe. They take the street's night
   ground and one accent, and otherwise get out of the way. A site this loud
   needs somewhere to put a list. */

.room-plain { background: var(--ink); color: #fff; }
.room-plain .backlink { color: var(--yellow); }
.room-plain h1 { font-family: 'Bungee', var(--sans); font-size: clamp(34px,5.6vw,58px); line-height: 1.05; color: var(--yellow); margin: 14px 0 0; }
.room-plain h2 { font-family: 'Bungee', var(--sans); font-size: 19px; color: var(--cyan); letter-spacing: .5px; margin: 34px 0 12px; }
.room-plain h3 { font-family: 'Archivo Black', var(--sans); font-size: 16px; color: #fff; margin: 22px 0 6px; }
.room-plain p, .room-plain li { font-size: 16.5px; line-height: 1.62; }
.room-plain .lede { font-size: 20px; line-height: 1.5; color: var(--chalk); max-width: 62ch; }
.room-plain a { color: var(--yellow); }
.room-plain a:hover { color: #fff; }
.room-plain .card { background: var(--ink-2); border: 3px solid var(--ink-3); border-radius: 16px; padding: 22px 24px; margin: 18px 0; }
.room-plain .card--call { border-color: var(--pink); }
.room-plain dl.credits { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px,1fr)); gap: 18px; }
.room-plain dl.credits dt { font-family: 'Bungee', var(--sans); font-size: 13px; color: var(--green); letter-spacing: .5px; }
.room-plain dl.credits dd { margin: 5px 0 0; font-size: 14.5px; line-height: 1.55; color: var(--chalk); }
.room-plain table { width: 100%; border-collapse: collapse; margin: 14px 0; }
.room-plain th, .room-plain td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--ink-3); font-size: 14.5px; vertical-align: top; }
.room-plain th { font-family: 'Bungee', var(--sans); font-weight: 400; font-size: 12px; color: var(--chalk); letter-spacing: .5px; }


/* §12 ── SUBROOM: The Chappell (off Pink Pony Club) ──────────────────────────
   RHINESTONE VATICAN. A chapel built by somebody who thinks a chapel should
   have more sequins on it: votive dark, gold leaf, stained glass, and an
   arcade of pointed arches with a video in each one.

   IT IS A SUBROOM AND IT STILL SHARES NOTHING WITH ITS PARENT. The dancefloor
   next door is flat hot pink, cream Shrikhand, and a grid of small white cards
   inside one big cream box. This is near-black indigo, gold Monoton, and free-
   standing arches on the bare ground. Being reached through Pink Pony Club is a
   fact about the doors, not a licence to inherit its face — the one instinct
   this site exists to refuse would arrive here first, wearing "but it is only a
   subroom" as its excuse.

   MONOTON WAS THE LAST UNCLAIMED DISPLAY FACE on the street. It held exactly one
   line on the index — "Living out loud", 27px — and no room had taken it as a
   headline. A neon marquee face set in gold leaf is the whole joke of this room
   in one typeface: the Vatican as rendered by a supper club.

   THE GLOW IS MEASURED, not assumed. Enid's card and the pony's headline both
   taught this file the same lesson — a room's ambient layer makes grounds that
   nobody wrote down, and the contrast checker only knows the flat colour. The
   rose window here peaks at #4E2E60 (violet at .22, then the gold rays at .10,
   composited over #1A0A33) and every ink in this room is checked against THAT
   as well as against the flat nave. See check-contrast.py, which holds both. */

.room-chappell { background: var(--nave); color: #EFE4FF; }
.room-chappell .backlink { font-family: 'Bungee', var(--sans); color: var(--leaf); }
.room-chappell a { color: var(--leaf); }
.room-chappell a:hover { color: var(--cream); }

/* The rose window. A violet bloom at the top of the nave with gold rays fanning
   out of it — a window you are standing under rather than looking at. */
.room-chappell .glow {
  position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background-image:
    repeating-conic-gradient(from 188deg at 50% 0%, rgba(255,214,102,.10) 0deg 3deg, rgba(255,214,102,0) 3deg 13deg),
    radial-gradient(90% 55% at 50% 0%, rgba(172,91,255,.22), rgba(26,10,51,0) 70%);
}
.room-chappell > * { position: relative; z-index: 1; }

.room-chappell h1 {
  font-family: 'Monoton', var(--sans); font-weight: 400;
  font-size: clamp(30px, 5.2vw, 58px); line-height: 1.12;
  color: var(--leaf); margin: 14px 0 0; max-width: 20ch;
  text-shadow: 0 0 14px rgba(240,196,83,.30);
}
html[data-intensity="gentle"] .room-chappell h1 { text-shadow: none; }
.room-chappell h2 { font-family: 'Bungee', var(--sans); font-size: 16px; letter-spacing: 1px; color: var(--leaf); margin: 0; }
.room-chappell .lede {
  font-family: 'Instrument Serif', serif; font-size: clamp(20px, 3vw, 27px);
  line-height: 1.34; color: #EFE4FF; max-width: 44ch; margin: 20px 0 0;
}

/* The nameplate over the door. The room is called The Chappell; the heading is
   what the playlist is called, and they are different sentences doing different
   jobs, so the plate says the first and the h1 says the second. */
.nameplate {
  display: inline-block; margin: 0; padding: 7px 16px;
  font-family: 'Bungee', var(--sans); font-size: 13px; letter-spacing: 3px;
  color: var(--nave); background: var(--leaf); border-radius: 3px;
}

/* A seam of rhinestones. Gold thread with a stone set every 22px — the one
   ornament in here that is pure ornament, and it is 6px tall. */
.seam {
  height: 6px; margin: 30px 0 0; border-radius: 3px;
  background-image:
    repeating-radial-gradient(circle at 11px 3px, var(--cream) 0 2px, rgba(255,243,230,0) 2px 11px),
    linear-gradient(90deg, rgba(240,196,83,.25), var(--leaf) 30%, var(--leaf) 70%, rgba(240,196,83,.25));
  background-size: 22px 6px, 100% 6px;
}

/* The votive rail — this room's consent banner. The dancefloor's is a cream-
   bordered black lozenge; this is a lit shelf of candles under a gold edge. The
   claim is the same claim, and it is the claim that has to be identical, not
   the box. */
.votive {
  margin: 26px 0 0; padding: 20px 22px 18px;
  background: var(--niche); border: 2px solid var(--leaf);
  border-radius: 4px 4px 14px 14px; border-top-width: 6px;
}
/* > strong, not strong: the banner's heading is its first child, and the
   paragraph under it uses <strong> inline for the sentence that carries the
   room's extra promise. Unscoped, that inline emphasis became a second Bungee
   heading in the middle of a sentence. */
.votive > strong {
  display: block; font-family: 'Bungee', var(--sans); font-weight: 400;
  font-size: clamp(17px,2.4vw,21px); line-height: 1.2; color: var(--leaf); margin-bottom: 10px;
}
.votive p { margin: 0; font-size: 15px; line-height: 1.56; color: #EFE4FF; }
.votive__candles { display: flex; gap: 7px; margin: 14px 0 0; }
.votive__candles span {
  flex: 1 1 0; height: 9px; border-radius: 4px;
  background-image: linear-gradient(90deg, var(--ruby), var(--leaf), var(--sapphire), var(--emerald));
}

/* The arcade. Free-standing arches on the bare nave, not cards inside a box —
   which is the structural difference from the jukebox next door, where ten white
   cards sit in one cream tray. Here the ground shows between them. */
.nave {
  list-style: none; margin: 20px 0 0; padding: 0;
  display: grid; gap: 30px 26px;
  grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
  align-items: start;
}
.niche {
  background: var(--niche); border: 3px solid var(--leaf);
  border-radius: 170px 170px 10px 10px;
  padding: 0 22px 20px; overflow: hidden;
}
/* The tympanum: panes of glass fanning from the springing of the arch. Purely
   decorative, aria-hidden, and carrying no text — which is why four saturated
   colours are allowed to sit next to each other here and nowhere else. */
.niche__glass {
  height: 92px; margin: 0 -22px 16px;
  background-image: repeating-conic-gradient(from 202deg at 50% 100%,
    var(--ruby) 0deg 8deg, var(--leaf) 8deg 15deg, var(--sapphire) 15deg 23deg,
    var(--emerald) 23deg 30deg, var(--amethyst) 30deg 38deg);
  border-bottom: 3px solid var(--leaf);
}
.niche h3 {
  margin: 0; font-family: 'Instrument Serif', serif; font-weight: 400;
  font-size: 25px; line-height: 1.16; color: var(--cream);
}
.niche__note { margin: 7px 0 13px; font-size: 14px; line-height: 1.45; color: #C3B2DE; }
.niche__credit { margin: 10px 0 0; font-size: 12.5px; color: #C3B2DE; }

/* The facade wears the room's clothes: glass behind gold, with the runtime on
   the button itself. Nothing reaches YouTube until it is pressed — §4's rule,
   and this room does not get an exception for being pretty. */
.room-chappell .facade {
  background: var(--glass); border: 2px solid var(--leaf);
  border-radius: 8px; color: var(--cream);
}
.room-chappell .facade:hover { background: #1C0C38; }
.room-chappell .facade__play { color: var(--leaf); }

/* THE CHANCEL — the east end, and the only object in this room that is not one
   of the thirteen. You walk down the nave past arches you take one at a time,
   and this is where the whole playlist stands: wider, one arch rather than a
   grid, on the same bare ground.

   IT IS THE SAME ROOM AND NOT A SECOND ONE. Identical ground, identical gold,
   identical cream serif, identical glass — every colour in here is a pair
   check-contrast.py already holds for a niche, so the east end introduces
   nothing to measure. What makes it the chancel is SIZE and SOLITUDE: a deeper
   arch and no siblings beside it. If it ever grows a colour of its own, this
   room has started having two of everything.

   AND ITS BUTTON IS THE ONE HERE THAT CANNOT SAY HOW LONG. The niches each
   carry a runtime because a press is only consent if you know what you are
   agreeing to; a playlist has no length to give, so that label says it runs
   until you stop it and the votive rail says which button does which. */
.chancel {
  background: var(--niche); border: 3px solid var(--leaf);
  border-radius: 240px 240px 10px 10px;
  padding: 0 26px 22px; overflow: hidden; margin: 30px 0 0;
}
.chancel__glass {
  height: 128px; margin: 0 -26px 18px;
  background-image: repeating-conic-gradient(from 208deg at 50% 100%,
    var(--ruby) 0deg 6deg, var(--leaf) 6deg 11deg, var(--sapphire) 11deg 17deg,
    var(--emerald) 17deg 22deg, var(--amethyst) 22deg 28deg);
  border-bottom: 3px solid var(--leaf);
}
.chancel h3 {
  margin: 0; font-family: 'Instrument Serif', serif; font-weight: 400;
  font-size: 31px; line-height: 1.14; color: var(--cream); max-width: 30ch;
}
.chancel__note { margin: 8px 0 15px; font-size: 15px; line-height: 1.5; color: #C3B2DE; max-width: 58ch; }
.chancel__credit { margin: 11px 0 0; font-size: 12.5px; line-height: 1.45; color: #C3B2DE; max-width: 62ch; }

/* The room rule, in the apse. */
.gloria {
  margin: 30px 0 0; padding: 20px 22px;
  background: var(--glass); border-left: 6px solid var(--leaf); border-radius: 0 12px 12px 0;
}
.gloria h2 { margin: 0 0 9px; }
.gloria p { margin: 0; font-size: 15px; line-height: 1.56; color: #EFE4FF; }


/* §13 ── THE CAMPGROUNDS (off the end of the street) ─────────────────────────
   AN AREA, NOT A ROOM. The street is a row of shopfronts shoulder to shoulder under
   neon, and some people do not want a shopfront. This is where the street runs
   out: a field past the treeline with numbered pitches on it, for the ones who
   would rather live on the edge of town and be left alone.

   IT HAS NO AMBIENT LAYER AT ALL, at any setting, and that is the design rather
   than an oversight. Every other page here has something that moves when the
   dial is turned up — the marquee, the sparkle, the mirrorball, the rose
   window. MAX GLITTER buys you nothing out here, because an area that exists
   for people who want quiet cannot have a loud setting and mean it. The dial
   still governs the pitches, which are their own worlds and set their own
   noise; it is this field that stays still.

   COLD WHERE THE STREET IS BLACK AND THE YURT IS WARM. Night-blue spruce, bone
   lettering routed into signs, lichen for the body — no neon, no glitter, one
   moon-coloured link. Walking from here into the Faery Yurt should feel like
   stepping out of the night air into a lit tent, which only works if the field
   is genuinely cold. Alfa Slab One is the routed park sign; Bitter is the
   laminated notice on the board. Neither face is set anywhere else. */

.campgrounds { background: var(--dusk); color: var(--bone); font-family: 'Bitter', Georgia, serif; }
.campgrounds a { color: var(--moon); }
.campgrounds a:hover { color: var(--bone); }
.campgrounds p, .campgrounds li { font-size: 16.5px; line-height: 1.66; }

/* The backlink drops Bungee. It is the one piece of shared furniture that
   carries a typeface, and out here the street's voice would be the only loud
   thing in the field. */
.campgrounds .backlink { font-family: 'Bitter', Georgia, serif; font-size: 15px; letter-spacing: 0; color: var(--moon); }

.campgrounds h1 {
  font-family: 'Alfa Slab One', Georgia, serif; font-weight: 400;
  font-size: clamp(38px, 7vw, 72px); line-height: 1.02;
  color: var(--bone); margin: 12px 0 0;
}
.campgrounds h2 { font-family: 'Alfa Slab One', Georgia, serif; font-weight: 400; font-size: 19px; color: var(--moss); margin: 0 0 11px; }
.campgrounds h3 { font-family: 'Alfa Slab One', Georgia, serif; font-weight: 400; font-size: 26px; line-height: 1.12; color: var(--bone); margin: 0; }
.campgrounds .lede { font-size: 19.5px; line-height: 1.6; color: var(--lichen); max-width: 54ch; margin: 20px 0 0; }
.campgrounds .trailmark { margin: 0; font-size: 14px; color: var(--moss); }

/* The stream along the bottom of the field. Drawn in the page rather than in
   this file, because it is a picture of a place and not a border — see
   campgrounds.html. IT IS A STREAM AND NOT A TREELINE on purpose: the Faery
   Yurt ends on a treeline of its own, and two pages in one area reaching for
   the same drawing is exactly how an area quietly becomes a design system. The
   field gets the water; the yurt keeps the trees. */
.stream { margin: 30px 0 0; line-height: 0; }
.stream svg { display: block; width: 100%; height: auto; }

/* The board at the gate. The one boxed thing in the field, because it is the
   one thing that is actually a box nailed to two posts. */
.board {
  margin: 30px 0 0; padding: 22px 24px;
  background: var(--spruce); border: 3px solid var(--bark); border-radius: 3px;
}
.board p { margin: 0 0 12px; color: var(--lichen); }
.board p:last-child { margin-bottom: 0; }
.board ul { margin: 0; padding: 0 0 0 20px; color: var(--lichen); }
.board li { margin: 0 0 9px; }
.board li::marker { color: var(--moss); }

/* The pitches. Marker posts standing on open ground — a timber on the left and
   nothing around them. STRUCTURALLY THE OPPOSITE OF THE STREET, where six
   shopfronts sit in a grid of equal boxes with awnings on. Nobody pitches a
   tent in a box, and the ground showing between them is the whole point of
   having come out here. */
.pitches { list-style: none; margin: 26px 0 0; padding: 0; display: flex; flex-direction: column; gap: 30px; }
.pitch { border-left: 5px solid var(--bark); padding: 2px 0 2px 22px; }
.pitch__no { display: block; margin: 0 0 6px; font-family: 'Alfa Slab One', Georgia, serif; font-size: 13px; letter-spacing: 2px; color: var(--moss); }
.pitch h3 a { color: var(--bone); text-decoration-color: var(--moss); text-underline-offset: 4px; }
.pitch h3 a:hover { color: var(--moon); }
.pitch p { margin: 10px 0 0; color: var(--lichen); max-width: 58ch; }
.pitch__who { margin: 8px 0 0; font-size: 14.5px; color: var(--moss); }

/* An unpitched plot is dashed, which is the same grammar the street's empty
   storefront uses — the one borrowing allowed here, because "nobody has taken
   this yet" is a fact about the site and not a look. */
.pitch--open { border-left-style: dashed; }
.pitch--open h3 { color: var(--lichen); }

/* A plot that is taken but has nothing on it yet. Solid post, because somebody
   has it; no link, because there is no door. A campground has this state and a
   website usually pretends it does not — the honest alternative is publishing
   a room before it is a room. */
.pitch--raising h3 { color: var(--bone); }

/* THE SIGN AND THE THING THE SIGN IS ABOUT. The notice is nailed to the post on
   the left; the drawing stands further out on the ground beside it. An open plot
   has no drawing at all, which is the whole grammar: what is pitched is what you
   can see from here. */
.pitch { display: flex; flex-wrap: wrap; gap: 8px 30px; align-items: center; }
.pitch__sign { flex: 1 1 32ch; min-width: 0; }
.pitch__art { flex: 0 1 260px; line-height: 0; }
.pitch__art svg { display: block; width: 100%; height: auto; }

/* THE TWO DRAWINGS ARE SIGNS, NOT ROOMS, and that is the whole reason they may
   sit on one board without this field becoming a design system. Both are drawn
   in the field's own inks — spruce and bark for the masses, moss for every line,
   weight rather than tint doing the hierarchy — because you are looking at them
   across cold ground at night. What tells them apart is THE ONE LIT COLOUR EACH,
   and the two lights do opposite things:

     · the yurt EMITS. Candle amber out of the crown, out of the doorway, and
       onto the grass in front of it; round, soft-edged, strung with lights, sat
       against the trees. It is a lantern. You walk in out of the night air.
     · the hermitage CATCHES. Nothing there glows except one window, and that
       window is a SCREEN rather than a flame — connected solitude, which is the
       pitch's whole argument. Everything else is hard-edged and angled at a sky
       that is not there yet: the moon lands on the panels, three sunflowers hold
       the only warm colour on the pitch, and the aerial is the one line reaching
       off it.

   Round and warm against angular and cool, light coming out against light being
   collected. Draw the next pitch the same way — in the field's inks, with one
   light of its own — and do NOT give it the yurt's amber or the hermitage's
   moon because they are there already.

   NOTHING IN EITHER OF THEM MOVES, at any setting, like everything else in this
   field. The yurt's fairy lights twinkle on its own page; out here they are
   still, because this is the field's drawing of it and not the room. */


/* §14 ── PITCH 1: The Faery Yurt (in the campgrounds) ────────────────────────
   HELEN'S ROOM, AND IT IS HERS. Built from the mockup Helen Edgar sent on
   2026-09-20 — her palette, her typefaces, her copy, her drawings. What this
   file did was translate it onto the street's plumbing (the dial, self-hosted
   faces, the press-to-play rule) and change exactly one colour, which is
   written up beside --tallow-3 in §2.

   IT SHARES NOTHING WITH THE FIELD IT IS PITCHED ON, and the temptation to
   make it match was stronger here than it has ever been: this is the first
   thing in a brand new area, so "the area should look like an area" is the
   most reasonable-sounding way the harmonising instinct could possibly have
   arrived. The campground is cold blue spruce, routed bone signs and bare
   ground. This is warm brown, candlelight, old serifs and soft cards. You walk
   in out of the night air. That only works if the field is cold and the tent
   is not — the contrast IS the door.

   ALWAYS NIGHT, NEVER DARK. The tent ground carries a canvas weave and an
   ember glow at the crown, which makes a ground nobody wrote: #31231A at its
   brightest. Every ink in here is checked against THAT as well as the flat
   hearth, the same way the Chappell is checked against its rose window. It is
   what caught Helen's smallest grey. See check-contrast.py. */

.room-yurt { background: var(--hearth); color: var(--tallow); font-family: 'Crimson Pro', Georgia, serif; font-size: 17px; line-height: 1.7; }
.room-yurt a { color: var(--ember-2); text-decoration-color: rgba(224,144,74,.45); text-underline-offset: 3px; }
.room-yurt a:hover { color: var(--candle); }
.room-yurt .backlink { font-family: 'Cormorant Garamond', Georgia, serif; font-weight: 600; font-size: 15px; letter-spacing: .06em; color: var(--tallow-2); }

/* The tent itself: a lit column standing on the dark field. Helen drew this as
   a page background; on the body it is a pitched tent with the night around it,
   which is what it is. The weave is two crossed hatches at 2% — canvas, not
   texture for its own sake — and the vignette is the canvas falling away at the
   edges. None of it moves, so none of it is gated: gentle takes away the
   wobble, never the room. */
.yurt {
  width: min(780px, 100% - 40px); margin-inline: auto; padding: 0 0 70px;
  background-image:
    radial-gradient(ellipse 900px 500px at 50% -80px, rgba(224,144,74,.10), transparent 70%),
    radial-gradient(ellipse 640px 1400px at 50% 50%, transparent 60%, rgba(0,0,0,.4) 100%),
    repeating-linear-gradient(45deg,  rgba(242,230,212,.022) 0 2px, transparent 2px 8px),
    repeating-linear-gradient(-45deg, rgba(242,230,212,.016) 0 2px, transparent 2px 8px);
}

.room-yurt h1, .room-yurt h2, .room-yurt h3 {
  font-family: 'Cormorant Garamond', Georgia, serif; font-weight: 600;
  color: var(--tallow); text-wrap: balance; letter-spacing: .01em;
}
.room-yurt h1 { font-size: clamp(42px, 7vw, 67px); font-style: italic; margin: 0 0 18px; }
.room-yurt h2 { font-size: 30px; font-style: italic; margin: 0 0 6px; }
.room-yurt section { padding: 34px 0; }
.room-yurt .section-intro { color: var(--tallow-2); max-width: 60ch; margin: 0 0 22px; }

/* The fairy lights strung across the canvas, and the smoke hole above them.
   Twelve bulbs, and they only twinkle at MAX — the crown's five behave the
   same way. Nothing in this room moves until somebody asks for movement. */
.lights { display: flex; justify-content: space-evenly; padding: 16px 6px 0; overflow: hidden; }
.lights span {
  flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%;
  background: var(--candle); box-shadow: 0 0 6px 2px rgba(233,200,116,.6);
}
.lights span:nth-child(odd) { background: var(--ember-2); box-shadow: 0 0 6px 2px rgba(242,182,115,.55); }

html[data-intensity="max"] .lights span,
html[data-intensity="max"] .crown-light,
html[data-intensity="max"] .firefly,
html[data-intensity="max"] .glint { animation: yurt-twinkle 3.4s ease-in-out infinite; transform-origin: center; }
html[data-intensity="max"] .lights span:nth-child(odd) { animation-delay: .6s; }
html[data-intensity="max"] .lights span:nth-child(3n)  { animation-delay: 1.4s; }
html[data-intensity="max"] .lights span:nth-child(4n)  { animation-delay: 2.1s; }
html[data-intensity="max"] .vinyl { animation: yurt-spin 6s linear infinite; }

@keyframes yurt-twinkle { 0%, 100% { opacity: .38; transform: scale(.85); } 50% { opacity: 1; transform: scale(1.05); } }
@keyframes yurt-spin { to { transform: rotate(360deg); } }

.yurt-head { position: relative; text-align: center; padding: 54px 12px 40px; }
.yurt-head .eyebrow {
  font-family: 'Cormorant Garamond', Georgia, serif; font-weight: 600; font-size: 15px;
  letter-spacing: .14em; text-transform: uppercase; color: var(--tallow-3); margin: 0 0 18px;
}
.yurt-head .eyebrow a { color: var(--tallow-2); }
/* `.yurt-tagline`, not `.tagline`: the street's masthead claims that name in
   §5 and this paragraph was quietly taking display:flex and a 940px max-width
   from it. A rename, and nothing of Helen's design moved. */
.yurt-head .yurt-tagline { font-size: 19.5px; color: var(--tallow-2); max-width: 46ch; margin: 0 auto; }
.crown { width: 148px; margin: 0 auto 16px; }
.crown svg, .vine svg, .sprig svg { display: block; width: 100%; height: auto; }
.vine { position: absolute; top: -8px; width: 120px; pointer-events: none; }
.vine--l { left: -6px; }
.vine--r { right: -6px; transform: scaleX(-1); }
.sprig { display: flex; justify-content: center; padding: 6px 0; }
.sprig svg { width: 220px; }
.sprig--flip svg { transform: scaleX(-1); }

/* The soft furnishings. Everything in this room that holds copy is a card with
   a hairline of candlelight around it — which is why the arches next door and
   the bare posts outside had to be neither. */
/* `.room-yurt .hearth-card`, not `.hearth-card`: the two cards that hold copy
   are <section> elements, and `.room-yurt section` above sets the page's
   vertical rhythm with `padding: 34px 0`. That rule out-specifies a bare class,
   so the cards were getting 34px top and bottom and NOTHING at the sides --
   two paragraphs pressed against their own border. */
.room-yurt .hearth-card {
  background: linear-gradient(180deg, var(--canvas), var(--tent));
  border: 1px solid rgba(233,200,116,.18); border-radius: 6px; padding: 26px 28px;
  box-shadow: 0 18px 40px -20px rgba(0,0,0,.55);
}
.welcome { display: flex; gap: 28px; align-items: center; }

/* The portrait, in a wooden frame. THE FRAME IS MATTING AND STAYS; the sepia
   wash that Helen's mockup put ON the photograph does not. polaroids.html
   promises, in these words, that we will not "Crop you. Filter you." — and a
   promise the site makes to everybody is not waived by the one person it
   happens to be about this time, because the next photograph would arrive
   under a rule that had already been bent once. Border, shadow and mat are
   things around a picture; a filter is a thing done to it. make-polaroids.py
   refuses a filter on a photograph now rather than leaving this to memory. */
.portrait-frame {
  flex: 0 0 auto; width: 148px; padding: 8px; border-radius: 4px;
  background-image: linear-gradient(160deg, #4A372B, #2A1E17);
  box-shadow: 0 10px 24px -12px rgba(0,0,0,.55), inset 0 0 0 1px rgba(233,200,116,.15);
}
.portrait-frame img { display: block; width: 100%; border-radius: 2px; }
.welcome p { margin: 0 0 14px; }
.welcome p:last-child { margin-bottom: 0; }

/* The record. Helen's soundtrack is not recorded yet and the room says so out
   loud instead of hiding an empty shelf — the same thing Enid's wall does when
   nobody has sent a photograph. */
.record { display: flex; align-items: center; gap: 22px; background: var(--canvas); border: 1px solid rgba(233,200,116,.18); border-radius: 6px; padding: 22px; }
.vinyl {
  flex: 0 0 auto; width: 74px; height: 74px; border-radius: 50%;
  background-image:
    radial-gradient(circle at center, var(--candle) 0 6px, #0C0908 6px 9px, transparent 9px),
    repeating-radial-gradient(circle at center, #17110F 0 3px, var(--canvas) 3px 6px);
  box-shadow: 0 8px 18px -8px rgba(0,0,0,.55);
}
.record__soon {
  display: inline-block; margin: 0 0 8px; padding: 3px 12px;
  font-family: 'Cormorant Garamond', Georgia, serif; font-weight: 600; font-style: italic;
  font-size: 14px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ember-2); border: 1px solid rgba(224,144,74,.4); border-radius: 999px;
}
.record p:last-child { margin: 0; color: var(--tallow-2); }

/* The bookshelf. Spines stood on a timber plank, scrollable sideways, because a
   shelf you cannot overfill is not a shelf. The six spine colours are grounds
   for the cream lettering and every one of them is in check-contrast.py —
   Helen's fourth was the other thing the checker caught. */
.shelf { background: linear-gradient(180deg, transparent 0 calc(100% - 22px), var(--timber) calc(100% - 22px)); padding-bottom: 22px; }
.shelf__row { display: flex; align-items: flex-end; gap: 6px; overflow-x: auto; padding: 10px 4px 4px; scrollbar-width: thin; }
.spine {
  flex: 0 0 auto; writing-mode: vertical-rl; text-orientation: mixed;
  display: flex; align-items: center; justify-content: center; white-space: nowrap;
  font-family: 'Cormorant Garamond', Georgia, serif; font-weight: 600; font-size: 16px;
  letter-spacing: .02em; color: var(--tallow); padding: 12px 6px;
  border-radius: 5px 5px 2px 2px;
  box-shadow: inset 2px 0 0 rgba(255,255,255,.08), 0 6px 12px -8px rgba(0,0,0,.55);
}
.spine.c1 { background-image: linear-gradient(90deg, #6E2F2B, #8A3D34); height: 190px; }
.spine.c2 { background-image: linear-gradient(90deg, #38491F, #4A5F2A); height: 212px; }
.spine.c3 { background-image: linear-gradient(90deg, #5A3D63, #75507F); height: 178px; }
.spine.c4 { background-image: linear-gradient(90deg, #7A5324, #8A5F26); height: 200px; }
.spine.c5 { background-image: linear-gradient(90deg, #29414A, #375968); height: 186px; }
.spine.c6 { background-image: linear-gradient(90deg, #4A2F4F, #653D6B); height: 204px; }
.shelf__note { margin: 10px 0 0; font-size: 15px; font-style: italic; color: var(--tallow-3); }

/* The glimmer window. A pair of shutters on a label, opened by a checkbox — no
   script, and nothing behind them but a drawing, so there is nothing to consent
   to and nothing to load. The shutters swing at regular and max and snap at
   gentle, because §3 takes transitions away there and a shutter that teleports
   still shows you the view. */
.glimmer { display: flex; flex-direction: column; align-items: center; }
.glimmer__check { position: absolute; opacity: 0; pointer-events: none; }
.glimmer__frame {
  position: relative; display: block; width: min(100%, 360px); aspect-ratio: 4 / 5;
  padding: 14px; cursor: pointer; border-radius: 8px 8px 4px 4px;
  background-image: linear-gradient(160deg, #4A372B, #241A16 70%);
  box-shadow: 0 24px 50px -22px rgba(0,0,0,.55), inset 0 0 0 1px rgba(233,200,116,.15);
}
.glimmer__sash { position: relative; display: block; width: 100%; height: 100%; border-radius: 3px; overflow: hidden; background: #0C0E14; box-shadow: inset 0 0 0 6px #1A120E, inset 0 0 24px rgba(0,0,0,.6); }
.glimmer__sash::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(rgba(12,14,20,0) 0 92%, rgba(20,14,10,.9) 100%),
    linear-gradient(90deg, transparent 49.3%, rgba(233,200,116,.14) 49.3% 50.7%, transparent 50.7%),
    linear-gradient(0deg,  transparent 49.3%, rgba(233,200,116,.14) 49.3% 50.7%, transparent 50.7%);
}
.glimmer__scene { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
.glimmer__shutter {
  position: absolute; top: 14px; bottom: 14px; width: calc(50% - 14px); border-radius: 3px;
  background-image:
    linear-gradient(90deg, rgba(0,0,0,.25), transparent 8%, transparent 92%, rgba(0,0,0,.25)),
    linear-gradient(160deg, #4A372B, #2A1E17);
  box-shadow: inset 0 0 0 1px rgba(233,200,116,.12), 0 10px 20px -10px rgba(0,0,0,.55);
  transition: transform .7s cubic-bezier(.6,0,.2,1);
}
.glimmer__shutter--l { left: 14px; transform-origin: left center; }
.glimmer__shutter--r { right: 14px; transform-origin: right center; }
.glimmer__check:checked + .glimmer__frame .glimmer__shutter--l { transform: rotateY(-108deg); }
.glimmer__check:checked + .glimmer__frame .glimmer__shutter--r { transform: rotateY(108deg); }

/* The checkbox is invisible, so §2's outline would land on nothing and a
   keyboard visitor would tab onto the shutters with no way to tell. The ring
   goes on the frame instead — the thing that actually looks focused. */
.glimmer__check:focus-visible + .glimmer__frame { outline: 4px solid var(--candle); outline-offset: 4px; }
.glimmer__hint { display: block; margin-top: 12px; text-align: center; font-family: 'Caveat', cursive; font-size: 21px; color: var(--tallow-3); }
.glimmer__hint .is-open { display: none; }
.glimmer__check:checked + .glimmer__frame + .glimmer__hint .is-shut { display: none; }
.glimmer__check:checked + .glimmer__frame + .glimmer__hint .is-open { display: inline; }
.sill { display: flex; gap: 14px; align-items: flex-end; justify-content: center; margin-top: -6px; }
.sill__book { position: relative; width: 46px; height: 34px; border-radius: 2px; background-image: linear-gradient(160deg, #E8DCC4, #D8C8A6); box-shadow: 0 6px 14px -8px rgba(0,0,0,.55); transform: rotate(-3deg); }
.sill__book::before, .sill__book::after { content: ""; position: absolute; left: 8px; right: 8px; height: 1.5px; background: rgba(90,70,40,.4); }
.sill__book::before { top: 13px; }
.sill__book::after  { top: 20px; }
.sill__pen { width: 52px; height: 5px; border-radius: 3px; background-image: linear-gradient(90deg, #2C3E3A, var(--candle) 85%); box-shadow: 0 4px 8px -4px rgba(0,0,0,.55); transform: rotate(24deg); }
/* The sill keeps its tilt at Regular and MAX -- it is Helen's windowsill and
   those are her angles. This is the dial, which is our plumbing and applies to
   every room on the street: at Gentle nothing rotates. Section 14 shipped with
   no gentle rule in it at all, so the book sat at -3deg and the pen at 24deg
   for anybody who had asked the wobble to stop. Found by check-gentle.py on
   its first run, a day after the room went up and after two people had read
   it -- which is the whole case for the tool. */
html[data-intensity="gentle"] .sill__book,
html[data-intensity="gentle"] .sill__pen { transform: none; }

/* The regulation nook, and who else lives here. */
.nook { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 12px; }
.nook li { display: flex; align-items: center; gap: 12px; background: var(--canvas); border: 1px solid rgba(233,200,116,.18); border-radius: 6px; padding: 16px 14px; }
.nook svg { flex: 0 0 auto; width: 30px; height: 30px; }
.nook span { font-size: 16px; color: var(--tallow-2); }

/* One of the six tiles does something. AN EASTER EGG THAT STILL ADMITS IT IS
   THERE: it wears Helen's wording and the same candlelit card as its five
   neighbours, and a small note marker surfaces on hover and on focus. The
   discovery is meant to be "one of these is a button", not "a page I was
   reading quietly made a noise at me" — a hidden noise would be the exact thing
   the dial and the press-to-play facades exist to prevent, arriving as a joke.
   The button's accessible name says it is a sound and how long, so a keyboard
   or screen-reader visitor is told MORE than a mouse one rather than less.

   NOT `display: contents` on the <li>, which is what this did first. It puts
   the button straight into the grid and it also drops the list item out of the
   accessibility tree in browsers that still carry that bug — trading a list of
   six things for a list of five and a loose button, to save one line of CSS.
   The <li> stays a real grid cell and the button fills it.

   `.nook .egg__mark`, not `.egg__mark`: `.nook span` is (0,1,1) and a bare class
   is (0,1,0), so the marker was quietly taking the tile label's size and colour
   instead of its own. Same shape as the card padding two screens up. */
/* A tile with a sound behind it IS the button, so the <li> stops being a card
   and becomes a bare grid cell — otherwise `.nook li`'s own ground, border and
   padding draw a second box around the button's, and four of the six tiles
   read as boxes inside boxes while the two silent ones stay flat. */
.nook li.nook__egg { display: flex; background: none; border: 0; padding: 0; }
.egg {
  display: flex; align-items: center; gap: 12px; width: 100%; cursor: pointer;
  text-align: left; font: inherit; color: inherit;
  background: var(--canvas); border: 1px solid rgba(233,200,116,.18);
  border-radius: 6px; padding: 16px 14px;
}
.egg:hover { background: var(--canvas-2); border-color: rgba(233,200,116,.4); }
.egg svg { flex: 0 0 auto; width: 30px; height: 30px; }
.nook .egg__label { flex: 1 1 auto; font-size: 16px; color: var(--tallow-2); }
.nook .egg__mark {
  flex: 0 0 auto; align-self: flex-start;
  font-family: 'Cormorant Garamond', Georgia, serif; font-weight: 600;
  font-size: 14px; letter-spacing: .04em; color: var(--tallow-3);
  opacity: 0; transition: opacity .18s ease;
}
.egg:hover .egg__mark, .egg:focus-visible .egg__mark { opacity: 1; }
/* Gentle takes transitions away, which would leave the marker stuck invisible
   for anybody at that setting. It is a label about consent, so at Gentle it is
   simply always on: the quiet setting should reveal more, never less. */
html[data-intensity="gentle"] .nook .egg__mark { opacity: 1; }
.egg[data-playing] { border-color: var(--ember-2); }
.egg[data-playing] .egg__mark { opacity: 1; color: var(--ember-2); }

.residents { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 14px; }
.resident { background: linear-gradient(180deg, var(--canvas), var(--tent)); border: 1px solid rgba(233,200,116,.18); border-radius: 6px; padding: 18px; text-align: center; }
.resident svg { display: block; width: 44px; height: 44px; margin: 0 auto 10px; }
.resident h3 { font-style: italic; font-size: 21px; margin: 0 0 4px; }
.resident p { margin: 0; font-size: 16px; color: var(--tallow-3); }

/* Where to find me, and the treeline the yurt is pitched behind. */
.whereabouts { display: flex; gap: 20px; align-items: center; }
.whereabouts .glyph { flex: 0 0 auto; width: 56px; height: 56px; }
.whereabouts .glyph svg { width: 100%; height: 100%; }
.whereabouts p { margin: 0; color: var(--tallow-2); }
.room-yurt .treeline { margin: 12px 0 0; line-height: 0; }
.room-yurt .treeline svg { display: block; width: 100%; height: auto; }
.room-yurt .colophon { margin: 40px 0 0; text-align: center; font-size: 16px; color: var(--tallow-3); }


/* §15 ── ROOM: The Arcade ────────────────────────────────────────────────────
   The only room on this street with a game in it. Coin-op at
   midnight: a grape carpet, a cabinet built out of hard blocks, and a screen
   that is a different black from the room it stands in. ONE FACE, and it is a
   pixel face — the eighteenth family in fonts/_sources.json, and the one thing
   no other room here could borrow without becoming this one.

   NOTHING ON THE PLAYFIELD MOVES UNTIL SOMEBODY PUTS THE COIN IN. That is the
   jukebox's consent model wearing a different costume, and it is the whole
   reason this room can hold a game without the dial having to lie: motion the
   visitor started is not ambient motion. The decoration around it — the glow,
   the marquee bulbs — obeys the dial exactly like every other room's does.

   THE GAME'S SPEED IS A SECOND CONTROL AND THE PLAYER HOLDS IT. The dial picks
   its default (Slow at Gentle) and nothing more; all three speeds are offered
   at every dial setting, because there is no content behind a dial position
   here either. Tying the speed to the dial would have made Gentle a different
   game, which is the "lite version" mistake with a joystick on it.

   THE PLAYFIELD MOVES THINGS WITH left/top AND NOT WITH transform. Not for
   performance. Rotation and skew are exactly what tools/check-gentle.py reads
   out of the computed matrix, and a room that put its game behind a transform
   would be asking that checker to take the room's word for something. There is
   nothing to take on trust if there is no transform to read. */

/* .arcade IS THE CHROME AND NOT THE PAGE. The carpet, the cabinet build, the
   marquee bulbs and the pixel face belong to the room and are worn by the foyer
   and by every machine standing in it. That is not the harmonising instinct
   getting in: an arcade is precisely a room whose cabinets share a body and
   differ behind the glass, and the worlds here are the SCREENS -- a flat dark
   field and a kelp bay have nothing to do with each other. Each page also
   carries its own card class (room-arcade, game-quill, game-otter), which is
   what make-og.py keys on, so the thing that styles and the thing that unfurls
   are never the same word. */
.arcade { background: var(--carpet); color: var(--tube); min-height: 100vh; position: relative; }
.arcade > * { position: relative; z-index: 1; }

/* The cabinet's own light, spilling down the carpet. §3 hides .glow at Gentle,
   which is the only reason this can be an ambient layer at all. The composite
   it makes with the carpet is #2D1C25 and every ink that lands on it is
   measured against that in check-contrast.py. */
.arcade .glow {
  position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background:
    radial-gradient(ellipse 70% 42% at 50% 0%, rgba(255,194,26,.10), transparent 70%),
    radial-gradient(ellipse 50% 34% at 14% 88%, rgba(255,107,228,.07), transparent 72%);
}

/* The marquee bulbs over the door. They only chase at MAX; at Regular they are
   a row of lit bulbs, which is what a marquee looks like when it is switched on
   and not flashing. Decorative and aria-hidden — the room never says anything
   with a bulb that it does not also say in words. */
.bulbs {
  display: flex; gap: 10px; justify-content: center; flex-wrap: wrap;
  padding: 13px 16px; background: var(--cab); border-bottom: 4px solid var(--coin);
}
.bulbs span { width: 11px; height: 11px; border-radius: 50%; background: var(--coin); opacity: .85; }
.bulbs span:nth-child(even) { background: var(--zap); }
html[data-intensity="max"] .bulbs span { animation: bulbchase 1.6s steps(2) infinite; }
.bulbs span:nth-child(3n+2) { animation-delay: .25s; }
.bulbs span:nth-child(3n+3) { animation-delay: .5s; }
@keyframes bulbchase { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }

.arcade .backlink { font-family: 'Press Start 2P', monospace; font-size: 11px; color: var(--coin); }
.arcade a { color: var(--mint); }
.arcade a:hover { color: var(--coin); }

.arc-eyebrow { font-family: 'Press Start 2P', monospace; font-size: 11px; line-height: 1.7; color: var(--tube-2); margin: 14px 0 0; }
.arcade h1 {
  font-family: 'Press Start 2P', monospace;
  font-size: clamp(21px, 5.4vw, 52px); line-height: 1.25;
  color: var(--coin); margin: 16px 0 0;
  text-shadow: 4px 4px 0 #0B0413;
}
.arcade h2 { font-family: 'Press Start 2P', monospace; font-size: 14px; line-height: 1.6; color: var(--zap); margin: 0 0 14px; }
.arcade h3 { font-family: 'Press Start 2P', monospace; font-size: 11px; line-height: 1.7; color: var(--mint); margin: 18px 0 8px; }
.arcade .lede { font-size: 19px; line-height: 1.6; color: var(--tube); max-width: 58ch; margin: 20px 0 0; }
.arcade p, .arcade li { font-size: 16px; line-height: 1.62; }

/* One bank per cabinet: the machine, and the panels that belong to it. The
   room started with a single cabinet and a shared sidebar, which stopped
   working the moment there were two -- a readout headed YOUR ESMX floating
   above an otter game is furniture belonging to nobody. Each cabinet now
   carries its own. A third one adds a third bank and changes nothing else. */
.arc-bank   { display: flex; flex-wrap: wrap; gap: 18px; align-items: flex-start; margin: 26px 0 0; }
.arc-side   { flex: 1 1 320px; display: flex; flex-direction: column; gap: 18px; }
.arc-tail   { display: flex; flex-wrap: wrap; gap: 18px; align-items: flex-start; margin: 26px 0 0; }
.arc-tail > * { flex: 1 1 320px; }

/* The bay's running account of itself. Not a score: the newest line is on top,
   it keeps only the last few, and nothing here is stored or totalled. */
.baylog { margin: 0 0 12px; padding: 0; list-style: none; min-height: 44px; }
.baylog li { font-size: 14.5px; line-height: 1.6; color: var(--tube); padding: 4px 0; border-bottom: 1px solid var(--carpet); }
.baylog li:first-child { color: var(--mint); }
.baylog li:last-child { border-bottom: 0; }

/* ── The second screen: a kelp bay ────────────────────────────────────────
   Same cabinet, different world behind the glass, which is what an arcade is.
   The scanline is a background here too, so the only grounds anything sits on
   are the shoal, the deep, and what the stripe makes of each. */
.bay {
  position: relative; width: 100%; aspect-ratio: 8 / 5; overflow: hidden;
  background-image:
    repeating-linear-gradient(0deg, transparent 0 3px, rgba(255,255,255,.035) 3px 6px),
    linear-gradient(180deg, var(--shoal) 0 44%, var(--bay) 100%);
}
.bay[data-playing] { touch-action: none; cursor: crosshair; }
.bay:focus-visible { outline-offset: -4px; }

/* The waterline. Everything above it is air: an otter at the surface has its
   head out, which is the whole point of floating. */
.waterline {
  position: absolute; left: 0; right: 0; top: 18%; height: 3px;
  background: var(--kelp-2); opacity: .5;
}
/* THE BED IS MARKED BY ITS EDGE, NOT BY ITS FILL. check-contrast.py put the
   seabed at 1.10 against the water above it -- invisible -- and lightening the
   fill until it cleared 3:1 started swallowing the cobbles and the urchin that
   sit on it, which are the things a player actually reaches for. So the floor
   stays dark and the boundary is a line, measuring 8.44 against the water and
   9.25 against the bed. The information is "here is the floor", and a line
   carries it perfectly well. */
.seabed {
  position: absolute; left: 0; right: 0; bottom: 0; height: 7%;
  background: #04161D; border-top: 3px solid var(--cobble);
}

.otter  { position: absolute; width: 15%;  transform: translate(-50%, -50%); }
.otter[data-face="left"] { transform: translate(-50%, -50%) scaleX(-1); }
.fish   { position: absolute; width: 6%;   transform: translate(-50%, -50%); }
.cobble { position: absolute; width: 4.2%; transform: translate(-50%, -50%); }
.shelly { position: absolute; width: 5.4%; transform: translate(-50%, -50%); }
/* Kelp grows off the seabed and is the only thing here that is scenery and
   mechanism at once -- it is what holds a floating otter still. */
.frond  { position: absolute; bottom: 0; width: 7%; transform: translateX(-50%); }

/* ── The third screen: a shore ────────────────────────────────────────────
   Pale, and deliberately: two dark screens in a row would have made the third
   cabinet look like a variant of the second. Sky, a band of sea, shingle. The
   scanline here is DARK rather than light, because a white stripe over a pale
   ground is invisible -- which means the un-striped base is the lightest ground
   on this screen and therefore the one every ink is measured against. */
.shore {
  position: relative; width: 100%; aspect-ratio: 8 / 5; overflow: hidden;
  background-image:
    repeating-linear-gradient(0deg, transparent 0 3px, rgba(0,0,0,.05) 3px 6px),
    linear-gradient(180deg, var(--sky) 0 40%, var(--sea) 40% 52%, var(--shingle) 52% 100%);
}
.shore[data-playing] { touch-action: none; cursor: crosshair; }
.shore:focus-visible { outline-offset: -4px; }
/* The overcast is the palest screen in the cabinet: yellow was 1.03 on the sky.
   The cabinet's pen-dark is 5.41 on the darkest band of sea and 11.04 on the
   sky, and it is what the coin is already made of. */
.shore:focus-visible, .shore :focus-visible { outline-color: var(--pen-dark); }

.peng   { position: absolute; width: 13%; transform: translate(-50%, -100%); }
.peng[data-face="left"] { transform: translate(-50%, -100%) scaleX(-1); }
.pebble { position: absolute; width: 4%;  transform: translate(-50%, -50%); }
.nest   { position: absolute; width: 15%; transform: translate(-50%, -100%); }
/* Further up the beach is further away, so the neighbours are drawn smaller.
   Without it every penguin was the same size on the same line and there was no
   telling which one you were steering. */
.peng--them { width: 10.5%; }
.nest--theirs { width: 12.5%; }

.peng .pose { visibility: hidden; }
.peng .pose[data-on] { visibility: visible; }
.peng .beakful { visibility: hidden; }
.peng[data-carrying] .beakful { visibility: visible; }
/* Before anybody presses start the penguin is simply standing there. */
.shore:not([data-playing]) .peng .pose[data-pose="stand"] { visibility: visible; }
.shore:not([data-playing]) .peng { left: 19%; top: 92%; width: 22%; }
.shore:not([data-playing]) .attract { padding-left: 33%; align-items: flex-start; text-align: left; }
.shore[data-playing] .attract { display: none; }
/* The attract copy is the one place on this screen with type on it, and the
   screen is pale, so it inverts: dark on light where the other two are light
   on dark. */
.shore .attract p { color: var(--pen-dark); }
.shore .coin { background: var(--pen-dark); color: var(--sky); border-color: var(--sky); }
.shore .coin:hover { background: var(--peb-press); }

/* The poses. A trick is a run of drawn frames, NOT a rotation applied to one
   of them -- which is a decision about check-gentle.py and not about style.
   The angled poses are rotated INSIDE their own <svg>, where a transform is
   part of the drawing the way a path's d is; nothing in this room ever rotates
   a DOM element, at any dial setting, playing or not. Frame-swapping is also
   what an actual cabinet did. */
.otter .pose { visibility: hidden; }
.otter .pose[data-on] { visibility: visible; }

/* A stone being carried rides on the chest, which is where an otter puts it. */
.otter .carry { visibility: hidden; }
.otter[data-carrying] .carry { visibility: visible; }

/* ── The foyer: cabinets standing there, seen from the door ───────────────
   The Arcade stopped being one long page the moment it had a second machine.
   It is a room you walk into now, and what you see is what you see in a real
   one: a lit marquee, an attract screen, and a body you walk up to. Each
   cabinet's own page carries the game, its controls, its refusals and its
   credits, and its own share card -- which is the argument that decided it.
   With both games on one page, a link to the otter unfurled as a picture of a
   porcupine, which is exactly the fault make-og.py exists to refuse. */
.cabrow {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 20px; margin: 28px 0 0; padding: 0; list-style: none;
}
.cabfront {
  display: flex; flex-direction: column; height: 100%; text-decoration: none;
  background: var(--cab); border: 5px solid var(--coin); border-radius: 8px;
  overflow: hidden; transition: border-color .15s ease;
}
.cabfront:hover { border-color: var(--mint); }
.cabfront__marquee {
  display: block; padding: 15px 16px; text-align: center;
  background: var(--coin); color: var(--carpet);
  font-family: 'Press Start 2P', monospace; font-size: clamp(12px, 2.5vw, 17px); line-height: 1.5;
}
.cabfront:hover .cabfront__marquee { background: var(--mint); }

/* The attract screen, standing still. Nothing here animates at any dial
   setting -- a foyer full of moving screens would be the one thing this room
   promises it is not, before you have pressed anything. */
.cabfront__screen {
  display: block; position: relative; margin: 14px 14px 0;
  aspect-ratio: 8 / 5; overflow: hidden;
  border: 4px solid #0B0413; border-radius: 6px;
  background-image:
    repeating-linear-gradient(0deg, transparent 0 3px, rgba(255,255,255,.035) 3px 6px),
    linear-gradient(180deg, var(--crt) 0 100%);
}
.cabfront__screen--bay {
  background-image:
    repeating-linear-gradient(0deg, transparent 0 3px, rgba(255,255,255,.035) 3px 6px),
    linear-gradient(180deg, var(--shoal) 0 44%, var(--bay) 100%);
}
.cabfront__screen--shore {
  background-image:
    repeating-linear-gradient(0deg, transparent 0 3px, rgba(0,0,0,.05) 3px 6px),
    linear-gradient(180deg, var(--sky) 0 40%, var(--sea) 40% 52%, var(--shingle) 52% 100%);
}
.cabfront__screen .sprite { left: 50%; top: 54%; width: 46%; }
.cabfront__screen .peng { left: 50%; top: 94%; width: 34%; }
.cabfront__screen .peng .pose[data-pose="stand"] { visibility: visible; }
.cabfront__screen .otter  { left: 50%; top: 52%; width: 50%; }
.cabfront__screen .otter .pose[data-pose="swim"] { visibility: visible; }

.cabfront__body {
  flex: 1; display: flex; flex-direction: column; justify-content: space-between;
  gap: 14px; padding: 15px 17px 17px;
}
.cabfront__blurb { display: block; font-size: 14.5px; line-height: 1.55; color: var(--tube); }
.cabfront__press { display: block; font-family: 'Press Start 2P', monospace; font-size: 11px; color: var(--mint); }
.cabfront:hover .cabfront__press { color: var(--coin); }

/* ── The cabinet ──────────────────────────────────────────────────────────── */
.cabinet {
  flex: 1 1 560px;
  background: var(--cab); border: 5px solid var(--coin); border-radius: 8px;
  padding: 0 0 18px; overflow: hidden;
}
.cab-marquee {
  margin: 0; padding: 15px 18px; text-align: center;
  background: var(--coin); color: var(--carpet);
  font-family: 'Press Start 2P', monospace; font-size: clamp(13px, 3.1vw, 22px); line-height: 1.5;
}
.cab-sub { margin: 0; padding: 11px 18px 0; font-size: 14px; color: var(--tube-2); text-align: center; }

/* The screen. The scanlines are a BACKGROUND and sit under everything, so the
   only two grounds any type here lands on are --crt and the #0F1F24 the
   scanline makes. Overlaying them instead would have darkened every quill on
   the field by an amount nobody had measured. */
.screen {
  margin: 14px 16px 0; padding: 0;
  background: var(--crt); border: 4px solid #0B0413; border-radius: 6px;
}
.field {
  position: relative; width: 100%; aspect-ratio: 8 / 5; overflow: hidden;
  background-image: repeating-linear-gradient(0deg, transparent 0 3px, rgba(255,255,255,.035) 3px 6px);
}
.field:focus-visible { outline-offset: -4px; }
/* The field swallows drags so a finger steering Esmx does not scroll the page
   out from under the cabinet. */
.field[data-playing] { touch-action: none; cursor: crosshair; }

/* Everything on the field is positioned in per-cent of the field, so the game
   is the same game at 360px and at 1180px and nothing has to be told the pixel
   size of anything. */
/* transform: translate, and deliberately not the standalone `translate`
   property. A pure translation carries no rotation and no skew, which is what
   check-gentle.py is reading for — and it reads the COMPUTED TRANSFORM, which
   the standalone property never reaches. Centring these the other way would
   have worked and been invisible to the checker, and a room should not hold
   anything the checker cannot see. */
.sprite { position: absolute; width: 17%; transform: translate(-50%, -50%); }
/* Esmx turns round rather than moonwalking. scaleX is a mirror, not a tilt:
   check-gentle.py reads it as layout, which is exactly what it is. */
.sprite[data-face="left"] { transform: translate(-50%, -50%) scaleX(-1); }
/* A slot nobody has filled is EMPTY, not grey. A bare Esmx should look bare. */
.esmx-mane .q[data-off] { visibility: hidden; }
.quill  { position: absolute; width: 5.4%; transform: translate(-50%, -50%); }

/* The idle screen, before the coin. It is markup rather than a drawing so a
   screen reader gets the same offer a sighted visitor does. */
.attract {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 16px; text-align: center; padding: 18px;
}
.attract p { margin: 0; font-family: 'Press Start 2P', monospace; font-size: clamp(10px, 2.1vw, 13px); line-height: 1.9; color: var(--tube); }
.field[data-playing] .attract, .bay[data-playing] .attract { display: none; }
/* Before the coin, Esmx stands in the corner of the attract screen the way a
   cabinet's side art does, and the offer is set beside them. A visitor with no
   JavaScript gets exactly this and nothing broken: a picture of the mascot, the
   name of the game, and a room underneath that explains it. */
.field:not([data-playing]) .sprite { left: 17%; top: 64%; width: 27%; }
.bay:not([data-playing]) .otter { left: 19%; top: 66%; width: 26%; }
.field:not([data-playing]) .attract,
.bay:not([data-playing]) .attract { padding-left: 31%; align-items: flex-start; text-align: left; }
/* Before the coin, the otter is side art and is simply itself. */
.bay:not([data-playing]) .otter .pose[data-pose="swim"] { visibility: visible; }

.coin {
  cursor: pointer; font-family: 'Press Start 2P', monospace;
  font-size: clamp(11px, 2.4vw, 15px); line-height: 1.5;
  background: var(--coin); color: var(--carpet);
  border: 4px solid var(--carpet); border-radius: 6px; padding: 15px 20px;
}
.coin:hover { background: var(--mint); }

.screen-say {
  margin: 0; padding: 12px 15px; min-height: 66px;
  border-top: 4px solid #0B0413; background: var(--crt);
  font-family: 'Press Start 2P', monospace; font-size: 11px; line-height: 1.8; color: var(--mint);
}

/* ── The controls under the screen ────────────────────────────────────────── */
.controls { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-start; padding: 16px 16px 0; }
.dpad { display: grid; grid-template-columns: repeat(3, 52px); grid-template-rows: repeat(3, 44px); gap: 6px; }
.dpad button { cursor: pointer; background: var(--carpet); color: var(--mint); border: 3px solid var(--mint); border-radius: 6px; font-family: 'Press Start 2P', monospace; font-size: 13px; }
.dpad button:hover, .dpad button[data-held] { background: var(--mint); color: var(--crt); }
.dpad .up { grid-area: 1 / 2; } .dpad .left { grid-area: 2 / 1; }
.dpad .right { grid-area: 2 / 3; } .dpad .down { grid-area: 3 / 2; }
.dpad .hub { grid-area: 2 / 2; border-color: var(--cab); background: var(--cab); }

.knobs { flex: 1 1 240px; display: flex; flex-direction: column; gap: 12px; }
.knobs fieldset { margin: 0; padding: 0; border: 0; }
.knobs legend { padding: 0 0 8px; font-family: 'Press Start 2P', monospace; font-size: 10px; line-height: 1.7; color: var(--tube-2); }
.knobrow { display: flex; flex-wrap: wrap; gap: 8px; }
.knob {
  cursor: pointer; flex: 1 1 auto;
  font-family: 'Press Start 2P', monospace; font-size: 10px; line-height: 1.6;
  padding: 12px 10px; border-radius: 6px;
  border: 3px solid var(--cab); background: var(--carpet); color: var(--tube);
}
.knob:hover { border-color: var(--mint); color: var(--mint); }
.knob[aria-pressed="true"] { background: var(--mint); color: var(--crt); border-color: var(--mint); }
.knob--stop { background: var(--zap); color: var(--carpet); border-color: var(--zap); }
.knob--stop:hover { background: var(--coin); border-color: var(--coin); color: var(--carpet); }

/* ── The plates down the side ─────────────────────────────────────────────── */
.plate { background: var(--cab); border: 4px solid var(--carpet); border-radius: 8px; padding: 18px 20px; }
.plate p { margin: 0 0 12px; font-size: 15px; }
.plate p:last-child { margin-bottom: 0; }
.plate ul { margin: 0; padding-left: 20px; }
.plate li { font-size: 15px; margin-bottom: 10px; }
.plate li:last-child { margin-bottom: 0; }
.plate small { display: block; font-size: 13.5px; line-height: 1.6; color: var(--tube-2); }

/* The mane you have built, as a row of spikes AND as a list of words. The
   words are not a fallback for the spikes; colour is never the only thing
   carrying a difference on this site, and a mane nobody can read is a mane
   nobody can tell anyone else about. */
.mane-count { font-family: 'Press Start 2P', monospace; font-size: 15px; line-height: 1.6; color: var(--coin); margin: 0 0 12px; }
.mane-strip { display: flex; flex-wrap: wrap; gap: 5px; align-items: flex-end; min-height: 44px; margin: 0 0 12px; }
.mane-strip svg { width: 20px; height: 34px; }
.mane-list { margin: 0; font-size: 15px; line-height: 1.7; color: var(--tube); }
.mane-empty { color: var(--tube-2); font-size: 14.5px; }

.take {
  margin-top: 14px; padding: 15px 16px; border-radius: 6px;
  background: var(--carpet); border: 3px solid var(--mint);
}
.take h3 { margin-top: 0; }
.take p { font-size: 14.5px; }

.arc-foot { margin: 34px 0 44px; }
.arc-foot .plate { border-color: var(--cab); background: transparent; }


/* §16 ── ROOM: The Latibulum ─────────────────────────────────────────────────
   A BURROW, NOT A TENT, AND THE DIFFERENCE IS LOAD-BEARING. This is the second
   warm brown room on the street and it had every opportunity to become a
   second Faery Yurt — same candlelight, same earth tones, same instinct to
   make the visitor feel held. It is not one, and the thing that keeps it apart
   is structural rather than decorative:

     · the yurt reads CREAM ON DARK all the way down; almost every word in here
       sits DARK ON A LIT PLASTER WALL, and the earth ground is what is left
       over around it. Two rooms lit by the same kind of light, inverted.
     · the yurt is a pitched column of canvas with fairy lights strung across
       the top. This is dug into a hill: round doorway, arched panels, thick
       walls, a low lamp, and no sky in it anywhere.
     · the yurt sets high-contrast italic serifs. This sets a planed slab and a
       rounded sans, because a smial is carpentry and not calligraphy.

   "They are both cosy, so they should feel the same" is the subroom excuse
   wearing a woolly jumper. The whole argument of this street is that walking
   from one room into another should feel like walking outside first.

   LOW STIMULATION IS THE BRIEF, AND THE DIAL STILL WINS. The room is quiet at
   every setting because it was designed quiet, not because Gentle took
   anything away — there is no tilt in here to reset and nothing is hidden at
   any level. ONE thing moves, and only at MAX: the lamp breathes, in opacity,
   over nine seconds. That is the whole of what MAX GLITTER buys in a burrow,
   and the room says so on its own face rather than leaving somebody to press
   it and wonder whether it worked.

   THE TWO OBJECTS ARE PRESS-TO-PLAY AND NOTHING ELSE, which is the street's
   oldest rule arriving in the quietest room: a wireless and a television that
   make no sound, fetch nothing, and say how long they run BEFORE you press
   them. Both facades are generated — see tools/make-latibulum.py. */

.room-latibulum {
  background: var(--loam); color: var(--oat);
  font-family: 'Nunito', ui-rounded, system-ui, sans-serif;
  font-size: 17px; line-height: 1.68;
}

/* The hollow itself. Two lamp pools and a vignette of packed earth falling
   away at the edges — the brighter pool tops out at --lamp .16, which is the
   #453620 in check-contrast.py. None of it moves, so none of it is gated. */
.burrow {
  /* PADDED, NOT JUST WIDTH-LIMITED. The lamp pools and the vignette make this
     element visible as a room with edges, and everything that is not on a
     plaster wall -- the headings, the ledes, the house rules, the dial -- sat
     flush against those edges with nothing between the words and the earth.
     The walls carry their own padding, which is exactly why the bare sections
     were the ones that looked wrong. The width goes up by the same amount the
     padding takes away, so the column of type is the length it always was. */
  width: min(932px, 100% - 44px); margin-inline: auto; padding: 0 26px 72px;
  background-image:
    radial-gradient(ellipse 760px 420px at 50% 120px, rgba(240,195,107,.16), transparent 72%),
    radial-gradient(ellipse 520px 380px at 84% 62%, rgba(240,195,107,.07), transparent 70%),
    radial-gradient(ellipse 700px 1500px at 50% 50%, transparent 58%, rgba(0,0,0,.42) 100%);
}

.room-latibulum a { color: var(--lamp); text-decoration-color: rgba(240,195,107,.45); text-underline-offset: 3px; }
.room-latibulum a:hover { color: var(--plaster); }
.room-latibulum .backlink { font-family: 'Bree Serif', Georgia, serif; font-size: 13px; letter-spacing: .06em; color: var(--oat-2); }
.room-latibulum h1, .room-latibulum h2, .room-latibulum h3 {
  font-family: 'Bree Serif', Georgia, serif; font-weight: 400; text-wrap: balance;
}
.room-latibulum h1 { font-size: clamp(40px, 6.6vw, 64px); line-height: 1.04; color: var(--oat); margin: 0 0 12px; }
.room-latibulum h2 { font-size: 27px; color: var(--oat); margin: 0 0 10px; }
.room-latibulum h3 { font-size: 20px; color: var(--umber); margin: 0 0 8px; }
.room-latibulum section { padding: 30px 0; }
.room-latibulum .lede { font-size: 19.5px; line-height: 1.6; color: var(--oat-2); max-width: 56ch; margin: 0 0 18px; }

.smial-head { text-align: center; padding: 46px 10px 16px; }
.smial-head .eyebrow {
  font-family: 'Bree Serif', Georgia, serif; font-size: 13.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--oat-2); margin: 0 0 22px;
}
.smial-head .lede { margin-inline: auto; }
.smial-head .burrow-tagline { font-size: 21px; color: var(--lamp); margin: 0 0 20px; }

/* The round door, looked at from the inside. It is a drawing rather than a
   link: you are already through it, and a door on this page that went
   somewhere would be the one piece of furniture here that asked something of
   you. */
.roundel { width: 178px; margin: 0 auto 22px; }
.roundel svg { display: block; width: 100%; height: auto; }

/* THE LIT WALL. Every panel that holds copy is plaster with the lamp on it —
   dark type on a warm ground, which is the inversion the whole room is built
   on. `.room-latibulum .wall`, not `.wall`, because `.room-latibulum section`
   above sets the vertical rhythm and would otherwise out-specify the padding
   here and leave two paragraphs pressed against the edge of their own wall.
   The yurt learned this the same way. */
.room-latibulum .wall {
  background: linear-gradient(180deg, var(--plaster), var(--plaster-2));
  color: var(--umber); border-radius: 22px; padding: 28px 30px;
  border: 1px solid rgba(58,42,28,.22);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.5), 0 20px 44px -26px rgba(0,0,0,.8);
}
/* A wall with the hill's own curve on top. The arch is the room's one repeated
   shape and it is why nothing in here is square. */
/* The top corners are quarter-circles of this radius, so the straight part of
   the top edge does not begin until 200px in from each side. Copy set inside
   that has to start BELOW the curve or the vault crops its own first line —
   which is what 44px of top padding did on the first build. The padding is the
   arch. */
.room-latibulum .wall--arched { border-radius: 200px 200px 22px 22px; padding: 104px 46px 30px; text-align: center; }
.room-latibulum .wall--arched p { text-align: left; }
.room-latibulum .wall a { color: var(--door); text-decoration-color: rgba(47,90,60,.5); }
.room-latibulum .wall a:hover { color: var(--rust); }
/* The lit plaster takes the burrow's umber ring, 9.80 and 8.14 across the
   wall's gradient; the lamplit dark outside the walls keeps the yellow. */
.room-latibulum .wall :focus-visible { outline-color: var(--umber); }
.room-latibulum .wall h2 { color: var(--umber); }
.room-latibulum .wall p { color: var(--umber); }
.room-latibulum .wall .note { color: var(--umber-2); font-size: 15px; }

/* The two objects. Both are wooden cases with something dark set into them,
   both are silent, and both are built the same way on purpose — a wireless and
   a television bought in the same decade and dragged underground. */
.thing { display: grid; gap: 22px; grid-template-columns: minmax(0, 1fr); margin: 0 0 8px; }
/* The object itself — aerial and case together — so the grid gap above sits
   between the thing and the plate that describes it, and not between a
   television and its own aerial.

   AND IT IS NARROWER THAN THE COLUMN, deliberately. At the full width of the
   page a wireless is a billboard with a knob on it: the screen recess came out
   848px across and read as a hole in the wall rather than as a thing standing
   in the room. Furniture is smaller than the room it is in. */
.thing__set { display: block; width: min(560px, 100%); margin-inline: auto; }
.thing__case {
  background:
    repeating-linear-gradient(90deg, rgba(0,0,0,.06) 0 3px, transparent 3px 11px),
    linear-gradient(180deg, #8A5F38, var(--beam) 55%, #5E3F23);
  border: 1px solid #4A321C; padding: 16px 16px 12px;
  box-shadow: 0 22px 46px -26px rgba(0,0,0,.9);
}
.wireless .thing__case { border-radius: 170px 170px 14px 14px; padding-top: 30px; }
.telly    .thing__case { border-radius: 26px; }

/* The facade, dressed as furniture. `overflow: hidden` so the case clips the
   iframe when the button becomes one — without it the player's own square
   corners sit on top of the rounded ones and the object stops being an object.
   §4 supplies the 16/9 box and the "nothing before the press" behaviour; this
   only changes what it is made of. */
.room-latibulum .facade {
  background: var(--recess); color: var(--oat);
  border: 3px solid #3E2A16; border-radius: 10px; overflow: hidden;
  font-family: 'Nunito', system-ui, sans-serif; font-size: 15px;
  box-shadow: inset 0 0 26px rgba(0,0,0,.85);
}
.room-latibulum .facade:hover { background: #211a11; }
.room-latibulum .facade__play { font-family: 'Bree Serif', Georgia, serif; font-size: 13px; letter-spacing: .1em; color: var(--lamp); }
.telly .facade { border-radius: 9% / 11%; border-width: 5px; }

/* The grille cloth over the wireless's speaker, and the tuning strip under it.
   Both are drawings and neither carries a word, so both are hidden from the
   accessibility tree in the markup. */
/* Speaker cloth: a weave rather than a rail, which is what 26px of vertical
   stripe looked like. Two crossed hatches over the dark of the recess, the same
   trick the yurt's canvas uses, because that is what woven cloth actually is. */
.grille {
  height: 54px; margin: 0 0 14px; border-radius: 44px 44px 6px 6px;
  background:
    repeating-linear-gradient(90deg, rgba(0,0,0,.45) 0 2px, transparent 2px 6px),
    repeating-linear-gradient(0deg,  rgba(0,0,0,.45) 0 2px, transparent 2px 6px),
    linear-gradient(180deg, #6B4926, #4A321C);
  border: 2px solid #3E2A16;
}
.tuner { display: flex; align-items: center; gap: 12px; margin: 12px 2px 0; }
.tuner__scale { flex: 1 1 auto; height: 18px; border-radius: 8px; background: linear-gradient(180deg, #F6EBD2, var(--plaster-2)); border: 1px solid #4A321C; position: relative; }
.tuner__scale::before { content: ""; position: absolute; inset: 0; background: repeating-linear-gradient(90deg, rgba(58,42,28,.55) 0 1px, transparent 1px 13px); }
.tuner__needle { position: absolute; top: -3px; bottom: -3px; left: 38%; width: 3px; border-radius: 2px; background: var(--rust); box-shadow: 0 0 0 1px rgba(255,255,255,.35); }
/* A FLAT DISC RATHER THAN A TURNED ONE. The first version was a radial
   gradient running from a highlight down to #8A6120, which looked like brass
   and measured 1.93 against the lightest of the three woods behind it — a knob
   you could not see on the cabinet it is screwed to. The shading is an inset
   shadow now, so the colour that identifies the knob is one colour and clears
   3:1 on all three. The same measurement moved --brass itself; see
   check-contrast.py. */
.set-knob { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%; background: var(--brass); box-shadow: inset -4px -4px 0 rgba(58,26,0,.22); }

/* The television's aerial and its two dials. The aerial is the reason this is
   a television and not a box: it is the only thing in the room that points at
   a sky it cannot see. */
.aerial { display: block; width: 130px; height: 46px; margin: 0 auto -2px; }
.dials { display: flex; gap: 12px; justify-content: flex-end; align-items: center; margin: 12px 2px 0; }

.thing__plate { margin-top: 4px; }
.thing__plate .runs { font-family: 'Bree Serif', Georgia, serif; font-size: 13px; letter-spacing: .08em; text-transform: uppercase; color: var(--umber-2); margin: 0 0 8px; }

/* The shelf of things to do with a bodymind. Soft, round, and NOT A CHECKLIST:
   no state, no counter, no tick. A tile here is a suggestion lying on a shelf,
   which is why none of them is a button — the moment one is, the room has
   started keeping score, and this site refuses a tally beside a practice that
   is not about volume in the cabinet two doors down as well. */
.burrow-shelf { display: grid; grid-template-columns: repeat(auto-fit, minmax(178px, 1fr)); gap: 14px; margin: 18px 0 0; padding: 0; list-style: none; }
.burrow-shelf li {
  display: flex; gap: 12px; align-items: flex-start;
  background: rgba(255,255,255,.34); border: 1px solid rgba(58,42,28,.18);
  border-radius: 18px; padding: 14px 15px;
}
.burrow-shelf svg { flex: 0 0 auto; width: 26px; height: 26px; }
.burrow-shelf b { display: block; font-family: 'Bree Serif', Georgia, serif; font-weight: 400; font-size: 17px; color: var(--umber); }
.burrow-shelf span { display: block; font-size: 14.5px; line-height: 1.5; color: var(--umber-2); margin-top: 2px; }

.saying { margin: 22px 0 0; padding: 18px 0 4px 20px; border-left: 4px solid var(--door); }
.saying p { font-family: 'Bree Serif', Georgia, serif; font-size: 19px; line-height: 1.5; color: var(--umber); margin: 0 0 8px; }
.saying cite { display: block; font-style: normal; font-size: 14.5px; color: var(--umber-2); }

/* The lamp. The only thing in this room that ever moves, and only at MAX —
   opacity, over nine seconds, no rotation and no scale. A burrow whose loudest
   setting was actually loud would be a burrow lying about what it is. */
.lamp-pool { display: block; width: 92px; height: 92px; margin: 0 auto; }
html[data-intensity="max"] .lamp-flame { animation: latibulum-breathe 9s ease-in-out infinite; }
@keyframes latibulum-breathe { 0%, 100% { opacity: .72; } 50% { opacity: 1; } }

.burrow-rules { margin: 0; padding: 0; list-style: none; }
.burrow-rules li { position: relative; padding: 0 0 0 26px; margin: 0 0 12px; color: var(--oat); }
.burrow-rules li::before { content: ""; position: absolute; left: 0; top: .55em; width: 11px; height: 11px; border-radius: 50%; background: var(--lamp); }
.burrow-rules strong { color: var(--plaster); }

.burrow-note { font-size: 14.5px; line-height: 1.6; color: var(--oat-2); }
.burrow-note a { color: var(--lamp); }


/* §17 ── ROOM: The Jungle Room ───────────────────────────────────────────────
   A VIEWING ROOM UNDER A CLOSED ROOF, and the thing it is NOT is the
   campgrounds. That is the pairing to watch here the way the yurt and the
   burrow are the pairing to watch two sections up: both are outdoors, both are
   dark, both are green. What keeps them apart is structural rather than a
   choice of swatch:

     · the campground is night-BLUE under nothing — a bare field with the sky
       still on it and posts standing alone on open ground. This is night-GREEN
       under a ROOF, with light arriving only where the leaves let it, and
       nothing in it stands alone because everything overlaps something.
     · the campground routes its lettering like a park sign: flat, incised,
       even-stroke. This sets a face whose strokes SWELL as they turn, because
       a rainforest is the one place where growing and thickening are the same
       verb.
     · the campground is cold and dry and you are outside in it. This is warm
       and wet and you are inside it. You walked in under something.

   "They are both green, so they should feel the same" is the subroom excuse in
   a poncho, and it is wrong for the same reason every previous version of it
   was wrong.

   EVERY SCREEN IS A LEAF, and that is the whole shape of the room: an aperture
   with two pointed corners and two round ones, which is a leaf and is also a
   gap in the canopy. Nothing else on this street is that shape, and it is why
   thirty-odd rectangles of video do not read as a spreadsheet.

   THE ONE ROOM WHERE A FACADE CANNOT SAY HOW LONG IT RUNS. Every other
   press-to-play control here carries a runtime, because that is what lets
   somebody decide before pressing. A live camera has no runtime — the honest
   answer is that it does not stop — and storing the length of whatever stream
   happens to be up today would put a number on the page that is wrong
   tomorrow. So the promise is kept the other way round: the label says the
   thing runs until you close it, and the room says out loud that the picture
   is whatever is happening there now, including nothing. make-jungle.py
   REFUSES a cam carrying a length, which is the exact inverse of the check
   make-latibulum.py runs, and both are the same promise.

   WHAT MOVES, AND ONLY AT MAX: the light through the canopy, and the dot
   beside the word LIVE. Both are opacity and nothing else. There is not one
   rotation in this section — every leaf that hangs at an angle hangs at an
   angle because its path is drawn that way inside its own <svg>, which is part
   of the picture rather than a tilt applied to it. That is deliberate: a
   transform is the one thing check-gentle.py can see, so a room that hid its
   decoration behind one would be asking that tool to take its word for
   something. See the same argument in §15. */

/* THE LIGHT IS ON THE WHOLE PAGE RATHER THAN ON THE COLUMN, which took a
   second go. Painted on the column it stopped at the column's edges, and the
   top of it drew a hard bright line straight across the page under the canopy
   — a shaft with a lid on it. Light does not stop where the text column does.
   The brightest of these tops out at --sun .12, which is the #232E1A in
   check-contrast.py: the ground every word in this room is really read on. */
.room-jungle {
  background-color: var(--canopy); color: var(--daylight);
  font-family: 'Cabin', ui-sans-serif, system-ui, sans-serif;
  font-size: 17px; line-height: 1.66;
}
/* The light gets a layer of its own rather than living on an element that also
   holds words. Two reasons, and the second is the one that matters: a shaft
   painted on the text column stopped at the column's edges and drew a hard
   bright line across the page under the canopy, which is a shaft with a lid on
   it — and at MAX the light shifts, so whatever carries it is what fades.
   Put it on the column and MAX GLITTER would have dimmed every word in the
   room by a tenth, twice a minute, in a room built for people who came here to
   stop being asked to work. The brightest of these tops out at --sun .12,
   which is the #232E1A in check-contrast.py: the ground every word in this
   room is really read on. */
.room-jungle::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background-image:
    linear-gradient(196deg, transparent 0, rgba(245,208,107,.10) 26px, rgba(245,208,107,.10) 46px, transparent 84px),
    linear-gradient(168deg, transparent 0, rgba(245,208,107,.07) 16px, rgba(245,208,107,.07) 28px, transparent 58px),
    linear-gradient(186deg, transparent 0, rgba(245,208,107,.05) 34px, rgba(245,208,107,.05) 56px, transparent 110px),
    radial-gradient(ellipse 900px 460px at 50% 0, rgba(245,208,107,.12), transparent 72%);
  background-position: 16% 0, 58% 0, 88% 0, 50% 0;
  background-repeat: no-repeat;
}

/* The column. It carries no ground of its own: the light above belongs to the
   whole page and this only decides how wide the words are. */
.jungle { width: min(1060px, 100% - 44px); margin-inline: auto; padding: 0 24px 80px; }
html[data-intensity="max"] .room-jungle::before { animation: jungle-light 22s ease-in-out infinite; }
@keyframes jungle-light { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }

.room-jungle a { color: var(--heliconia); text-decoration-color: rgba(255,133,87,.45); text-underline-offset: 3px; }
.room-jungle a:hover { color: var(--sun); }
.room-jungle .backlink { font-family: 'Cabin', system-ui, sans-serif; font-weight: 700; font-size: 13px; letter-spacing: .14em; text-transform: uppercase; color: var(--sap); }
.room-jungle h1, .room-jungle h2, .room-jungle h3 {
  font-family: 'Yeseva One', Georgia, serif; font-weight: 400; text-wrap: balance;
}
.room-jungle h1 { font-size: clamp(42px, 7.4vw, 78px); line-height: 1.02; color: var(--daylight); margin: 0 0 14px; }
.room-jungle h2 { font-size: 30px; color: var(--sun); margin: 0 0 6px; }
.room-jungle h3 { font-size: 21px; line-height: 1.25; color: var(--daylight); margin: 0 0 7px; }
.room-jungle section { padding: 34px 0; }
.room-jungle .lede { font-size: 19.5px; line-height: 1.58; color: var(--sap); max-width: 58ch; margin: 0 0 18px; }

/* The canopy itself, hanging over the top of the page. A band of overlapping
   leaves drawn already at their angles, because a leaf that hangs straight is
   a label. It is a drawing and carries no words, so it is hidden in the
   markup. */
.canopy-roof { display: block; width: 100%; height: clamp(88px, 13vw, 150px); margin: 0; }

.jungle-head { padding: 26px 4px 8px; }
.jungle-head .eyebrow {
  font-family: 'Cabin', system-ui, sans-serif; font-weight: 700;
  font-size: 13px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--orchid); margin: 0 0 18px;
}
.jungle-tagline { font-family: 'Yeseva One', Georgia, serif; font-size: 23px; line-height: 1.3; color: var(--heliconia); margin: 0 0 18px; }

/* A root buttress: a panel that flares at the foot the way a rainforest tree
   does, because nothing down here stands on a straight trunk. Copy panels are
   the only thing in the room that is not a leaf. */
.buttress {
  background: var(--understory); color: var(--daylight);
  border: 1px solid var(--buttress);
  border-radius: 10px 10px 60px 60px / 10px 10px 26px 26px;
  padding: 26px 30px 34px;
}
.buttress h2 { color: var(--sun); }
.buttress .note { color: var(--sap); font-size: 15px; }

/* A gallery. The head is a leaf glyph, the name, and one line of ours about
   what this group of cams is for — lifted in spirit from our own events page,
   which groups them this way and is not ours to re-sort. */
.gallery { padding-top: 10px; }
.gallery__head { display: flex; gap: 14px; align-items: flex-start; margin: 0 0 22px; padding-bottom: 14px; border-bottom: 1px solid var(--buttress); }
.gallery__head svg { flex: 0 0 auto; width: 34px; height: 34px; margin-top: 4px; }
.gallery__head p { margin: 0; color: var(--sap); font-size: 16px; max-width: 62ch; }

.cams { display: grid; grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); gap: 26px; margin: 0; padding: 0; list-style: none; }

/* A cam. Leaf-shaped, top-left and bottom-right rounded hard, the other two
   corners left pointed — the same silhouette at every size, on the card and on
   the aperture inside it. */
.cam {
  display: flex; flex-direction: column; gap: 14px;
  background: var(--understory); border: 1px solid var(--buttress);
  border-radius: 40px 6px 40px 6px; padding: 16px 18px 20px;
}
.cam__view { border-radius: 34px 4px 34px 4px; overflow: hidden; }

/* The facade, dressed as a gap in the leaves. §4 supplies the 16/9 box and the
   nothing-before-the-press behaviour; this only changes what it is made of.
   `overflow: hidden` on the wrapper above is what clips the player into the
   leaf once the button becomes an iframe — without it the video's square
   corners sit on top of the pointed ones and the aperture stops being one. */
.room-jungle .facade {
  background: #041209; color: var(--daylight);
  border: 0; border-radius: 34px 4px 34px 4px;
  font-family: 'Cabin', system-ui, sans-serif; font-size: 15px;
  box-shadow: inset 0 0 0 1px rgba(87,160,92,.5), inset 0 0 60px rgba(0,0,0,.8);
}
.room-jungle .facade:hover { background: #07200F; }
.room-jungle .facade__play {
  font-family: 'Cabin', system-ui, sans-serif; font-weight: 700;
  font-size: 13px; letter-spacing: .14em; text-transform: uppercase; color: var(--sun);
}

/* LIVE, and no runtime, because there is not one. The dot is the only other
   thing in the room that moves and it only moves at MAX. */
/* The dot sits on the FIRST line rather than in the middle of the block: this
   label wraps on a narrow card, and a centred dot beside two lines of type
   floats between them looking like a bullet that lost its list. */
.cam__live {
  display: flex; align-items: flex-start; gap: 8px; margin: 0 0 8px;
  font-family: 'Cabin', system-ui, sans-serif; font-weight: 700;
  font-size: 12.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--sun);
}
.cam__dot { flex: 0 0 auto; margin-top: .42em; width: 9px; height: 9px; border-radius: 50%; background: var(--heliconia); }
html[data-intensity="max"] .cam__dot { animation: jungle-blink 3.4s ease-in-out infinite; }
@keyframes jungle-blink { 0%, 100% { opacity: 1; } 50% { opacity: .4; } }

.cam p { margin: 0 0 10px; font-size: 15.5px; line-height: 1.56; color: var(--daylight); }
.cam__who { margin: 0; font-size: 14px; color: var(--sap); }

/* A cam whose owner has embedding switched off. It gets a way out rather than
   a screen that would show a refusal where a picture should be — see the note
   in data/jungle.json and the check in make-jungle.py. It is deliberately NOT
   dressed as an aperture: a door is not a window, and pretending otherwise is
   what the broken version would have done. */
/* COLUMN, not row. As a row the heading and the explanation sat side by side
   and a <br> between them did nothing, because a line break is not a thing a
   flex container honours between two items. */
.cam--away .cam__away {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; text-align: center;
  aspect-ratio: 16 / 9; padding: 20px 24px;
  background: repeating-linear-gradient(135deg, rgba(87,160,92,.10) 0 9px, transparent 9px 18px), #041209;
  border: 2px dashed var(--palm); border-radius: 34px 4px 34px 4px;
  font-family: 'Cabin', system-ui, sans-serif; font-weight: 700;
  font-size: 15px; line-height: 1.45; color: var(--daylight); text-decoration: none;
}
.cam--away .cam__away:hover { color: var(--sun); border-color: var(--sun); }
.cam--away .cam__away .jungle-note { font-weight: 400; max-width: 34ch; }

.jungle-rules { margin: 0; padding: 0; list-style: none; max-width: 66ch; }
.jungle-rules li { position: relative; padding: 0 0 0 30px; margin: 0 0 14px; }
.jungle-rules li::before {
  content: ""; position: absolute; left: 0; top: .42em; width: 14px; height: 14px;
  background: var(--palm); border-radius: 100% 0 100% 0;
}
.jungle-rules strong { color: var(--sun); }

.jungle-note { font-size: 14.5px; line-height: 1.62; color: var(--sap); }

/* THE DOOR AT THE BACK OF THIS ROOM, and it is an easter egg rather than a
   signpost. The Chappell's door is a bordered panel with a heading shouting at
   you; this one is the same shape, turned right down: a hairline, small type,
   and the room's dimmest ink. You find it by getting to the bottom of the room
   rather than by being told.

   QUIET IS A VISUAL SETTING AND NOT A PERCEPTUAL ONE. This is an ordinary
   focusable link with real words in it, in the tab order, at full touch size,
   read out by a screen reader exactly like every other link on the street — on
   a Disabled people's site a secret that is only findable by a sighted mouse
   user is not a secret, it is an exclusion. Nothing here is display:none,
   nothing is a one-pixel target, and the reason is written here so the next
   person to make it subtler knows where the floor is. */
.den-door {
  display: block; margin: 40px 0 0; padding: 16px 0 0;
  border-top: 1px solid var(--buttress); text-decoration: none;
  max-width: 62ch;
}
.den-door .den-door__mark {
  display: block; font-family: 'Cabin', system-ui, sans-serif; font-weight: 700;
  font-size: 11.5px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--palm); margin: 0 0 6px;
}
.den-door .den-door__say { display: block; font-size: 14.5px; line-height: 1.6; color: var(--sap); }
.den-door:hover .den-door__mark { color: var(--sun); }
.den-door:hover .den-door__say { color: var(--daylight); }


/* §18 ── SUBROOM: The Den (off the Jungle Room) ──────────────────────────────
   GRACELAND'S JUNGLE ROOM, WHICH IS WHY THERE IS A DOOR AT THE BACK OF OURS.
   Elvis Presley's den: dark wood panelling, carved Polynesian furniture, fur
   thrown over it, a waterfall of cut fieldstone on the north wall, jade glass
   lamps, and a bright green shag carpet. In 1976 it was converted into a
   recording studio and the bulk of his last two albums were made in it. That
   fact is the whole reason this subroom exists — the joke would have been
   enough for a link, and the discography is what earns a room.

   IT IS A SUBROOM AND IT SHARES NOTHING WITH ITS PARENT, and this is the
   hardest version of that yet, because the two rooms have the SAME NAME and the
   same colour. The Chappell at least did not sound like Pink Pony Club. So the
   separation has to be structural and it has to be stated:

     · UPSTAIRS THE GREEN IS THE DARKNESS. The Jungle Room is a near-black green
       under a closed canopy with the light coming DOWN through it, and every
       word in it is cream on that dark. Here the room is BROWN — panelled, lit
       by lamps at knee height, no sky and no daylight anywhere — and the green
       is the brightest thing in it, laid on the floor, with the track list set
       DARK ON THE CARPET. Same colour, opposite job.
     · upstairs is outdoors and open, and nothing in it is square. This is a
       low, closed, rectangular room full of furniture: carved frames, notched
       corners, heavy borders, a piece of fake fur on the bench.
     · upstairs sets a high-contrast serif whose strokes swell as they curve.
       This sets a slab with NO contrast in it at all, because one is a
       botanical plate and the other is a record sleeve from 1976.

   "It is only the room behind the other one, it should match" is the excuse
   this street has refused five times now, and it has never been more persuasive
   than it is here, where both rooms are literally called the Jungle Room.

   EVERY BUTTON SAYS HOW LONG IT RUNS, and that is the parent's rule inverted
   rather than broken. make-jungle.py REFUSES a runtime because a live camera
   never ends; make-den.py REFUSES a track without one because a song has a
   length and withholding it is withholding the thing that lets somebody decide.
   Read the two tools together.

   THE DOOR IN IS DELIBERATELY QUIET AND IS NOT HIDDEN. An easter egg on a
   Disabled people's site is a visual joke, never a perceptual one: `.den-door`
   is dim, small and off to one side, and it is an ordinary focusable link with
   real text in it, in the tab order, at full size, reachable by keyboard and
   readable by a screen reader like anything else. Subtle means quiet. It does
   not mean display:none, a one-pixel target, or a thing only a mouse can find. */

.room-den {
  background: var(--panel); color: var(--coconut);
  font-family: 'Karla', ui-sans-serif, system-ui, sans-serif;
  font-size: 17px; line-height: 1.62;
}
/* The panelling, and two lamps standing on the floor of it. No daylight in this
   room at all: the brighter pool tops out at --tiki .14, which is the #412B10
   in check-contrast.py, and the red one is the corner lamp in the photographs.
   Vertical grooves, because that is what a panelled wall is. */
.room-den::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background-image:
    radial-gradient(ellipse 560px 420px at 12% 78%, rgba(240,176,64,.14), transparent 70%),
    radial-gradient(ellipse 460px 360px at 88% 26%, rgba(242,112,90,.09), transparent 72%),
    repeating-linear-gradient(90deg, rgba(0,0,0,.20) 0 2px, transparent 2px 34px);
}

.den { width: min(980px, 100% - 44px); margin-inline: auto; padding: 0 22px 80px; }

.room-den a { color: var(--tiki); text-decoration-color: rgba(240,176,64,.45); text-underline-offset: 3px; }
.room-den a:hover { color: var(--coconut); }
.room-den .backlink { font-family: 'Karla', system-ui, sans-serif; font-weight: 700; font-size: 12.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--rattan); }
.room-den h1, .room-den h2, .room-den h3 { font-family: 'Ultra', Georgia, serif; font-weight: 400; text-wrap: balance; }
.room-den h1 { font-size: clamp(34px, 6vw, 62px); line-height: 1.06; color: var(--coconut); margin: 0 0 14px; }
.room-den h2 { font-size: 26px; line-height: 1.12; color: var(--tiki); margin: 0 0 6px; }
.room-den h3 { font-size: 19px; line-height: 1.2; color: var(--cocoa); margin: 0 0 6px; }
.room-den section { padding: 30px 0; }
.room-den .lede { font-size: 19px; line-height: 1.56; color: var(--rattan); max-width: 58ch; margin: 0 0 16px; }

.den-head { padding: 30px 4px 6px; }
.den-head .eyebrow {
  font-family: 'Karla', system-ui, sans-serif; font-weight: 700;
  font-size: 12.5px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--jade); margin: 0 0 18px;
}
.den-tagline { font-family: 'Ultra', Georgia, serif; font-size: 20px; line-height: 1.3; color: var(--rum); margin: 0 0 16px; }

/* The waterfall on the north wall: cut fieldstone, and the one drawing in the
   room that moves — at MAX only, and only in opacity. */
.falls { display: block; width: 168px; height: auto; margin: 0 0 20px; }
html[data-intensity="max"] .falls__water { animation: den-fall 7s ease-in-out infinite; }
@keyframes den-fall { 0%, 100% { opacity: .78; } 50% { opacity: 1; } }

/* A panel on the wall: cut stone, for anything that is not the carpet. */
.stonewall {
  background: linear-gradient(180deg, #3A2113, #2B1709);
  border: 2px solid var(--teak); border-left: 9px solid var(--stone);
  border-radius: 4px; padding: 24px 26px;
}
.stonewall h2 { color: var(--tiki); }
.stonewall .note { color: var(--rattan); font-size: 15px; }

/* THE CARPET. Every session is a rectangle of shag with the track list set
   dark on it, which is the inversion this whole room turns on. The fleck is
   two hatches of black and white at low alpha — shag is not a flat colour, it
   is a surface with a nap on it. */
.carpet {
  background-image:
    repeating-linear-gradient(64deg, rgba(0,0,0,.09) 0 2px, transparent 2px 5px),
    repeating-linear-gradient(-51deg, rgba(255,255,255,.07) 0 2px, transparent 2px 6px),
    linear-gradient(170deg, var(--shag), var(--shag-2));
  border: 10px solid var(--teak); border-radius: 3px;
  padding: 26px 26px 30px;
  box-shadow: inset 0 0 0 2px rgba(30,17,7,.35), 0 26px 50px -30px rgba(0,0,0,.95);
}
.session { margin: 0 0 22px; }
.session__when {
  font-family: 'Karla', system-ui, sans-serif; font-weight: 700; font-size: 12.5px;
  letter-spacing: .18em; text-transform: uppercase; color: var(--cocoa-2); margin: 0 0 4px;
}
.carpet .session h2 { color: var(--cocoa); }
.session__sub { margin: 0; max-width: 62ch; color: var(--cocoa-2); font-size: 15.5px; line-height: 1.5; }

.cuts { display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); gap: 18px; margin: 0; padding: 0; list-style: none; }

/* A cut, framed the way the furniture in that room is framed: heavy teak with
   the corners notched out of it. Nothing on this street has that silhouette,
   and nothing upstairs has a straight edge at all. */
.cut {
  display: flex; gap: 14px; align-items: flex-start;
  background: rgba(246,236,217,.78);
  border: 3px solid var(--teak);
  clip-path: polygon(12px 0, calc(100% - 12px) 0, 100% 12px, 100% calc(100% - 12px),
                     calc(100% - 12px) 100%, 12px 100%, 0 calc(100% - 12px), 0 12px);
  padding: 16px 18px;
}
/* A track card is cream laid over the shag, so a play button's ring stands on
   something pale: yellow was 1.04 there. The panel brown is 12.83 at the
   card's darkest. The carpet between the cards keeps the yellow. */
.cut :focus-visible { outline-color: var(--panel); }
.cut__no { flex: 0 0 auto; margin: 0; font-family: 'Ultra', Georgia, serif; font-size: 26px; line-height: 1; color: var(--teak); }
.cut__body { min-width: 0; flex: 1 1 auto; }
.cut__by { margin: 0 0 8px; font-size: 13.5px; line-height: 1.45; color: var(--cocoa-2); }
.cut__note { margin: 0 0 12px; font-size: 15px; line-height: 1.5; color: var(--cocoa); }
.cut__runs { margin: 10px 0 0; font-size: 13px; line-height: 1.45; color: var(--cocoa-2); }

/* The facade, dressed as the lacquered top of a console. §4 supplies the 16/9
   box and the nothing-before-the-press behaviour; this only changes what it is
   made of. */
.room-den .facade {
  background: var(--panel); color: var(--coconut);
  border: 3px solid var(--teak); border-radius: 3px;
  font-family: 'Karla', system-ui, sans-serif; font-size: 14.5px;
  box-shadow: inset 0 0 22px rgba(0,0,0,.8);
}
.room-den .facade:hover { background: #170D05; }
.room-den .facade__play { font-family: 'Karla', system-ui, sans-serif; font-weight: 700; font-size: 12px; letter-spacing: .14em; color: var(--tiki); }

.den-rules { margin: 0; padding: 0; list-style: none; max-width: 66ch; }
.den-rules li { position: relative; padding: 0 0 0 28px; margin: 0 0 13px; }
/* A tiki notch rather than a bullet: a small stepped block, which is the shape
   the carving on that furniture keeps making. */
.den-rules li::before {
  content: ""; position: absolute; left: 0; top: .48em; width: 13px; height: 13px;
  background: var(--jade);
  clip-path: polygon(0 0, 100% 0, 100% 62%, 62% 62%, 62% 100%, 0 100%);
}
.den-rules strong { color: var(--tiki); }

.den-note { font-size: 14.5px; line-height: 1.6; color: var(--rattan); }


/* §19 ── ROOM: The Solarpunk Hermitage (pitch 03 in the campgrounds) ─────────
   RYAN'S OWN PITCH, and the first DAYLIT room on this street. That is not a
   mood, it is the entire structural separation: every other world here is a
   dark ground with light applied to it — neon on black, candle on canvas, lamp
   on earth, a screen in a dark arcade, shafts through a canopy — and this one
   is a lit ground with things standing in it. A solar cabin that reads as
   night would be an argument against itself.

   AND IT IS PITCHED ON A FIELD THAT IS THE OPPOSITE. You arrive out of cold
   blue dusk into full sun, which is the campground's own promise working a
   second time and in the other direction: walking into the Faery Yurt is
   stepping out of the night into a lit tent, and walking in here is stepping
   out of the night into the morning. Same field, two different doors.

   THE CAVE, THE CAMPFIRE AND THE WATERING HOLE ARE NOT DECOR. They are David
   Thornburg's primordial learning spaces, which our own glossary documents:
   the cave is where you learn from yourself, the campfire is where you learn
   from a storyteller, the watering hole is where you learn from peers. They are
   named and credited on the page rather than borrowed silently, because the
   whole point of naming a room after somebody's framework is that the framework
   came from somebody.

   TECH AND NATURE IS SET IN THE TYPE. Fraunces swells and curls; Sora is drawn
   on a grid with flat terminals. The room is the argument that those are not
   opposites, so it is not going to make one of them a decoration on the other. */

.hermitage {
  background: var(--noon); color: var(--furrow-2);
  font-family: 'Sora', ui-sans-serif, system-ui, sans-serif;
}
.hermitage a { color: var(--sprout-2); text-underline-offset: 3px; }
.hermitage a:hover { color: var(--furrow); }
/* Daylight takes the furrow's ring. Yellow was 1.05 and 1.18 on the plaster
   and the table; furrow is 12.29 and 13.83 there and 4.80 on the brightest
   chair, which is the one this had to clear. check-focus.py. */
.hermitage :focus-visible { outline-color: var(--furrow); }
/* Out of the daylight the ring changes with the ground. The cave is velvet and
   takes its own gilt, 7.49 to 10.06 across the three velvets and the laptop's
   lid; the big screen is glass and takes the yellow, 14.52. */
.hermitage :is(.cave, .laptop__lid) :focus-visible { outline-color: var(--gilt); }
.hermitage .bigscreen__glass :focus-visible { outline-color: var(--yellow); }
.hermitage p, .hermitage li { font-size: 17px; line-height: 1.68; }
.hermitage .backlink { font-family: 'Sora', ui-sans-serif, sans-serif; font-size: 15px; letter-spacing: 0; color: var(--sprout-2); }

.hermitage h1 {
  font-family: 'Fraunces', Georgia, serif; font-weight: 700;
  font-size: clamp(40px, 7.4vw, 78px); line-height: 1.02;
  color: var(--furrow); margin: 10px 0 0; letter-spacing: -0.015em;
}
.hermitage h2 { font-family: 'Fraunces', Georgia, serif; font-weight: 700; font-size: 30px; line-height: 1.14; color: var(--furrow); margin: 0 0 12px; }
.hermitage h3 { font-family: 'Fraunces', Georgia, serif; font-weight: 700; font-size: 21px; color: var(--furrow); margin: 0; }
.hermitage .lede { font-size: 20px; line-height: 1.58; color: var(--furrow-2); max-width: 56ch; margin: 20px 0 0; }
.hermitage .trailmark { margin: 0; font-size: 13.5px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--sprout-2); }

/* THE SKY IS A REAL BAND AND NOT A TINT ON THE PAGE. A wash behind everything
   would have made the whole room pale blue, which is a mood; a band with a
   horizon in it is a place you are standing outside of. It is the only
   gradient in this section. */
.daylight { background: linear-gradient(180deg, var(--daysky) 0%, var(--daysky-2) 78%, var(--noon) 100%); padding: 0 0 8px; margin: 0 0 4px; }
.daylight .wrap { padding: 26px 0 0; }

/* The cabin itself, drawn in daylight — which is a different drawing from the
   one on the campground's board, and deliberately. Out there it is a dark
   shape with a light in it seen across a cold field at night; here you have
   arrived and the sun is on it. Same building, and nothing in common to look
   at, which is what arriving somewhere is. */
.cabin { line-height: 0; margin: 14px 0 0; }
.cabin svg { display: block; width: 100%; height: auto; }

/* The three spaces, as cards you walk into. Not a grid of equal boxes — the
   street already is one, and this is a smallholding. */
.spaces { list-style: none; margin: 30px 0 0; padding: 0; display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.space {
  background: var(--noon-2); border: 2px solid var(--sprout); border-radius: 14px;
  padding: 20px 22px; display: flex; flex-direction: column; gap: 10px;
}
.space p { margin: 0; color: var(--furrow-2); font-size: 16px; }
.space__from { margin: 0; font-size: 14px; color: var(--sprout-2); }
.space--soon { border-style: dashed; }
.space--soon h3 { color: var(--furrow-2); }

/* SECTION-LEVEL NOTE: THE CAVE IS THE HARD ONE ON THIS WHOLE STREET, and the reason
   is written in §2 beside its colours. It is the fourth warm enclosed room
   here, after the Faery Yurt, The Latibulum and The Den — and "it is a cosy
   reading nook, it should feel like the other cosy places" is the Latibulum
   argument arriving for the second time, which is exactly when it stops being
   obviously wrong. What keeps it apart is structural and has to stay:

     · the other three are each lit by ONE source flickering in the dark. This
       one is EVENLY LIT, at reading brightness, all the way across. The panels
       on the roof are why, which makes the lighting an argument rather than a
       mood. The candles are ornaments on a room that does not need them.
     · the other three are made of canvas, earth and panelling. This is made of
       TEXTILE — heavy curtain, no wood, no carpentry, and no straight edge in
       it but the shelves, which is why everything down here is round-cornered
       and nothing has a mitre.
     · you reach the others out of the dark. You reach this one out of full
       daylight, and it is darker than where you came from. Every other warm
       room on this street is a relief from the cold; this is a relief from
       the bright.

   Flatten any one of those and the street has two cosy rooms doing the same
   thing twice, which is worse than either doing it once. */
.cave {
  margin: 34px 0 0; padding: 30px 30px 34px; border-radius: 22px;
  background: var(--velvet); color: var(--wick);
  box-shadow: inset 0 0 0 10px var(--velvet-2), inset 0 0 0 12px var(--velvet-3);
}
.cave h2, .cave h3 { color: var(--wick); }
.cave p { color: var(--wick-2); }
.cave a { color: var(--gilt); }
.cave a:hover { color: var(--wick); }
.cave__lede { max-width: 58ch; }

/* The candles. THE ONLY MOVING THING IN THIS ROOM, and the dial governs it —
   the field outside has no ambient layer at any setting, but a pitch is its own
   world and sets its own noise, which the campground's board says out loud.
   Scoped with :where() so a decorative selector cannot out-specify the reset,
   which is the mistake that shipped on the yurt's windowsill. */
.candles { display: flex; gap: 22px; justify-content: center; margin: 0 0 18px; }
.candle-flame { transform-origin: 50% 100%; }
html[data-intensity="regular"] .candle-flame,
html[data-intensity="max"] .candle-flame { animation: guttering 3.4s ease-in-out infinite; }
@keyframes guttering {
  0%, 100% { transform: scaleY(1) skewX(0deg); opacity: .95; }
  38%      { transform: scaleY(1.07) skewX(-3deg); opacity: 1; }
  71%      { transform: scaleY(.95) skewX(2deg); opacity: .9; }
}

/* The shelves. A book is a <details>, which is a real disclosure widget with a
   keyboard and a screen reader already attached — the alternative was a div
   listening for clicks and re-implementing all of that worse. */
.shelves { list-style: none; margin: 22px 0 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.book { border-radius: 12px; background: var(--velvet-2); border: 1px solid rgba(233,194,112,.30); }
.book > summary {
  cursor: pointer; list-style: none; padding: 14px 18px; min-height: 44px;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px;
  font-family: 'Fraunces', Georgia, serif; font-weight: 700; font-size: 18px; color: var(--wick);
  border-radius: 12px;
}
.book > summary::-webkit-details-marker { display: none; }
.book > summary::after { content: '\2014\A0 open'; font-family: 'Sora', sans-serif; font-weight: 400; font-size: 13.5px; color: var(--gilt); margin-left: auto; }
.book[open] > summary::after { content: '\2014\A0 close'; }
.book__by { font-family: 'Sora', sans-serif; font-weight: 400; font-size: 15px; color: var(--wick-2); }
.book__open { padding: 0 18px 18px; }
.book__open p { margin: 0 0 12px; max-width: 62ch; }
.book__links { display: flex; flex-wrap: wrap; gap: 10px 18px; margin: 0; font-size: 14.5px; }
.book__cited { margin: 10px 0 0; font-size: 13.5px; color: var(--wick-2); }

/* The laptop. SAME-ORIGIN, AND STILL PRESS-TO-OPEN, which is not the same rule
   as the jukebox facades and lands in the same place. Nothing here is being
   kept from a third party — the frame is this site — but loading a whole copy
   of the street inside a room on the street, unasked, would mean a second dial,
   a second set of fonts and a screen reader walking the whole site twice for
   somebody who only came in to read. So it waits to be woken, like everything
   else with a screen in it here. */
.laptop { margin: 26px 0 0; }
.laptop__lid {
  background: var(--velvet-3); border: 2px solid var(--gilt); border-radius: 12px 12px 4px 4px;
  padding: 10px; aspect-ratio: 16 / 10; display: flex; overflow: hidden;
}
.laptop__screen { flex: 1; border: 0; border-radius: 4px; background: var(--noon); width: 100%; height: 100%; }
.laptop__wake {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  background: #0B1418; color: var(--wick); border: 0; border-radius: 4px; cursor: pointer;
  font-family: 'Sora', sans-serif; font-size: 16px; padding: 18px; text-align: center;
}
.laptop__wake b { font-family: 'Fraunces', Georgia, serif; font-weight: 700; font-size: 20px; color: var(--gilt); }
.laptop__wake span { font-size: 14px; color: var(--wick-2); max-width: 40ch; }
.laptop__base { height: 12px; border-radius: 0 0 14px 14px; background: var(--velvet-2); border: 2px solid var(--gilt); border-top: 0; }
.laptop__note { margin: 10px 0 0; font-size: 14px; color: var(--wick-2); }

/* The campfire. A SHAG RUG WITH BEAN BAGS ON IT, which is the third green
   carpet on this street and has to answer for itself: The Den's is a slab of
   1976 pile with a track list set DARK ON TOP OF IT, and this is a rug you sit
   ON with the furniture standing in it and every word beside it rather than
   over it. One is a record sleeve; this is a floor with people on it.

   THE ROOM IS A ROOM AND NOT A LIST. The set, the coffee table and the three
   chairs are laid out the way they would be — screen at the back, table in the
   middle, chairs across the front — which is why this is a grid with named
   areas rather than a stack of cards. The channel guide is NOT in the scene: a
   television has a listings magazine and the magazine is not furniture, so it
   is a disclosure below the rug that opens when you want it. */
.rug {
  margin: 22px 0 0; padding: 26px 22px 30px; border-radius: 18px;
  background:
    repeating-linear-gradient(94deg, rgba(0,0,0,.05) 0 3px, transparent 3px 7px),
    repeating-linear-gradient(-86deg, rgba(255,255,255,.05) 0 2px, transparent 2px 9px),
    var(--turf);
  display: grid; gap: 22px; justify-items: center;
}

/* The set. A deep box on legs with a black screen in it — and the screen is a
   DIFFERENT dark from anything else in this bright room, because a television
   that is off is the only genuinely black thing in a cabin full of daylight. */
.bigscreen { width: min(720px, 100%); }
.bigscreen__body {
  background: var(--bakelite); border-radius: 16px; padding: 14px 14px 10px;
  box-shadow: 0 6px 0 rgba(22,41,28,.18);
}
/* SIXTEEN BY NINE IS A FLOOR HERE AND NOT A FIXED RATIO, and that is the whole
   fix for a play button somebody could not reach. A channel title runs to a
   hundred characters; at phone width that is four lines, and with the runtime
   and the button under it the panel wanted 215px inside a 152px screen, so the
   one control that matters sat below the bottom of the set. Scrolling INSIDE a
   television to find the play button is not a fix.

   The grid stacks everything into one cell and the row takes the height of the
   tallest thing in it: ::before holds the 16:9 floor, and the panel pushes past
   it only when a long title needs the room. The set is its normal shape almost
   always, never clips, and truncates nothing — which matters more than a set
   that never moves, because the alternatives were hiding the title or hiding
   the button. */
.bigscreen__glass {
  display: grid; border-radius: 10px; overflow: hidden;
  background: var(--bigscreen-off);
}
.bigscreen__glass > * { grid-area: 1 / 1; min-width: 0; }
.bigscreen__glass::before { content: ""; grid-area: 1 / 1; padding-top: 56.25%; }
.bigscreen__glass iframe { width: 100%; height: 100%; border: 0; display: block; }
.bigscreen__off {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 7px; padding: 14px; text-align: center;
}
/* The runtime and the control sit on one line, because they are one sentence —
   how long it runs, and the button that starts it — and because a row saves the
   set a whole line of height at phone width. */
.bigscreen__go { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center; justify-content: center; }
.bigscreen__stand { margin: 0; font-family: 'Sora', sans-serif; font-size: 12px; letter-spacing: 2.5px;
  color: var(--bigscreen-dim); }
.bigscreen__now { margin: 0; font-family: 'Fraunces', Georgia, serif; font-weight: 700;
  font-size: clamp(15px, 2.1vw, 21px); line-height: 1.22; color: var(--bigscreen-lit); max-width: 36ch; }
.bigscreen__runs { margin: 0; font-family: 'Sora', sans-serif; font-size: 14px; color: var(--bigscreen-dim); }
.bigscreen__play {
  border: 2px solid var(--bigscreen-lit); background: transparent; color: var(--bigscreen-lit);
  border-radius: 999px; padding: 11px 22px; font-family: 'Sora', sans-serif; font-size: 15px; cursor: pointer;
}
.bigscreen__play:hover { background: var(--bigscreen-lit); color: var(--bigscreen-off); }
/* The way out, on the one channel that cannot be shown here. DASHED, like the
   door out in the listing below it, so the two are obviously the same kind of
   thing and neither is mistaken for a play button. */
.bigscreen__door {
  border: 2px dashed var(--bigscreen-lit); color: var(--bigscreen-lit);
  border-radius: 999px; padding: 11px 22px; font-family: 'Sora', sans-serif;
  font-size: 15px; text-decoration: none; min-height: 44px; display: inline-flex;
  align-items: center;
}
.bigscreen__door:hover { background: var(--bigscreen-lit); color: var(--bigscreen-off); }
/* No [hidden] guard here any more: it is in §2, for everything, because doing
   it per component is what let the off panel stay on screen. */
.bigscreen__brand { display: flex; gap: 5px; justify-content: flex-end; padding: 8px 4px 0; }
.bigscreen__brand span { width: 26px; height: 4px; border-radius: 2px; background: var(--bakelite-2); }
.bigscreen__legs { display: flex; justify-content: space-between; padding: 0 60px; }
.bigscreen__legs i { display: block; width: 14px; height: 18px; background: var(--bakelite);
  border-radius: 0 0 4px 4px; }

/* The coffee table, between the chairs and the set, with the controls on it —
   which is where a remote actually ends up. Wood, ring-marked, and the one
   rectangle in this scene with a grain on it. */
.coffee { width: min(560px, 100%); }
.coffee__top {
  background:
    radial-gradient(circle at 78% 72%, transparent 15px, rgba(22,41,28,.07) 15px 17px, transparent 17px),
    radial-gradient(circle at 22% 30%, transparent 12px, rgba(22,41,28,.07) 12px 14px, transparent 14px),
    repeating-linear-gradient(97deg, rgba(22,41,28,.05) 0 1px, transparent 1px 12px),
    var(--cedar);
  border-radius: 10px; padding: 14px 16px 16px; border: 3px solid var(--furrow);
  box-shadow: 0 4px 0 rgba(22,41,28,.16);
}
.coffee__legs { display: flex; justify-content: space-between; padding: 0 34px; }
.coffee__legs i { display: block; width: 12px; height: 20px; background: var(--cedar);
  border: 3px solid var(--furrow); border-top: 0; border-radius: 0 0 3px 3px; }
/* THE SENTENCE CAME OFF THE TABLE. Body copy on the cedar tabletop measures
   3.29 in the dark ink and 4.20 in the pale one -- both under 4.5, so the
   tabletop cannot carry a sentence in either direction. It is furniture, not a
   surface to set type on; the note sits under the rug on the page ground. */
.rug__note { margin: 12px 0 0; font-size: 14px; color: var(--furrow-2); max-width: 70ch; }
.remote { display: flex; flex-wrap: wrap; gap: 10px 12px; align-items: center; justify-content: center; }
.remote__btn {
  background: var(--noon); color: var(--furrow); border: 2px solid var(--furrow);
  border-radius: 999px; padding: 11px 18px; font-family: 'Sora', sans-serif; font-size: 14.5px;
  cursor: pointer; box-shadow: 0 2px 0 var(--furrow);
}
.remote__btn:hover { background: var(--noon-2); }
.remote__btn:active { transform: none; box-shadow: 0 1px 0 var(--furrow); }
/* The only controls on the wood. The room's dark ring was 2.65 on the cedar,
   so these take the daylight they are made of: noon is 4.20 on the cedar and
   5.25 where the grain darkens it most. */
.coffee__top :focus-visible { outline-color: var(--noon); }
.remote__what {
  margin: 0; flex: 1 1 16ch; min-width: 16ch; text-align: center;
  font-size: 13.5px; color: var(--furrow); background: var(--noon);
  border: 2px solid var(--furrow); border-radius: 8px; padding: 8px 10px;
}

/* The three chairs. NO TWO THE SAME COLOUR, because nobody furnishes a room
   like this by agreeing. Each carries what somebody left on it. */
.bags { list-style: none; margin: 0; padding: 0; width: 100%;
  display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.bag {
  background: var(--bag); color: var(--furrow);
  border: 3px solid var(--furrow);
  border-radius: 40% 40% 26% 26% / 22% 22% 16% 16%;
  padding: 40px 26px 32px; display: flex; flex-direction: column; gap: 7px;
  box-shadow: inset 0 -10px 22px rgba(22,41,28,.14);
}
.bag h3 { font-family: 'Fraunces', Georgia, serif; font-weight: 700; font-size: 19px;
  margin: 0; color: var(--furrow); }
.bag p { margin: 0; font-size: 14.5px; color: var(--furrow); }
.bag__on { font-style: italic; font-size: 13.5px !important; }
.bag__credit { font-size: 13px !important; }
.bag__cited { font-size: 13.5px !important; }
.bag__cited a { color: var(--furrow); text-underline-offset: 3px; }
.bag__cited a:hover { color: var(--furrow-2); }

/* The listings magazine. A <details>, for the third time in this room and the
   same reason each time: the widget already has a keyboard and a screen reader
   on it. */
.guide { margin: 22px 0 0; background: var(--noon-2); border: 2px solid var(--furrow); border-radius: 12px; }
.guide > summary {
  cursor: pointer; list-style: none; padding: 16px 20px; min-height: 44px;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px; border-radius: 10px;
}
.guide > summary::-webkit-details-marker { display: none; }
.guide__label { font-family: 'Fraunces', Georgia, serif; font-weight: 700; font-size: 21px; color: var(--furrow); }
.guide__hint { font-size: 14px; color: var(--furrow-2); }
.guide > summary::after { content: '\25BC'; margin-left: auto; color: var(--furrow-2); font-size: 13px; }
.guide[open] > summary::after { content: '\25B2'; }
.guide__open { padding: 0 20px 20px; }
.guide__note { margin: 0 0 16px; font-size: 15px; max-width: 70ch; }
.channels { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); align-items: start; }
.ch { background: var(--noon); border: 2px solid var(--sprout); border-radius: 12px;
  padding: 14px 16px; display: flex; flex-direction: column; gap: 7px; }
.ch__no { margin: 0; font-family: 'Sora', sans-serif; font-size: 11.5px; letter-spacing: 2px;
  color: var(--sprout-2); }
.ch h3 { font-family: 'Fraunces', Georgia, serif; font-weight: 700; font-size: 17px;
  line-height: 1.2; margin: 0; color: var(--furrow); }
.ch p { margin: 0; font-size: 14.5px; }
.ch__by { color: var(--furrow-2); font-size: 13.5px !important; }
.ch__why { font-size: 13px !important; color: var(--furrow-2); }
.ch--on { border-color: var(--furrow); box-shadow: inset 0 0 0 3px var(--noon-2); }
.tune {
  margin-top: auto; background: var(--sprout); color: var(--noon); border: 0; border-radius: 999px;
  font-family: 'Sora', sans-serif; font-size: 14.5px; padding: 12px 16px; cursor: pointer;
}
.tune:hover { background: var(--sprout-2); }
.ch--on .tune { background: var(--furrow); }

/* THE WATERING HOLE. Three benches under a window, and the shape has to answer
   to the two zones either side of it in the same room: the cave is enclosed,
   round-cornered and dark; the campfire is seated, and its cards are rounded
   because a bean bag has no corners in it. THIS IS FLAT-TOPPED AND SQUARE —
   worktops with a lip at the front, things laid out on them, and you are
   standing up. One room, three postures.

   A table is a surface and not a card, so it has a top edge and a shadow under
   it and no border all the way round: a rectangle with a full outline reads as
   another card, and this room already has two kinds of those. */
.table {
  margin: 24px 0 0; padding: 20px 22px 24px;
  background: var(--noon-2); border-top: 5px solid var(--cedar);
  border-radius: 3px 3px 10px 10px;
  box-shadow: 0 3px 0 rgba(22,41,28,.10);
}
.table h3 { font-size: 24px; margin: 0 0 8px; }
.table__what { margin: 0 0 4px; max-width: 70ch; font-size: 15.5px; }

/* The pressed sheets. A <details> again, for the reason the cave's spines are:
   the widget already has a keyboard and a screen reader attached. They are laid
   out in columns because a herbarium is a drawer of sheets rather than a list —
   the one place in this room where the grid is the meaning. */
.sheets { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); align-items: start; }
.sheet { background: var(--noon); border: 1px solid var(--cedar); border-radius: 2px; }
.sheet > summary {
  cursor: pointer; list-style: none; padding: 12px 14px; min-height: 44px;
  display: flex; flex-direction: column; gap: 2px;
  font-family: 'Fraunces', Georgia, serif; font-weight: 700; font-size: 17px; color: var(--furrow);
}
.sheet > summary::-webkit-details-marker { display: none; }
.sheet__as { font-family: 'Sora', sans-serif; font-weight: 400; font-size: 13px; color: var(--furrow-2); }
.sheet__open { padding: 0 14px 14px; }
.sheet__open p { margin: 0 0 9px; font-size: 14.5px; }
.sheet__credit { font-style: italic; color: var(--furrow-2); }
.sheet__cited { margin: 0 !important; font-size: 13px !important; color: var(--furrow-2); }

/* The solar bench. Things lying on a worktop, not filed — so they are a plain
   column of laid-out items with a rule between them, rather than boxes. */
.bench { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 0;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); }
.lay { padding: 16px 0; border-top: 1px solid var(--cedar); display: flex; flex-direction: column; gap: 7px; }
.bench .lay + .lay { padding-left: 0; }
.lay h4 { font-family: 'Fraunces', Georgia, serif; font-weight: 700; font-size: 17.5px;
  line-height: 1.22; color: var(--furrow); margin: 0; }
.lay p { margin: 0; font-size: 15px; }
.lay__by { color: var(--furrow-2); font-size: 13.5px !important; }
.lay__cited { font-size: 13px !important; color: var(--furrow-2); }
.lay__go { font-size: 14.5px !important; }
.lay .facade { margin-top: auto; }
.lay--read { padding-right: 18px; }

/* The Star Stuff table. EVERY ITEM IS A DOOR TO ANOTHER SITE and none of it is
   reproduced, so each one leads with its link rather than ending in one. */
.kinship { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); }
.kin { background: var(--noon); border-left: 4px solid var(--sprout); padding: 12px 14px;
  display: flex; flex-direction: column; gap: 6px; }
.kin h4 { font-family: 'Fraunces', Georgia, serif; font-weight: 700; font-size: 17px;
  line-height: 1.22; margin: 0; }
.kin p { margin: 0; font-size: 14.5px; }
.kin__why { color: var(--furrow-2); font-size: 13.5px !important; }

/* §20 ── ROOM: Club Chronic ──────────────────────────────────────────────────
   A BLACK WALL WITH PAPER STUCK TO IT. Every other room on this street is a
   ground with things drawn on it; this is a ground with things GLUED on,
   overlapping, in layers, going back years. That is the structural difference
   and it is the one that has to hold, because the room this could collapse
   into is already here.

   THE ZINE TABLE IS THE COLLISION AND IT IS A CLOSE ONE. Both are punk, both
   are photocopied, both are made of paper. What keeps them apart:

     · the zine is ONE SHEET you hold, black on white, and the page IS the
       paper. Here the paper is a hundred small rectangles stuck to something
       else, and the something else — the wall — is the room.
     · the zine is CUT UP with scissors and scattered at angles. This is PASTED
       DOWN in layers, flat, overlapping, because that is what happens to a
       wall over years and it is the opposite gesture: one is collage as
       violence, the other is collage as sediment.
     · the zine sets a typewriter and a handwriting. This sets a CONDENSED
       display face, because a flyer crams a whole bill onto one sheet, and a
       marker that went over the top of the paper rather than being it.

   AND IT DOES NOT STROBE, AT ANY SETTING. A punk club has exactly one obvious
   ambient effect and it is a strobe, which can trigger seizures — so this room
   has no ambient motion at all. That looks like the campgrounds' rule and is a
   different rule: the field is still because quiet is what it is FOR, and this
   room is still because the obvious idea here hurts people. A room whose whole
   argument is come in as you are cannot have a light in it that puts somebody
   on the floor. The dial still works; there is simply nothing here it turns up,
   and that is stated in the room rather than left to be discovered. */

.club { background: var(--brick); color: var(--paste); font-family: 'Barlow', system-ui, sans-serif; }
.club a { color: var(--marker); text-underline-offset: 3px; }
.club a:hover { color: var(--paste); }
/* The wall keeps the yellow; a flyer is paper pasted onto it and takes the
   bootblack its words are printed in, 15.56 and 11.85 where yellow was 1.03. */
.club .flyer :focus-visible { outline-color: var(--bootblack); }
.club p, .club li { font-size: 17px; line-height: 1.6; }
.club .backlink { font-family: 'Anton', Impact, sans-serif; letter-spacing: 1px; color: var(--marker); }

.club h1 {
  font-family: 'Anton', Impact, sans-serif; font-weight: 400;
  font-size: clamp(46px, 11vw, 122px); line-height: .92;
  text-transform: uppercase; letter-spacing: -0.01em;
  color: var(--paste); margin: 6px 0 0;
}
.club h2 { font-family: 'Anton', Impact, sans-serif; font-weight: 400; text-transform: uppercase;
  font-size: clamp(26px, 4.4vw, 40px); line-height: 1.02; letter-spacing: .5px; color: var(--paste); margin: 0 0 14px; }
.club h3 { font-family: 'Anton', Impact, sans-serif; font-weight: 400; text-transform: uppercase;
  font-size: 22px; line-height: 1.06; color: var(--paste); margin: 0; }
.club .lede { font-size: 19px; line-height: 1.55; color: var(--paste-2); max-width: 56ch; margin: 18px 0 0; }
.club .trailmark { margin: 0; font-family: 'Permanent Marker', cursive; font-size: 15px; color: var(--marker); }

/* THE AWNING. CBGB's was a flat black box with the name across it and the
   whole bill underneath in smaller type — the one piece of signage that told
   you the building was a venue. Here it is the masthead, and it is the only
   thing in the room that is not stuck to the wall: it hangs off it. */
.awning {
  background: var(--bootblack); border: 4px solid var(--paste);
  padding: 20px 24px 22px; margin: 18px 0 0;
  box-shadow: 10px 10px 0 var(--grime);
}
.awning__sub { margin: 10px 0 0; font-family: 'Barlow', sans-serif; font-weight: 600;
  font-size: 14px; letter-spacing: 2.4px; text-transform: uppercase; color: var(--newsprint); }

/* The sharpie. Somebody wrote on the wall and nobody painted over it. It is
   the room's own voice — the door policy, the asides — and it is never a
   control, so it never has to be findable, only readable. */
.sharpie {
  font-family: 'Permanent Marker', cursive; color: var(--marker);
  font-size: clamp(19px, 3vw, 27px); line-height: 1.32; margin: 26px 0 0; max-width: 24ch;
}
.sharpie--red { color: var(--siren); }

/* THE PASTE-UP. Flyers stuck to the wall, overlapping, in a grid dense enough
   that the wall shows only at the edges. Each one is paper and carries DARK
   type, so this room reads both ways like the burrow does — and unlike that
   burrow's one lit wall these are a hundred small grounds pasted onto a dark
   one, which is why they have staples and torn corners instead of a lamp. */
.pasteup { list-style: none; margin: 22px 0 0; padding: 0;
  display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); }
.flyer {
  position: relative; background: var(--paste); color: var(--bootblack);
  padding: 16px 16px 18px; display: flex; flex-direction: column; gap: 7px;
  box-shadow: 4px 4px 0 rgba(0,0,0,.55);
}
.flyer:nth-child(3n) { background: var(--paste-2); }
.flyer::before,
.flyer::after {
  content: ""; position: absolute; top: -3px; width: 13px; height: 7px;
  background: var(--staple); box-shadow: 0 1px 0 rgba(0,0,0,.5);
}
.flyer::before { left: 16px; transform: none; }
.flyer::after  { right: 16px; }
.flyer h3 { color: var(--bootblack); font-size: 19px; }
.flyer p { margin: 0; color: var(--brick); font-size: 14.5px; line-height: 1.45; }
.flyer__where { font-family: 'Barlow', sans-serif; font-weight: 600; font-size: 11.5px;
  letter-spacing: 2px; text-transform: uppercase; color: var(--grime); }
.flyer__go { margin-top: auto; font-family: 'Anton', Impact, sans-serif; font-size: 15px;
  letter-spacing: 1px; text-transform: uppercase; }
.flyer__go a { color: var(--brick); text-decoration-thickness: 2px; }
.flyer__go a:hover { color: var(--bootblack); }

/* THE STAGE. Two facades, and neither of them says how long it runs, because a
   playlist somebody keeps adding to has no length — see the note in
   data/club.json. They say they run until you stop them, which is the Jungle
   Room's honest label arriving on a record shelf. */
/* align-items:start, because the two services' players are different heights —
   YouTube's is 16:9 and Spotify's is a fixed 352px list. Stretching the decks
   to match left the shorter one with a hole in it where nothing was. */
.stage { margin: 26px 0 0; display: grid; gap: 18px; align-items: start;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.deck { background: var(--brick-2); border: 3px solid var(--paste); padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.deck__where { margin: 0; font-family: 'Anton', Impact, sans-serif; font-size: 17px; letter-spacing: 1.5px;
  text-transform: uppercase; color: var(--marker); }
.deck__by { margin: 0; font-size: 14px; color: var(--newsprint); }
.deck p { margin: 0; font-size: 15px; color: var(--paste-2); }
.club .facade {
  background: var(--bootblack); border: 3px solid var(--marker); border-radius: 0;
  color: var(--paste); font-family: 'Anton', Impact, sans-serif; letter-spacing: 1px;
  text-transform: uppercase; font-size: 17px; text-align: center;
  display: flex; align-items: center; justify-content: center; margin-top: auto;
}
.club .facade:hover { background: var(--grime); }
.club .facade iframe { border-radius: 0; }
/* Spotify's own player is 352px tall and does not want a 16:9 box. */
.deck--spotify .facade { aspect-ratio: auto; min-height: 172px; }
.deck--spotify .facade iframe { position: static; width: 100%; height: 352px; }
/* Apple's is 450px and wants one even less: it is a square of artwork, a
   transport and a scrolling track list stacked beside each other, so 16:9 crops
   the list off the bottom. STYLED FROM THE CONTAINER, never from the button --
   love-embed.js replaces a pressed facade with a bare <div class="facade"> and
   anything the button was wearing evaporates, which is how Swaying Sweetgrass
   shipped its players at 0x0. */
.deck--apple .facade { aspect-ratio: auto; min-height: 172px; }
.deck--apple .facade iframe { position: static; width: 100%; height: 450px; }

/* A DOOR ON THE STAGE, and the only deck here that is not a screen. Qobuz
   publishes no embed: framed, the playlist renders a catalogue page with one
   Listen on Qobuz button and no play control on any row, so this is a way out
   rather than a player. IT IS DELIBERATELY NOT GIVEN THE FACADE'S BOX. The
   Jungle Room's link-outs take 16/9 because they stand in a grid of screens and
   have to line up with them; on a stage a 16:9 plate IS the shape of a player,
   and this cannot play anything. Dashed rather than solid for the same reason:
   in this room a solid bootblack plate inside a marker ring means press it and
   it plays HERE.

   THE SUB-LINE IS THE SAME INK AS THE LABEL ON PURPOSE. Every ground in this
   room is a pair somebody measured, --paste on --bootblack among them, and
   reaching for a quieter grey would have put an unmeasured pair on the stage to
   save a design decision the room can make with type instead -- which is what
   this room does anyway: Anton shouts and Barlow does not. */
.deck--away .deck__away {
  margin-top: auto; display: flex; flex-direction: column; gap: 6px;
  padding: 14px 18px; text-align: center; text-decoration: none;
  background: var(--bootblack); border: 3px dashed var(--marker);
  color: var(--paste); font-family: 'Anton', Impact, sans-serif;
  letter-spacing: 1px; text-transform: uppercase; font-size: 17px;
}
.deck--away .deck__away:hover { background: var(--grime); }
.deck--away .deck__off {
  font-family: 'Barlow', system-ui, sans-serif;
  letter-spacing: 0; text-transform: none; font-size: 14px;
}

/* THE RACK. Records along the back wall, filed under six headings. Each sleeve
   is a facade and each one says how long it runs before it is pressed. */
.rack { margin: 30px 0 0; }
.rack__no { margin: 0; font-family: 'Anton', Impact, sans-serif; font-size: 13px; letter-spacing: 3px;
  text-transform: uppercase; color: var(--siren); }
.rack__intro { margin: 8px 0 0; color: var(--paste-2); max-width: 62ch; }
.sleeves { list-style: none; margin: 16px 0 0; padding: 0;
  display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(258px, 1fr)); align-items: start; }
.sleeve { background: var(--brick-2); border: 2px solid var(--grime); padding: 13px 14px 15px;
  display: flex; flex-direction: column; gap: 6px; }
.sleeve__role { margin: 0; font-family: 'Permanent Marker', cursive; font-size: 13px; color: var(--marker); }
.sleeve h3 { font-size: 17px; line-height: 1.1; }
.sleeve__by { margin: 0; font-size: 13.5px; color: var(--newsprint); }
.sleeve p { margin: 0; font-size: 14.5px; color: var(--paste-2); }
.sleeve .facade { font-size: 14px; border-width: 2px; min-height: 44px; }

/* The door policy board, which is the one boxed thing on the wall because it
   is the one thing that is actually a notice. */
.policy { margin: 26px 0 0; border: 3px dashed var(--marker); padding: 20px 22px; background: var(--brick-2); }
.policy ul { margin: 0; padding: 0 0 0 20px; color: var(--paste-2); }
.policy li { margin: 0 0 9px; }
.policy li::marker { color: var(--siren); }
.policy li:last-child { margin-bottom: 0; }

/* §21 ── THE PEBBLE BOARD (street furniture, not a storefront) ───────────────
   A community noticeboard bolted to the pavement outside the shops. It is NOT
   a door and it is not in the grid of them, for the same reason the signpost to
   the campgrounds is not: a room is permanent and singular, and this thing is
   defined by being replaced. A shop whose entire stock is swapped out every
   gathering, with the old stock in the basement, is a periodical.

   THE FRAME IS CONSTANT AND THE PAPER IS NOT, which is the one place on this
   street besides the Arcade where two pages are meant to resemble each other.
   The board, its lamp, its glass and its plate belong to the street and stay
   put; what is pinned to them is that edition's own world. A noticeboard, like
   a cabinet, is ONE BODY WITH DIFFERENT THINGS BEHIND THE GLASS -- and this is
   the second instance, not a licence for a third. Each edition still gets its
   own share card, because a card is where the shortcut would be invisible.

   THE PAPER HERE IS NORAH HOBBS'S and came from a page she built in June. Two
   of her three typefaces had to go, because Caveat is the Faery Yurt's hand and
   Special Elite is the Zine Table's typewriter -- and a punk-paper noticeboard
   set in the zine's own typewriter is precisely the collapse this street
   refuses. Her Atkinson Hyperlegible stays: it is the Braille Institute's
   low-vision face, so swapping the body text would be an access regression
   rather than a style choice. Everything else below is hers, measured and
   unmoved. See _typefaces in data/pebble-board.json.

   THE OUTSIDE IS NIGHT AND THE INSIDE IS LAMPLIT PAPER, which is what keeps
   this off The Latibulum. Both are warm and lit; the burrow is DUG, enclosed,
   with no sky in it, and this is a thing standing outdoors with the street's
   own dark showing all round the edge of the glass.                           */

.pebbleboard {
  background:
    radial-gradient(120% 60% at 50% -10%, rgba(246,227,184,0.09), transparent 60%),
    var(--pbnight);
  color: var(--pbchalk);
  font-family: 'Atkinson Hyperlegible', var(--sans);
}
.pebbleboard .backlink { font-family: 'Josefin Sans', var(--sans); letter-spacing: 2px;
  font-size: 12px; text-transform: uppercase; color: var(--pbchalk); }

/* ── The fixture ───────────────────────────────────────────────────────────
   Painted municipal timber, a little pitched roof, one lamp, glass, cork.     */

.pb-board {
  position: relative;
  margin: 26px 0 0;
  padding: 16px;
  background: linear-gradient(#486a61 0 3px, var(--pbframe) 3px);
  border-radius: 10px 10px 4px 4px;
  box-shadow: 0 26px 60px -30px #000, inset 0 -3px 0 rgba(0,0,0,0.35);
}
/* The lamp. Ornament: it lands on the frame and on the cork, never under a word
   -- every card the paper carries is opaque. Measured as ornament all the same,
   because a lamp nobody can make out is not a lamp. */
.pb-lamp {
  position: absolute; left: 50%; top: -34px; width: 300px; height: 96px;
  transform: translateX(-50%);
  background: radial-gradient(60% 100% at 50% 0, var(--pblamp), transparent 72%);
  opacity: 0.42; pointer-events: none;
}
.pb-plate {
  position: relative; margin: 0 auto 14px; width: max-content;
  padding: 7px 18px 6px; border-radius: 2px;
  background: linear-gradient(#cdb06a, var(--pbplate));
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.28), 0 2px 5px rgba(0,0,0,0.4);
  font-family: 'Josefin Sans', var(--sans);
  font-size: 12.5px; font-weight: 600; letter-spacing: 3px; text-transform: uppercase;
  color: var(--pbplate-ink);
}
.pb-cork {
  padding: 30px 20px 40px;
  border-radius: 4px;
  background:
    radial-gradient(90% 55% at 50% 0, rgba(246,227,184,0.14), transparent 70%),
    repeating-conic-gradient(rgba(0,0,0,0.05) 0 25%, transparent 0 50%) 0 0 / 7px 7px,
    var(--pbcork);
  box-shadow: inset 0 0 0 2px rgba(0,0,0,0.3), inset 0 12px 30px -14px rgba(0,0,0,0.7);
}

/* ── The paper: Norah's scrapbook ──────────────────────────────────────────
   Everything from here to the rack is her page, carried over. Her measurements
   are in check-contrast.py under "pebble board".                              */

.pb-cover { max-width: 640px; margin: 0 auto 30px; }
.pb-sheet {
  position: relative; padding: 32px 30px 28px;
  background: var(--pbcard); border: 1px solid var(--pbline);
  box-shadow: 0 14px 30px -18px rgba(0,0,0,0.55), 0 2px 0 rgba(43,38,33,0.05);
}
.pb-sheet::before {
  content: ""; position: absolute; top: -14px; left: 50%;
  transform: translateX(-50%) rotate(-3deg);
  width: 110px; height: 30px; background: rgba(201,166,160,0.85);
  box-shadow: 0 2px 3px rgba(0,0,0,0.18);
}
.pb-kicker {
  font-family: 'Josefin Sans', var(--sans); font-size: 12px; font-weight: 600;
  letter-spacing: 2px; text-transform: uppercase; color: var(--pbink-soft); margin: 0;
}
.pebbleboard h1 {
  font-family: 'Gloria Hallelujah', cursive;
  font-size: clamp(30px, 6vw, 46px); line-height: 1.12;
  color: var(--pbink); margin: 8px 0 16px;
}
.pb-slug {
  display: inline-block; margin: 0 0 16px; padding: 6px 14px;
  font-family: 'Gloria Hallelujah', cursive; font-size: 18px; line-height: 1.35;
  color: var(--pbgold); background: var(--pbgold-bg);
  box-shadow: 0 2px 4px rgba(0,0,0,0.12);
}
.pb-lede { font-size: 16.5px; line-height: 1.6; color: var(--pbink-soft); margin: 0 0 14px; }
.pb-sign { margin: 20px 0 0; text-align: right;
  font-family: 'Gloria Hallelujah', cursive; font-size: 20px; color: var(--pbink); }
.pb-sign small { display: block; font-family: 'Atkinson Hyperlegible', var(--sans);
  font-size: 12.5px; color: var(--pbink-soft); }
.pb-when { margin: 18px 0 0; font-family: 'Josefin Sans', var(--sans); font-weight: 600;
  font-size: 12px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--pbink-soft); }

.pb-toc { display: flex; flex-wrap: wrap; gap: 8px 18px; justify-content: center;
  max-width: 760px; margin: 0 auto 34px; padding: 0; list-style: none;
  font-family: 'Josefin Sans', var(--sans); font-weight: 600; font-size: 13.5px;
  letter-spacing: 1px; text-transform: uppercase; }
.pb-toc a { color: var(--pbpaper); text-decoration: none; border-bottom: 1px dotted var(--pbpaper); }
.pb-toc a:hover { color: #fff; border-bottom-style: solid; }

.pb-spread { max-width: 1180px; margin: 0 auto 8px; padding: 0 0 34px; scroll-margin-top: 14px; }
.pb-tab {
  display: inline-block; margin: 0 0 20px 6px; padding: 7px 17px 6px;
  background: var(--pb-tape); color: var(--pbink);
  font-family: 'Josefin Sans', var(--sans); font-weight: 600;
  font-size: 13px; letter-spacing: 1.5px; text-transform: uppercase;
  box-shadow: 0 3px 6px rgba(0,0,0,0.25);
}
.pb-pins { display: flex; flex-wrap: wrap; gap: 32px 24px; margin: 0; padding: 0; list-style: none; }

/* A PINNED CARD, AND ITS TILT IS :where()-SCOPED so §3's reset out-specifies it.
   A decorative selector that climbs above the reset does not warn -- it just
   renders the louder rule, which is how the Faery Yurt's windowsill was still
   rotating at Gentle a day after that room went up. */
.pb-pin { width: 250px; margin: 0; }
:where(.pb-pin) .pb-card { transform: rotate(var(--pb-rot, 0deg)); }
html[data-intensity="gentle"] .pb-pin .pb-card { transform: none; }
.pb-card {
  position: relative; height: 100%; padding: 10px 10px 14px;
  background: var(--pbcard); border: 1px solid var(--pbline);
  box-shadow: 0 10px 22px -14px rgba(0,0,0,0.6), 0 1px 0 rgba(255,255,255,0.4);
  transition: transform .18s ease, box-shadow .18s ease;
}
/* The cork keeps the yellow; a card pinned to it takes the pencil's ink,
   14.12 where yellow was 1.24. check-focus.py. */
.pb-card :focus-visible { outline-color: var(--pbink); }
.pb-pin:hover .pb-card, .pb-pin:focus-within .pb-card {
  transform: rotate(0deg) translateY(-3px); z-index: 2;
  box-shadow: 0 16px 26px -14px rgba(0,0,0,0.65);
}
.pb-tape {
  position: absolute; top: -12px; left: 50%; width: 78px; height: 26px;
  background: var(--pb-tape); opacity: 0.88;
  transform: translateX(-50%) rotate(var(--pb-tape-rot, 0deg));
  box-shadow: 0 2px 3px rgba(0,0,0,0.2);
}
html[data-intensity="gentle"] .pb-tape { transform: translateX(-50%); }
/* NO FIXED RATIO AND NO object-fit: cover, which is two bugs in one line.
   Norah's original card cropped everything to 4:3, and polaroids.html promises
   in as many words that we will not "Crop you." -- the same promise that made
   the polaroid plate stop being square when the first real photograph arrived.
   A 674x900 portrait in a 4:3 box loses most of somebody.

   It was also laying out wrong: a <button> does not size itself to a child
   whose height comes from aspect-ratio plus width:100%, so the picture ran 28px
   past the bottom of the button and sat on top of the card's title. Letting
   every picture keep its own shape fixes the crop and the overlap at once, and
   a corkboard of scraps at different heights is what a corkboard looks like. */
.pb-shot { display: block; width: 100%; height: auto;
  background: #d9cfb4; border: 1px solid rgba(43,38,33,0.25); }
.pb-body { padding: 12px 3px 0; }
.pb-title { font-family: 'Gloria Hallelujah', cursive; font-size: 18px; line-height: 1.25;
  color: var(--pbink); margin: 0 0 4px; }
.pb-credit { font-family: 'Josefin Sans', var(--sans); font-weight: 600; font-size: 11.5px;
  letter-spacing: 0.6px; text-transform: uppercase; color: var(--pbink-soft); margin: 0 0 8px; }
.pb-note { font-size: 14px; line-height: 1.5; color: var(--pbink-soft); margin: 0 0 8px; }
.pb-more { margin: 0 0 8px; }
.pb-more summary { cursor: pointer; list-style: none; font-family: 'Josefin Sans', var(--sans);
  font-weight: 600; font-size: 11.5px; letter-spacing: 0.6px; text-transform: uppercase;
  color: var(--pbink-soft); }
.pb-more summary::-webkit-details-marker { display: none; }
.pb-more summary::before { content: "+ "; }
.pb-more[open] summary::before { content: "\2013 "; }
.pb-more p { margin: 8px 0 0; font-size: 14px; line-height: 1.5; color: var(--pbink-soft); }
.pb-go { display: inline-block; font-family: 'Josefin Sans', var(--sans); font-weight: 600;
  font-size: 11.5px; letter-spacing: 0.8px; text-transform: uppercase;
  color: var(--pbink); text-decoration: none; border-bottom: 1px solid var(--pbink-soft); }
.pb-go:hover { border-bottom-width: 2px; }

/* THE PRESS-TO-PLAY PLATE. The thumbnail is a LOCAL file: caching it at build
   time is what let the CSP keep img-src 'self', so opening this board makes no
   request to anybody. Nothing reaches YouTube until the button is pressed --
   §4's rule, and love-embed.js is still the only thing that builds the frame. */
.pb-play { position: relative; display: flex; width: 100%; padding: 0; cursor: pointer;
  background: none; border: 0; line-height: 0; }
/* A FOUR-BY-THREE VIDEO IS NOT A SIXTEEN-BY-NINE ONE WITH THE EDGES MISSING.
   §4 gives every play button the shape its player will have, and a flex item
   stretches to fill it -- so the board's three older, 4:3 videos were squashed
   flat, every face on them a third wider than it is. Not cropped either: those
   frames have no bars baked in, and cutting a quarter off a music video to fill
   a box is the same fault the other way round. Fitted, on the board's own night,
   which is exactly what the player shows once it is pressed. The 16:9
   thumbnails fill the box and are unchanged. */
.pb-play .pb-shot { object-fit: contain; background: var(--pbnight); }
.pb-play::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 46px; height: 46px;
  transform: translate(-50%, -50%);
  background: rgba(27,21,9,0.72); border: 2px solid var(--pbcard); border-radius: 50%;
  box-shadow: 0 2px 8px rgba(0,0,0,0.45);
}
.pb-play::before {
  content: ""; position: absolute; left: 50%; top: 50%; z-index: 1;
  transform: translate(-40%, -50%);
  border-left: 15px solid var(--pbcard);
  border-top: 9px solid transparent; border-bottom: 9px solid transparent;
}
.pb-play:hover::after, .pb-play:focus-visible::after { background: rgba(27,21,9,0.9); }
.pb-run { font-family: 'Josefin Sans', var(--sans); font-weight: 600; font-size: 11.5px;
  letter-spacing: 0.6px; text-transform: uppercase; color: var(--pbink-soft); margin: 8px 0 0; }
/* love-embed.js swaps the button for div.facade wrapping the iframe. */
.pb-card .facade iframe { width: 100%; aspect-ratio: 16 / 9; border: 0; display: block; }

/* ── The memorial, which is the one dark thing on the paper ────────────────
   Norah set it on its own dark spread and it stays that way: a page of bright
   scraps with a plain dark card at the end of it is the shape of the evening
   she is describing.                                                          */
.pb-memory { margin: 6px auto 0; padding: 54px 20px; background: var(--pbmem); }
.pb-memcard { position: relative; max-width: 560px; margin: 0 auto; padding: 40px 36px;
  background: var(--pbmem-card); border: 1px solid rgba(255,255,255,0.08);
  color: var(--pbmem-ink); text-align: center; }
.pb-tack { position: absolute; top: 14px; left: 50%; transform: translateX(-50%);
  width: 12px; height: 12px; border-radius: 50%; background: var(--pbmem-gold);
  box-shadow: 0 2px 3px rgba(0,0,0,0.5); }
.pb-memkicker { margin: 10px 0 4px; font-family: 'Josefin Sans', var(--sans); font-weight: 600;
  font-size: 12px; letter-spacing: 2px; text-transform: uppercase; color: var(--pbmem-gold); }
.pb-memcard h2 { font-family: 'Gloria Hallelujah', cursive; font-size: 32px;
  color: var(--pbmem-head); margin: 0 0 4px; }
.pb-memwho { margin: 0 0 20px; font-family: 'Gloria Hallelujah', cursive; font-size: 16px;
  line-height: 1.5; color: var(--pbmem-credit); }
.pb-memcard blockquote { margin: 0 0 20px; text-align: left; font-size: 15.5px; line-height: 1.75; }
.pb-memcard blockquote p { margin: 0 0 14px; }
.pb-memcard .pb-go { color: var(--pbmem-link); border-color: var(--pbmem-link); }

/* ── The lightbox ──────────────────────────────────────────────────────────
   A pinned scrap is 250px because that is what a scrap is, and nobody can look
   at a watercolour spread at 250px. A NATIVE <dialog>: the focus trap, Escape,
   the inert background and the backdrop are the browser's, not ours.

   THE WORDS COME WITH THE PICTURE. The description sits under it as real text
   rather than only in an alt attribute, so it reaches everybody -- and the
   title and credit come too, because a picture at full size with nobody's name
   on it would undo the one careful habit this street kept. Set on the memorial
   card's ground, which is a pair already measured rather than a new one
   invented for a panel.                                                        */
/* FLEX, NOT BLOCK, AND THAT IS THE WHOLE FIX. A <button> computes its height
   from an intrinsic pass in which a child's width:100% has not resolved yet,
   so a picture that is taller than that guess simply overflows -- measured at
   up to 28px past the bottom of the button, sitting on the card's title. A
   flex container takes its cross size from the item it actually laid out. */
.pb-zoom { display: flex; width: 100%; padding: 0; border: 0; background: none; cursor: zoom-in;
  line-height: 0; }
.pb-lightbox {
  max-width: min(94vw, 1100px); max-height: 94vh; width: auto;
  padding: 0; border: 0; border-radius: 4px;
  background: var(--pbmem-card); color: var(--pbmem-ink);
  box-shadow: 0 40px 90px -30px #000;
}
.pb-lightbox::backdrop { background: rgba(10,9,7,0.86); }
.pb-lightbox__inner { margin: 0; display: flex; flex-direction: column; max-height: 94vh; }
.pb-lightbox__pic {
  display: block; min-height: 0; max-width: 100%;
  /* The picture takes what is left after the words, and never so much that the
     words are pushed off a short window. */
  max-height: calc(94vh - 190px); object-fit: contain; background: #14120F;
}
.pb-lightbox__words { padding: 18px 22px 20px; }
.pb-lightbox__words h2 {
  font-family: 'Gloria Hallelujah', cursive; font-size: 24px; line-height: 1.2;
  color: var(--pbmem-head); margin: 0 0 4px;
}
.pb-lightbox__by {
  font-family: 'Josefin Sans', var(--sans); font-weight: 600; font-size: 12px;
  letter-spacing: 1.2px; text-transform: uppercase; color: var(--pbmem-credit); margin: 0 0 10px;
}
.pb-lightbox__desc { margin: 0; font-size: 15.5px; line-height: 1.6; max-width: 70ch; }
.pb-lightbox__shut {
  position: absolute; top: 10px; right: 10px; cursor: pointer;
  font-family: 'Josefin Sans', var(--sans); font-weight: 600; font-size: 12px;
  letter-spacing: 1.4px; text-transform: uppercase;
  padding: 9px 15px; border-radius: 3px;
  border: 2px solid var(--pbmem-credit); background: var(--pbmem); color: var(--pbmem-ink);
}
.pb-lightbox__shut:hover { border-color: var(--pbmem-head); color: var(--pbmem-head); }

/* ── The rack of back issues, under the board ──────────────────────────────
   Empty until something rotates out, and it says so. A rack that shows what it
   is waiting for is more use than one quietly closed up -- the same reason
   Enid's plates stay grey and pitch 02 stays open ground.                      */
.pb-rack { margin: 30px 0 0; padding: 22px 24px; border: 2px dashed var(--pbframe-lit);
  border-radius: 10px; background: rgba(0,0,0,0.25); }
.pb-rack h2 { font-family: 'Josefin Sans', var(--sans); font-weight: 600; font-size: 14px;
  letter-spacing: 2px; text-transform: uppercase; color: var(--pblamp); margin: 0 0 10px; }
.pb-rack p { margin: 0; font-size: 15.5px; line-height: 1.6; color: var(--pbchalk); }
.pb-rack ul { margin: 12px 0 0; padding-left: 20px; font-size: 15.5px; line-height: 1.7; }
.pb-rack a { color: var(--pblamp); }


/* §22 ── ROOM: The Mopery ────────────────────────────────────────────────────
   A dark academia library, a reading nook and a parlour with one screen in it.

   THE FOURTH WARM-LOOKING ROOM AND THE FIRST COLD ONE, which is the whole
   argument for it existing beside the warm ones. The Faery Yurt, The
   Latibulum, The Den and the Hermitage's cave are all lit by a single warm
   source and the light REACHES THE WALLS: canvas goes amber, plaster goes
   amber, panelling goes amber, curtain goes amber. This room has candles all
   over the top shelf and the walls stay blue-black stone, because the light
   from a candle travels about a foot and a library is enormous. Cosy is what
   those rooms are. This one is what it feels like to be let into a
   building after everybody has gone home.

   If the greys in here ever warm up, this has become the yurt with a bigger
   bookshelf, and the street has lost a room without anybody editing one.

   THE TYPE IS THE OTHER HALF OF IT. IM Fell English is a face that was PUNCHED
   -- Fell's Oxford types, ink spread and battered counters left in by the
   digitiser on purpose -- against Cormorant Garamond next door, which is
   high-contrast, clean and cut yesterday. Spectral does the reading, because
   the nook asks somebody for eighteen stanzas and a tome face does not survive
   that. See §1.

   THREE ZONES, ONE ROOM, WHICH IS THE HERMITAGE'S SHAPE AND NOT ITS LOOK: the
   library, the parlour with the screen, and the Raven nook. The two things
   behind doors -- the oracle deck and the doomscroll -- are §23 and §24 and
   share nothing with this or with each other.                                  */

.room-mopery {
  background:
    /* Cold light down the tall windows, and nowhere else. Not an ambient
       layer: it does not move at any setting, because a library at night is
       many things and none of them is animated. */
    radial-gradient(120% 60% at 50% -10%, rgba(120,150,190,0.10), transparent 60%),
    var(--mop-night);
  color: var(--mop-bone);
  font-family: 'Spectral', Georgia, serif;
}
.room-mopery .wrap { max-width: 1040px; margin: 0 auto; padding: 0 22px 84px; }
.room-mopery a { color: var(--mop-gilt); }
.room-mopery .backlink { color: var(--mop-dim); font-family: 'Spectral', Georgia, serif;
  font-size: 13px; letter-spacing: 2px; text-transform: uppercase; }
.room-mopery .backlink:hover { color: var(--mop-bone); }

/* ── The shop sign ─────────────────────────────────────────────────────────
   A second-hand bookshop hangs its name off a bracket, and the bracket is the
   only reason this room's masthead is not centred like everybody else's. It
   swings at MAX and at MAX only: a sign that moved at Regular would be ambient
   motion, which is the one thing the dial reserves for people who asked.       */
.mop-hang { display: flex; justify-content: center; padding: 30px 0 4px; }
.mop-sign {
  position: relative; text-align: center; padding: 22px 42px 24px;
  background: linear-gradient(180deg, var(--mop-stone), var(--mop-deep));
  border: 2px solid var(--mop-rule); border-radius: 3px;
  box-shadow: 0 26px 60px -34px #000;
  transform-origin: 50% -34px;
}
.mop-sign::before {
  content: ""; position: absolute; left: 50%; top: -34px; width: 2px; height: 34px;
  background: var(--mop-rule);
}
.mop-sign h1 {
  margin: 0; font-family: 'IM Fell English', Georgia, serif; font-weight: 400;
  font-size: clamp(42px, 9vw, 74px); line-height: 0.96; color: var(--mop-gilt);
}
.mop-sign .mop-est {
  margin: 12px 0 0; font-size: 12.5px; letter-spacing: 3px; text-transform: uppercase;
  color: var(--mop-dim);
}
html[data-intensity="max"] .mop-sign { animation: mop-swing 9s ease-in-out infinite; }
@keyframes mop-swing {
  0%, 100% { transform: rotate(-0.7deg); }
  50%      { transform: rotate(0.7deg); }
}

.mop-lede {
  max-width: 62ch; margin: 30px auto 0; font-size: 18px; line-height: 1.68;
  color: var(--mop-bone); text-align: center;
}
.mop-lede em { font-family: 'IM Fell English', Georgia, serif; font-style: italic; }
.mop-quiet { max-width: 62ch; margin: 14px auto 0; font-size: 15px; line-height: 1.6;
  color: var(--mop-dim); text-align: center; }

.mop-rule {
  display: block; width: 180px; height: 0; margin: 34px auto;
  border-top: 1px solid var(--mop-rule); border-bottom: 1px solid var(--mop-rule);
  padding-top: 3px;
}

/* Most sections in this room are separated by a drawn rule, which carries its
   own margins. The last few sit straight after one another, and without this
   the next heading starts on the bottom edge of the previous card. */
.room-mopery section + section { margin-top: 54px; }

.room-mopery h2 {
  font-family: 'IM Fell English', Georgia, serif; font-weight: 400;
  font-size: clamp(28px, 5vw, 40px); line-height: 1.1; color: var(--mop-gilt);
  margin: 0 0 6px;
}
.room-mopery h2 + p { margin: 0 0 22px; color: var(--mop-dim); font-size: 16px; max-width: 66ch; }

/* ── The bookcases ─────────────────────────────────────────────────────────
   A case is a back panel, a shelf board under the spines, and a row of candles
   standing on the top of it. The spines are BUTTONS, of assorted heights and
   widths, set vertically the way a spine is -- and each one carries its own
   measured pair, because a shelf with one unreadable title on it is a shelf
   the reader cannot tell is broken.                                            */
.mop-case {
  /* The top margin is the candles' room. They are absolutely positioned above
     the case, so without it they stand on whatever paragraph happens to be
     above -- which is how the first one came to be burning through a sentence. */
  position: relative; margin: 60px 0 46px; padding: 0 0 18px;
  background: linear-gradient(180deg, var(--mop-stone), var(--mop-night) 78%);
  border: 1px solid var(--mop-rule); border-radius: 2px;
}
.mop-card {
  margin: 0; padding: 16px 20px 4px;
  font-family: 'IM Fell English', Georgia, serif; font-size: 25px; line-height: 1.15;
  color: var(--mop-gilt);
}
.mop-card + p { margin: 6px 20px 0; font-size: 15px; line-height: 1.6; color: var(--mop-dim);
  max-width: 68ch; }

.mop-shelf {
  display: flex; align-items: flex-end; gap: 7px; flex-wrap: wrap;
  margin: 22px 20px 0; padding: 0 0 14px;
  border-bottom: 7px solid var(--mop-shelf);
}
.mop-spine {
  flex: 0 0 auto; cursor: pointer; padding: 18px 10px;
  writing-mode: vertical-rl; text-orientation: mixed;
  font-family: 'IM Fell English', Georgia, serif; font-size: 16.5px; letter-spacing: 0.4px;
  border: 1px solid rgba(0,0,0,0.5); border-radius: 1px 1px 0 0;
  text-align: left; line-height: 1.25;
}
.mop-spine b { font-weight: 400; }
.mop-spine i { font-style: normal; opacity: 0.78; font-size: 13.5px; }
.mop-spine:hover, .mop-spine:focus-visible { outline: 2px solid var(--mop-gilt); outline-offset: 2px; }
.mop-spine--oxblood  { background: var(--mop-oxblood);  color: var(--mop-bone); height: 250px; }
.mop-spine--sugar    { background: var(--mop-sugar);    color: var(--mop-deep); height: 232px; }
.mop-spine--ink      { background: var(--mop-inkspine); color: var(--mop-bone); height: 262px; }
.mop-spine--graphite { background: var(--mop-graphite); color: var(--mop-bone); height: 240px; }
.mop-spine--tar      { background: var(--mop-tar);      color: var(--mop-bone); height: 256px; }
.mop-spine--wine     { background: var(--mop-wine);     color: var(--mop-bone); height: 228px; }
.mop-spine--vellum   { background: var(--mop-vellum);   color: var(--mop-deep); height: 246px; }
.mop-spine--dust     { background: var(--mop-dust);     color: var(--mop-deep); height: 234px; }
.mop-spine--moss     { background: var(--mop-moss);     color: var(--mop-bone); height: 258px; }

/* ── The candles on the top shelf ──────────────────────────────────────────
   Ornament, aria-hidden, and carrying no text at all -- which is why the wax
   and the halo are in ORNAMENT in check-contrast.py with their measurements
   written beside them rather than being quietly exempt.

   THE FLAME MOVES AT MAX AND NOWHERE ELSE. §3 kills animation outright at
   Gentle with !important; Regular is not covered by that, so the flicker is
   gated on max explicitly rather than being left to the reset. Ambient motion
   is the one thing on this street nobody arrives in by default.                */
.mop-candles {
  /* All along the top of the case rather than bunched at one end, because the
     room's claim is that the candlelight does not reach the walls -- which only
     reads as a claim if there are candles the whole way across to not reach
     them from. */
  position: absolute; inset: auto 0 100% 0; display: flex; justify-content: space-between;
  gap: 16px; padding: 0 34px; pointer-events: none;
}
.mop-candle { position: relative; width: 9px; }
.mop-candle span {
  display: block; background: linear-gradient(180deg, #D9C7A6, var(--mop-wax));
  border-radius: 3px 3px 0 0;
}
.mop-candle:nth-child(odd)  span { height: 34px; }
.mop-candle:nth-child(even) span { height: 22px; }
.mop-candle::before {
  content: ""; position: absolute; left: 50%; bottom: 100%; width: 7px; height: 11px;
  margin-left: -3.5px; border-radius: 50% 50% 40% 40%;
  background: radial-gradient(circle at 50% 70%, #FFF1CE, var(--mop-flame) 55%, rgba(243,185,95,0) 100%);
}
.mop-candle::after {
  content: ""; position: absolute; left: 50%; bottom: 100%; width: 54px; height: 54px;
  margin: 0 0 -20px -27px; border-radius: 50%;
  background: radial-gradient(circle, rgba(243,185,95,0.16), rgba(243,185,95,0) 70%);
}
html[data-intensity="max"] .mop-candle::before { animation: mop-flicker 2.6s ease-in-out infinite; }
html[data-intensity="max"] .mop-candle:nth-child(3n)::before { animation-duration: 3.4s; }
html[data-intensity="max"] .mop-candle:nth-child(3n+1)::before { animation-duration: 2.1s; }
@keyframes mop-flicker {
  0%, 100% { transform: scaleY(1);    opacity: 1; }
  40%      { transform: scaleY(0.86); opacity: 0.82; }
  70%      { transform: scaleY(1.08); opacity: 0.95; }
}

/* ── What a spine opens to ─────────────────────────────────────────────────
   A native <dialog> and showModal(), the same decision the Pebble Board made
   and for the same five reasons: focus trap, Escape, inert background,
   backdrop and focus return all belong to the browser. Nothing here
   re-implements any of them.                                                   */
.mop-sheet {
  max-width: min(94vw, 680px); width: auto; padding: 0; border: 1px solid var(--mop-rule);
  border-radius: 2px; background: var(--mop-stone); color: var(--mop-bone);
  box-shadow: 0 40px 90px -30px #000;
}
.mop-sheet::backdrop { background: rgba(4,6,8,0.88); }
.mop-sheet__inner { margin: 0; padding: 30px 32px 28px; max-height: 88vh; overflow: auto; }
.mop-sheet h2 {
  font-family: 'IM Fell English', Georgia, serif; font-size: 34px; line-height: 1.08;
  color: var(--mop-gilt); margin: 0 0 4px;
}
.mop-sheet__by {
  margin: 0 0 4px; font-size: 13px; letter-spacing: 2.4px; text-transform: uppercase;
  color: var(--mop-dim);
}
.mop-sheet__note { margin: 18px 0 0; font-size: 16.5px; line-height: 1.7; }
.mop-sheet__talker {
  margin: 18px 0 0; padding: 12px 15px; font-family: 'IM Fell English', Georgia, serif;
  font-style: italic; font-size: 17px; color: var(--mop-flame);
  border-left: 2px solid var(--mop-wax); background: rgba(0,0,0,0.25);
}
.mop-sheet__get { margin: 22px 0 0; padding: 18px 0 0; border-top: 1px solid var(--mop-rule); }
.mop-sheet__get h3 {
  margin: 0 0 10px; font-size: 12px; letter-spacing: 2.4px; text-transform: uppercase;
  color: var(--mop-dim); font-family: 'Spectral', Georgia, serif; font-weight: 600;
}
.mop-sheet__get ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 9px; }
.mop-sheet__get a { display: inline-block; font-size: 15.5px; }
.mop-sheet__get em { display: block; font-size: 13.5px; color: var(--mop-dim); font-style: normal; }
.mop-shut {
  margin: 24px 0 0; cursor: pointer; padding: 10px 17px; border-radius: 2px;
  font-family: 'Spectral', Georgia, serif; font-size: 12.5px; font-weight: 600;
  letter-spacing: 2px; text-transform: uppercase;
  border: 1px solid var(--mop-rule); background: var(--mop-night); color: var(--mop-bone);
}
.mop-shut:hover { border-color: var(--mop-gilt); color: var(--mop-gilt); }

/* THE RECORDS THE POPUP IS A CLONE OF. They are on the page, [hidden], one per
   book -- see make-mopery.py. Two copies of a note in one document is how a
   shelf ends up disagreeing with its own popup, so there is one copy and the
   dialog borrows it. The room's <noscript> unhides them, which is why they are
   styled at all: with the script off this becomes a plain catalogue under each
   shelf instead of a row of buttons that do nothing. */
.mop-record h4 { margin: 0 0 4px; font-family: 'IM Fell English', Georgia, serif;
  font-weight: 400; font-size: 28px; line-height: 1.1; color: var(--mop-gilt); }

/* ── The parlour, and the one screen in it ─────────────────────────────────
   ONE SCREEN, A LISTING BESIDE IT, AND TUNING IS NOT PLAYING. The shape is the
   Solarpunk Hermitage's campfire television and the behaviour is identical,
   because the promise is the site's rather than that room's: while the set is
   off, previous and next fetch nothing and the whole listing can be walked
   without a request leaving the page. It looks nothing like that set. That one
   is a wooden box on a rug with an aerial; this is a dark plate in a stone
   chimney breast with candles guttering down both jambs.                       */
.mop-parlour {
  margin: 10px 0 0; padding: 30px 26px 28px;
  background: var(--mop-deep); border: 1px solid var(--mop-rule); border-radius: 2px;
}
.mop-hearth { position: relative; display: flex; gap: 18px; align-items: stretch; }
.mop-drip {
  flex: 0 0 26px; position: relative; border-radius: 2px;
  background: linear-gradient(180deg, #D9C7A6 0 10%, var(--mop-wax) 100%);
}
/* The wax runs. Drawn rather than animated: a candle that has been burning all
   evening has already dripped, and watching it happen is a different room. */
.mop-drip::after {
  content: ""; position: absolute; inset: 0; border-radius: 2px;
  background:
    radial-gradient(7px 16px at 20% 34%, rgba(217,199,166,0.85), transparent 70%),
    radial-gradient(6px 22px at 74% 58%, rgba(217,199,166,0.75), transparent 70%),
    radial-gradient(8px 14px at 42% 80%, rgba(217,199,166,0.8), transparent 70%);
}
.mop-drip::before {
  content: ""; position: absolute; left: 50%; bottom: 100%; width: 11px; height: 17px;
  margin-left: -5.5px; border-radius: 50% 50% 40% 40%;
  background: radial-gradient(circle at 50% 70%, #FFF1CE, var(--mop-flame) 55%, rgba(243,185,95,0) 100%);
}
html[data-intensity="max"] .mop-drip::before { animation: mop-flicker 3.1s ease-in-out infinite; }

.mop-screen {
  position: relative; flex: 1 1 auto; aspect-ratio: 16 / 9;
  background: #04060A; border: 1px solid var(--mop-rule); border-radius: 2px; overflow: hidden;
}
.mop-screen iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.mop-off {
  position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: center;
  gap: 8px; padding: 22px 26px; text-align: center;
}
.mop-off__now {
  margin: 0; font-family: 'IM Fell English', Georgia, serif; font-size: clamp(22px, 4vw, 34px);
  line-height: 1.1; color: var(--mop-bone);
}
.mop-off__runs { margin: 0; font-size: 14px; letter-spacing: 1.6px; text-transform: uppercase;
  color: var(--mop-dim); }
.mop-play, .mop-door {
  align-self: center; margin-top: 12px; cursor: pointer; text-decoration: none;
  padding: 11px 22px; border-radius: 2px;
  font-family: 'Spectral', Georgia, serif; font-weight: 600; font-size: 13px;
  letter-spacing: 2.2px; text-transform: uppercase;
  border: 1px solid var(--mop-gilt); background: transparent; color: var(--mop-gilt);
}
.mop-play:hover, .mop-door:hover { background: var(--mop-gilt); color: var(--mop-deep); }

.mop-tuner { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin: 20px 0 0; }
.mop-turn {
  cursor: pointer; padding: 10px 16px; border-radius: 2px;
  font-family: 'Spectral', Georgia, serif; font-weight: 600; font-size: 12.5px;
  letter-spacing: 2px; text-transform: uppercase;
  border: 1px solid var(--mop-rule); background: var(--mop-night); color: var(--mop-bone);
}
.mop-turn:hover { border-color: var(--mop-gilt); color: var(--mop-gilt); }
/* THE DIAL SAYS WHERE IT IS GOING AND HOW LONG THAT RUNS, BEFORE THE PRESS. A
   next button that only says "next" is the one place this design could quietly
   stop telling somebody what they are about to start. */
.mop-nextup { margin: 0; font-size: 14px; color: var(--mop-dim); }

.mop-cuts { list-style: none; margin: 22px 0 0; padding: 0; }
.mop-cut {
  display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: baseline;
  padding: 13px 4px 13px 16px; border-top: 1px solid var(--mop-rule);
}
.mop-cut:last-child { border-bottom: 1px solid var(--mop-rule); }
.mop-cut--on { background: rgba(211,171,88,0.09); border-left: 2px solid var(--mop-gilt);
  padding-left: 14px; }
.mop-cut__who { font-family: 'IM Fell English', Georgia, serif; font-size: 21px;
  color: var(--mop-bone); }
.mop-cut__sub { font-size: 14.5px; color: var(--mop-dim); flex: 1 1 200px; }
.mop-cut__runs { font-size: 12.5px; letter-spacing: 1.6px; text-transform: uppercase;
  color: var(--mop-dim); }
.mop-cut__note { flex: 1 1 100%; margin: 6px 0 0; font-size: 15px; line-height: 1.6;
  color: var(--mop-bone); }
.mop-cut__wrote { flex: 1 1 100%; margin: 6px 0 0; font-size: 13px; color: var(--mop-dim); }
.mop-tune {
  cursor: pointer; padding: 8px 14px; border-radius: 2px;
  font-family: 'Spectral', Georgia, serif; font-weight: 600; font-size: 11.5px;
  letter-spacing: 1.8px; text-transform: uppercase;
  border: 1px solid var(--mop-rule); background: transparent; color: var(--mop-gilt);
}
.mop-tune:hover { border-color: var(--mop-gilt); }

/* ── The Raven nook ────────────────────────────────────────────────────────
   The poem, twenty-six wood engravings, a scanned book, and a picker that hands
   the whole thing to every other voice on this street.

   THE PICKER IS THE ONE PLACE HERE WHERE BORROWING EVERY ROOM'S FACE IS THE
   JOKE RATHER THAN THE FAILURE. It is not harmonising: nothing about the
   Playhouse arrives when you set the poem in Titan One, only the letterforms,
   for as long as you want them. @font-face is lazy, so choosing a face is what
   downloads it and a reader who never opens the picker never pays for one.

   AND THE PLATES ARE SET IN ONE COLUMN WITH THE POEM RATHER THAN IN A GALLERY.
   Dore's edition put them in a block after the text; a gallery would be a
   faithful copy of that and a worse way to read, so they are interleaved at the
   lines their own captions quote, and the page says out loud that the placing
   is ours. See _dore in data/mopery.json.                                      */
.mop-scan {
  display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  align-items: start; margin: 10px 0 0; padding: 26px 26px 24px;
  background: var(--mop-stone); border: 1px solid var(--mop-rule); border-radius: 2px;
}
.mop-scan__head { grid-column: 1 / -1; margin: 0; font-family: 'IM Fell English', Georgia, serif;
  font-weight: 400; font-size: 26px; line-height: 1.15; color: var(--mop-gilt); }
.mop-scan__why { grid-column: 1 / -1; margin: 0; font-size: 15px; line-height: 1.62;
  color: var(--mop-dim); max-width: 78ch; }
.mop-scan__out { grid-column: 1 / -1; margin: 0; font-size: 13px; letter-spacing: 1.6px;
  text-transform: uppercase; }
.mop-leafshot { margin: 0; }
/* THE LEAVES KEEP A PALE GROUND BEHIND THEM. A scanned page is paper with
   nothing printed in the margins, so on a dark wall its edges dissolve and the
   object stops reading as a book. This is a mount, which is what you put a
   loose leaf on. */
.mop-leafshot img { display: block; width: 100%; height: auto; background: #D8D0BE;
  border: 1px solid var(--mop-rule); }
.mop-leafshot figcaption { margin: 9px 0 0; font-size: 13.5px; line-height: 1.5;
  color: var(--mop-dim); }

.mop-hand { margin: 22px 0 0; padding: 16px 18px; font-size: 15px; line-height: 1.65;
  color: var(--mop-bone); border-left: 2px solid var(--mop-wax); background: rgba(0,0,0,0.25); }

.mop-poembox {
  margin: 34px 0 0; padding: 30px clamp(20px, 4vw, 44px) 30px; background: var(--mop-stone);
  border: 1px solid var(--mop-rule); border-radius: 2px;
}
.mop-picker { display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin: 0 0 20px; padding: 0 0 18px; border-bottom: 1px solid var(--mop-rule); }
.mop-picker label { font-size: 12px; letter-spacing: 2.2px; text-transform: uppercase;
  color: var(--mop-dim); }
.mop-picker select {
  font-family: 'Spectral', Georgia, serif; font-size: 15px;
  padding: 8px 11px; border-radius: 2px; max-width: 100%;
  border: 1px solid var(--mop-rule); background: var(--mop-night); color: var(--mop-bone);
}
.mop-picker select:focus-visible { outline: 2px solid var(--mop-gilt); outline-offset: 2px; }
.mop-byline { margin: 0 0 12px; font-size: 13px; letter-spacing: 2.4px; text-transform: uppercase;
  color: var(--mop-dim); }
.mop-where { margin: 0 0 26px; padding: 0 0 22px; font-size: 14.5px; line-height: 1.62;
  color: var(--mop-dim); border-bottom: 1px solid var(--mop-rule); max-width: 78ch; }

/* The poem column is narrow because a line of The Raven is long and a reader
   should not have to hunt for the start of the next one. The plates break out
   of it, because they were printed full page. */
.mop-poem { margin: 0 auto; max-width: 34em; font-family: 'IM Fell English', Georgia, serif;
  font-size: 18px; line-height: 1.62; color: var(--mop-bone); }
.mop-poem p { margin: 0 0 24px; }
.mop-poem .mop-in { display: block; padding-left: 3.2em; }

.mop-plate { margin: 30px auto 34px; max-width: 460px; text-align: center; }
/* THE ENGRAVINGS ARE PAPER AND THE ROOM IS NOT. Dore's plates are near-white
   at the edges; dropped straight onto blue-black stone they float with no
   object under them, so each one sits on a mount the colour of the page it was
   printed on. Ornament: nothing is set on it. */
.mop-plate img { display: block; width: 100%; height: auto; padding: 10px;
  background: #E3DCCB; border: 1px solid var(--mop-rule); }
.mop-plate figcaption { margin: 12px auto 0; max-width: 40ch; font-family: 'Spectral', Georgia, serif;
  font-size: 14px; line-height: 1.55; color: var(--mop-dim); font-style: italic; }

/* ── The two doors at the back ─────────────────────────────────────────────
   Not shopfronts: this is a library, and the way further in is a card in the
   catalogue and a door in the panelling. Both are ordinary focusable links
   with real text at full size, for the reason written up in CLAUDE.md about
   The Den: on a Disabled people's site, subtle means visually quiet and never
   means a thing only a sighted mouse user can find.                            */
.mop-ways { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  margin: 10px 0 0; }
.mop-way {
  display: block; text-decoration: none; padding: 26px 26px 24px;
  background: var(--mop-stone); border: 1px solid var(--mop-rule); border-radius: 2px;
}
.mop-way:hover { border-color: var(--mop-gilt); background: var(--mop-shelf); }
.mop-way b { display: block; font-family: 'IM Fell English', Georgia, serif; font-weight: 400;
  font-size: 30px; line-height: 1.08; color: var(--mop-gilt); margin: 0 0 8px; }
.mop-way span { display: block; font-size: 15.5px; line-height: 1.62; color: var(--mop-bone); }
.mop-way em { display: block; margin: 12px 0 0; font-style: normal; font-size: 12px;
  letter-spacing: 2px; text-transform: uppercase; color: var(--mop-dim); }

.mop-foot { margin: 54px 0 0; padding: 26px 0 0; border-top: 1px solid var(--mop-rule);
  font-size: 14.5px; line-height: 1.7; color: var(--mop-dim); }
.mop-foot a { color: var(--mop-gilt); }


/* §23 ── SUBROOM: The Oracle Deck (off the Mopery's parlour) ─────────────────
   Thirteen old engravings, and a question on the back of each one.

   THE SUBROOM PROBLEM, THIRD TIME. The Chappell hangs off Pink Pony Club and
   shares nothing with it; The Den hangs off the Jungle Room and is the same
   green doing the opposite job. This hangs off a library whose whole ground is
   BLUE-BLACK, so this room is warm ash and has not one blue in it. Three
   things keep them apart and all three are structural:

     · the library is lit from candles that do not reach the walls. This is lit
       from NOWHERE -- a flat ash ground with no source in it at all, because a
       table with cards on it is the only thing you are looking at.
     · the library is PRINTED: Fell's Oxford types, ink spread, a page that has
       been through a press. This is CUT: Cinzel is inscriptional Roman
       capitals, letters chiselled rather than impressed, and there is no
       lowercase display anywhere in the room.
     · the library is furniture -- shelves, a chimney breast, a window. There is
       no furniture here. Thirteen rectangles on a plain ground, and the only
       warm thing in the room is the paper the engravings are printed on.

   AND NO GOLD ON INDIGO, which is The Chappell's and would make a third
   subroom that looked like the first one.

   THE DECK ASKS AND DOES NOT ANSWER, and that is enforced rather than intended:
   make-oracle.py refuses a card whose reading is not a question and refuses the
   vocabulary of prediction outright. A deck on a Disabled people's site that
   told somebody how their life was going to go would be doing the thing our own
   pages exist to refuse, in the one room dark enough to get away with it.

   AND THE WHOLE DECK IS ON THE PAGE. Drawing a card is a button; reading every
   card is scrolling. Nothing here is behind a dice roll, because a room that
   made somebody gamble to reach its content would have put content behind
   chance -- which is the "lite version" mistake with a deck in its hand.       */

.room-oracle {
  background: var(--orc-slate); color: var(--orc-cut);
  font-family: 'Cardo', Georgia, serif;
}
.room-oracle .wrap { max-width: 1060px; margin: 0 auto; padding: 0 22px 84px; }
.room-oracle a { color: var(--orc-brass); }
.room-oracle .backlink { color: var(--orc-dim); font-family: 'Cinzel', Georgia, serif;
  font-size: 12px; letter-spacing: 3px; }
.room-oracle .backlink:hover { color: var(--orc-cut); }

.orc-head { padding: 44px 0 0; text-align: center; }
.orc-head h1 {
  margin: 0; font-family: 'Cinzel', Georgia, serif; font-weight: 700;
  font-size: clamp(34px, 7vw, 60px); line-height: 1.06; letter-spacing: 4px;
  text-transform: uppercase; color: var(--orc-cut);
}
.orc-head .orc-sub {
  margin: 16px auto 0; max-width: 60ch; font-size: 17.5px; line-height: 1.68; color: var(--orc-cut);
}
.orc-head .orc-fine { margin: 12px auto 0; max-width: 62ch; font-size: 15px; line-height: 1.6;
  color: var(--orc-dim); }

/* A cut rule: two lines and a lozenge, which is what a stonecutter does when a
   line has to stop. */
.orc-cut-rule {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  margin: 34px 0; color: var(--orc-edge);
}
.orc-cut-rule::before, .orc-cut-rule::after {
  content: ""; flex: 0 1 190px; height: 1px; background: currentColor;
}
/* THE LOZENGE IS A SHAPE AND NOT A ROTATED SQUARE, which is not fussiness:
   check-gentle.py can only see the computed matrix, so a decorative
   rotate(45deg) reads to it exactly like a room's tilt outranking somebody's
   Gentle setting -- and it reported this one. Clipping a diamond out of a
   square says the same thing to the eye and the truth to the tool. Same call
   arcade.js made when it moved its sprites with left/top rather than
   transform. */
.orc-cut-rule span { width: 11px; height: 11px; background: var(--orc-brass);
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%); }

.room-oracle h2 {
  font-family: 'Cinzel', Georgia, serif; font-weight: 700; font-size: clamp(20px, 3.4vw, 28px);
  letter-spacing: 3px; text-transform: uppercase; color: var(--orc-cut); margin: 0 0 8px;
}
.room-oracle h2 + p { margin: 0 0 24px; color: var(--orc-dim); font-size: 16px; max-width: 68ch; }

/* ── The draw ──────────────────────────────────────────────────────────────
   One button, one card face-up, and a way to put it back. The card that comes
   up is the same object as the one in the index below, built from the same
   markup -- the script moves a card into the slot rather than rendering a
   second version of it, so the drawn card can never say something the index
   does not.                                                                    */
.orc-table {
  padding: 32px 26px 30px; background: var(--orc-deep);
  border: 1px solid var(--orc-edge); border-radius: 2px;
}
.orc-draw { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; justify-content: center; }
.orc-btn {
  cursor: pointer; padding: 14px 26px; border-radius: 2px;
  font-family: 'Cinzel', Georgia, serif; font-weight: 700; font-size: 13px;
  letter-spacing: 3px; text-transform: uppercase;
  border: 1px solid var(--orc-brass); background: transparent; color: var(--orc-brass);
}
.orc-btn:hover { background: var(--orc-brass); color: var(--orc-deep); }
.orc-btn--quiet { border-color: var(--orc-edge); color: var(--orc-dim); }
.orc-btn--quiet:hover { background: transparent; border-color: var(--orc-dim); color: var(--orc-cut); }

.orc-slot { margin: 26px auto 0; max-width: 560px; }
.orc-empty { margin: 0; text-align: center; font-size: 16px; line-height: 1.65; color: var(--orc-dim); }
.orc-said { margin: 18px 0 0; text-align: center; font-size: 15px; color: var(--orc-dim); }

/* ── A card ────────────────────────────────────────────────────────────────
   The plate, the name cut under it, the question, the note, and the museum's
   own credit line. The credit is ON THE CARD rather than in a footer: CC0 asks
   for nothing and this site names the hand anyway, which is the same reason
   Kaya Oldaker is on the Arcade's markup.                                      */
.orc-card {
  background: var(--orc-slate); border: 1px solid var(--orc-edge); border-radius: 2px;
  padding: 18px 18px 20px;
}
/* A PLATE IS WHATEVER SHAPE IT WAS PRINTED, and this is the second thing this
   room got wrong: a fixed 4/5 box with object-fit contain made a 560px-wide
   slot into a 700px-tall one, so the moon arrived at the size of a window and
   pushed its own name off the screen. The pictures are all roughly 500x625 and
   the only constraint they need is a ceiling. */
.orc-face {
  display: block; margin: 0 auto; background: #0B0A09; border-radius: 1px;
  width: auto; height: auto; max-width: 100%; max-height: 360px;
}
.orc-name {
  margin: 18px 0 0; font-family: 'Cinzel', Georgia, serif; font-weight: 700;
  font-size: clamp(19px, 3vw, 25px); letter-spacing: 3px; text-transform: uppercase;
  color: var(--orc-cut); text-align: center;
}
.orc-ask {
  margin: 12px 0 0; text-align: center; font-family: 'Cardo', Georgia, serif; font-style: italic;
  font-size: 19px; line-height: 1.5; color: var(--orc-red);
}
.orc-note { margin: 16px 0 0; font-size: 16px; line-height: 1.68; color: var(--orc-cut); }
.orc-plate {
  margin: 16px 0 0; padding: 13px 0 0; border-top: 1px solid var(--orc-edge);
  font-size: 13.5px; line-height: 1.6; color: var(--orc-dim);
}
.orc-plate b { font-weight: 400; color: var(--orc-cut); font-style: italic; }
.orc-plate a { color: var(--orc-brass); }

/* ── The index: the whole deck, face up, in order ──────────────────────────  */
.orc-index { list-style: none; margin: 0; padding: 0;
  display: grid; gap: 20px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }

.orc-foot { margin: 54px 0 0; padding: 26px 0 0; border-top: 1px solid var(--orc-edge);
  font-size: 14.5px; line-height: 1.7; color: var(--orc-dim); }
.orc-foot a { color: var(--orc-brass); }


/* §24 ── SUBROOM: The Doomscroll (off the Mopery's library) ──────────────────
   Public domain poems of doom, laid out as a feed, newest first, on a scroll.

   THE ZINE TABLE IS THE ROOM THIS COLLAPSES INTO, and it is a closer call than
   any other pair on this street because both of them are ink on paper. What
   keeps them apart is not the palette, it is the OBJECT:

     · the zine is a PHOTOCOPY -- stark white, pure black, cut up with scissors,
       scattered at angles, and the page IS the sheet. This is FOXED NEWSPRINT,
       warm and grey, in one unbroken roll with nothing cut and nothing rotated,
       lying on a dark desk you can see the edges of.
     · the zine sets a typewriter and a handwriting. This sets a blackletter
       masthead over a long serif column, which is a broadside and not a zine.
     · the zine is one sheet you hold. This is a roll that keeps going, which is
       the joke: a doomscroll is a scroll.

   If this paper ever goes white, or anything in here starts sitting at an
   angle, the two rooms have become one room.

   AND THE BLACKLETTER IS DISPLAY ONLY. UnifrakturMaguntia sets the masthead and
   nothing else -- never a headline a reader has to get through, never a line of
   a poem. Eighteen lines of blackletter is an access failure wearing
   atmosphere, and this is the room most likely to talk itself into one.        */

.room-doom { background: var(--dsc-desk); color: var(--dsc-bone);
  font-family: 'Vollkorn', Georgia, serif; }
.room-doom .wrap { max-width: 900px; margin: 0 auto; padding: 0 22px 84px; }
.room-doom .backlink { color: var(--dsc-paper); font-family: 'Vollkorn', Georgia, serif;
  font-size: 13px; letter-spacing: 2px; text-transform: uppercase; }
.room-doom .backlink:hover { color: #fff; }
/* EVERY LINK ON THE PAPER, AND THIS IS WHY THE RULE IS AT THE ROOM RATHER THAN
   ON THE COMPONENTS. This room declared a link colour for the provenance line
   and nowhere else, so every other link on the scroll fell through to the base
   stylesheet's pale pink -- which is a colour chosen for a near-black street
   and measures 2.4 on newsprint. Ryan found it at the foot of the page.
   check-contrast.py could not: it holds pairs for colours somebody decided on,
   and nobody had decided this one, which is the shape of hole an INHERITED
   value leaves. A pale room on a dark street has to say what its links are. */
.room-doom .dsc-roll a { color: var(--dsc-red); }
.room-doom .dsc-roll a:hover { color: var(--dsc-ink); }
/* On the roll the ring is the newsprint's ink, 12.44 to 10.73 across it. The
   desk around it is dark and keeps the yellow. */
.room-doom .dsc-roll :focus-visible { outline-color: var(--dsc-ink); }

/* ── The roll ──────────────────────────────────────────────────────────────
   One continuous sheet with a curled lip at each end. The curl is drawn, not
   animated: a scroll somebody has already unrolled is not still unrolling.     */
.dsc-roll {
  position: relative; margin: 26px 0 0; padding: 0;
  background: linear-gradient(90deg, var(--dsc-paper-2) 0, var(--dsc-paper) 5%,
                                     var(--dsc-paper) 95%, var(--dsc-paper-2) 100%);
  color: var(--dsc-ink);
  box-shadow: 0 30px 70px -34px #000;
}
.dsc-curl {
  height: 26px;
  background: linear-gradient(180deg, var(--dsc-paper-2), var(--dsc-paper));
  border-bottom: 1px solid var(--dsc-rule);
}
.dsc-curl--foot { background: linear-gradient(0deg, var(--dsc-paper-2), var(--dsc-paper));
  border-bottom: 0; border-top: 1px solid var(--dsc-rule); }
.dsc-sheet { padding: 34px clamp(20px, 5vw, 56px) 40px; }

.dsc-masthead { text-align: center; padding: 0 0 12px; border-bottom: 3px double var(--dsc-rule); }
.dsc-masthead h1 {
  margin: 0; font-family: 'UnifrakturMaguntia', Georgia, serif; font-weight: 400;
  font-size: clamp(40px, 10vw, 84px); line-height: 1.02; color: var(--dsc-ink);
}
.dsc-masthead .dsc-slug {
  margin: 10px 0 0; font-size: 12.5px; letter-spacing: 3px; text-transform: uppercase;
  color: var(--dsc-ink-2);
}
.dsc-lede { margin: 22px 0 0; font-size: 17.5px; line-height: 1.7; color: var(--dsc-ink); }
.dsc-lede + .dsc-lede { margin-top: 14px; }
.dsc-lede b { font-weight: 600; }
.dsc-note { margin: 18px 0 0; padding: 14px 16px; font-size: 15px; line-height: 1.62;
  color: var(--dsc-ink-2); border-left: 3px solid var(--dsc-rule);
  background: rgba(138,128,115,0.12); }

/* ── The feed ──────────────────────────────────────────────────────────────  */
.dsc-feed { list-style: none; margin: 30px 0 0; padding: 0; }
.dsc-item { padding: 26px 0; border-top: 1px solid var(--dsc-rule); }
.dsc-item:first-child { border-top: 3px double var(--dsc-rule); }
.dsc-when {
  margin: 0 0 8px; font-size: 12.5px; letter-spacing: 2.6px; text-transform: uppercase;
  color: var(--dsc-red);
}
.dsc-headline {
  margin: 0; font-weight: 600; font-size: clamp(22px, 4vw, 31px); line-height: 1.14;
  color: var(--dsc-ink);
}
.dsc-stand { margin: 10px 0 0; font-size: 16.5px; line-height: 1.62; color: var(--dsc-ink-2); }
.dsc-by { margin: 10px 0 0; font-size: 14.5px; color: var(--dsc-ink); }
.dsc-by b { font-weight: 600; font-style: italic; }
.dsc-more {
  margin: 14px 0 0; cursor: pointer; padding: 10px 18px; border-radius: 0;
  font-family: 'Vollkorn', Georgia, serif; font-weight: 600; font-size: 12.5px;
  letter-spacing: 2px; text-transform: uppercase;
  border: 1px solid var(--dsc-ink); background: transparent; color: var(--dsc-ink);
}
.dsc-more:hover { background: var(--dsc-ink); color: var(--dsc-paper); }

/* ── The whole poem ────────────────────────────────────────────────────────
   A native <dialog>, the Pebble Board's decision again. THE POEM IS ENTIRE:
   nothing on this scroll is excerpted, because a feed that hands you the worst
   line of something is exactly what this room is a joke about.                 */
.dsc-full {
  max-width: min(94vw, 680px); width: auto; padding: 0;
  border: 1px solid var(--dsc-rule); border-radius: 0;
  background: var(--dsc-paper); color: var(--dsc-ink);
  box-shadow: 0 40px 90px -30px #000;
}
.dsc-full::backdrop { background: rgba(14,12,10,0.9); }
.dsc-full__inner { margin: 0; padding: 32px clamp(20px, 5vw, 44px) 30px; max-height: 90vh; overflow: auto; }
.dsc-full h3 { margin: 0 0 4px; font-weight: 600; font-size: 30px; line-height: 1.12;
  color: var(--dsc-ink); }
.dsc-full__by { margin: 0; font-size: 14px; letter-spacing: 2px; text-transform: uppercase;
  color: var(--dsc-ink-2); }
.dsc-poem { margin: 24px 0 0; font-size: 17.5px; line-height: 1.6; }
.dsc-poem p { margin: 0 0 20px; }
.dsc-poem p:last-child { margin: 0; }
.dsc-prov {
  margin: 26px 0 0; padding: 16px 0 0; border-top: 1px solid var(--dsc-rule);
  font-size: 13.5px; line-height: 1.65; color: var(--dsc-ink-2);
}
.dsc-prov b { font-weight: 600; color: var(--dsc-ink); }
.dsc-prov a { color: var(--dsc-red); }
.dsc-close {
  margin: 22px 0 0; cursor: pointer; padding: 10px 18px;
  font-family: 'Vollkorn', Georgia, serif; font-weight: 600; font-size: 12.5px;
  letter-spacing: 2px; text-transform: uppercase;
  border: 1px solid var(--dsc-ink); background: transparent; color: var(--dsc-ink);
}
.dsc-close:hover { background: var(--dsc-ink); color: var(--dsc-paper); }

.dsc-foot { margin: 40px 0 0; padding: 26px 0 0; border-top: 1px solid rgba(220,215,204,0.25);
  font-size: 14.5px; line-height: 1.7; color: var(--dsc-paper); }
.dsc-foot a { color: var(--dsc-paper); }


/* §25 ── ROOM: Swaying Sweetgrass (pitch 02 in the campgrounds) ──────────────
   A MEADOW LEFT ALONE, with one path cut into it and a fire pit at the end of
   the path. Pitch 02 was open ground until this; the field's board now has
   something on it.

   THE LIGHT IS BEHIND THE GRASS AND THAT IS THE WHOLE ROOM. Every warm room on
   this street is lit by a flame you could put your hand over — the Faery Yurt's
   candle, The Latibulum's one low lamp, The Den's knee-height bulbs, the
   Hermitage's cave, the Mopery's top shelf. By the time a SIXTH warm room turns
   up, "they are all cosy, they should feel the same" has stopped sounding like
   tidying and started sounding like taste, which is exactly when it gets in.
   What keeps this one out of that family is not the palette, it is the physics:

     · those rooms are lit FROM INSIDE THEM, and every object in them has a lit
       face and a shadow side. Here the sun is low, a hundred feet off, and
       BEHIND everything — so nothing has a lit face at all. The blades glow
       because the light is coming THROUGH them. That is why the greens go
       yellow (--glow, --seed) while the ground stays dark: transmitted light,
       not reflected light, and the whole palette falls out of it.
     · those rooms are enclosed and full of furniture. THERE IS NO FURNITURE IN
       A MEADOW. The only built things on this page are the path and the fire
       ring, and you go a long way through nothing to reach them.
     · those rooms are BROWN. This is green-gold. Chlorophyll with the sun
       through it is a completely different warmth from tallow or varnish, and
       if the greens in here ever go brown at the edges this has become the yurt
       with more grass in it.

   AND IT IS THE FOURTH GREEN THING, which is the other collision. The Jungle
   Room is night-green UNDER A ROOF: light falls down and lands in patches, and
   nothing stands alone because everything overlaps something. The Den is green
   carpet in a brown box. The campground is night-blue on bare open ground. This
   is open like the field and lit like neither — the sky is behind you at eye
   level rather than above you, and the grass is over your head.

   IT STANDS THINGS ON A LINE INSTEAD OF HANGING THEM OFF A POST, which is the
   structural inversion of the field it is pitched on. Up there every notice is
   nailed to a timber down its left side. Down here everything sits ON the
   ground and grows up off it, because that is what grass does, and a meadow
   with a row of posts in it is a fence.

   SENTENCE CASE THROUGHOUT. The campground routs its signs in capitals; this
   room never shouts, and the one place capitals appear is the dial, which is
   furniture.

   Eczar and Alegreya Sans, set nowhere else. See §1.                          */

.meadow {
  background:
    radial-gradient(120% 70% at 78% 4%, rgba(201,162,39,.10), transparent 62%),
    var(--soil);
  background-attachment: fixed;
  color: var(--straw);
  font-family: 'Alegreya Sans', var(--sans);
}
/* A reading column between two bands of grass. The bottom padding is SMALL
   because a band follows almost every one of these and the grass is the
   separator — a room-sized gap before it as well would read as a fault in the
   page rather than as a stretch of meadow. The last one gets the full run-out. */
.meadow .wrap { max-width: 860px; margin: 0 auto; padding: 0 22px 34px; }
.meadow .wrap:last-of-type { padding-bottom: 90px; }
.meadow p, .meadow li { font-size: 17.5px; line-height: 1.68; }
.meadow a { color: var(--seed); text-underline-offset: 4px; }
.meadow a:hover { color: var(--straw); }

/* The backlink drops Bungee, the way the campground's does. The street's voice
   out here would be the only hard edge in the room. */
.meadow .backlink { font-family: 'Alegreya Sans', var(--sans); font-size: 15px;
  letter-spacing: 0; color: var(--awn); }
.meadow .backlink:hover { color: var(--straw); }

.meadow h1 {
  font-family: 'Eczar', Georgia, serif; font-weight: 600;
  font-size: clamp(40px, 8vw, 84px); line-height: 1.02;
  color: var(--glow); margin: 14px 0 0;
}
.meadow h2 {
  font-family: 'Eczar', Georgia, serif; font-weight: 600;
  font-size: clamp(26px, 4vw, 38px); line-height: 1.12;
  color: var(--glow); margin: 0 0 14px;
}
.meadow h3 {
  font-family: 'Eczar', Georgia, serif; font-weight: 600;
  font-size: 21px; line-height: 1.2; color: var(--straw); margin: 0;
}
.meadow .lede { font-size: 20.5px; line-height: 1.6; color: var(--straw);
  max-width: 54ch; margin: 22px 0 0; }
.meadow .trailmark { margin: 0; font-size: 14px; color: var(--awn); }
.meadow .sr { position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; }

/* ── The grass ────────────────────────────────────────────────────────────
   Bands of it between every section, drawn in the pages rather than here
   because they are pictures of a place and not borders — the rule the
   campground's stream and the yurt's crown follow. The band runs the full
   width of the viewport and the reading column sits over it, so the meadow
   is behind the words rather than beside them.

   THE SWAY IS THIS ROOM'S AMBIENT LAYER AND IT IS THE ONLY MOTION IN IT. The
   field above has none at any setting, which is the field's own rule and not
   an area style — a pitch is its own world and sets its own noise, the way
   Helen's fairy lights twinkle at MAX on a page pitched in a still field.

   NOTHING IS DECLARED AT GENTLE. §3 kills animation with !important and would
   catch this anyway, but a rule that only exists at regular and max cannot be
   the thing that leaks: there is no base animation for a reset to have to beat.
   The transform-box/origin pair is what makes a blade pivot at its root
   instead of at the middle of the drawing.                                    */
.swg-band { line-height: 0; margin: 0; width: 100vw; margin-left: calc(50% - 50vw); }
.swg-band svg { display: block; width: 100%; height: auto; }
.swg-sway { transform-box: fill-box; transform-origin: 50% 100%; }

@keyframes swg-lean { 0%, 100% { transform: rotate(-1.1deg); } 50% { transform: rotate(1.1deg); } }
@keyframes swg-gust { 0%, 100% { transform: rotate(-2.6deg); } 47% { transform: rotate(3deg); } }
@keyframes swg-drift { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(14px, -9px); } }

html[data-intensity="regular"] .meadow .swg-sway { animation: swg-lean 9s ease-in-out infinite; }
html[data-intensity="max"]     .meadow .swg-sway { animation: swg-gust 5.5s ease-in-out infinite; }
html[data-intensity="max"]     .meadow .swg-flit { animation: swg-drift 11s ease-in-out infinite; }

/* Staggered so the band moves like grass and not like a comb. */
.meadow .swg-sway:nth-child(3n)   { animation-delay: -1.7s; }
.meadow .swg-sway:nth-child(3n+1) { animation-delay: -3.9s; }
.meadow .swg-sway:nth-child(5n)   { animation-delay: -2.8s; }

/* The clearing is an OBJECT and not a band: the bands run the full width of the
   viewport because the meadow does, and the fire pit is a place inside it that
   you walk to. Full-bleeding it would make the clearing as wide as the field. */
.swg-pit { width: auto; margin-left: 0; margin-top: 18px; }
.swg-pit svg { max-width: 760px; margin-inline: auto; }

/* ── Sections ─────────────────────────────────────────────────────────────
   No boxes. A section is a heading and some words standing on the ground, and
   what separates two of them is grass rather than a rule.                     */
.swg-sec { margin: 40px 0 0; }
.swg-sec p { max-width: 62ch; }
.swg-lead-in { color: var(--awn); font-size: 16px; letter-spacing: 1.5px;
  text-transform: lowercase; margin: 0 0 6px; }

/* The one panel shape in the room, and it has no border and no corners of its
   own: a patch of ground a little more sheltered than the rest. It sits ON a
   line at the foot for the reason above. */
.swg-plot { background: var(--shade); padding: 22px 24px;
  border-bottom: 2px solid var(--stem); margin: 26px 0 0; }
.swg-plot p:last-child { margin-bottom: 0; }

/* ── The passages from the book ───────────────────────────────────────────
   Set in the display face because they are the reason the room exists, and
   indented off a single stem rather than boxed. The stem is at the LEFT and
   this is the one place in the room that has one, which is allowed because a
   quotation really is hanging off something.                                  */
.swg-quote { margin: 34px 0 0; padding: 0 0 0 26px; border-left: 2px solid var(--stem); }
.swg-quote blockquote { margin: 0; }
.swg-quote blockquote p {
  font-family: 'Eczar', Georgia, serif; font-weight: 600;
  font-size: clamp(19px, 2.4vw, 24px); line-height: 1.5;
  color: var(--glow); margin: 0; max-width: 46ch;
}
.swg-quote figcaption { margin: 12px 0 0; font-size: 15px; color: var(--awn); }
.swg-quote cite { font-style: italic; }
.swg-q-ours { margin: 3px 0 0 !important; font-size: 14px; color: var(--sedge); }

/* ── The clearing, and what is told at the fire ───────────────────────────
   Ten recordings standing on the ground round the pit. Each one is its own
   plant: a title, who published it, how long it runs, and a press.            */
.swg-sits { list-style: none; margin: 26px 0 0; padding: 0;
  display: grid; gap: 26px; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); }
/* THE LINE HAS TO BE AN ACTUAL LINE. This room's stated structure is that
   things stand on the ground rather than hang off a post, and the first
   version let each item's rule sit wherever its own text happened to stop --
   so a row of two came out with the ground at two different heights, which
   reads as a fault rather than as a field. The item fills its grid row and the
   press is pushed to the foot, so every rule in a row is the same ground. */
.swg-sit { padding: 0 0 18px; border-bottom: 2px solid var(--stem);
  display: flex; flex-direction: column; }
/* ONLY THE BUTTON OPTS OUT OF STRETCHING, and it is written this way round
   because the other way round shipped broken. A facade is TWO ELEMENTS in
   sequence -- a <button> before the press and a <div> holding the iframe after
   it -- and a rule aimed at ".facade" hits both. `align-items: flex-start` on
   this column was added so the Play rule would not run the full width of the
   card; it also stopped the PRESSED div from stretching, and since the iframe
   inside it is absolutely positioned it contributes no size, so the shell
   collapsed to 0x0. The sound played and there was no picture and no controls,
   which is the worst shape this failure could take: the page looks like it
   worked. Ryan found it by pressing one.
   The default here is stretch, which is what the player needs; the button asks
   for flex-start on its own. Anything added to this column later gets the
   right behaviour without knowing about any of this. */
.meadow .swg-sit button.facade { margin-top: auto; align-self: flex-start; }
.swg-sit h3 { color: var(--straw); }
.swg-by { margin: 6px 0 0; font-size: 14.5px; color: var(--sedge); letter-spacing: .3px; }
.swg-sit p { margin: 9px 0 0; color: var(--awn); font-size: 16.5px; }

/* The press. §4 supplies the mechanism and the 16/9 box; this dresses it as
   something growing out of the ground rather than a button sat on top of it. */
.meadow .facade {
  aspect-ratio: auto; border: 0; border-radius: 0;
  background: transparent; color: var(--seed);
  width: auto; margin: 12px 0 0; padding: 9px 0 0;
  border-top: 1px solid var(--stem);
  font-family: 'Alegreya Sans', var(--sans); font-size: 15.5px;
  font-weight: 500; letter-spacing: .4px;
}
.meadow .facade:hover { background: transparent; color: var(--straw); border-top-color: var(--sedge); }
/* Once it is pressed it becomes a real player and needs the box back. */
/* The pressed state, in every room shape on this page. `align-self` is belt
   and braces for the flex column above; `width: 100%` covers the plain block
   flow of the field guide and the grass clip, where .meadow .facade's
   `width: auto` is only correct because a block fills its parent. */
.meadow div.facade { aspect-ratio: 16 / 9; padding: 0; margin-top: 14px; border-top: 0;
  width: 100%; align-self: stretch; }
.meadow div.facade iframe { border-radius: 0; }

/* Ryan's grass was shot on a phone and is taller than it is wide. A 16/9 box
   round a 9/16 video is two black bars and a small picture.
   SCOPED FROM THE CONTAINER AND NOT FROM A CLASS ON THE BUTTON, because the
   button is gone by the time this matters: love-embed.js replaces it with a
   plain <div class="facade"> and every other class it was wearing is dropped.
   The first version put swg-tall on the button, which styled nothing anybody
   could see and left the player landscape. The Pebble Board hit this first and
   answered it the same way -- see .pb-card .facade iframe in §21. */
.swg-clip { max-width: 320px; }
.swg-clip div.facade { aspect-ratio: 9 / 16; }

/* ── The chapter readings, which are doors and not screens ────────────────
   Deliberately unlike everything else on the page: no press, no runtime badge
   in the same shape as the fire's, no box. A list of links that leaves. The
   room says why in its own copy and make-sweetgrass.py refuses one marked as
   a screen.                                                                   */
.swg-doors { list-style: none; margin: 20px 0 0; padding: 0;
  columns: 2; column-gap: 34px; }
.swg-door { break-inside: avoid; padding: 7px 0; font-size: 16px;
  display: flex; gap: 10px; justify-content: space-between; align-items: baseline; }
.swg-len { flex: 0 0 auto; font-size: 14px; color: var(--sedge); font-variant-numeric: tabular-nums; }

/* ── The field guide ──────────────────────────────────────────────────────
   Same furniture as the fire, one column, because these are somebody else's
   teachings and a grid of them starts to look like a catalogue of people.     */
.swg-teaches { list-style: none; margin: 26px 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 26px; }
.swg-teach { padding: 0 0 18px; border-bottom: 2px solid var(--stem); max-width: 62ch; }
.swg-teach p { margin: 9px 0 0; color: var(--awn); font-size: 16.5px; }

/* ── The braid ────────────────────────────────────────────────────────────
   Three bundles of seven, and the layout IS the count: three columns, seven
   strands each, numbered down the side. make-sweetgrass.py refuses a bundle
   that is not seven, because that number is an Elder's teaching and not a
   design decision anybody here is allowed to round off.                       */
.swg-bundles { list-style: none; margin: 30px 0 0; padding: 0;
  display: grid; gap: 34px; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
/* The three bundles are a braid and have to rhyme, so the strand lists are
   pushed to the foot: the quoted words above them are different lengths and
   left to themselves the three purple bands ended up at three heights, which
   is the same "ground at two heights" fault the fire's rules had. */
.swg-bundle { padding: 0 0 0 18px; border-left: 2px solid var(--stem);
  display: flex; flex-direction: column; }
.swg-bundle .swg-strands { margin-top: auto; padding-top: 16px; }
.swg-bundle h3 { color: var(--glow); font-size: 20px; }
.swg-seven { color: var(--seed); }
.swg-bundle blockquote { margin: 12px 0 0; }
.swg-bundle blockquote p { margin: 0; color: var(--awn); font-size: 16px; line-height: 1.6; }
.swg-strands { list-style: none; margin: 16px 0 0; padding: 0; }
/* The purple-white band sits at the FOOT of the strand list, because that is
   where it is on the plant: the stems are banded where they meet the ground. */
.swg-strands li { display: flex; gap: 11px; align-items: baseline;
  font-size: 15.5px; padding: 3px 0; color: var(--straw); }
.swg-strands li:last-child { border-bottom: 3px solid var(--band); padding-bottom: 8px; }
.swg-strand-no { flex: 0 0 1.4em; font-family: 'Eczar', Georgia, serif;
  font-size: 13px; color: var(--sedge); font-variant-numeric: tabular-nums; }
.swg-braid-say { max-width: 56ch; font-family: 'Eczar', Georgia, serif; font-weight: 600;
  font-size: 19px; line-height: 1.5; color: var(--glow); margin: 24px 0 0; }
.swg-braid-say--root { color: var(--band); }
.swg-braid-who { margin: 26px 0 0; font-size: 15px; color: var(--awn); max-width: 62ch; }

/* ── The shelf, the path, the small print ─────────────────────────────────  */
.swg-book { margin: 18px 0 0; font-size: 18px; color: var(--straw); }
.swg-go { margin: 10px 0 0; font-size: 17px; }
.swg-cited, .swg-cap { margin: 10px 0 0; font-size: 15px; color: var(--sedge); max-width: 56ch; }

/* The path in. A natural surface you can get a chair down, which is a real
   specification and not a nice idea, so it is set out as one. */
.swg-spec { list-style: none; margin: 20px 0 0; padding: 0; max-width: 62ch; }
.swg-spec li { padding: 10px 0 10px 22px; position: relative; border-bottom: 1px solid var(--stem); }
.swg-spec li::before { content: ""; position: absolute; left: 0; top: 1.05em;
  width: 10px; height: 2px; background: var(--sedge); }
.swg-spec strong { color: var(--glow); font-weight: 500; }

.swg-foot { margin: 40px 0 0; font-size: 15px; color: var(--awn); max-width: 64ch; }


/* §26 ── ROOM: The Adventurer's Guild ────────────────────────────────────────
   A JOB BOARD, AND THE ONE TIDY ROOM ON THIS STREET.

   The trope is the adventurer's guild with the inn over it and the board of
   posted jobs by the door, ranked by difficulty class. The joke here is that on
   a street whose entire architecture is that nothing matches, somebody has come
   in and FILED EVERYTHING: ruled boxes, square corners, a class in the margin, a
   stamp when a job is done. Tidiness as one room's costume, which is the only
   way this site can wear it.

   SO THE RULES OF THIS SECTION ARE NEGATIVE ONES, and they are what keep it
   from turning into any of its neighbours. No gradient. No shadow. No rounded
   corner. No ambient layer at any dial setting. Everything square to everything
   else, nothing rotated, nothing overlapping. If a rule in here ever grows a
   soft edge, the sheet has become a place.

   THE THREE ROOMS IT COULD COLLAPSE INTO, and what holds it off each:

     · THE SOLARPUNK HERMITAGE is the other room you can read by daylight. It
       has a SUN in it -- one direction, warm, shadows falling away from it,
       sunflowers at the door. There is NO LIGHT SOURCE IN HERE AT ALL: this is
       lit like a photocopy of a document, evenly, from nowhere, and nothing in
       it casts anything.
     · THE DOOMSCROLL is the other pale ground on a dark street. That is foxed
       newsprint, warm and grey, ONE UNBROKEN ROLL with nothing cut and nothing
       ruled, lying on a dark desk whose edges you can see. This is manila, and
       it is made of rules: boxes, columns, a margin, a stamp.
     · THE ZINE TABLE and CLUB CHRONIC are the other rooms made of paper, and
       both are paper that somebody CUT UP -- scattered, angled, overlapping,
       pasted. Nothing here is cut or angled or overlapping. A clerk did this.

   A PALE ROOM ON A DARK STREET HAS TO STATE ITS OWN LINK COLOUR, at the room,
   which is the hole the Doomscroll left: it declared a link colour for one line
   and every other link on that pale page fell through to the base stylesheet's
   `a` -- a pink chosen for a near-black street, measuring about 2.4 on paper,
   and the contrast checker had nothing to hold a pair for because nobody had
   DECIDED anything. `.room-guild a` below is that decision, made once, at the
   room.                                                                       */

.room-guild {
  background: var(--gu-paper); color: var(--gu-ink);
  font-family: 'Public Sans', var(--sans);
}
.room-guild a { color: var(--gu-file); }
/* A clerk's ring is the ink. Yellow on manila measured 1.01 -- the worst on
   the street -- and the ink is 12.13 on the sheet and 10.19 on a posting. */
.room-guild :focus-visible { outline-color: var(--gu-ink); }
.room-guild .backlink { color: var(--gu-file); }
.room-guild .sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

.guild { max-width: 980px; margin: 0 auto; padding: 0 22px 70px; }

/* The masthead is a filing header: two rules with the name between them, and a
   docket line under it. Rye is the posted-bill face and is used HERE AND ON THE
   JOB TITLES AND NOWHERE ELSE — a woodtype at paragraph length is an access
   failure wearing atmosphere, which is the lesson the Doomscroll's blackletter
   already had to learn one room over. */
.guild-head { border-top: 6px solid var(--gu-ink); border-bottom: 2px solid var(--gu-ink); margin-top: 26px; padding: 18px 0 14px; }
.room-guild h1 {
  font-family: 'Rye', var(--sans); font-weight: 400;
  font-size: clamp(34px, 6.4vw, 62px); line-height: 1.04;
  margin: 0; color: var(--gu-ink);
}
.guild-docket {
  display: flex; flex-wrap: wrap; gap: 6px 26px;
  margin: 12px 0 0; font-size: 12.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--gu-ink-2);
}
.guild-lede { margin: 18px 0 0; font-size: 17px; line-height: 1.6; max-width: 66ch; }
.room-guild h2 {
  font-family: 'Rye', var(--sans); font-weight: 400;
  font-size: clamp(21px, 3.2vw, 29px); line-height: 1.1;
  margin: 46px 0 12px; padding-bottom: 8px;
  border-bottom: 2px solid var(--gu-ink);
}
.guild-note { margin: 0 0 12px; font-size: 15.5px; line-height: 1.6; max-width: 66ch; color: var(--gu-ink-2); }
.guild-note b, .guild-lede b { color: var(--gu-ink); }

/* The counter where you hand a code in. A boxed form on a form. */
.hand { border: 2px solid var(--gu-ink); padding: 20px 22px; margin: 26px 0 0; background: var(--gu-paper-2); }
.hand__title { margin: 0 0 4px; font-size: 13px; letter-spacing: .16em; text-transform: uppercase; font-weight: 700; }
.hand__why { margin: 0 0 14px; font-size: 15px; line-height: 1.55; max-width: 60ch; }
.hand__row { display: flex; flex-wrap: wrap; gap: 10px; align-items: stretch; }
.hand__in {
  flex: 1 1 13em; min-width: 0; min-height: 46px; padding: 8px 12px;
  border: 2px solid var(--gu-ink); background: var(--gu-paper);
  color: var(--gu-ink); font-family: inherit; font-size: 17px; letter-spacing: .2em;
}
.hand__do {
  min-height: 46px; padding: 8px 22px; cursor: pointer;
  border: 2px solid var(--gu-ink); background: var(--gu-ink);
  color: var(--gu-paper); font-family: inherit; font-size: 15px;
  font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
}
.hand__do:hover { background: var(--gu-stamp); border-color: var(--gu-stamp); }
.hand__said { margin: 14px 0 0; font-size: 15.5px; line-height: 1.55; max-width: 64ch; }
.hand__said:empty { display: none; }
.hand__nostore { margin: 12px 0 0; font-size: 14px; line-height: 1.5; color: var(--gu-stamp); max-width: 64ch; }
.hand__forget {
  margin-top: 14px; cursor: pointer; min-height: 44px; padding: 6px 14px;
  border: 2px solid var(--gu-ink-2); background: transparent;
  color: var(--gu-ink-2); font-family: inherit; font-size: 13px; letter-spacing: .06em;
}
.hand__forget:hover { border-color: var(--gu-stamp); color: var(--gu-stamp); }

/* THE BOARD. One ruled row per job, in the order they were written rather than
   sorted by class — sorting by difficulty would stack the long walks at the
   bottom and read as a ladder you climb, which is the scoreboard this room
   refuses arriving as a sort order. */
.guild-board { list-style: none; margin: 0; padding: 0; border-top: 2px solid var(--gu-ink); }
/* THE ROW IS PADDED ON ALL FOUR SIDES, and the alternating band is why. With
   `padding: 20px 0` the class sat flush against the left edge of the tint and
   the DONE stamp against the right, which reads as a row that has overflowed
   its own cell rather than as a form. Nothing else in this room touches an
   edge; a ruled cell should not either. */
.job {
  display: grid; grid-template-columns: 82px 1fr auto; gap: 0 20px;
  align-items: start; padding: 20px 18px; border-bottom: 1px solid var(--gu-rule);
}
.job:nth-child(even) { background: var(--gu-paper-2); }
.job__class {
  margin: 0; font-family: 'Rye', var(--sans); font-size: 27px; line-height: 1;
  color: var(--gu-file);
}
.job__where {
  display: block; margin-top: 6px; font-family: 'Public Sans', var(--sans);
  font-size: 11px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--gu-ink-2);
}
.job__body { min-width: 0; }
.job__title { font-family: 'Rye', var(--sans); font-weight: 400; font-size: 21px; line-height: 1.16; margin: 0; }
.job__room { margin: 7px 0 0; font-size: 12.5px; letter-spacing: .1em; text-transform: uppercase; }
.job__posted { margin: 11px 0 0; font-size: 15.5px; line-height: 1.6; max-width: 62ch; }
.job__takes { margin: 11px 0 0; font-size: 14px; color: var(--gu-ink-2); }
.job__takes b { color: var(--gu-ink); letter-spacing: .1em; text-transform: uppercase; font-size: 12px; }
.job__hints { display: flex; flex-wrap: wrap; gap: 8px 16px; margin-top: 12px; }
.job__hint > summary {
  cursor: pointer; min-height: 44px; display: flex; align-items: center;
  font-size: 12.5px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--gu-file);
}
.job__hint > p { margin: 0 0 6px; font-size: 15px; line-height: 1.55; max-width: 60ch; }
.job__hint[open] { flex: 1 1 100%; border-left: 3px solid var(--gu-rule); padding-left: 12px; }
.job__done { margin-top: 14px; border-top: 2px solid var(--gu-stamp); padding-top: 10px; }
.job__learned { margin: 0; font-size: 15px; line-height: 1.6; max-width: 62ch; }

/* The stamp. A rubber stamp is ink pressed onto paper at whatever angle the
   hand held it — and a rotation here would be decoration outranking somebody's
   Gentle setting, which is what check-gentle.py measures and cannot be asked to
   take a room's word about. So this one was pressed square, like everything
   else the clerk did. */
.job__stamp {
  margin: 0; align-self: center; justify-self: end;
  font-family: 'Public Sans', var(--sans); font-weight: 700;
  font-size: 15px; letter-spacing: .22em;
  color: var(--gu-stamp); border: 3px double var(--gu-stamp);
  padding: 5px 12px;
}
.job--done .job__title { color: var(--gu-ink-2); }
.job--just { background: var(--gu-paper-2); transition: background 600ms ease-out; }

/* Sparks, at MAX only, and moved with `top` and a translate rather than any
   rotation — the call arcade.js made, for the same reason: a checker that can
   only read the off-diagonal terms of a matrix must not be asked to take this
   file's word for something else. NOTHING FLASHES AND NOTHING STROBES, here or
   anywhere, which is Club Chronic's rule holding a room away. They rise once
   and fade, and quest.js takes them out of the document afterwards. */
.guild-sparks { position: fixed; inset: 0; pointer-events: none; overflow: hidden; z-index: 40; }
.guild-spark {
  position: absolute; bottom: 0; width: 7px; height: 7px;
  background: var(--gu-stamp); opacity: 0;
}
html[data-intensity="max"] .guild-spark { animation: gu-rise 2.1s ease-out forwards; }
@keyframes gu-rise {
  0%   { opacity: 0; transform: translateY(0); }
  12%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(-62vh); }
}

/* The house rules, and the room over the board. */
.guild-rules { border: 2px solid var(--gu-ink); padding: 20px 22px; margin: 26px 0 0; }
.guild-rules ul { margin: 12px 0 0; padding-left: 20px; }
.guild-rules li { margin: 0 0 8px; font-size: 15.5px; line-height: 1.55; max-width: 62ch; }
.guild-inn {
  border-top: 6px solid var(--gu-ink); margin-top: 46px; padding-top: 18px;
  font-size: 15.5px; line-height: 1.6; max-width: 66ch; color: var(--gu-ink-2);
}
/* The desk at the end: the credits and the dial, side by side. The street's
   chalk pavement does NOT run through this room -- a shared footer would be the
   one piece of the street's own look reaching into a world, which is the same
   leak check-classes.py caught here on its first run when this page was wearing
   .pavement and .masthead__dial outright. Every room ends in its own voice. */
.guild-desk { display: flex; flex-wrap: wrap; gap: 30px; align-items: flex-start; border-top: 2px solid var(--gu-ink); margin-top: 46px; padding-top: 24px; }
.guild-desk__half { flex: 1 1 300px; min-width: 0; }
.guild-desk__half .dial { max-width: 380px; }

/* THE WAY UP TO ROOM 429, and it is the one thing in this room that is allowed
   to be a door rather than a form. It stays inside the guild's own rules --
   square, ruled, no gradient, no shadow, no rounded corner, no light -- because
   the room it points at is the opposite of all of that and the contrast IS the
   arrival. A stair drawn in the checkpoint's colours here would be this room
   borrowing a world it is not, which is the failure the guild's own note
   warns about running backwards.

   THE CHECKPOINT IS NOT BEHIND THIS DOOR. It is a shopfront on the street as
   well, and that is a decision rather than a convenience: a room arguing that
   rest is owed rather than earned cannot be reachable only by walking through
   the job board. This is the back stair, and the front door is on the street. */
.guild-stair {
  display: block; text-decoration: none; color: var(--gu-ink);
  border: 2px solid var(--gu-ink); border-top-width: 6px;
  margin-top: 26px; padding: 18px 22px;
}
.guild-stair:hover, .guild-stair:focus-visible { background: var(--gu-paper-2); }
.guild-stair__to { display: block; font-family: 'Rye', var(--sans); font-size: 19px; letter-spacing: .02em; }
.guild-stair__why { display: block; margin-top: 8px; font-size: 15.5px; line-height: 1.6; max-width: 66ch; color: var(--gu-ink-2); }

/* §27 ── ROOM: The Feed ──────────────────────────────────────────────────────
   AN ARRIVALS BOARD IN A DARK CONCOURSE, AND THE ONLY MACHINE ON THIS STREET.

   A hall with freestanding split-flap indicator boards standing down it on
   metal legs, one per site, each lit from inside itself. The room's whole
   argument is in the object: a board is SET by somebody with a machine, at a
   time, and it is a picture of the railway rather than the railway. That is
   what lets this room carry other people's arrivals honestly — it says the
   minute it was set, and the live thing is one press away on every plate.

   THE LIGHT IS THE ROOM, and it is a THIRD kind of transmitted light, which
   matters because one neighbour has already claimed the idea. Swaying
   Sweetgrass is lit THROUGH a translucent body — the sun a hundred feet off
   and behind, diffuse, no edges, nothing with a lit face. This is lit through
   an APERTURE: a hard light a finger's width behind a mask, so every letter
   has a crisp edge, every flap throws a hairline shadow on the one below it,
   and the enamel between the letters stays completely dead. Diffuse
   transmission against masked transmission. If the edges in here ever go soft,
   this has become the meadow with a timetable in it.

   AND THE FURNITURE IS DARKER THAN THE ROOM, which nothing else here does.
   Every other dark room on this street stands lighter objects in a darker
   ground; the carcass of a board is the darkest thing in this hall and the
   brightest thing in it at the same time. That inversion is why the room reads
   as machines in a space rather than as a page with panels on it, and it is
   the reason the share card is drawn as an object standing on a floor.

   THE ROOM IT COULD COLLAPSE INTO IS THE ADVENTURER'S GUILD, and this is the
   hardest case since The Den — because both rooms are MADE OF RULED ROWS, both
   have square corners, and in both of them nothing is rotated and nothing
   overlaps. That room's own section says its tidiness "cannot spread: the
   moment anywhere else starts looking orderly the joke has become a system",
   and a second orderly room is exactly what spreading looks like. What holds
   them apart is not the layout, because the layout really is the same:

     · THE GUILD HAS NO LIGHT SOURCE AND NO DEPTH. It is lit the way a
       photocopy of a document is lit — evenly, from nowhere — and nothing in
       it casts anything. This room is NOTHING BUT light and depth: one source
       per board, inside it, and every object in the hall separated from every
       other by a shadow.
     · THE GUILD IS A DOCUMENT. This is a MACHINE. A clerk filed that; an
       engineer bolted this together and somebody switched it on. Orderly is
       not one joke — a bureaucracy being orderly and a mechanism being orderly
       are different subjects, and the mechanism is the only one of the two
       that is allowed to be dark.
     · AND THE GUILD IS PALE. This is the far end of the street's own night.

   If anything in here ever loses its shadow, or if the boards ever sit flat on
   the page instead of standing in a hall, the two rooms have become one and it
   is this one that has to move.

   TYPE: Michroma sets the h1 and the nameboard over each board AND NOTHING
   ELSE — a very wide squared face is what machined signage looks like and what
   a paragraph must never be, which is the Doomscroll's blackletter lesson
   arriving in the one room whose actual subject is lettering. Space Mono sets
   every row, every date and every plate, because a flap board is a grid of
   cells with one character in each and a monospace IS that grid. The room's
   prose is the street's ordinary --sans, so only the machine has an accent.

   MOTION: the flaps settle once on arrival at Regular and riffle before
   settling at MAX. Both are KEYFRAMES rather than static transforms, which is
   deliberate: §3 kills animation at Gentle with !important and nothing can
   out-specify that by accident, so there is no room here for the fault
   check-gentle.py exists to catch. NOTHING FLASHES — the animations move
   scaleY and touch opacity nowhere, because three fast opacity steps in a row
   is a flicker whatever it is called, and Club Chronic's rule holds on the
   whole street. Both are one-shot: a board that riffled forever would be
   ambient motion nobody can turn off short of Gentle.                        */

.room-feed {
  background: var(--fd-hall); color: var(--fd-lamp);
  font-family: var(--sans);
}
/* DECIDED AT THE ROOM, once, which is the hole the Doomscroll left and the
   Playhouse had open since it opened: a room that only states a link colour on
   the components that happen to get one leaves every other link falling
   through to §2's `a`, and an inherited colour was never decided, so
   check-contrast.py has nothing to hold a pair for and the run passes while a
   paragraph sits under the bar. Every ground this room has is measured against
   this signal green. */
.room-feed a { color: var(--fd-signal); }
.room-feed a:hover { color: var(--fd-lamp); }
.room-feed .backlink { font-family: 'Space Mono', ui-monospace, monospace; font-size: 13px; letter-spacing: .04em; color: var(--fd-signal); }

.concourse { max-width: 1000px; margin: 0 auto; padding: 0 22px 74px; position: relative; }

/* THE POOL THE BOARDS THROW ON THE FLOOR. A fixed layer behind everything, so
   it is NOT in the DOM path of any text and check-contrast-live.py will read
   the hall underneath it — which is why the composite is measured by hand in
   check-contrast.py instead, at --fd-lamp 4% over --fd-hall, the same way the
   Chappell's rose window and the burrow's lamp pool are. It is light and not
   motion, so it stays at Gentle: the dial takes away the wobble, never the
   room. */
.concourse::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(120% 60% at 50% 32%, rgba(239,234,224,.04), rgba(239,234,224,0) 70%);
}

.concourse__top {
  display: flex; flex-wrap: wrap; gap: 12px 24px;
  justify-content: space-between; align-items: baseline; padding-top: 12px;
}

/* ── The hall's own head ─────────────────────────────────────────────────── */
.hall { margin: 30px 0 0; }
.hall .eyebrow {
  margin: 0 0 12px; font-family: 'Space Mono', ui-monospace, monospace;
  font-size: 12px; letter-spacing: .34em; text-transform: uppercase;
  color: var(--fd-dim);
}
.room-feed h1 {
  font-family: 'Michroma', var(--sans); font-weight: 400;
  font-size: clamp(25px, 5.4vw, 54px); line-height: 1.12;
  letter-spacing: .02em; text-transform: uppercase;
  margin: 0; color: var(--fd-lamp);
}
.hall__tagline {
  margin: 16px 0 0; max-width: 46ch;
  font-family: 'Space Mono', ui-monospace, monospace; font-size: 15px;
  line-height: 1.5; color: var(--fd-amber);
}
.hall__where {
  margin: 0; font-family: 'Space Mono', ui-monospace, monospace;
  font-size: 12.5px; letter-spacing: .05em; color: var(--fd-dim);
}
.room-feed .lede { margin: 20px 0 0; max-width: 66ch; font-size: 17.5px; line-height: 1.6; }
.room-feed .lede b { color: var(--fd-amber); font-weight: 700; }

/* The two generated lines. They sit on their own plate because what they say —
   the minute this was set — is the one claim on the page that stops being true
   on its own. */
.hall__set, .hall__shape {
  margin: 18px 0 0; max-width: 72ch;
  font-family: 'Space Mono', ui-monospace, monospace;
  font-size: 13.5px; line-height: 1.6; color: var(--fd-dim);
}
.hall__set {
  border-left: 3px solid var(--fd-amber); padding: 2px 0 2px 14px;
  color: var(--fd-lamp);
}
.hall__set b { color: var(--fd-amber); }
.hall__note { margin: 16px 0 0; max-width: 68ch; font-size: 15.5px; line-height: 1.6; color: var(--fd-dim); }
.hall__note b { color: var(--fd-lamp); }

/* ── A structural bay of the concourse ───────────────────────────────────── */
.girder { margin: 52px 0 0; border-top: 1px solid var(--fd-girder); padding-top: 22px; }
.room-feed h2 {
  font-family: 'Space Mono', ui-monospace, monospace; font-weight: 700;
  font-size: clamp(15px, 2.1vw, 19px); line-height: 1.3;
  letter-spacing: .1em; text-transform: uppercase;
  margin: 0 0 16px; color: var(--fd-amber);
}
.girder p { margin: 0 0 14px; max-width: 70ch; font-size: 16.5px; line-height: 1.62; }
.girder p b { color: var(--fd-lamp); font-weight: 700; }
.girder p:last-child { margin-bottom: 0; }

/* ── One board ───────────────────────────────────────────────────────────────
   Carcass, nameboard, rows, plate, and two legs under it. The legs are a
   ::after on the section, so a board really does stand on the floor of the
   hall rather than lying on the page — which is the whole separation from the
   job board one room over. */
.indicator {
  position: relative; margin: 46px 0 62px;
  background: var(--fd-enamel);
  border: 2px solid var(--fd-girder);
  border-radius: 3px;
  padding: 18px 18px 16px;
  box-shadow: 0 0 34px rgba(239,234,224,.05), 0 14px 0 -8px rgba(4,7,10,.85);
}
.indicator::after {
  content: ""; position: absolute; left: 12%; right: 12%; bottom: -22px; height: 22px;
  border-left: 7px solid var(--fd-girder); border-right: 7px solid var(--fd-girder);
  pointer-events: none;
}
.indicator__head { border-bottom: 1px solid var(--fd-girder); padding-bottom: 14px; }
.indicator__name {
  margin: 0; font-family: 'Michroma', var(--sans); font-weight: 400;
  font-size: clamp(12.5px, 1.7vw, 16px); line-height: 1.45;
  letter-spacing: .12em; text-transform: uppercase;
}
.indicator__name a { color: var(--fd-lamp); text-decoration-thickness: 1px; text-underline-offset: 5px; }
.indicator__name a:hover { color: var(--fd-amber); }
.indicator__what {
  margin: 10px 0 0; max-width: 72ch; font-size: 15px; line-height: 1.58;
  color: var(--fd-dim);
}
.indicator__also {
  margin: 14px 0 0; max-width: 72ch;
  font-family: 'Space Mono', ui-monospace, monospace;
  font-size: 13px; line-height: 1.55; color: var(--fd-dim);
}

/* ── The rows ────────────────────────────────────────────────────────────────
   An <ol> because newest-first is an order that means something. Each row is a
   flap: its own face, a hairline seam across the middle of the letters, and a
   shadow under it. The date column is fixed-width because on a board it is. */
.flaps { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 4px; }
.flap {
  position: relative; overflow: hidden;
  display: grid; grid-template-columns: 11ch 1fr; gap: 4px 18px; align-items: baseline;
  background: var(--fd-flap);
  border-radius: 2px;
  padding: 11px 14px 12px;
  box-shadow: 0 2px 0 rgba(4,7,10,.9);
  transform-origin: 50% 0;
  padding-bottom: 23px;
}
.flap__when {
  font-family: 'Space Mono', ui-monospace, monospace; font-weight: 700;
  font-size: 13.5px; letter-spacing: .02em; color: var(--fd-amber);
  font-variant-numeric: tabular-nums;
}
.flap__dest { min-width: 0; }
.flap__dest a {
  font-family: 'Space Mono', ui-monospace, monospace; font-weight: 700;
  font-size: 14.5px; line-height: 1.5; color: var(--fd-lamp);
  text-decoration-color: var(--fd-girder); text-underline-offset: 4px;
}
.flap__dest a:hover { color: var(--fd-amber); text-decoration-color: var(--fd-amber); }
/* THE LOWER LEAF OF THE FLAP, and the lit fold along the top of it. It sits at
   the FOOT of the row and crosses no letter, and getting here took two goes at
   the same mistake.

   A real Solari flap splits straight through the middle of the glyphs, so that
   is what this was first: one near-black hairline at top 50%. On the share card
   it read as a STRIKETHROUGH — the row lettered NEVER looked deleted rather
   than printed. Two solid faces with a lit fold between them fixed the card and
   then failed again on a phone, worse: a destination here WRAPS to two and
   three lines, top 50% of a tall row lands in the middle of the second line,
   and half the board looked struck out.

   THE REASON IS STRUCTURAL AND IS NOT GOING AWAY. A real board's rows are one
   line of fixed-width characters and cannot wrap; ours carry the titles people
   actually gave their pages, and those wrap. So the fold cannot live at a
   proportion of the row — there is no proportion that is not inside somebody's
   sentence. It lives at the foot, where it is the lower leaf of the flap
   showing under the lettering, which is a thing a flap board really does have
   and a thing no width can push into a word.

   SOLID rather than a gradient, deliberately: text over a gradient with no
   background-colour under it is exactly what check-contrast-live.py has to
   decline to measure. Nothing is set on this band at all, which is why it is in
   check-contrast.py's ORNAMENT rather than in a pair. */
.flap__split {
  position: absolute; left: 0; right: 0; bottom: 0; height: 11px;
  background: var(--fd-flap-lo);
  border-top: 1px solid var(--fd-fold);
}

/* ── The plate screwed to the foot of the board ──────────────────────────── */
.enamel {
  display: flex; flex-wrap: wrap; gap: 6px 22px; justify-content: space-between;
  margin: 16px 0 0; padding-top: 13px;
  border-top: 1px solid var(--fd-girder);
  font-family: 'Space Mono', ui-monospace, monospace;
  font-size: 12.5px; line-height: 1.5; color: var(--fd-dim);
}
.enamel__feed a { color: var(--fd-signal); }
.enamel__read { color: var(--fd-amber); }

/* ── The foot of the hall ───────────────────────────────────────────────── */
.concourse__foot { display: flex; flex-wrap: wrap; gap: 26px; align-items: flex-start; margin: 56px 0 0; border-top: 1px solid var(--fd-girder); padding-top: 24px; }
.concourse__col { flex: 1 1 330px; min-width: 0; }
.concourse__col p { margin: 0 0 14px; font-size: 16px; line-height: 1.6; }
.concourse__col p:last-child { margin-bottom: 0; }
.concourse__col--dial { flex: 0 1 340px; }

/* ── The board settling ─────────────────────────────────────────────────────
   scaleY only. No opacity anywhere in either keyframe: a flap that faded in
   and out three times would be a flicker under another name, and this street
   does not flicker at any setting. §3's `animation: none !important` is what
   switches both of these off at Gentle, which is why neither is written as a
   static transform. */
@keyframes fd-settle {
  from { transform: scaleY(.10); }
  to   { transform: scaleY(1); }
}
@keyframes fd-riffle {
  0%   { transform: scaleY(.08); }
  16%  { transform: scaleY(1); }
  30%  { transform: scaleY(.20); }
  46%  { transform: scaleY(1); }
  58%  { transform: scaleY(.34); }
  74%  { transform: scaleY(1); }
  84%  { transform: scaleY(.62); }
  100% { transform: scaleY(1); }
}
html[data-intensity="regular"] .flap { animation: fd-settle .34s cubic-bezier(.2,.8,.3,1) 1 both; }
html[data-intensity="max"]     .flap { animation: fd-riffle 1.05s linear 1 both; }
/* The stagger, so a board reads left to right and top to bottom the way one
   actually resets rather than all at once. :where() contributes no specificity,
   which keeps these delays from outranking anything §3 has to say. */
html[data-intensity="regular"] :where(.flap:nth-child(2)) { animation-delay: .06s; }
html[data-intensity="regular"] :where(.flap:nth-child(3)) { animation-delay: .12s; }
html[data-intensity="regular"] :where(.flap:nth-child(4)) { animation-delay: .18s; }
html[data-intensity="regular"] :where(.flap:nth-child(5)) { animation-delay: .24s; }
html[data-intensity="regular"] :where(.flap:nth-child(6)) { animation-delay: .30s; }
html[data-intensity="max"] :where(.flap:nth-child(2)) { animation-delay: .10s; }
html[data-intensity="max"] :where(.flap:nth-child(3)) { animation-delay: .20s; }
html[data-intensity="max"] :where(.flap:nth-child(4)) { animation-delay: .30s; }
html[data-intensity="max"] :where(.flap:nth-child(5)) { animation-delay: .40s; }
html[data-intensity="max"] :where(.flap:nth-child(6)) { animation-delay: .50s; }

/* The job marker lying on the floor of this room. §4 supplies the behaviour;
   this only says what colour a board's own ink is. */
.room-feed .quest__mark { border-color: var(--fd-girder); }
.room-feed .quest__panel { background: var(--fd-enamel); border-color: var(--fd-girder); }

/* Phones. WRITTEN LAST IN THE SECTION, on purpose: a media block placed above
   the rules it overrides loses exactly the declarations the base rule also sets
   and keeps the rest, which is the half-breakpoint the sound board shipped and
   which looks for all the world like a cache problem. The date stops being a
   column and becomes a line above the destination, because eleven characters of
   fixed-width date plus a title is not a thing that fits across 375px — and
   hiding the date to keep the grid would be the lite-version mistake arriving
   through a breakpoint. */
@media (max-width: 560px) {
  .flap { grid-template-columns: 1fr; gap: 6px; padding: 12px 13px 23px; }
  .indicator { padding: 15px 13px 14px; }
  .indicator::after { left: 9%; right: 9%; }
  .enamel { gap: 5px 14px; }
}

/* §28 ── THE GARDEN (through the gate in the wall, halfway down the street) ───
   NOT A ROOM AND NOT AN AREA EITHER. The campgrounds is a field with pitches on
   it and every pitch is a page of ours; this is a garden whose beds are OTHER
   SITES. Every bed here links straight out to a site we publish, because each
   of those is already its own room and rebuilding it behind a door on this
   street would be a worse copy of somewhere that exists.

   IT IS THE THIRD DAYLIT THING ON THE STREET and the third pale ground, so the
   separation is written in :root beside the palette rather than left to taste:
   the Hermitage's sun lands on a WALL and is warm, the Guild has no light
   source in it at all, and here the light is overhead and has come down THROUGH
   LEAVES -- so the pale is green, the shadows are small and hard and directly
   under things, and there is no wall in the room to stand in front of.

   A BED IS A PLANK ALONG THE FRONT, and that is the third shape this site has
   for a list of places. The street is a grid of outlined boxes with awnings on;
   the field is a line down the LEFT of each pitch, a post standing on open
   ground; a raised bed is an edge along the BOTTOM with soil above it, because
   you look into one from the path. Same job, three geometries, no two alike.

   THE DRAWINGS ARE TOLD APART BY FORM AND NOT BY COLOUR, which is the
   campground's grammar deliberately inverted. Out there each pitch gets ONE LIT
   COLOUR of its own -- the yurt emits, the hermitage catches, the meadow carries
   -- and that grammar runs out at about the fourth pitch, because there are not
   many kinds of light. A garden has as many kinds of GROWTH as you like. So
   every drawing here is in the same two greens, the same soil and the same one
   flower colour, and what tells them apart is the habit: a rhizome running
   sideways, an umbel coming into flower, a plant with no chlorophyll in it, a
   frame with seedlings under glass, a runner rooting a new plant beside itself,
   a seed head gone dry, a scramble over everything, a tendril reaching. Each
   one says something true about the site it stands for, and make-garden.py
   refuses a bed whose drawing it has not got and two beds that share one.

   THE ROOM MOVES AND THE CAMPGROUNDS DOES NOT, which is the other half of not
   being an area. That field has no ambient layer at any setting on purpose. The
   leaf shadow here is still at Gentle, drifts at Regular and drifts further at
   MAX -- a garden with no wind in it is simply a still afternoon, and the light
   itself is never taken away, because the light is not the wobble. Both
   animations are keyframes, so §3 kills them at Gentle with !important and the
   fault check-gentle.py exists to catch has nowhere to live here. Nothing
   flashes, pulses or strobes at any setting: Club Chronic's rule, holding in
   the brightest room on the street.

   A PALE ROOM ON A DARK STREET STATES ITS OWN LINK COLOUR, AT THE ROOM.
   `.garden a` below is that decision. It is the hole the Doomscroll left and
   the Playhouse had had open since it opened: an inherited link colour was
   never DECIDED, so check-contrast.py has no pair to hold and a run passes
   while a paragraph of links sits at 2.4 on paper.                            */

.garden {
  background: var(--gd-day); color: var(--gd-loam);
  font-family: 'Mulish', var(--sans);
}
.garden a { color: var(--gd-leaf); }
.garden a:hover { color: var(--gd-bloom); }
/* The loam, 14.60 on the path and 15.56 on a limewashed board, where yellow
   was 1.20 and 1.28. check-focus.py. */
.garden :focus-visible { outline-color: var(--gd-loam); }
/* The backlink drops Bungee, the campground's call: it is the one piece of
   shared furniture carrying a typeface, and the street's voice in here would be
   the only shouting thing in the garden. */
.garden .backlink {
  font-family: 'Mulish', var(--sans); font-size: 15px;
  letter-spacing: 0; color: var(--gd-leaf);
}
.garden p, .garden li { font-size: 16.5px; line-height: 1.68; }

/* THE LEAF SHADOW. Opaque blobs of one declared colour rather than a wash of
   something translucent, which is what keeps this the one room with no
   composite ground in it -- see the note in :root. It is FIXED, so the light
   stays where it is while the page scrolls under it, the way light does.
   The drift is a translate: check-gentle.py can only read rotation and skew out
   of a computed matrix, and a room must not ask a checker to take its word for
   something. arcade.js made the same call about its sprites. */
.gd-dapple {
  position: fixed; inset: -14vh -18vw; z-index: 0; pointer-events: none;
  background:
    radial-gradient(13% 9% at 9% 14%,  var(--gd-dapple) 0 70%, transparent 72%),
    radial-gradient(9% 7% at 19% 27%,  var(--gd-dapple) 0 68%, transparent 70%),
    radial-gradient(15% 8% at 33% 8%,  var(--gd-dapple) 0 70%, transparent 72%),
    radial-gradient(8% 11% at 44% 21%, var(--gd-dapple) 0 66%, transparent 68%),
    radial-gradient(12% 7% at 58% 12%, var(--gd-dapple) 0 70%, transparent 72%),
    radial-gradient(10% 9% at 71% 24%, var(--gd-dapple) 0 68%, transparent 70%),
    radial-gradient(14% 8% at 86% 9%,  var(--gd-dapple) 0 70%, transparent 72%),
    radial-gradient(9% 10% at 94% 22%, var(--gd-dapple) 0 66%, transparent 68%),
    radial-gradient(11% 8% at 6% 39%,  var(--gd-dapple) 0 70%, transparent 72%),
    radial-gradient(13% 9% at 24% 47%, var(--gd-dapple) 0 68%, transparent 70%),
    radial-gradient(8% 7% at 38% 38%,  var(--gd-dapple) 0 70%, transparent 72%),
    radial-gradient(12% 10% at 52% 49%, var(--gd-dapple) 0 66%, transparent 68%),
    radial-gradient(10% 8% at 66% 40%, var(--gd-dapple) 0 70%, transparent 72%),
    radial-gradient(14% 9% at 81% 48%, var(--gd-dapple) 0 68%, transparent 70%),
    radial-gradient(9% 8% at 96% 41%,  var(--gd-dapple) 0 70%, transparent 72%),
    radial-gradient(12% 8% at 12% 62%, var(--gd-dapple) 0 70%, transparent 72%),
    radial-gradient(9% 10% at 29% 71%, var(--gd-dapple) 0 66%, transparent 68%),
    radial-gradient(15% 8% at 46% 63%, var(--gd-dapple) 0 70%, transparent 72%),
    radial-gradient(10% 9% at 61% 73%, var(--gd-dapple) 0 68%, transparent 70%),
    radial-gradient(13% 8% at 77% 64%, var(--gd-dapple) 0 70%, transparent 72%),
    radial-gradient(9% 7% at 91% 72%,  var(--gd-dapple) 0 70%, transparent 72%),
    radial-gradient(11% 9% at 8% 86%,  var(--gd-dapple) 0 68%, transparent 70%),
    radial-gradient(14% 8% at 27% 93%, var(--gd-dapple) 0 70%, transparent 72%),
    radial-gradient(9% 10% at 43% 84%, var(--gd-dapple) 0 66%, transparent 68%),
    radial-gradient(12% 8% at 59% 94%, var(--gd-dapple) 0 70%, transparent 72%),
    radial-gradient(10% 9% at 74% 85%, var(--gd-dapple) 0 68%, transparent 70%),
    radial-gradient(13% 8% at 89% 93%, var(--gd-dapple) 0 70%, transparent 72%);
}
html[data-intensity="regular"] .gd-dapple { animation: gd-breeze 34s ease-in-out infinite alternate; }
html[data-intensity="max"]     .gd-dapple { animation: gd-breeze 17s ease-in-out infinite alternate; }
@keyframes gd-breeze {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(2.4vw, 1.1vh, 0); }
}
/* Everything else stands on the path rather than in the light. */
.garden main, .garden footer { position: relative; z-index: 1; }

.garden h1 {
  font-family: 'Faustina', Georgia, serif; font-weight: 600;
  font-size: clamp(40px, 7.2vw, 76px); line-height: 1.04;
  color: var(--gd-loam); margin: 10px 0 0;
}
.garden h2 {
  font-family: 'Faustina', Georgia, serif; font-weight: 600;
  font-size: clamp(22px, 3.4vw, 31px); line-height: 1.14;
  color: var(--gd-leaf); margin: 42px 0 12px;
}
.garden h3 {
  font-family: 'Faustina', Georgia, serif; font-weight: 600;
  font-size: 25px; line-height: 1.16; color: var(--gd-loam); margin: 0;
}
.garden .lede {
  font-family: 'Faustina', Georgia, serif; font-size: clamp(20px, 2.6vw, 24px);
  line-height: 1.5; color: var(--gd-loam-2); max-width: 50ch; margin: 18px 0 0;
}
.garden .trailmark {
  margin: 0; font-size: 14px; letter-spacing: .04em; color: var(--gd-loam-2);
}
.gd-note { margin: 0 0 14px; max-width: 66ch; color: var(--gd-loam-2); }
.gd-note b, .gd-note strong, .garden .lede b { color: var(--gd-loam); }
.gd-note:last-child { margin-bottom: 0; }

/* A LIMEWASHED PLANK LAID ON THE PATH. It is brighter than the ground and
   therefore invisible on its own -- 1.07 -- so it is carried by a hairline and
   by a hard shadow directly beneath it. HARD, AND STRAIGHT DOWN: the sun is
   overhead in this room, which is exactly what stops these boards reading as
   the Hermitage's panels, where a low sun throws everything sideways and soft.
   No blur in this section anywhere. */
.gd-plank {
  position: relative; margin: 28px 0 0; padding: 20px 24px;
  background: var(--gd-board); border: 1px solid var(--gd-edge);
  box-shadow: 0 5px 0 rgba(43, 32, 19, .14);
}
.gd-plank h2 { margin-top: 0; }
.gd-plank ul { margin: 0; padding: 0 0 0 20px; color: var(--gd-loam-2); }
.gd-plank li { margin: 0 0 10px; }
.gd-plank li:last-child { margin-bottom: 0; }
.gd-plank li::marker { color: var(--gd-leaf-2); }
.gd-plank li b { color: var(--gd-loam); }

/* THE BEDS. One column of wide low bands, each with the soil above its own
   front plank and the plant standing at the left end of it. NOT A GRID OF
   EQUAL BOXES, which is the street, and not a post on open ground, which is
   the field. */
.gd-beds { list-style: none; margin: 26px 0 0; padding: 0; }
.gd-bed {
  display: flex; flex-wrap: wrap; gap: 6px 28px; align-items: center;
  padding: 6px 0 16px; border-bottom: 7px solid var(--gd-loam-2);
  margin: 0 0 26px;
}
.gd-bed:last-child { margin-bottom: 0; }
.gd-bed__art { flex: 0 1 270px; line-height: 0; }
.gd-bed__art svg { display: block; width: 100%; height: auto; }
.gd-bed__sign { flex: 1 1 30ch; min-width: 0; }

/* The label on a stake. A small limewashed board with the name written on it in
   the same hand as the garden's own name, because that is the claim this room
   makes about type: there is no signwriter here, only labels. */
.gd-bed__label {
  display: inline-block; margin: 0 0 4px; padding: 7px 14px 8px;
  background: var(--gd-board); border: 1px solid var(--gd-edge);
  box-shadow: 0 4px 0 rgba(43, 32, 19, .14);
}
.gd-bed__label h3 a { color: var(--gd-loam); text-decoration-color: var(--gd-leaf-2); text-underline-offset: 4px; }
.gd-bed__label h3 a:hover { color: var(--gd-leaf); }
.gd-bed__host {
  display: block; margin: 5px 0 0; font-size: 13px;
  letter-spacing: .06em; color: var(--gd-loam-2);
}
.gd-bed__what { margin: 12px 0 0; max-width: 58ch; color: var(--gd-loam-2); }
.gd-bed__what b { color: var(--gd-loam); }
/* WHO ELSE'S HANDS ARE IN IT, on the face of the bed rather than only in the
   liner notes -- a credit filed where nobody reads it is the one habit this
   street did not drop. make-garden.py refuses a bed without this line. */
.gd-bed__with {
  margin: 9px 0 0; font-family: 'Faustina', Georgia, serif; font-style: italic;
  font-size: 15.5px; color: var(--gd-loam-2);
}
.gd-bed__with b { font-style: normal; font-weight: 600; color: var(--gd-loam); }

/* THE GARDEN NEXT DOOR, AND IT IS THE FOURTH GEOMETRY FOR A LIST OF PLACES.
   The street is a grid of outlined boxes with awnings; the field is a line down
   the LEFT of each pitch; a bed is an edge along the BOTTOM with soil above it.
   A plot is a pair of NARROW COLUMNS SIDE BY SIDE with the drawing above its
   own name, because you are looking across at them rather than down into them
   from a path, and things seen from the far side of a boundary are seen end-on
   and small.

   THE RULE UNDER A PLOT IS DOUBLE AND THE RULE UNDER A BED IS SOLID, which is
   the same echo doing opposite work: a bed's heavy plank repeats the plank
   drawn along the front of its soil, and a plot's two lines repeat the two
   winding ivy stems drawn across the foot of its picture. Same ink, same
   weight, one object each.

   AND A PLOT'S NAME IS NOT ON A LIMEWASHED BOARD. Every bed's label is a stake
   driven into our own ground; nobody gets to go and put a label in somebody
   else's garden, so the name over there is simply written down. That is the
   whole visual difference and it is doing the argument's work: the plots are
   Helen Edgar's, make-garden.py refuses one that turns up on our own roster,
   and the drawing stops where the ivy runs because we do not know the shape of
   her soil. No new colour in any of this -- the ivy, the stars caught in it,
   the plants and every word are in the room's own inks on the room's own path.

   THE BOUNDARY WAS A WOVEN FENCE FOR AN AFTERNOON AND IT IS IVY BECAUSE HELEN
   ASKED. She was right about more than the picture: a fence says KEPT OUT and
   ivy says THIS IS AS FAR AS WE CAN SEE, and the second one is what that line
   was always doing. The stars in it are glimmers and not a sky -- this room is
   still midday, nothing is lit by them, and nothing ambient was added to the
   page, so the one daylit garden on the street stays daylit. */
.gd-over {
  list-style: none; display: flex; flex-wrap: wrap;
  gap: 24px 34px; margin: 24px 0 0; padding: 0;
}
.gd-plot {
  flex: 1 1 28ch; min-width: 0;
  padding: 0 0 16px; border-bottom: 7px double var(--gd-loam-2);
}
.gd-plot__art { max-width: 300px; margin: 0 0 12px; line-height: 0; }
.gd-plot__art svg { display: block; width: 100%; height: auto; }
.gd-plot__sign { min-width: 0; }
.gd-plot__label h3 a {
  color: var(--gd-loam); text-decoration-color: var(--gd-leaf-2);
  text-underline-offset: 4px;
}
.gd-plot__label h3 a:hover { color: var(--gd-leaf); }
.gd-plot__host {
  display: block; margin: 5px 0 0; font-size: 13px;
  letter-spacing: .06em; color: var(--gd-loam-2);
}
.gd-plot__what, .gd-plot__habit { margin: 10px 0 0; color: var(--gd-loam-2); }
.gd-plot__what b, .gd-plot__habit b { color: var(--gd-loam); }
/* WHOSE IT IS, AND WHAT OF IT IS ALREADY OVER HERE. The beds' who-line is one
   italic sentence saying who helped us; a plot has two, because the second one
   is the reason a neighbour's garden is on a page about ours at all, and
   make-garden.py refuses a plot without it. */
.gd-plot__whose, .gd-plot__here {
  margin: 9px 0 0; font-family: 'Faustina', Georgia, serif; font-style: italic;
  font-size: 15.5px; color: var(--gd-loam-2);
}
.gd-plot__whose b, .gd-plot__here b {
  font-style: normal; font-weight: 600; color: var(--gd-loam);
}

/* THE GARDEN SPIDER. It sits in the middle of the garden rather than at the
   gate, because it is not the way in -- and the panel says so in the site's own
   words: a spider is a guide to the garden and never a replacement for it, and
   its best answer is an entrance. The drawing is ours and is an orb weaver in
   its web, drawn in the garden's inks like everything else here. IT DOES NOT
   MOVE AT ANY SETTING, and that is not the campground's rule arriving by the
   back door: a web that twitched when you were not looking at it is a different
   feeling entirely, in a room whose whole argument is that you may wander. */
.gd-spider {
  display: flex; flex-wrap: wrap; gap: 10px 30px; align-items: center;
  margin: 28px 0 0; padding: 20px 24px;
  background: var(--gd-board); border: 1px solid var(--gd-edge);
  box-shadow: 0 5px 0 rgba(43, 32, 19, .14);
}
.gd-spider__art { flex: 0 1 220px; line-height: 0; }
.gd-spider__art svg { display: block; width: 100%; height: auto; }
.gd-spider__say { flex: 1 1 30ch; min-width: 0; }
.gd-spider__say h2 { margin: 0 0 10px; }
.gd-spider__ask {
  display: inline-block; margin: 14px 0 0; padding: 12px 20px;
  min-height: 44px;
  background: var(--gd-leaf); color: var(--gd-board);
  font-family: 'Faustina', Georgia, serif; font-weight: 600; font-size: 17px;
  text-decoration: none; border: 1px solid var(--gd-leaf);
}
.garden .gd-spider__ask { color: var(--gd-board); }
.gd-spider__ask:hover { background: var(--gd-loam); border-color: var(--gd-loam); }
.garden .gd-spider__ask:hover { color: var(--gd-board); }

/* HOW TO START ONE OF YOUR OWN. A row of sown drills rather than a numbered
   list of steps: the first one needs no software at all, and our own field
   guide says to stop wherever it stops being useful, so this is not a ladder.
   Each drill is a line in the soil with one thing sown in it. */
.gd-drills { list-style: none; margin: 22px 0 0; padding: 0; }
.gd-drill {
  padding: 0 0 14px 22px; margin: 0 0 16px;
  border-left: 3px solid var(--gd-leaf-2);
  border-bottom: 1px dashed var(--gd-edge);
}
.gd-drill:last-child { margin-bottom: 0; }
.gd-drill h3 { margin: 0 0 6px; font-size: 21px; }
.gd-drill p { margin: 0; max-width: 62ch; color: var(--gd-loam-2); }

/* THE HEDGE AT THE FOOT OF THE GARDEN, with the gate you came in by drawn into
   it. The field's boundary is a stream and the yurt keeps the trees, so a
   garden takes the hedge -- the same division of the drawing that keeps those
   two apart, arriving a page later. Drawn in the page rather than in this file,
   because it is a picture of a place and not a border: see the-garden.html. */
.gd-hedge { margin: 34px 0 0; line-height: 0; }
.gd-hedge svg { display: block; width: 100%; height: auto; }

/* The garden's own quest marker sits on the path like every other, and the
   panel borrows this room's ink and ground from §4. Nothing to do here but let
   it. */


/* §29 ── ROOM: The Zibaldone ──────────────────────────────────────────────────
   A commonplace book left open on a desk. Asked for by somebody in our
   community as a quote bank; built as the thing that has been doing that job
   since the fourteenth century, which our own glossary already had an entry
   for. See the palette note in §2 for what keeps this apart from the four
   other paper rooms on this street -- the short version is that every one of
   those is PRINTED and this one is WRITTEN, and that not one of them is lit
   from anywhere you could point at while this one is lit from the left at
   desk height.

   THE RAKING LIGHT IS THE ROOM AND IT IS DONE THREE TIMES, because a light you
   can locate has three consequences and leaving any of them out makes it
   decoration. The paper is brighter on the left than the right. Every sheet
   casts a shadow DOWN AND RIGHT, away from it. And the fold has a gradient in
   it, which is the only reason this reads as a bound book rather than as a
   sheet of paper -- The Doomscroll is the same colours with no fold, and the
   fold is the whole difference.

   NOTHING IN HERE IS A COMPOSITE GROUND. The raking light is a gradient, which
   means the colour under a word at the left edge of a sheet is not the colour
   under a word at the right edge -- exactly the thing check-contrast.py cannot
   reconstruct and check-contrast-live.py declines to guess at, because a
   gradient with no background-colour under it is what made that tool report
   222 pieces of pale text as near-black on near-black. So EVERY SHEET CARRIES
   A FLAT background-color AS WELL, and the gradient is painted over it in
   background-image. The flat colour is the darker end. That makes the measured
   pair the honest one rather than the flattering one, and it makes the sheets
   measurable at all.

   THE TILTS ARE :where()-SCOPED so they cannot climb above §3's gentle reset.
   That reset is (0,2,1) and a room's own `.thing:nth-child(even)` is (0,2,0),
   which loses -- but only just, and it has already been got wrong twice on
   this street, once on Enid's wall and once in the Faery Yurt, where a
   windowsill was still rotating at Gentle a day after the room shipped. Inside
   :where() the selector weighs nothing at all and the argument cannot recur.

   AND THE LINK COLOUR IS DECLARED AT THE ROOM, on both grounds this room
   actually has. That is the hole The Doomscroll left and the Playhouse was
   found to have been carrying since it opened: a colour nobody DECIDED leaves
   no pair for check-contrast.py to hold, so the run passes while a paragraph
   of links is illegible. This is a pale room on a near-black street, so the
   base stylesheet's pink would arrive here at about 2.4 -- and the top line
   sits on the DESK rather than on the paper, which is a second ground and
   therefore a second decision. Both are made here, once, where the room is. */

body.room-zibaldone {
  background-color: var(--zb-desk);
  /* Walnut, across the grain. Very low contrast on purpose: it is the surface
     the book is lying on and it is not supposed to be read. */
  background-image:
    repeating-linear-gradient(92deg, transparent 0 7px, rgba(0, 0, 0, .18) 7px 8px),
    repeating-linear-gradient(92deg, rgba(255, 255, 255, .025) 0 23px, transparent 23px 47px);
  color: var(--zb-oak);
  font-family: 'Lora', Georgia, serif;
}

.zb-desk { max-width: 1120px; margin: 0 auto; padding: 0 20px 64px; }

/* The two grounds, and the two link decisions. */
.room-zibaldone a { color: var(--zb-rubric); text-underline-offset: 3px; }
.room-zibaldone a:hover, .room-zibaldone a:focus-visible { color: var(--zb-aniline); }
/* The paper takes the iron-gall ink, 9.28 and 10.35 where yellow was 1.03.
   Only the paper: the desk the leaves lie on is dark and keeps the yellow. */
.room-zibaldone :is(.zb-sheet, .zb-flyleaf, .zb-leaf) :focus-visible { outline-color: var(--zb-iron); }
/* The sign-off is the one shared line that lies on the desk rather than on
   paper, so it takes the paper's own colours: the room's oak and rubric are
   1.07 and 1.74 on the wood, and the laid paper is 9.70 and 10.83 at the
   desk's lightest. The desk keeps the yellow ring. */
.room-zibaldone .signoff { color: var(--zb-laid-2); }
.room-zibaldone .signoff a { color: var(--zb-laid); }

.zb-topline {
  display: flex; flex-wrap: wrap; gap: 10px 18px;
  justify-content: space-between; align-items: baseline;
  padding: 10px 2px 22px;
}
.zb-topline a, .room-zibaldone .zb-topline .backlink { color: var(--zb-tape); }
.zb-topline a:hover, .room-zibaldone .zb-topline .backlink:hover { color: #fff; }
.zb-topline__note {
  margin: 0; font-family: 'Kalam', cursive; font-size: 15px; color: var(--zb-tape);
}

/* ── A sheet ─────────────────────────────────────────────────────────────────
   Laid paper: chain lines far apart, laid lines close together, and the tooth
   the raking light catches. All three are background-images over a flat
   background-color, for the reason in the section note. */
.zb-flyleaf, .zb-sheet {
  position: relative;
  background-color: var(--zb-laid);
  background-image:
    repeating-linear-gradient(90deg, rgba(120, 100, 66, .07) 0 1px, transparent 1px 27px),
    repeating-linear-gradient(0deg, rgba(120, 100, 66, .045) 0 1px, transparent 1px 4px),
    linear-gradient(100deg, rgba(255, 252, 244, .85) 0%, rgba(255, 252, 244, 0) 46%);
  box-shadow: 7px 9px 0 rgba(0, 0, 0, .22), 0 1px 0 rgba(255, 255, 255, .5) inset;
  border-radius: 2px 5px 5px 2px;
  padding: 30px 34px 34px 46px;
  margin: 0 0 26px;
}
/* THE FOLD. This is the one declaration that makes the room a book instead of
   a page, which is why it is on every sheet rather than once on the page: a
   spread is bound at the left, and a reader scrolling past six sheets should
   pass six folds. It carries no text and is in ORNAMENT with its measurement. */
.zb-flyleaf::before, .zb-sheet::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 22px;
  background: linear-gradient(90deg, var(--zb-gutter) 0%, rgba(201, 182, 147, .45) 38%, transparent 100%);
  border-radius: 2px 0 0 2px;
  pointer-events: none;
}

.zb-flyleaf { padding-bottom: 40px; }
.zb-eyebrow {
  margin: 0 0 14px; font-family: 'Kalam', cursive; font-size: 16px;
  color: var(--zb-pencil);
}
.room-zibaldone h1 {
  margin: 0; font-family: 'EB Garamond', Georgia, serif; font-weight: 600;
  font-size: clamp(44px, 8vw, 78px); line-height: 1.02; letter-spacing: -0.5px;
  color: var(--zb-oak);
}
.zb-tagline {
  margin: 10px 0 0; font-family: 'EB Garamond', Georgia, serif; font-style: italic;
  font-size: clamp(21px, 3vw, 27px); color: var(--zb-rubric);
}
.zb-lede { margin: 16px 0 0; font-size: 17.5px; line-height: 1.62; max-width: 62ch; }
.room-zibaldone h2 {
  margin: 0 0 14px; font-family: 'EB Garamond', Georgia, serif; font-weight: 600;
  font-size: 31px; line-height: 1.12; color: var(--zb-oak);
}
.room-zibaldone h2::after {
  content: ""; display: block; width: 74px; height: 2px; margin-top: 9px;
  background: var(--zb-rubric);
}
.zb-sheet p { max-width: 64ch; }

/* The keeper's own asides, in the hand. Never a quotation -- the generator
   refuses one, and this rule is why that refusal has teeth. */
.zb-hand {
  font-family: 'Kalam', cursive; font-size: 16.5px; line-height: 1.5;
  color: var(--zb-pencil); margin: 18px 0 0; padding-left: 15px;
  border-left: 2px solid var(--zb-tape);
}

/* ── The house rules ─────────────────────────────────────────────────────── */
.zb-rule {
  display: flex; flex-wrap: wrap; gap: 6px 26px; align-items: baseline;
  margin: 22px 0; padding: 20px 22px;
  background: var(--zb-laid-2);
  border: 1px solid var(--zb-gutter); border-left: 5px solid var(--zb-rubric);
  border-radius: 3px;
}
.zb-rule__n {
  margin: 0; flex: 0 0 auto;
  font-family: 'EB Garamond', Georgia, serif; font-weight: 600; font-size: 40px;
  line-height: 1; color: var(--zb-rubric);
}
.zb-rule__why { margin: 0; flex: 1 1 320px; font-size: 16px; line-height: 1.55; }
.room-zibaldone code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .88em;
  background: rgba(99, 90, 75, .14); padding: 1px 5px; border-radius: 3px;
}
.zb-rules { margin: 20px 0 0; padding-left: 22px; max-width: 66ch; }
.zb-rules li { margin-bottom: 15px; line-height: 1.6; }

/* ── The quire ───────────────────────────────────────────────────────────── */
.zb-quire {
  list-style: none; margin: 22px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(305px, 1fr)); gap: 24px;
}

/* A leaf is a slip laid ON the page, so it has its own paper, its own shadow
   away from the light, and a strip of gummed paper holding it down. */
.zb-leaf {
  position: relative;
  background: var(--zb-laid-2);
  border: 1px solid var(--zb-gutter);
  border-radius: 2px;
  padding: 26px 20px 18px;
  box-shadow: 4px 5px 0 rgba(0, 0, 0, .13);
}
.zb-leaf::before {
  content: ""; position: absolute; top: -8px; left: 50%; width: 76px; height: 17px;
  margin-left: -38px; background: var(--zb-tape); opacity: .9;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .12);
}

/* THE ANGLES ARE :where()-SCOPED. See the section note: §3's gentle reset is
   (0,2,1) and this would otherwise be (0,2,0), which is one step from being
   the Faery Yurt's windowsill all over again. Inside :where() it weighs
   nothing, so Gentle cannot lose. */
:where(.zb-quire .zb-leaf:nth-child(3n+1)) { transform: rotate(-0.55deg); }
:where(.zb-quire .zb-leaf:nth-child(3n+2)) { transform: rotate(0.4deg); }
:where(.zb-quire .zb-leaf:nth-child(4n+3)) { transform: rotate(0.75deg); }
/* AND THE ROOM RESETS ITS OWN, because §3's reset names .tilt-a to .tilt-d and
   nothing else -- it is a reset for the shared tilt classes, not a reset for
   the word `transform`. :where() guarantees this rule cannot be OUT-ranked; it
   does not conjure a rule to outrank it. check-gentle.py found all seven leaves
   still lying at their angles at Gentle, which is exactly what that tool is
   for and exactly the way it found the Faery Yurt's windowsill. */
html[data-intensity="gentle"] .zb-leaf { transform: none; }

.zb-leaf__pressed {
  float: right; width: 76px; height: 76px; margin: 0 0 6px 12px; shape-outside: circle(50%);
}
.zb-leaf__pressed svg { width: 100%; height: 100%; display: block; }

.zb-leaf__quote {
  margin: 0; font-size: 22px; line-height: 1.42; color: var(--zb-nib, var(--zb-oak));
}
/* The inks. An ink is a colour somebody sat down with, so the leaf sets one
   custom property and everything written on it takes it from there rather
   than each rule naming a colour -- which is how a component grows a second
   child that nobody rescopes. */
.zb-leaf--oak     { --zb-nib: var(--zb-oak); }
.zb-leaf--iron    { --zb-nib: var(--zb-iron); }
.zb-leaf--violet  { --zb-nib: var(--zb-aniline); }
.zb-leaf--rubric  { --zb-nib: var(--zb-rubric); }

/* The three text faces, sized against each other rather than set to one number:
   EB Garamond runs small and Lora runs large at the same point size, so equal
   numbers would be unequal type. */
.zb-leaf--eb-garamond .zb-leaf__quote { font-family: 'EB Garamond', Georgia, serif; font-size: 25.5px; }
.zb-leaf--newsreader  .zb-leaf__quote { font-family: 'Newsreader', Georgia, serif;  font-size: 23px; }
.zb-leaf--lora        .zb-leaf__quote { font-family: 'Lora', Georgia, serif;        font-size: 21px; }

.zb-leaf__cite {
  margin: 13px 0 0; font-size: 14px; line-height: 1.5; color: var(--zb-pencil);
  padding-top: 11px; border-top: 1px solid var(--zb-gutter); clear: both;
}
.zb-leaf__cite b { color: var(--zb-oak); }
.zb-leaf__for { margin: 11px 0 0; font-size: 15.5px; line-height: 1.5; }
.zb-leaf__tag {
  font-family: 'Kalam', cursive; font-weight: 700; font-size: 13px;
  color: var(--zb-rubric); letter-spacing: .3px; margin-right: 5px;
}
.zb-leaf__hand {
  margin: 12px 0 0; font-family: 'Kalam', cursive; font-size: 15.5px; line-height: 1.45;
  color: var(--zb-pencil);
}

/* The provenance tab. A native <details>, so it is focusable, announced and
   works with scripts off -- the guild's marker rule, arriving where what is
   behind the tab is the room's own evidence. */
.zb-leaf__prov { margin-top: 14px; }
.zb-leaf__prov > summary {
  cursor: pointer; list-style: none; display: flex; flex-wrap: wrap; gap: 8px;
  align-items: center; padding: 7px 0 0; border-top: 1px dashed var(--zb-gutter);
}
.zb-leaf__prov > summary::-webkit-details-marker { display: none; }
.zb-leaf__badge {
  font-family: 'Kalam', cursive; font-weight: 700; font-size: 12.5px;
  color: var(--zb-laid); background: var(--zb-pencil);
  padding: 2px 9px; border-radius: 2px;
}
.zb-leaf__when { font-size: 12.5px; color: var(--zb-pencil); font-style: italic; }
.zb-leaf__prov > summary::after {
  content: "read the check"; margin-left: auto;
  font-size: 12.5px; color: var(--zb-rubric); text-decoration: underline;
}
.zb-leaf__prov[open] > summary::after { content: "close"; }
.zb-leaf__prov p { margin: 10px 0 0; font-size: 14px; line-height: 1.55; color: var(--zb-pencil); }
.zb-leaf__pasted { font-style: italic; }

/* ── The attribution slip ────────────────────────────────────────────────── */
.zb-slip { margin: 22px 0 0; }
.zb-slip__tasl {
  margin: 0 0 20px; padding: 14px 16px; font-size: 15.5px; line-height: 1.55;
  background: var(--zb-laid-2); border: 1px dashed var(--zb-gutter); border-radius: 3px;
}
.zb-slip__row { margin: 0 0 17px; max-width: 62ch; }
.zb-slip__row--extra { border-left: 3px solid var(--zb-aniline); padding-left: 13px; }
.zb-slip label {
  display: flex; flex-wrap: wrap; gap: 5px 9px; align-items: baseline;
  font-family: 'EB Garamond', Georgia, serif; font-weight: 600; font-size: 19px;
  color: var(--zb-oak);
}
.zb-slip__req {
  font-family: 'Kalam', cursive; font-weight: 700; font-size: 12px;
  color: var(--zb-rubric);
}
.zb-slip__key {
  margin-left: auto; font-family: 'Kalam', cursive; font-size: 13px;
  color: var(--zb-pencil);
}
.zb-slip__help { margin: 4px 0 7px; font-size: 14px; line-height: 1.5; color: var(--zb-pencil); max-width: 60ch; }
.zb-slip input[type="text"], .zb-slip textarea, .zb-slip__out textarea {
  width: 100%; font: inherit; font-size: 16px; font-family: 'Lora', Georgia, serif;
  color: var(--zb-oak); background: var(--zb-laid);
  border: 1px solid var(--zb-pencil); border-radius: 2px; padding: 9px 11px;
}
.zb-slip textarea, .zb-slip__out textarea { line-height: 1.5; resize: vertical; }
.zb-slip__act { display: flex; flex-wrap: wrap; gap: 12px 18px; align-items: center; margin: 22px 0 0; }
.zb-slip__copy {
  cursor: pointer; font-family: 'Kalam', cursive; font-weight: 700; font-size: 17px;
  padding: 11px 22px; border-radius: 3px;
  color: var(--zb-laid); background: var(--zb-oak); border: 2px solid var(--zb-oak);
}
.zb-slip__copy:hover:not(:disabled) { background: var(--zb-rubric); border-color: var(--zb-rubric); }
.zb-slip__copy:disabled { opacity: .45; cursor: not-allowed; }
.zb-slip__said { margin: 0; font-size: 15px; color: var(--zb-oak); }
.zb-slip__out { margin: 18px 0 0; }
.zb-slip__out label { font-size: 16px; margin-bottom: 6px; }
.zb-slip__nojs {
  margin: 18px 0 0; padding: 14px 16px; font-size: 15px; line-height: 1.55;
  background: var(--zb-laid-2); border-left: 4px solid var(--zb-aniline);
}

/* ── The foot ────────────────────────────────────────────────────────────── */
.zb-foot { display: flex; flex-wrap: wrap; gap: 24px 30px; align-items: flex-start; }
.zb-foot__who { flex: 1 1 380px; }
.zb-foot__dial { flex: 0 1 340px; }

/* MAX is the lamp moving, and it is the only ambient thing in this room. A
   low sun crossing a desk is slow, and nothing flashes: this is a 90-second
   drift of one translucent gradient, at a contrast small enough that what it
   is doing is making the paper feel lit rather than making anything blink.
   §3 takes every animation away at Gentle with !important, which is what makes
   one declaration here safe. Club Chronic's rule holds: no flicker, no strobe,
   no pulsing, at any setting. */
html[data-intensity="max"] .zb-flyleaf, html[data-intensity="max"] .zb-sheet {
  background-size: auto, auto, 260% 100%;
  animation: zb-lamp 90s ease-in-out infinite;
}
@keyframes zb-lamp {
  0%, 100% { background-position: 0 0, 0 0, 0% 0; }
  50%      { background-position: 0 0, 0 0, 42% 0; }
}


/* §30 ── ROOM: The Rabbit Hole ────────────────────────────────────────────────
   A shaft with things hanging in it. Ryan's brief, 2026-09-22: a room on rabbit
   holing, leading with our own glossary entry, carrying that page's videos,
   some public domain Alice art, and a feed your head section.

   THE ROOM IS A DESCENT AND THE PAGE IS THE DESCENT. Not a metaphor applied to
   a layout: the ground actually darkens from the mouth of the hole to the foot
   of the document, every block is a thing you pass rather than a thing you sit
   at, and the further down you read the less light there is on it. See the
   palette note in §2 for what keeps this apart from The Latibulum, which is
   the same floor plan, and from The Mopery and The Doomscroll, which are the
   same colours and the same motion respectively.

   NOTHING IN HERE IS FURNITURE, and that is the load-bearing difference from
   the burrow. A burrow has a chair in it. A shaft has ledges, and a ledge is a
   place a thing has come to rest on the way down rather than a place anybody
   sat down. So every panel is flush to the wall, none of them has a foot, and
   not one of them casts a shadow downward onto anything -- there is nothing
   below to catch it.

   EVERY BLOCK THAT CARRIES TEXT SITS ON A FLAT GROUND OF ITS OWN, and the body
   gradient carries nothing but the header's own lines. That is the Zibaldone's
   lesson taken one step further: a gradient with no background-color under it
   is what made check-contrast-live.py report 222 pieces of pale text as
   near-black on near-black, and the fix there was a flat colour under the
   gradient. Here the gradient runs the height of the DOCUMENT rather than the
   height of a sheet, so the colour under a word depends on how far somebody
   has scrolled -- which no flat colour can honestly stand in for. The panels
   solve it instead, and the only type left on the gradient is at the very top,
   where the flat body colour and the gradient's first stop are the same value.

   THE ENGRAVINGS ARE THE ONLY BRIGHT THING DOWN HERE AND THAT IS WHAT THEY
   PHYSICALLY ARE: black ink on white paper. Putting them on a paper mat is not
   a frame added for looks, it is the object -- and it is also what makes the
   caption measurable, because a caption on a mat has a flat ground while a
   caption floating on the shaft would not.

   NOTHING IN THIS ROOM MOVES AT ANY SETTING except the ambient wash, which §3
   takes away at Gentle through .glow like every other room's. There is no
   tilt anywhere in here, which is deliberate rather than an omission: a
   rotation is indistinguishable from a tilt to check-gentle.py, which can only
   read the computed matrix -- The Oracle Deck's lozenge and arcade.js's sprites
   both made that call. A room with no transform in it cannot get that wrong.

   AND THE WORDS TO THE SONG ARE NOT HERE. The glossary entry this room is
   built on prints all of them; tools/make-rabbit-hole.py refuses a lyric field
   and refuses any value shaped like verse, for the reason make-zibaldone.py
   refuses a song outright. The section titles are phrases and are credited as
   phrases. Do not put the words back: the room looks thin without them, which
   is exactly why the refusal is in a tool and not in a comment.               */

body.room-rabbit-hole {
  /* The flat colour is the LIGHTEST end, which is the worse case for pale type
     and therefore the honest one. See the palette note in §2. */
  background-color: var(--rh-slate);
  background-image: linear-gradient(180deg,
    var(--rh-slate) 0,
    var(--rh-slate-2) 46%,
    var(--rh-deep) 100%);
  background-attachment: fixed;
  color: var(--rh-chalk);
  font-family: 'Jost', system-ui, sans-serif;
  font-size: 17.5px;
  line-height: 1.62;
}

/* The link colour is DECLARED AT THE ROOM, on both grounds this room has: the
   shaft and the paper mats. That is the hole The Doomscroll left and the
   Playhouse had been carrying since it opened -- a colour nobody DECIDED
   leaves no pair for check-contrast.py to hold, so the run passes while a
   paragraph of links is illegible. Brass is 6.74 and up on the dark and 1.83
   on the paper, so the mats get their own decision rather than inheriting a
   flattering one. */
.room-rabbit-hole a { color: var(--rh-brass); text-underline-offset: 3px; }
.room-rabbit-hole a:hover,
.room-rabbit-hole a:focus-visible { color: #fff; }
.room-rabbit-hole .rh-cut__cap a,
.room-rabbit-hole .rh-cut__cap a:visited { color: var(--rh-brass-dark); }
.room-rabbit-hole .rh-cut__cap a:hover,
.room-rabbit-hole .rh-cut__cap a:focus-visible { color: var(--rh-ink); }
.room-rabbit-hole .rh-cut__cap :focus-visible { outline-color: var(--rh-ink); }

.rh-shaft { max-width: 900px; margin: 0 auto; padding: 0 20px 72px; }

.rh-topline {
  display: flex; flex-wrap: wrap; gap: 10px 18px;
  justify-content: space-between; align-items: baseline;
  padding: 10px 2px 26px;
}
.rh-topline__note {
  margin: 0; font-family: 'Jost', system-ui, sans-serif;
  font-size: 14px; letter-spacing: 1.4px; text-transform: uppercase;
  color: var(--rh-dim);
}
.room-rabbit-hole .rh-topline .backlink { color: var(--rh-dim); }
.room-rabbit-hole .rh-topline .backlink:hover { color: #fff; }

/* ── The mouth of the hole ───────────────────────────────────────────────────
   The one drawing in this room that is ours. It is a shaft seen from inside
   it, looking up: a disc of sky at the top, ribs of cut earth receding, and
   roots and stones at the rim. Abstract on purpose -- there is nothing
   representational in it and nobody is in it, because the engravings further
   down are the real thing and a drawing of my own beside them would be a
   worse copy of somebody else's line. */
.rh-mouth { padding: 0 0 18px; text-align: center; }
.rh-well { width: min(320px, 74vw); margin: 0 auto 10px; display: block; }

.rh-eyebrow {
  margin: 0 0 14px;
  font-family: 'Jost', system-ui, sans-serif; font-weight: 500;
  font-size: 13px; letter-spacing: 3px; text-transform: uppercase;
  color: var(--rh-daylight);
}
.room-rabbit-hole h1 {
  margin: 0 0 12px;
  font-family: 'Playfair Display', Georgia, serif; font-weight: 700;
  font-size: clamp(42px, 9vw, 76px); line-height: 1.02;
  letter-spacing: -0.5px; color: #fff; text-wrap: balance;
}
.rh-tagline {
  margin: 0 auto 20px; max-width: 30ch;
  font-family: 'Playfair Display', Georgia, serif; font-weight: 700;
  font-size: clamp(20px, 3.4vw, 27px); line-height: 1.26;
  color: var(--rh-brass);
}
.rh-lede {
  margin: 0 auto; max-width: 62ch; font-size: 19px; color: var(--rh-chalk);
}

/* ── A ledge ─────────────────────────────────────────────────────────────────
   Flush to the wall, no foot, no shadow underneath it. A brass hairline along
   the TOP edge only, because the light is above you: that is the one lit edge
   a thing in a shaft has, and putting the rule on all four sides would light
   it from nowhere, which is the Adventurer's Guild's job and not this room's. */
.rh-ledge {
  background-color: var(--rh-slate-2);
  border-top: 2px solid var(--rh-brass);
  padding: 26px 26px 28px;
  margin: 0 0 30px;
}
.rh-ledge--deep { background-color: var(--rh-deep); }

.room-rabbit-hole h2 {
  margin: 0 0 14px;
  font-family: 'Playfair Display', Georgia, serif; font-weight: 700;
  font-size: clamp(27px, 5vw, 38px); line-height: 1.1; color: #fff;
  text-wrap: balance;
}
.room-rabbit-hole h3 {
  margin: 0 0 6px;
  font-family: 'Playfair Display', Georgia, serif; font-weight: 700;
  font-size: 22px; line-height: 1.2; color: #fff;
}
.room-rabbit-hole p { margin: 0 0 14px; }
.room-rabbit-hole p:last-child { margin-bottom: 0; }

.rh-note { font-size: 15.5px; color: var(--rh-dim); }

/* A passage somebody else wrote. Indented from the brass rule rather than
   boxed, because a box would make it furniture. */
.rh-quote {
  margin: 0 0 16px; padding: 2px 0 2px 18px;
  border-left: 2px solid var(--rh-graphite);
  font-family: 'Playfair Display', Georgia, serif; font-weight: 700;
  font-size: 20px; line-height: 1.35; color: var(--rh-daylight);
}
.rh-quote cite,
.rh-quote--cite {
  display: block; margin-top: 8px;
  font-family: 'Jost', system-ui, sans-serif; font-weight: 400; font-style: normal;
  font-size: 14.5px; letter-spacing: 0.4px; color: var(--rh-dim);
}

/* ── An engraving ────────────────────────────────────────────────────────────
   The mat is what the thing physically is: white paper. It carries its own
   flat ground so the caption's pair is the honest one -- see the section note.
   Nothing is rotated: this room has no transform in it anywhere. */
.rh-cut { margin: 0 0 34px; }
.rh-cut__mat {
  background-color: var(--rh-paper);
  padding: 22px;
  display: flex; justify-content: center;
}
.rh-cut__mat img {
  display: block; max-width: 100%; height: auto;
  max-height: 460px; width: auto; object-fit: contain;
  /* The scans are greyscale with a white surround, so they sit on the mat
     without a border. NO FILTER IS APPLIED TO ANY OF THEM -- make-polaroids.py
     refuses a filter on a photograph of a person, and while these are
     engravings rather than portraits, a wash laid over somebody else's line to
     make it match a palette is the same act on a smaller stake. */
  mix-blend-mode: multiply;
}
.rh-cut__cap {
  background-color: var(--rh-paper);
  color: var(--rh-ink);
  padding: 0 22px 20px;
}
.rh-cut__at {
  margin: 0 0 8px;
  font-family: 'Jost', system-ui, sans-serif; font-weight: 500;
  font-size: 12.5px; letter-spacing: 2.6px; text-transform: uppercase;
  color: var(--rh-brass-dark);
}
.rh-cut__ours {
  margin: 0 0 10px;
  font-family: 'Playfair Display', Georgia, serif; font-weight: 700;
  font-size: 21px; line-height: 1.28; color: var(--rh-ink);
}
.rh-cut__prov { margin: 0; font-size: 14px; line-height: 1.5; color: var(--rh-ink); }

/* ── A press ─────────────────────────────────────────────────────────────────
   §4 supplies the 16/9 box and the nothing-before-the-press behaviour;
   love-embed.js is still the only thing on this street that builds the frame.
   THE CONTAINER DEFAULTS TO STRETCH AND THE BUTTON OPTS OUT, because
   love-embed.js replaces the pressed button with a bare <div class="facade">
   and anything the button was wearing evaporates -- which is how Swaying
   Sweetgrass shipped two players at 0x0 while their audio played. */
.rh-presses { list-style: none; margin: 0; padding: 0; }
.rh-press {
  background-color: var(--rh-slate-2);
  border-top: 2px solid var(--rh-brass);
  margin: 0 0 22px; padding: 22px;
  display: grid; gap: 20px; align-items: start;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}
.rh-press__slot { display: flex; flex-direction: column; align-items: stretch; }
.rh-press__slot button.facade { align-self: stretch; }
.rh-press__runs {
  margin: 0 0 8px;
  font-family: 'Jost', system-ui, sans-serif; font-weight: 500;
  font-size: 11.5px; letter-spacing: 1.6px; color: var(--rh-dim);
}
.rh-press__who {
  margin: 0 0 8px;
  font-family: 'Jost', system-ui, sans-serif; font-weight: 500;
  font-size: 15px; color: var(--rh-brass);
}
.rh-press__plate p:last-child { margin-bottom: 0; }

/* ── The trail ───────────────────────────────────────────────────────────────
   One thing leads to another, drawn as the thing it is: each step further in
   than the last. The indent is a PADDING rather than a transform, for
   arcade.js's reason -- rotation and skew in the computed matrix are all
   check-gentle.py can read, so a room must not ask it to take its word for
   something. This is layout, and it is the same at all three settings. */
.rh-trail { list-style: none; margin: 0; padding: 0; }
.rh-step {
  padding-left: calc(var(--step) * 16px);
  border-left: 2px solid var(--rh-graphite);
  margin: 0 0 18px;
  padding-top: 2px; padding-bottom: 2px;
}
.rh-step > a {
  font-family: 'Playfair Display', Georgia, serif; font-weight: 700;
  font-size: 21px; line-height: 1.2;
  display: inline-block; margin-left: 16px;
}
.rh-step > p {
  margin: 4px 0 0 16px; font-size: 16px; color: var(--rh-dim); max-width: 60ch;
}

/* The wash. §3 hides .glow at Gentle for every room, so this is the one thing
   in here the dial touches, and it is the only thing in here that is not
   flat. It carries no text -- the panels do all of that -- so it introduces no
   pair for anybody to measure. */
.room-rabbit-hole .glow {
  position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background: radial-gradient(120% 60% at 50% -12%,
    rgba(191, 198, 204, 0.20) 0%,
    rgba(191, 198, 204, 0.07) 34%,
    transparent 68%);
}
.rh-shaft { position: relative; z-index: 1; }


/* §31 ── ROOM: The Healing Checkpoint (room 429) ─────────────────────────────
   A SAVE ROOM WITH THE LIGHT IN THE FLOOR, and that one physical fact is the
   whole of its separation from a street already crowded with warm enclosed
   places to sit down in.

   THE LIGHT COMES UP. Every other world here is lit from somewhere else and no
   two of them from the same place: the Jungle Room from above through a roof of
   leaves, the Zibaldone from one side at desk height, Swaying Sweetgrass from
   behind and a hundred feet away, The Feed through a mask a finger's width in
   front of a lamp, the Garden from directly overhead, the Adventurer's Guild
   from nowhere at all. In here it comes out of the floor. So every top surface
   is DARK and every underside carries a rim, the shadows run up the walls
   rather than down them, and the room gets lighter towards your feet. Nothing
   else on this street does that. If this room ever grows a lamp, a candle or a
   window it has joined a family of five.

   THAT FAMILY IS THE COLLAPSE TO WATCH, and by now it has arrived so often --
   the Faery Yurt, The Latibulum, The Den, the Hermitage's cave, The Mopery --
   that "they are all somewhere to rest, so they should feel the same" has
   stopped sounding like tidying and started sounding like taste. Every one of
   those is lit by A FLAME YOU COULD PUT YOUR HAND OVER. There is no flame in
   here; the light is under water and you could put your hand IN it. And all
   five are brown, amber or candle-gold, where there is no warm GROUND anywhere
   in this room at all -- only one warm INK, --hc-clay, which is what pale stone
   looks like when a cold light lands on it.

   THE ADVENTURER'S GUILD IS ITS OTHER DOOR AND ITS EXACT OPPOSITE, which is the
   hardest thing to hold here because the two rooms are one link apart. That one
   is manila, square, ruled, hairlined, lit like a photocopy from nowhere, with
   nothing casting anything. THERE IS NOT A STRAIGHT EDGE IN THIS ROOM: the
   alcove is an arch, every panel and control is a long radius, every border is
   a soft gradient rather than a line, and there is steam in the air so nothing
   has a hard edge at all. A board and an inn share a building and nothing else.
   If anything in here ever grows a hairline rule the guild has spread -- and
   §26 says in its own words that it cannot, because the moment anywhere else
   starts looking orderly the joke has become a system.

   THE ARCADE'S KELP BAY IS THE ONLY OTHER WATER ON THIS STREET and it is a
   SCREEN: a flat dark field under a scanline, inside a cabinet, that you look
   AT. This is water in the floor of a room you are standing IN, there is no
   screen anywhere in it, and the aqua here is the light rather than the
   subject.

   THE MOPERY AND THE RABBIT HOLE are the other cold dark stone-coloured rooms.
   The Mopery is a BUILDING you stand up in, blue-black to the skirting, lit by
   candles that stop an inch from each wick. The Rabbit Hole is lit from ABOVE
   AND BEHIND and gets DARKER the further down you read; this gets LIGHTER the
   further down you look, which is that room's gradient turned upside down, and
   it is green-black where that one is grey-slate. If these greys ever lose
   their green the two have become one and it is this one that moves.

   --hc-chamber IS THE FLAT BODY GROUND AND IT IS THE LIGHTEST OF THE THREE
   DARKS, which is the Rabbit Hole's arrangement and its reason: in a room
   setting pale type on a dark wall the honest flat colour is the lightest one,
   because that is the worse case for the type standing on it. --hc-lit is
   nobody's choice -- it is --hc-glim at .10 over --hc-chamber, the brightest
   the pool makes the room, and it is what the header's type sits on. Both are
   in check-contrast.py.

   AND EVERY BLOCK THAT CARRIES TEXT SITS ON A FLAT PANEL OF ITS OWN, because
   the pool is a FIXED layer: what is under a word depends on where that word
   is in the viewport, and no single flat value could honestly stand in for it.
   Only the header is left standing on the room itself, and it is measured
   against both. */

.room-checkpoint {
  background: var(--hc-chamber);
  color: var(--hc-steam);
  font-family: 'Rubik', var(--sans);
}
.room-checkpoint a { color: var(--hc-glim); }
.room-checkpoint a:hover,
.room-checkpoint a:focus-visible { color: var(--hc-clay); }
.room-checkpoint b, .room-checkpoint strong { font-weight: 500; color: #fff; }

/* THE LIGHT ITSELF, AND IT IS NOT THE DIAL'S. Fixed rather than scrolling,
   because the floor does not move when you do. It never animates and it is
   never switched off: §3 hides `.glow` at Gentle for every room on the street
   and that is correct for an EFFECT, but this is where the light in this room
   comes from, and a Gentle that unlit the room rather than quieting it would be
   the lite-version mistake with a torch. It carries no text. */
.hc-pool {
  position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background: radial-gradient(150% 62% at 50% 112%,
    rgba(121, 220, 206, 0.10) 0%,
    rgba(121, 220, 206, 0.05) 40%,
    transparent 72%);
}

/* The steam over the water, which IS decoration and is therefore `.glow`. It
   drifts at MAX and stands still at Regular, and §3 takes it away entirely at
   Gentle. It moves with a translate and a scale: rotation and skew are all
   check-gentle.py can read in a computed matrix, and a room must not ask a
   checker to take its word for something. Nothing in here flashes, blinks or
   pulses at any setting -- Club Chronic's rule, in the room whose whole subject
   is not being jolted. */
.room-checkpoint .glow {
  position: fixed; left: 0; right: 0; bottom: 0; height: 48vh;
  pointer-events: none; z-index: 0;
  background:
    radial-gradient(58% 100% at 22% 108%, rgba(234, 242, 240, 0.05) 0%, transparent 70%),
    radial-gradient(50% 100% at 76% 108%, rgba(234, 242, 240, 0.04) 0%, transparent 70%);
}
html[data-intensity="max"] .room-checkpoint .glow {
  animation: hc-drift 32s ease-in-out infinite alternate;
}
@keyframes hc-drift {
  from { transform: translate3d(-2.5%, 0, 0) scaleY(1); }
  to   { transform: translate3d(2.5%, -5%, 0) scaleY(1.14); }
}

.hc-room { position: relative; z-index: 1; width: min(880px, 100% - 44px); margin-inline: auto; padding: 26px 0 70px; }

.hc-topline { display: flex; flex-wrap: wrap; gap: 12px 20px; align-items: baseline; justify-content: space-between; }
.hc-topline__note { margin: 0; font-size: 13px; letter-spacing: .12em; text-transform: uppercase; color: var(--hc-dim); }
.room-checkpoint .backlink {
  background: none; border: 2px solid var(--hc-lit); border-radius: 999px;
  font-family: 'Quicksand', var(--sans); font-weight: 700; letter-spacing: .06em;
  color: var(--hc-dim); padding: 9px 18px;
}
.room-checkpoint .backlink:hover,
.room-checkpoint .backlink:focus-visible { border-color: var(--hc-glim); color: var(--hc-glim); }

/* ── The doorway ──────────────────────────────────────────────────────────── */
.hc-arrival { margin: 30px 0 0; text-align: center; }
.hc-bed { display: block; width: min(420px, 100%); margin: 0 auto; }

/* The enamel plaque beside the door. A number on an inn door, not a readout on
   a terminal: this room sets no monospace, although it is full of HTTP, because
   Space Mono belongs to The Feed and Courier Prime to the zine table -- and
   because a status line in a fixed pitch would make this a machine, which is
   the one thing an inn is not. */
.hc-plate {
  display: inline-block; margin: 8px 0 0;
  font-family: 'Quicksand', var(--sans); font-weight: 700;
  font-size: 40px; line-height: 1; letter-spacing: .1em;
  color: var(--hc-clay);
  background: var(--hc-alcove);
  border-radius: 999px; padding: 14px 30px 16px;
  box-shadow: 0 -10px 26px -14px rgba(121, 220, 206, .75);
}
.hc-eyebrow {
  margin: 20px 0 0; font-size: 12.5px; letter-spacing: .26em;
  text-transform: uppercase; color: var(--hc-dim);
}
.room-checkpoint h1 {
  font-family: 'Quicksand', var(--sans); font-weight: 700;
  font-size: clamp(38px, 7vw, 66px); line-height: 1.04; letter-spacing: -.01em;
  margin: 10px 0 0; color: #fff;
}
.hc-tagline {
  font-family: 'Quicksand', var(--sans); font-weight: 700;
  font-size: clamp(20px, 3vw, 26px); margin: 12px 0 0; color: var(--hc-clay);
}
.hc-lede { margin: 18px auto 0; max-width: 62ch; font-size: 18px; line-height: 1.68; color: var(--hc-steam); }

/* ── The alcoves ──────────────────────────────────────────────────────────── */
/* An arch rather than a box, every time, and the radius is bigger at the top
   than at the foot because that is what a thing dug into a wall looks like when
   the light is below it. No border anywhere: the edge is a gradient. */
.hc-panel {
  position: relative; margin: 42px 0 0; padding: 30px 32px 32px;
  background: var(--hc-alcove);
  border-radius: 42px 42px 22px 22px;
  background-image: linear-gradient(to top, rgba(121, 220, 206, .07), transparent 46%);
}
.room-checkpoint h2 {
  font-family: 'Quicksand', var(--sans); font-weight: 700;
  font-size: clamp(24px, 3.6vw, 32px); line-height: 1.16; margin: 0;
  color: #fff;
}
.room-checkpoint h3 {
  font-family: 'Quicksand', var(--sans); font-weight: 700;
  font-size: 19px; margin: 32px 0 0; color: var(--hc-glim);
}
.room-checkpoint p { max-width: 64ch; }
.hc-panel p { margin: 16px 0 0; font-size: 16.5px; line-height: 1.68; }
.hc-note { color: var(--hc-dim); font-size: 15px !important; }
.hc-list { margin: 18px 0 0; padding-left: 22px; max-width: 64ch; }
.hc-list li { margin: 0 0 14px; font-size: 16.5px; line-height: 1.68; }

/* The one paragraph in the room that is set on the water. It carries the
   sentence the whole page exists to protect, so it is the only block here on a
   ground of its own. */
.hc-hold {
  margin-top: 26px !important; padding: 22px 26px;
  background: var(--hc-spring); border-radius: 26px;
  font-size: 16.5px !important;
}

/* ── The voices ───────────────────────────────────────────────────────────── */
.hc-voice { margin: 26px 0 0; padding: 0 0 0 22px; max-width: 64ch; }
.hc-voice blockquote { margin: 0; }
.hc-voice blockquote p {
  margin: 0; font-family: 'Quicksand', var(--sans); font-weight: 700;
  font-size: clamp(19px, 2.6vw, 23px); line-height: 1.42; color: var(--hc-clay);
}
.hc-voice figcaption { margin: 10px 0 0; font-size: 15px; line-height: 1.6; color: var(--hc-dim); }
.hc-voice__at { display: block; margin-top: 4px; font-size: 13.5px; }

.hc-helds { list-style: none; margin: 18px 0 0; padding: 0; display: grid; gap: 16px; }
.hc-held { background: var(--hc-vault); border-radius: 24px; padding: 20px 22px; }
.hc-held p { margin: 10px 0 0; font-size: 15.5px; line-height: 1.62; }
.hc-held__what { margin: 0 !important; font-family: 'Quicksand', var(--sans); font-weight: 700; font-size: 17px !important; color: #fff; }
.hc-held__whose { color: var(--hc-dim); font-size: 14.5px !important; }

/* ── The slips ────────────────────────────────────────────────────────────── */
/* A <details> per slip, which is what makes the whole set work with scripts
   off. The copy button ships hidden and checkpoint.js switches it on; §2's
   [hidden] guard carries !important, which is the only reason that holds
   against this room's own display rules. */
.hc-slipbox .hc-slip { margin: 14px 0 0; }
.hc-slip {
  background: var(--hc-vault); border-radius: 26px; overflow: hidden;
}
.hc-slip__mark {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px;
  cursor: pointer; list-style: none; padding: 18px 24px; min-height: 44px;
}
.hc-slip__mark::-webkit-details-marker { display: none; }
.hc-slip__mark::before {
  content: "+"; font-family: 'Quicksand', var(--sans); font-weight: 700;
  font-size: 21px; line-height: 1; color: var(--hc-glim); width: 18px;
}
.hc-slip[open] .hc-slip__mark::before { content: "\2212"; }
.hc-slip__after { font-family: 'Quicksand', var(--sans); font-weight: 700; font-size: 18px; color: var(--hc-steam); }
.hc-slip__note { font-size: 14.5px; color: var(--hc-dim); }
.hc-slip__mark:hover .hc-slip__after { color: var(--hc-glim); }
.hc-slip__panel { padding: 0 24px 22px; }
.hc-slip__text {
  margin: 0; padding: 20px 22px; background: var(--hc-spring); border-radius: 20px;
  font-family: 'Rubik', var(--sans); font-size: 16px; line-height: 1.6;
  color: var(--hc-steam); white-space: pre-wrap; overflow-wrap: anywhere;
}
.hc-slip__copy {
  margin: 14px 0 0; cursor: pointer; min-height: 44px;
  font-family: 'Quicksand', var(--sans); font-weight: 700; font-size: 15px;
  padding: 11px 22px; border-radius: 999px;
  border: 2px solid var(--hc-lit); background: var(--hc-alcove); color: var(--hc-glim);
}
.hc-slip__copy:hover, .hc-slip__copy:focus-visible { border-color: var(--hc-glim); color: #fff; }
.hc-slip__said { margin: 10px 0 0; font-size: 14.5px; line-height: 1.55; color: var(--hc-clay); max-width: 52ch; }

/* ── The way out ──────────────────────────────────────────────────────────── */
.hc-trail { list-style: none; margin: 20px 0 0; padding: 0; display: grid; gap: 18px; }
.hc-step > a { font-family: 'Quicksand', var(--sans); font-weight: 700; font-size: 18.5px; text-decoration: none; }
.hc-step > a:hover, .hc-step > a:focus-visible { text-decoration: underline; }
.hc-step > p { margin: 5px 0 0; font-size: 15.5px; line-height: 1.6; color: var(--hc-dim); max-width: 62ch; }
.hc-ways { margin-top: 26px !important; font-size: 16px !important; }

/* The desk at the end. The street's chalk pavement does not run through this
   room either; every room ends in its own voice. */
.hc-desk {
  display: flex; flex-wrap: wrap; gap: 30px; align-items: flex-start;
  margin: 48px 0 0; padding: 30px 32px 32px;
  background: var(--hc-vault); border-radius: 42px 42px 22px 22px;
}
.hc-desk__half { flex: 1 1 300px; min-width: 0; }
.hc-desk__half h2 { font-size: 21px; }
.hc-desk__half .hc-note { margin: 14px 0 0; font-size: 15px; line-height: 1.62; max-width: 62ch; }
.hc-desk__half .dial { max-width: 380px; }

/* The job marker lying on the floor of this room. §4 supplies the behaviour and
   the panel borrows this room's ink and ground, so opening it cannot introduce
   a pair nobody measured. */
.room-checkpoint .quest { margin-top: 40px; }


/* §32 ── ROOM: The Foundry ────────────────────────────────────────────────────
   A TYPE FOUNDRY: a grey iron workshop, lit through a dirty sawtooth roof, with
   a bench in it where any words on this street can be set in any face on this
   street and pulled as a proof. It is the only room here whose CONTENT is the
   typefaces rather than a room that happens to wear one.

   THE SEPARATION IS THE GREY, AND IT IS THE FIRST ONE ON THE STREET. Every
   other world here is either a night ground with light applied to it or a sheet
   of paper with the room cropped out. This is neither: it is the middle, the
   colour of the metal, and there is no black in it and no white in it except
   the proof lying on the bench. If this floor ever goes near-black it has
   joined the night rooms; if the page ever becomes the paper it has joined the
   paper rooms, which is where the real pull is, because this room is FULL of
   type specimens and the four paper rooms are the obvious neighbours:

     · THE MOPERY is a cold building you stand up in, lit by candles that do not
       reach the walls, and its type is impressed into the page. This is lit
       flatly from overhead by daylight nobody chose, and its type is standing
       on a bench waiting to be used. A library and a workshop.
     · THE GUILD is manila and is lit like a photocopy, from nowhere, with
       nothing casting anything. Here the light HAS a direction -- straight down
       -- so every object has a small hard shadow directly beneath it, and the
       room is dark rather than pale.
     · THE DOOMSCROLL is one unbroken roll of foxed warm newsprint. The only
       paper in here is a single cool sheet with the bench visible all round it.
     · THE ZIBALDONE is bound leaves lit by a lamp at desk height, with a
       gutter and a fold. There is no fold in here and nothing is bound.

   AND IT IS THE THIRD DAYLIT ROOM, which is the other thing to keep honest. The
   Hermitage has a low morning SUN in it, so everything has a lit face and a
   long shadow falling sideways. The Garden's light has come down through leaves
   at midday and every pale surface in it is tinted green. North light is the
   one a workshop was built for: the glazing faces AWAY from the sun so the work
   has no glare on it, which means flat, cool, directionless daylight and no lit
   face on anything at all. Nothing in this room is warm except the brass, and
   brass is a metal rather than a light.

   THERE IS NO TRANSFORM IN THIS SECTION. Not a tilt, not a rotation, nothing
   skewed -- which is deliberate in the room where a SLANT is one of the
   controls. check-gentle.py reads rotation and skew out of the computed matrix
   and cannot tell a leaning page from a leaning letter, so the machine slant on
   the bench is `font-style: oblique` and lives in the font shorthand where the
   checker is not being asked to take anybody's word for anything. arcade.js
   made the same call with left/top, and the Oracle Deck with its lozenge.

   THE LINK COLOUR IS DECIDED HERE, AT THE ROOM, on both grounds this room has.
   The Doomscroll shipped without that and every link on it fell through to the
   base stylesheet's pink, which was chosen for a near-black street and measures
   about 2.4 on paper. Brass is 4.91 on the floor and 6.45 on the bench, and
   both pairs are in check-contrast.py.                                        */

.room-foundry {
  background: var(--fo-floor);
  color: var(--fo-bone);
  font-family: 'Work Sans', var(--sans);
  font-size: 17px;
  line-height: 1.62;
}

.room-foundry a { color: var(--fo-brass); text-underline-offset: 3px; }
.room-foundry a:hover,
.room-foundry a:focus-visible { color: var(--fo-bone); }

/* The north light. A wide, soft, top-down wash with no edges and no colour in
   it, because a north light has none -- it is the sky with the sun taken out.

   IT IS ABSOLUTE AND IT STOPS, and the first draft was fixed and full height,
   which was wrong twice over. A light that follows the viewport is not a light,
   it is a veil in front of the reader -- and it MEASURED as one: the wash makes
   a composite ground of #596267 where it is strongest, and against that the
   brass this room sets its links in falls to 3.14 and the oil it sets its fine
   print in to 3.34, both under the bar. Fixed, that composite could arrive
   under ANY paragraph on the page depending on how far somebody had scrolled,
   which is the shape The Rabbit Hole's scrolling ground already taught this
   stylesheet: no flat value can honestly stand in for it. Absolute and 340px
   tall, the light comes in at the top of the room and the page scrolls out from
   under it, which is also what actually happens in a building. The only text it
   reaches is the topline, whose two inks are bone at 5.19 for that reason.

   It is on at every setting on the dial: it is not an effect
   applied to the room, it is where the light in the room comes from, and a
   Gentle that took it away would leave the workshop unlit rather than quiet.
   The Healing Checkpoint's pool in the floor is the same decision. It carries
   no text and it does not move. Measured at 1.52 against the floor, which is
   in check-contrast.py's ORNAMENT list with its number beside it. */
.fo-light {
  position: absolute;
  inset: 0 0 auto;
  height: 340px;
  pointer-events: none;
  z-index: 0;
  background:
    linear-gradient(to bottom, rgba(110,122,128,.46), rgba(110,122,128,.13) 52%, transparent),
    repeating-linear-gradient(104deg, rgba(110,122,128,.16) 0 3px, transparent 3px 30px);
}

/* The dust standing in that light. THIS is decoration, so it is `.glow` and §3
   switches it off at Gentle for the whole street. It drifts upward, slowly, and
   it neither flashes nor pulses -- Club Chronic's rule, kept in a room with a
   bright band across the top of it where a flicker would be easiest to add. */
.room-foundry .glow {
  position: absolute;
  inset: 0 0 auto;
  height: 340px;
  pointer-events: none;
  z-index: 0;
  opacity: .5;
  background-image:
    radial-gradient(1.6px 1.6px at 12% 30%, rgba(237,234,227,.9), transparent),
    radial-gradient(1.4px 1.4px at 31% 62%, rgba(237,234,227,.75), transparent),
    radial-gradient(1.8px 1.8px at 48% 18%, rgba(237,234,227,.8), transparent),
    radial-gradient(1.3px 1.3px at 67% 48%, rgba(237,234,227,.7), transparent),
    radial-gradient(1.7px 1.7px at 83% 26%, rgba(237,234,227,.85), transparent),
    radial-gradient(1.4px 1.4px at 92% 58%, rgba(237,234,227,.7), transparent);
}
html[data-intensity="max"] .room-foundry .glow { animation: fo-motes 21s linear infinite; }
@keyframes fo-motes {
  from { transform: translateY(8px); }
  to   { transform: translateY(-8px); }
}

.fo-shop { position: relative; z-index: 1; max-width: 1040px; margin: 0 auto; padding: 22px 20px 72px; }

.fo-topline { display: flex; flex-wrap: wrap; gap: 10px 20px; align-items: baseline; justify-content: space-between; }
/* BONE, NOT OIL, AND THE BACKLINK TOO. These two are the only words on the page
   standing on the lit ground rather than on the floor or on a bench panel, and
   at #596267 oil measures 3.34 and brass 3.14. .backlink carries
   `text-decoration: none` from §4, so its colour is the only channel it has. */
.fo-topline__note { margin: 0; font-size: 13px; letter-spacing: .09em; text-transform: uppercase; color: var(--fo-bone); }
.fo-topline .backlink { color: var(--fo-bone); }

/* The nameplate. A stencil is the one letterform on this street that is a HOLE
   rather than a mark -- a shape cut out of metal so it can be repeated, which
   is the whole idea of type -- and it is what is painted on a workshop's crates
   and machinery. It is the room's only display face and it sets nothing but
   this. Anton is the street's other condensed display face and belongs to Club
   Chronic; that one is solid, on a black wall, over a paste-up of flyers. */
.fo-plate {
  display: flex; flex-wrap: wrap; gap: 22px 30px; align-items: center;
  margin: 26px 0 0; padding: 26px 26px 28px;
  background: var(--fo-bench);
  border: 2px solid var(--fo-lead);
  box-shadow: 0 10px 0 -4px rgba(0,0,0,.34);
}
.fo-galley { width: 168px; height: auto; flex: 0 0 auto; }
.fo-plate__words { flex: 1 1 320px; }
.fo-plate__eyebrow { margin: 0; font-size: 12px; letter-spacing: .22em; text-transform: uppercase; color: var(--fo-brass); }
.fo-plate h1 {
  font-family: 'Stardos Stencil', var(--sans);
  font-size: clamp(44px, 8vw, 84px);
  line-height: .98; letter-spacing: .01em;
  margin: 6px 0 10px; color: var(--fo-bone);
}
.fo-plate__line { margin: 0; font-size: 19px; color: var(--fo-oil); }

.fo-lede { max-width: 66ch; margin: 30px 0 0; }
.fo-lede p { margin: 0 0 14px; }

/* ── The bench ─────────────────────────────────────────────────────────────
   No <form> element and no action: nothing here is submitted, there is nowhere
   to submit it to, and every control changes the proof in place. */
.fo-bench {
  margin: 34px 0 0; padding: 24px 22px 20px;
  background: var(--fo-bench);
  border: 2px solid var(--fo-lead);
  box-shadow: 0 10px 0 -4px rgba(0,0,0,.34);
}
.fo-bench h2 {
  font-family: 'Stardos Stencil', var(--sans);
  font-size: 26px; letter-spacing: .04em; margin: 0 0 4px; color: var(--fo-brass);
}
.fo-set { display: flex; flex-wrap: wrap; gap: 18px 26px; margin: 18px 0 0; padding: 0; border: 0; }
.fo-set--inks { display: block; border-top: 1px solid var(--fo-lead); padding-top: 16px; }
.fo-set--do { align-items: center; border-top: 1px solid var(--fo-lead); padding-top: 18px; }

.fo-pick { flex: 1 1 260px; min-width: 0; }
.fo-pick label,
.fo-knob label,
.fo-set--inks legend {
  display: block; font-size: 12px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--fo-brass); margin: 0 0 6px; padding: 0;
}
.fo-pick select,
.fo-pick textarea {
  width: 100%; font: inherit; font-size: 15px;
  color: var(--fo-bone); background: var(--fo-floor);
  border: 1px solid var(--fo-lead); border-radius: 0; padding: 9px 10px;
}
.fo-pick textarea { resize: vertical; min-height: 78px; }
.fo-pick__fine,
.fo-knob__fine,
.fo-inks__fine,
.fo-do__fine { margin: 7px 0 0; font-size: 13px; line-height: 1.5; color: var(--fo-oil); }
.fo-do__fine { flex: 1 1 320px; margin: 0; }

.fo-knob { flex: 1 1 210px; }
.fo-knob input[type="range"] { width: calc(100% - 66px); vertical-align: middle; accent-color: var(--fo-brass); }
.fo-knob output { display: inline-block; width: 60px; text-align: right; font-variant-numeric: tabular-nums; font-size: 14px; color: var(--fo-bone); }

/* Each ink says its own measured contrast ratio, on itself. There is no colour
   picker here and there is not going to be one: this is the one room on the
   street where somebody other than us chooses the colour of the text. */
.fo-ink { display: flex; align-items: center; gap: 10px; margin: 10px 0 0; font-size: 14px; cursor: pointer; }
.fo-ink__chip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 42px; height: 30px; flex: 0 0 auto; font-size: 15px;
  border: 1px solid var(--fo-lead);
}
.fo-ink__name { flex: 1 1 auto; }
.fo-ink__ratio { font-variant-numeric: tabular-nums; color: var(--fo-oil); font-size: 13px; }

.fo-print,
.fo-reset {
  font: inherit; font-size: 15px; letter-spacing: .04em;
  padding: 10px 18px; cursor: pointer;
  background: var(--fo-brass); color: #22160A;
  border: 1px solid var(--fo-brass); border-radius: 0;
}
.fo-reset { background: transparent; color: var(--fo-bone); border-color: var(--fo-lead); }
.fo-off { margin: 14px 0 0; font-size: 14px; color: var(--fo-bone); border-left: 3px solid var(--fo-brass); padding-left: 12px; }
.fo-said { margin: 14px 0 0; min-height: 22px; font-size: 14px; color: var(--fo-oil); }

/* ── The proof ─────────────────────────────────────────────────────────────
   The sheet is the one pale object in the room and it is the only thing that
   prints. Its ink and paper come off the chosen pair as custom properties, so
   the colours the room can produce are exactly the measured ones. */
.fo-pulled { margin: 34px 0 0; }
.fo-pulled__h { font-family: 'Stardos Stencil', var(--sans); font-size: 24px; letter-spacing: .04em; margin: 0 0 12px; color: var(--fo-brass); }
.fo-proof {
  --proof-ink: var(--fo-ink);
  --proof-paper: var(--fo-paper);
  background: var(--proof-paper); color: var(--proof-ink);
  padding: 40px 34px; overflow-wrap: break-word;
  box-shadow: 0 12px 26px -12px rgba(0,0,0,.7);
}
.fo-proof p { margin: 0 auto; white-space: pre-wrap; }
.fo-colophon {
  margin: 12px 0 0; font-size: 13px; line-height: 1.55; color: var(--fo-oil);
  border-top: 1px solid var(--fo-lead); padding-top: 10px;
}

.fo-notes { margin: 44px 0 0; max-width: 68ch; }
.fo-notes h2 {
  font-family: 'Stardos Stencil', var(--sans);
  font-size: 23px; letter-spacing: .04em; margin: 28px 0 8px; color: var(--fo-brass);
}
.fo-notes p { margin: 0 0 13px; }
.fo-from { margin: 0 0 14px; padding-left: 20px; }
.fo-from li { margin: 0 0 9px; }

.fo-desk {
  display: flex; flex-wrap: wrap; gap: 22px 34px; margin: 44px 0 0; padding: 22px;
  background: var(--fo-bench); border: 2px solid var(--fo-lead);
}
.fo-desk__half { flex: 1 1 320px; }
.fo-desk h2 { font-family: 'Stardos Stencil', var(--sans); font-size: 20px; letter-spacing: .04em; margin: 0 0 8px; color: var(--fo-brass); }
.fo-note { margin: 0 0 10px; font-size: 14px; color: var(--fo-oil); }

/* ── The cases ─────────────────────────────────────────────────────────────
   Every face, on the shelf its own record files it under, set in itself. This
   is where the room's index of the street lives: which room sets each face is
   a claim about love.css and make-foundry.py refuses one the stylesheet does
   not support. */
.fo-cases { margin: 46px 0 0; }
.fo-cases h2 { font-family: 'Stardos Stencil', var(--sans); font-size: 26px; letter-spacing: .04em; margin: 0 0 6px; color: var(--fo-bone); }
.fo-cases__fine { margin: 0 0 6px; max-width: 68ch; font-size: 14px; color: var(--fo-oil); }
.fo-shelf {
  margin: 30px 0 10px; font-size: 12px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--fo-brass); border-bottom: 1px solid var(--fo-lead); padding-bottom: 6px;
}
.fo-sorts { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }
.fo-sort { background: var(--fo-bench); border: 1px solid var(--fo-lead); padding: 14px 15px 13px; }
.fo-sort__show { margin: 0 0 6px; font-size: 27px; line-height: 1.16; color: var(--fo-bone); overflow-wrap: break-word; }
.fo-sort__who { margin: 0; font-size: 14px; color: var(--fo-bone); }
.fo-sort__meta { margin: 4px 0 0; font-size: 12.5px; color: var(--fo-oil); }
.fo-sort__vf { display: block; margin-top: 3px; color: var(--fo-oil); }

/* §33 ── ROOM: Danny the Street (the page about the name) ────────────────────
   THE ROAD SURFACE, SEEN FROM DIRECTLY ABOVE, UNDER ONE SODIUM LAMP AT FOUR IN
   THE MORNING. This page says where the street's name came from, so it is the
   one room here that is not a premises at all: no walls, no door, no furniture,
   nothing standing up in it anywhere. You are looking down at the thing you
   spend the rest of the site walking along.

   THE HARDEST COLLAPSE IS THE STREET ITSELF (§5), AND IT IS THE FIRST TIME A
   ROOM HAS HAD TO BE KEPT APART FROM THE FRONT DOOR. Both are a street at
   night. Every earlier version of this problem had two rooms to separate; this
   one has a room and the page it hangs off. What keeps them apart is where you
   are standing and what you can see from there:

     · §5 IS SEEN FROM THE PAVEMENT, at eye level, looking INTO lit windows.
       Every object in it stands up — awnings, fronts, a signpost, a
       noticeboard on legs — and it collides a typeface per shopfront on
       purpose. This is a PLAN: the kerbs run down both sides of the page, the
       centre line runs through the middle of it, and there is exactly one
       typeface and one hue in the whole room.
     · §5's light is coloured and comes from a dozen places at once, which is
       what a row of shops looks like. HERE THERE IS ONE LAMP AND IT HAS ONE
       COLOUR IN IT. Low-pressure sodium is effectively a single wavelength, so
       under it nothing has a colour of its own — only a brightness. That is not
       a palette decision that could be loosened later; it is the whole room. IF
       A SECOND HUE EVER APPEARS IN THIS SECTION THE LAMP HAS BEEN CHANGED FOR
       A DIFFERENT KIND OF LAMP, and the argument goes with it.

   AND IT IS THE SEVENTH WARM-LOOKING ROOM, after the Faery Yurt, The Latibulum,
   The Den, the Hermitage's cave, The Mopery and Swaying Sweetgrass. By now
   "they are all warm, they should feel the same" has arrived so often that it
   sounds like taste. The answer here is the same as it has been every time and
   it is physical: every one of those rooms is lit by a flame or by the sun, and
   in all of them things keep their own colours — green shag, indigo glass, gold
   leaf, a red spine. SODIUM TAKES COLOUR AWAY. A room where nothing can have a
   local colour is the opposite of a cosy one, however warm the grey looks, and
   there is nothing in here to sit on.

   THE CAMPGROUNDS (§13) IS THE OTHER OUTDOOR NIGHT, and the separation is the
   sky. Out there the field is cold blue with the sky still on it and the ground
   is what you are standing on. Under a lamp you cannot see up at all: the light
   is a lid, the dark past the kerb is absolute, and the ground is the only
   thing there is. The Rabbit Hole (§30) is the other hard grey and is cold, wet
   and vertical; this is warm, dry and flat.

   THERE IS NO TRANSFORM AND NO ANIMATION IN THIS SECTION, and both absences are
   decisions. A painted road legend is stretched along the road, and the only
   way to stretch type here would be a scale — which check-gentle.py reads out
   of the computed matrix and cannot tell from a page tilting itself, so the
   legends are letter-spaced and left alone. The Foundry made the same call in
   the room where a slant is a control. AND THERE IS NO AMBIENT LAYER AT ANY
   SETTING: the lamp is on at Gentle because it is the light in here rather than
   an effect applied to it, and nothing else moves, because nothing on a street
   at four in the morning does. Club Chronic's rule, in the quietest room that
   has ever held it.

   THE LINK COLOUR IS DECIDED HERE, AT THE ROOM, on both grounds this room has —
   sodium is 8.62 on the tar and 7.34 inside the lamp's own pool. The Doomscroll
   and the Playhouse both shipped without that decision and fell through to a
   pink chosen for a near-black street.                                        */

.room-danny {
  position: relative;
  background: var(--dn-tar);
  color: var(--dn-paint);
  font-size: 17px;
  line-height: 1.62;
}

.room-danny a { color: var(--dn-sodium); text-underline-offset: 3px; }
.room-danny a:hover,
.room-danny a:focus-visible { color: var(--dn-paint); }

/* THE LAMP. One pool, thrown from above and slightly behind the reader, which
   is where a street lamp is. It is absolute and it stops — the Foundry's rule,
   learned the hard way there: a light fixed to the viewport is not a light, it
   is a veil that arrives under whichever paragraph you happen to have scrolled
   to. It composites the tar to #2D261B at its strongest, and every ink in this
   room is held against that as well as against the bare road in
   check-contrast.py. It carries no text of its own and it does not move. */
.dn-lamp {
  position: absolute;
  inset: 0 0 auto;
  height: 620px;
  pointer-events: none;
  z-index: 0;
  background: radial-gradient(70% 420px at 50% -40px,
              rgba(240, 167, 63, .09), rgba(240, 167, 63, .035) 58%, transparent);
}

/* The road. The kerbs are the page's own edges, laid in stones with a joint
   between them, and they are ornament: 3.08 on the tar, which is under the bar,
   so they edge the room and never say anything. */
.dn-road {
  position: relative;
  z-index: 1;
  max-width: 880px;
  margin: 0 auto;
  padding: 0 clamp(22px, 5vw, 46px) 84px;
}
.dn-road::before,
.dn-road::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 11px;
  background: repeating-linear-gradient(180deg,
              var(--dn-kerb) 0 74px, var(--dn-tar) 74px 77px);
}
.dn-road::before { left: 0; }
.dn-road::after  { right: 0; }

.dn-topline {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 18px;
  justify-content: space-between;
  align-items: baseline;
  padding-top: 26px;
}
.room-danny .backlink { color: var(--dn-sodium); }
/* The two small notes in this room are Overpass at 400 and everything else is
   at 700: a painted road legend is laid down thick because it is read at speed
   from a long way off, and a line of small print on a sign is not. The bench in
   The Foundry offers both, and check-weights.py renders them to be sure they
   are two drawings rather than one file named twice. */
.dn-topline__note {
  margin: 0;
  font-family: 'Overpass', var(--sans);
  font-weight: 400;
  font-size: 11.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--dn-chalk);
}

/* The nameplate. An enamel street sign the colour of the road it is bolted
   over, with the two rules a cast plate has round it. It is NOT a pale panel,
   although a real one is: every word in this room is pale on the dark, which is
   the inversion The Latibulum is built on running the other way, and one lit
   panel in here would be a second ground nobody measured. */
.dn-plate {
  margin: 30px 0 0;
  padding: 20px 24px 22px;
  border: 2px solid var(--dn-paint);
  box-shadow: 0 0 0 4px var(--dn-tar), 0 0 0 6px var(--dn-paint);
}
.room-danny h1 {
  margin: 0;
  font-family: 'Overpass', var(--sans);
  font-weight: 700;
  font-size: clamp(32px, 6.4vw, 58px);
  line-height: 1.04;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--dn-paint);
}
.dn-plate__sub {
  margin: 12px 0 0;
  font-family: 'Overpass', var(--sans);
  font-weight: 700;
  font-size: 12.5px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--dn-sodium);
}

/* OURS, AND IT IS A DRAWING OF A ROAD. A stretch of tarmac from above: two
   kerbs, a broken centre line, a drain in the gutter, a manhole, and a word
   chalked across the middle of it. There is no character in it and there is not
   going to be one — Danny belongs to DC Comics, the drawings on this page are
   of a road, and a road is a thing nobody owns. */
.dn-draw {
  display: block;
  width: 100%;
  height: auto;
  margin: 26px 0 0;
}

.dn-lede {
  margin: 26px 0 0;
  font-size: 19px;
  line-height: 1.6;
}

/* The section headings are road legends: painted on, in capitals, spaced out
   along the road. Not stretched — see the note at the head of this section. */
.dn-leg {
  margin: 0 0 14px;
  font-family: 'Overpass', var(--sans);
  font-weight: 700;
  font-size: clamp(18px, 3.2vw, 24px);
  letter-spacing: .12em;
  line-height: 1.24;
  text-transform: uppercase;
  color: var(--dn-paint);
}
.dn-bay { margin: 0; padding: 0; }
.dn-bay + .dn-bay { margin-top: 10px; }
.dn-bay p { margin: 0 0 13px; }

/* The centre line between bays. Ornament, in the paint's own colour, because a
   centre line is paint. */
.dn-dash {
  height: 5px;
  border: 0;
  margin: 34px 0;
  background: repeating-linear-gradient(90deg,
              var(--dn-paint) 0 52px, transparent 52px 94px);
}

/* What Danny has been, in order. A date on the left in the lamp's own colour
   and the thing itself on the right; the rule between entries is a joint in
   the paving rather than a border on a card. */
.dn-when { list-style: none; margin: 18px 0 0; padding: 0; }
.dn-when > li {
  display: grid;
  grid-template-columns: 104px 1fr;
  gap: 4px 20px;
  padding: 15px 0;
  border-top: 1px dashed var(--dn-kerb);
}
.dn-when > li:last-child { border-bottom: 1px dashed var(--dn-kerb); }
.dn-when__when {
  font-family: 'Overpass', var(--sans);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: .08em;
  color: var(--dn-sodium);
}
.dn-when__what { margin: 0; }
.dn-when__what b { color: var(--dn-paint); }

/* Chalk. Danny talks by rearranging what Danny is made of, so the asides in
   this room are written on the road rather than framed on a card. */
.dn-chalked {
  margin: 20px 0 0;
  padding: 0 0 0 18px;
  border-left: 3px solid var(--dn-kerb);
  color: var(--dn-chalk);
  font-size: 16px;
}

/* The one quotation on the page, and the line saying where it was read. */
.dn-said {
  margin: 20px 0 0;
  padding: 16px 20px;
  border: 1px solid var(--dn-kerb);
}
.dn-said p { margin: 0; font-size: 18px; }
.dn-said__who {
  margin: 10px 0 0;
  font-family: 'Overpass', var(--sans);
  font-weight: 400;
  font-size: 11.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--dn-sodium);
}

/* The sources, and the rights note under them. Both are fine print in the
   chalk, which is 8.91 on the road. */
.dn-cite { list-style: none; margin: 16px 0 0; padding: 0; }
.dn-cite li { margin: 0 0 10px; font-size: 15px; color: var(--dn-chalk); }
.dn-note {
  margin: 26px 0 0;
  padding: 18px 20px;
  border: 1px dashed var(--dn-kerb);
  font-size: 15px;
  color: var(--dn-chalk);
}

/* The dial, at the end of the road, where every room keeps it. */
.dn-desk { margin: 40px 0 0; max-width: 460px; }


/* §34 ── THE OUTSKIRTS (past the last streetlight, off the street) ───────────
   THE SECOND AREA, AND THE ONE THAT HAD TO BE KEPT OFF THE FIRST. The
   campgrounds is the other one, and "an area should look like an area" is the
   excuse this street has already refused once — with the added trap this time
   that BOTH areas are outdoors, at night, with signs standing on the ground and
   nothing built. The separation is structural and has to stay:

     · the campgrounds is lit by NOTHING. It is a field with the sky still on
       it, everything evenly dim, nothing casting anything, and you can see all
       the way to the treeline. This is lit by HEADLIGHTS: one low, level,
       close beam from off the page, so a sign has a bright face and no back,
       and you can see about as far as the next board. The field is open. This
       is not dark because it is empty; it is dark because you have no light.
     · a campground sign is ROUTED into wood by a machine and maintained by
       somebody. A sign out here was PAINTED by whoever owned the premises,
       once, and has been in the weeds since. Alfa Slab One against Bowlby One
       SC, which is where that difference actually lives.
     · the campground is COLD — night-blue spruce, lichen, a moon-coloured
       link. Out here the only colours are the beam and the paint: bone, dead
       khaki and a rust red. Nothing out here is blue.

   AND IT IS NOT DANNY THE STREET, which is the other road on this site. That
   page is a road seen from DIRECTLY ABOVE under sodium, which is one hue and no
   shadows because there is nothing standing up in it. This is a road seen from
   ON it, at eye level, with things standing at the side. Same subject, opposite
   position, and the giveaway is that this one has a horizon and that one has a
   plan.

   NO AMBIENT LAYER AT ANY SETTING, the campgrounds' rule for a different
   reason. Out there the field is still because quiet is what the area is FOR.
   Here the beam is still because headlights that swept would be a car going
   past, and there is no other car — the light is yours and you have stopped. */

.outskirts { background: var(--osk-night); color: var(--osk-dim); }
.outskirts a { color: var(--osk-rust); }
.outskirts a:hover { color: var(--osk-beam); }
.outskirts p, .outskirts li { font-size: 16.5px; line-height: 1.66; }

/* The backlink drops Bungee, the campgrounds' reason: it is the one piece of
   shared furniture carrying a typeface, and the street's voice would be the
   loudest thing on an unlit road. */
.outskirts .backlink { font-family: var(--sans); font-size: 15px; letter-spacing: 0; color: var(--osk-rust); }
.outskirts .trailmark { margin: 0; font-size: 14px; color: var(--osk-dim); }

.outskirts h1 {
  font-family: 'Bowlby One SC', Impact, sans-serif; font-weight: 400;
  font-size: clamp(38px, 7.4vw, 76px); line-height: 1.04;
  color: var(--osk-beam); margin: 14px 0 0; letter-spacing: .5px;
}
.outskirts h2 { font-family: 'Bowlby One SC', Impact, sans-serif; font-weight: 400; font-size: 17px; letter-spacing: 1px; color: var(--osk-rust); margin: 0 0 12px; }
.outskirts h3 { font-family: 'Bowlby One SC', Impact, sans-serif; font-weight: 400; font-size: 25px; line-height: 1.14; color: var(--osk-beam); margin: 0; }
.outskirts .lede { font-size: 19.5px; line-height: 1.6; color: var(--osk-beam); max-width: 56ch; margin: 20px 0 0; }

/* The verge: the notice at the side of the road. Flat board, and the light is
   on its LEFT EDGE only — the side facing the road you are standing on. That
   single bright edge is the whole lighting model of this area, and it is why
   nothing in here has an even border. */
.verge {
  margin: 32px 0 0; padding: 20px 24px;
  background: var(--osk-board); border-left: 6px solid var(--osk-beam);
  border-radius: 0 2px 2px 0;
}
.verge ul { margin: 0; padding: 0 0 0 20px; }
.verge li { margin: 0 0 10px; }
.verge li:last-child { margin-bottom: 0; }
.verge li::marker { color: var(--osk-rust); }
.verge p { margin: 0; max-width: 64ch; }
.verge--foot { border-left-color: var(--osk-rust); }

/* The turnings. Boards standing at the side of the road with the drawing of
   what is down there beside them — the campgrounds' sign-and-the-thing
   grammar, which this area inherits DELIBERATELY and is the one borrowing
   allowed, because "here is a sign, and here is what you can see from the
   road" is a fact about how an edge-of-town works rather than a look. What is
   not borrowed is everything else: the post is a lit edge instead of a timber,
   and the drawing is what the beam reaches rather than a whole tent. */
.turnings { list-style: none; margin: 28px 0 0; padding: 0; display: flex; flex-direction: column; gap: 32px; }
.turning { display: flex; flex-wrap: wrap; gap: 10px 30px; align-items: center; border-left: 5px solid var(--osk-beam); padding: 4px 0 4px 22px; }
.turning__sign { flex: 1 1 32ch; min-width: 0; }
.turning__no { display: block; margin: 0 0 7px; font-family: 'Bowlby One SC', Impact, sans-serif; font-size: 12px; letter-spacing: 2.4px; color: var(--osk-rust); }
.turning h3 a { color: var(--osk-beam); text-decoration-color: var(--osk-rust); text-underline-offset: 4px; }
.turning h3 a:hover { color: var(--osk-rust); }
.turning p { margin: 10px 0 0; max-width: 58ch; }
.turning__who { margin: 9px 0 0; font-size: 14.5px; color: var(--osk-dim); }
.turning__art { flex: 0 1 264px; line-height: 0; }
.turning__art svg { display: block; width: 100%; height: auto; }

/* A turning that is named and not built. THE POST IS DASHED AND THE WORDS ARE
   NOT DIMMED, which is the whole care in this rule: the street's empty
   storefront uses the same dashed grammar, and the temptation is to fade the
   text to match the idea of "not there yet". A board you cannot read is not a
   subtler board, it is a broken one — and out here the whole conceit is that
   what the beam reaches, it reaches properly. The heading drops to the fine
   print's colour, which still clears the bar on this ground, and every word in
   the panel stays at full strength. */
.turning--dark { border-left-style: dashed; border-left-color: var(--osk-weed); }
.turning--dark h3 { color: var(--osk-dim); }
.turning--dark .turning__who { color: var(--osk-rust); }


/* §35 ── ROOM: Black Leather Lagoon (turning 01 in The Outskirts) ────────────
   A DRIVE-IN SCREEN STANDING IN BLACK WATER, showing to reeds. Turning 01 off
   The Outskirts, and it is the first pitch in the second area — which is
   exactly where the Faery Yurt already proved that an area does not get a house
   style. The road in is cold, dead, khaki and painted by hand. This is wet,
   lit, acid green and printed. You arrive out of the dark and there is
   something ON.

   THE ROOM IT MUST NOT COLLAPSE INTO IS CLUB CHRONIC, and it is the hardest
   call on the street since The Den. Both are music rooms. Both are dark. Both
   have an appreciation at the top and a rack of records down the page, and both
   hold make-club.py's pair of runtime rules. The separation is not tonal:

     · CLUB CHRONIC IS A WALL. Flat, frontal, no light source anywhere in it,
       no depth — a hundred rectangles of paper pasted onto black and layered
       like sediment. THIS ROOM HAS A HORIZON. One bright rectangle standing
       out in the water, everything else lit off it, every object with a face
       turned towards it and nothing behind. If the water in here ever goes
       flat, or the screen stops being the only light, they have become one
       room and it is this one that moves.
     · the club's paper is the SUBJECT — the room is made of flyers. There is
       no paper in here at all. A lobby card out in the shallows is a lit
       surface at a distance, not a thing you could take down and keep.
     · Anton against Chivo, which is the fight the type section describes: the
       obvious face for a monster bill is a condensed gothic, and the club has
       owned the street's condensed since it opened.

   AND IT IS NOT ENID'S ROOM, the other black-walled room with loud colour in
   it. That is an interior, flat-lit, with no modelling and many hues at once —
   a bedroom wall covered in stickers. This is outdoors, one light, and
   essentially two inks. Enid's room has no distance in it; this one is almost
   entirely distance.

   NOTHING IN HERE FLICKERS, AT ANY SETTING. A drive-in screen is a flickering
   object — that is nearly its definition — and building one without the
   flicker took more work than building one with it. Club Chronic's rule, in
   the room most likely to talk itself out of it: a light that can put somebody
   on the floor has no business in a room whose argument is come as you are.
   The dial governs the area and every other world on it. There is nothing in
   this room for it to flash, and there is not going to be. */

.lagoon { background: var(--lag-water); color: var(--lag-dim); font-family: 'Chivo', system-ui, sans-serif; }
.lagoon a { color: var(--lag-acid); }
.lagoon a:hover { color: var(--lag-screen); }
.lagoon p, .lagoon li { font-size: 16.5px; line-height: 1.68; }
.lagoon .backlink { font-family: 'Chivo', system-ui, sans-serif; font-size: 15px; letter-spacing: 0; color: var(--lag-acid); }
.lagoon .trailmark { margin: 0; font-size: 14px; color: var(--lag-dim); }
.lagoon h2 { font-family: 'Chivo', system-ui, sans-serif; font-weight: 700; font-size: 21px; letter-spacing: .3px; color: var(--lag-poster); margin: 0 0 13px; }
.lagoon h3 { font-family: 'Chivo', system-ui, sans-serif; font-weight: 700; font-size: 23px; line-height: 1.16; color: var(--lag-screen); margin: 0; }
.lagoon cite { font-style: italic; color: var(--lag-screen); }

/* THE BILL, AND THE ONLY PLACE CREEPSTER APPEARS. The h1 and the one line under
   it, and nothing else, ever. See §1: a dripping face is atmosphere paid for
   out of somebody's ability to read the page, and this room would spend that
   money everywhere if the rule were not written down twice. */
.bill { margin: 26px 0 0; }
.bill__pres { margin: 0; font-size: 13px; letter-spacing: 2.6px; text-transform: uppercase; color: var(--lag-dim); }
.lagoon h1 {
  font-family: 'Creepster', Impact, sans-serif; font-weight: 400;
  font-size: clamp(44px, 9vw, 96px); line-height: 1.06;
  color: var(--lag-acid); margin: 8px 0 0; letter-spacing: 1.5px;
}
.bill__sub { font-family: 'Creepster', Impact, sans-serif; font-size: clamp(20px, 3.4vw, 30px); color: var(--lag-screen); margin: 6px 0 0; letter-spacing: 1px; }
.bill__tag { margin: 14px 0 0; font-size: 18px; line-height: 1.5; color: var(--lag-poster); max-width: 52ch; }

.appreciation { margin: 34px 0 0; max-width: 64ch; }
.appreciation p { margin: 0 0 15px; }
.appreciation p:last-child { margin-bottom: 0; }
.lagoon .lede { font-size: 19.5px; line-height: 1.58; color: var(--lag-screen); margin: 0 0 15px; }

/* The Napa section, boxed because it is the one argument on the page that is
   about somebody else's telling rather than about a record. A flat card, not a
   quotation: nothing in it is anybody's words but ours. */
.napa { margin: 34px 0 0; padding: 22px 24px; background: var(--lag-card); border-left: 6px solid var(--lag-poster); border-radius: 0 3px 3px 0; max-width: 68ch; }
.napa p { margin: 0 0 13px; }
.napa p:last-child { margin-bottom: 0; }

.tide { margin: 34px 0 0; padding: 22px 24px; background: var(--lag-card); border-radius: 3px; }
.tide ul { margin: 0; padding: 0 0 0 20px; }
.tide li { margin: 0 0 11px; }
.tide li:last-child { margin-bottom: 0; }
.tide li::marker { color: var(--lag-acid); }

.drivein__intro, .posts__intro { max-width: 64ch; margin: 11px 0 0; }

/* THE SCREEN. A bone rectangle standing on two legs out in the water, and the
   facade is the picture on it. THE LIT STATE IS STYLED FROM THE CONTAINER AND
   NEVER FROM THE BUTTON -- love-embed.js replaces the pressed <button> with a
   bare <div class="facade">, so anything the button was wearing evaporates.
   That is the fault that shipped Swaying Sweetgrass's players at 0x0, and the
   container here is a plain block so a stretched div cannot collapse. */
.drivein { margin: 20px 0 0; }
.drivein__screen { height: 14px; background: var(--lag-screen); border-radius: 3px 3px 0 0; }
.feature { background: var(--lag-card); border: 3px solid var(--lag-screen); border-top: 0; padding: 20px 22px 22px; }
.feature__where { margin: 0; font-size: 12px; letter-spacing: 2.4px; text-transform: uppercase; color: var(--lag-acid); }
.feature h3 { margin: 7px 0 0; font-size: 26px; }
.feature__by { margin: 7px 0 0; font-size: 14.5px; color: var(--lag-dim); }
.feature p { margin: 12px 0 0; max-width: 62ch; }
.feature .facade { margin: 16px 0 0; border-color: var(--lag-blood); background: var(--lag-water); color: var(--lag-screen); font-family: 'Chivo', system-ui, sans-serif; }
.feature .facade:hover { background: var(--lag-card); }
/* The legs: two posts in the water, drawn with a border rather than an element
   each, because a leg is a line and not a box. Ornament, no text. */
.drivein__legs { height: 30px; border-left: 10px solid var(--lag-screen); border-right: 10px solid var(--lag-screen); margin: 0 38px; opacity: .62; }

/* THE RACK: lobby cards on posts out in the shallows. Each card has a bright
   top edge because the screen is in front of and above them, which is the same
   single-source rule the area's boards follow and the reason nothing in either
   place has an even border. The post under each card is a ::after rule rather
   than markup: it carries nothing and says nothing. */
.posts { list-style: none; margin: 22px 0 0; padding: 0; display: grid; gap: 30px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.post { display: flex; flex-direction: column; }
.post__card { background: var(--lag-card); border-top: 4px solid var(--lag-screen); padding: 18px 20px 20px; flex: 1 1 auto; }
.post::after { content: ""; display: block; width: 12px; height: 26px; margin: 0 auto; background: var(--lag-blood); opacity: .7; }
.post__role { margin: 0; font-size: 11.5px; letter-spacing: 2.2px; text-transform: uppercase; color: var(--lag-acid); }
.post h3 { margin: 8px 0 0; }
.post__by { margin: 6px 0 0; font-size: 14px; color: var(--lag-dim); }
.post__cover { margin: 8px 0 0; font-size: 14px; color: var(--lag-poster); }
.post p { margin: 12px 0 0; }
.post .facade { margin: 15px 0 0; border-color: var(--lag-blood); background: var(--lag-water); color: var(--lag-screen); font-family: 'Chivo', system-ui, sans-serif; font-size: 14.5px; }
.post .facade:hover { background: var(--lag-card); }

.further { margin: 40px 0 0; padding: 22px 24px; background: var(--lag-card); border-left: 6px solid var(--lag-acid); border-radius: 0 3px 3px 0; max-width: 68ch; }
.further p { margin: 0 0 13px; }
.further__go { margin: 0; font-size: 15px; }

/* §36 ── ROOM: Sithen (turning 02 in The Outskirts) ──────────────────────────
   A FAIRY FORT SEEN FROM THE OUTSIDE, UNDER A FULL MOON. Turning 02 off The
   Outskirts, and the second thing to stand on that road, which is where an area
   would start growing a house style if it were ever going to. It does not: the
   road is khaki, rust and bone, lit from one low angle and painted by hand.
   This is grey-violet, silver and thorn-black, lit from directly overhead.

   THE DOOR IS NOT OPENED, AND THAT IS THE DESIGN. Every other underground place
   on this street is an INTERIOR with one small flame in it -- The Latibulum's
   lamp, the Faery Yurt's candles, The Den's panelling, the Hermitage's curtained
   cave. This room is the same idea in every respect except the one that matters,
   because it never goes in. There is no interior and there is no flame. If a
   door is ever opened here it becomes a SUBROOM with its own world, the way The
   Den hangs off the Jungle Room; it does not become this page with rooms added.

   AND THERE IS NO GREEN IN IT ANYWHERE, which is what holds it off the
   campgrounds -- the other cold night ground on this site, and by a long way the
   likeliest collapse. That field is blue-green: spruce, lichen, moss, a
   moon-coloured link. Grass under a full moon has no colour, only a brightness,
   so every value here sits on one grey-violet line. The other separation is
   structural and simpler: the campgrounds is an OPEN FIELD with posts standing
   about in it and the sky on it, and this is ONE OBJECT that you circle. If a
   green ever appears in this section it has become the campgrounds with a
   hedge, and it is this room that moves.

   MOONLIGHT IS FROM ABOVE AND HEADLIGHTS ARE FROM THE SIDE, which is why
   nothing in here has the road's single bright edge. Panels are evenly lit and
   sit on the ground; what little shadow there is goes straight down. */

.sithen { background: var(--sth-night); color: var(--sth-dim); font-family: 'Literata', Georgia, serif; }
.sithen a { color: var(--sth-moon); }
.sithen a:hover { color: var(--sth-bone); }
.sithen p, .sithen li { font-size: 16.5px; line-height: 1.7; }
.sithen .backlink { font-family: 'Literata', Georgia, serif; font-size: 15px; letter-spacing: 0; color: var(--sth-moon); }
.sithen .trailmark { margin: 0; font-size: 14px; color: var(--sth-dim); }
.sithen h2 { font-family: 'Italiana', Georgia, serif; font-weight: 400; font-size: 27px; letter-spacing: 1.4px; color: var(--sth-bone); margin: 0 0 13px; }
.sithen h3 { font-family: 'Italiana', Georgia, serif; font-weight: 400; font-size: 25px; letter-spacing: .8px; line-height: 1.2; color: var(--sth-bone); margin: 0; }
.sithen .lede { font-size: 19.5px; line-height: 1.62; color: var(--sth-bone); max-width: 62ch; margin: 26px 0 0; }
.sithen cite, .sithen i { font-style: italic; }

/* The mound itself. The h1 is the one place this face goes very large, and the
   drawing sits under it rather than beside it -- you are looking ACROSS a field
   at a thing on the horizon, so it is wide and shallow and the words are above
   it, which is where your eyes are. */
.mound { margin: 26px 0 0; }
.mound__over { margin: 0; font-size: 13px; letter-spacing: 2.4px; text-transform: uppercase; color: var(--sth-dim); }
.sithen h1 {
  font-family: 'Italiana', Georgia, serif; font-weight: 400;
  font-size: clamp(52px, 11vw, 124px); line-height: 1.02;
  color: var(--sth-bone); margin: 10px 0 0; letter-spacing: 4px;
}
.mound__sub { margin: 4px 0 0; font-family: 'Italiana', Georgia, serif; font-size: clamp(19px, 3vw, 27px); letter-spacing: 1.6px; color: var(--sth-moon); }
.mound__art { margin: 20px 0 0; line-height: 0; }
.mound__art svg { display: block; width: 100%; height: auto; }

/* A panel of banked earth. FLAT, and it sits ON the ground rather than being
   lit from an edge: the road outside gets its light from one side and this gets
   it from overhead, which in a stylesheet means an even panel and no bright
   border anywhere. */
.bank {
  margin: 34px 0 0; padding: 22px 26px; max-width: 68ch;
  background: var(--sth-bank); border-radius: 2px;
}
.bank p { margin: 0 0 13px; }
.bank p:last-child { margin-bottom: 0; }
.bank--turn { border-top: 2px solid var(--sth-thorn); }
.bank--door { border-top: 2px solid var(--sth-thorn); }
.bank__later { font-size: 15px; color: var(--sth-dim); }

.ring__intro { max-width: 66ch; margin: 11px 0 0; }

/* The documented half. Plain rows, no ornament: this is the part of the page
   that is supposed to be checkable, and dressing it up would make it look like
   the other half. */
.dugs { list-style: none; margin: 22px 0 0; padding: 0; display: flex; flex-direction: column; gap: 20px; }
.dug { padding: 0 0 0 20px; border-left: 2px solid var(--sth-thorn); max-width: 68ch; }
.dug__what { margin: 0; color: var(--sth-bone); font-weight: 700; }
.dug p { margin: 7px 0 0; }

/* The rules along the bank. NUMBERED AND IN TWO HALVES, which is the whole
   argument made visible: the inherited half above the line and ours below it,
   so nobody has to work out by tone which is which. */
.taboos { list-style: none; margin: 24px 0 0; padding: 0; display: flex; flex-direction: column; gap: 26px; }
.rule { display: flex; gap: 20px; align-items: flex-start; max-width: 74ch; }
.rule__no { flex: 0 0 auto; margin: 0; font-family: 'Italiana', Georgia, serif; font-size: 30px; line-height: 1; color: var(--sth-moon); min-width: 1.6em; }
.rule__body { flex: 1 1 auto; min-width: 0; background: var(--sth-bank); padding: 18px 20px; border-radius: 2px; }
.rule__said { margin: 9px 0 0; color: var(--sth-bone); }
.rule__from { margin: 8px 0 0; font-size: 14px; color: var(--sth-dim); }
.rule__like { margin: 14px 0 0; padding: 13px 0 0; border-top: 1px solid var(--sth-thorn); }
.rule__like b { color: var(--sth-moon); font-weight: 700; }

.creditors { margin: 42px 0 0; padding: 22px 26px; max-width: 70ch; background: var(--sth-bank); border-top: 2px solid var(--sth-moon); border-radius: 2px; }
.creditors p { margin: 0 0 13px; }
.creditors__go { font-size: 15.5px; }
.creditors__src { margin: 0; font-size: 14.5px; color: var(--sth-dim); }

/* §37 ── ROOM: Covenstead (a shopfront on the street) ────────────────────────
   A KITCHEN IN THE AFTERNOON, WITH ONE WINDOW AND THE MISMATCHED CHINA OUT.
   This room began as turning 03 in The Outskirts and was moved onto the street
   -- Ryan's call, 2026-09-22 -- because a covenstead is a group that meets
   REGULARLY, which is neither what the campgrounds are for (quiet, apart, at
   peace in nature) nor what the road out of town is for (night revelry, and
   being as far off as you can get). A group that meets every week wants a
   premises with a door on a street.

   IT CHANGED WORLDS WHEN IT MOVED, which is the whole reason this is not a
   relocation with the same stylesheet. Out there it was a dark room lit by
   several lamps that did not match. Here it is daylit, warm and domestic, and
   THE ARGUMENT MOVED WITH IT RATHER THAN BEING DROPPED: the thing that carries
   "several people who do not match, meeting anyway" is now the CHINA. Nobody's
   cup is anybody else's cup. That device is load bearing and has to survive any
   future redecoration of this room -- if the crockery is ever made to match,
   the room has lost its subject and kept its wallpaper.

   THREE PALE ROOMS ALREADY EXIST HERE AND THE LIGHT IS WHAT TELLS THEM APART:
     · the Solarpunk Hermitage is a LANDSCAPE under low morning sun, shadows
       falling away from it, a cabin with solar infrastructure on it.
     · the Garden is MIDDAY from directly overhead, through leaves, outdoors,
       and everything in it is tinted green by the canopy.
     · the Adventurer's Guild has NO LIGHT SOURCE AT ALL. It is lit the way a
       photocopy is lit, evenly, from nowhere, and casts nothing.
     · this is an INTERIOR with one window in the side of it, mid-afternoon.
       The light comes from one side, lands in a patch on the wall and the
       table, and the rest of the room is soft shade. You are indoors, sitting
       down, and it is somebody's house.
   AND ITS WALL IS WARM AND SLIGHTLY PINK where both the other daylit rooms are
   green-white. If this limewash ever cools towards green it has become the
   garden with furniture in it.

   IT IS ALSO NOT THE LATIBULUM, the street's other dark-on-lit-plaster room.
   That is a BURROW: underground, no daylight anywhere in it, one lamp at knee
   height, earth all round the plaster. This has a window, and the whole room is
   lit by what comes through it.

   THE TYPE DID NOT CHANGE AND DID NOT NEED TO. See §1: the witches this room is
   partly built on are practical, domestic and unglamorous, so the faces are
   deliberately ordinary -- which was true of a kitchen at night and is true of
   the same kitchen in daylight. */

.covenstead { background: var(--cov-wash); color: var(--cov-ink-2); font-family: 'Asap', system-ui, sans-serif; }
.covenstead a { color: var(--cov-delft); }
.covenstead a:hover { color: var(--cov-rose); }
/* The ring is the tea-dark ink, 13.17 on the limewash and 14.77 on a cloth,
   where yellow was 1.10 and 1.23. check-focus.py. */
.covenstead :focus-visible { outline-color: var(--cov-ink); }
.covenstead p, .covenstead li { font-size: 16.5px; line-height: 1.68; }
.covenstead .backlink { font-family: 'Asap', system-ui, sans-serif; font-size: 15px; letter-spacing: 0; color: var(--cov-delft); }
.covenstead .trailmark { margin: 0; font-size: 14px; color: var(--cov-ink-2); }
.covenstead h2 { font-family: 'Petrona', Georgia, serif; font-weight: 700; font-size: 25px; color: var(--cov-ink); margin: 0 0 13px; }
.covenstead h3 { font-family: 'Petrona', Georgia, serif; font-weight: 700; font-size: 23px; line-height: 1.2; color: var(--cov-ink); margin: 0; }
.covenstead .lede { font-size: 19.5px; line-height: 1.6; color: var(--cov-ink); max-width: 62ch; margin: 24px 0 0; }
.covenstead .skip { color: var(--cov-ink); }

/* THE PATCH OF AFTERNOON SUN, which is where the window light lands. It is a
   GROUND rather than an effect -- text sits on it and both grounds are measured
   -- so it is a flat colour and never a gradient under type, which is The
   Rabbit Hole's rule. */
.meet { margin: 26px 0 0; padding: 24px 26px 4px; background: var(--cov-sun); border-radius: 3px; }
.meet__over { margin: 0; font-size: 13px; letter-spacing: 2.2px; text-transform: uppercase; color: var(--cov-ink-2); }
.covenstead h1 {
  font-family: 'Petrona', Georgia, serif; font-weight: 700;
  font-size: clamp(44px, 8.4vw, 84px); line-height: 1.04;
  color: var(--cov-ink); margin: 10px 0 0;
}
/* The greeting, in the three glazes at once — the only place all three appear
   together, and the reason all three are measured against both grounds rather
   than treated as ornament. */
.meet__sub { margin: 10px 0 0; font-family: 'Petrona', Georgia, serif; font-size: clamp(19px, 3vw, 28px); line-height: 1.3; color: var(--cov-delft); }
.meet__sub b:nth-of-type(1) { color: var(--cov-sage); font-weight: 700; }
.meet__sub b:nth-of-type(2) { color: var(--cov-rose); font-weight: 700; }
.meet__art { margin: 18px 0 0; line-height: 0; }
.meet__art svg { display: block; width: 100%; height: auto; }

/* A scrubbed panel: the table, and every boxed piece of the room. It sits on
   the wall rather than glowing — in here the light comes through a window and
   lands, so a panel is a shade DARKER than the patch it sits beside and never
   brighter than the room. */
.scrub { margin: 32px 0 0; padding: 22px 26px; max-width: 68ch; background: var(--cov-sun); border-radius: 3px; border-left: 4px solid var(--cov-sage); }
.scrub p { margin: 0 0 13px; }
.scrub p:last-child { margin-bottom: 0; }
.scrub ul { margin: 0; padding: 0 0 0 20px; }
.scrub li { margin: 0 0 10px; }
.scrub li:last-child { margin-bottom: 0; }
.scrub li::marker { color: var(--cov-rose); }

.parting { border-left-color: var(--cov-delft); }
.thanks { margin: 42px 0 0; padding: 22px 26px; max-width: 70ch; background: var(--cov-sun); border-left: 4px solid var(--cov-rose); border-radius: 3px; }
.thanks p { margin: 0 0 13px; }
.thanks p:last-child { margin-bottom: 0; }
.thanks__src { font-size: 14.5px; color: var(--cov-ink-2); }

.seats__intro { max-width: 66ch; margin: 11px 0 0; }

/* The places at the table. EACH SEAT HAS ITS OWN CUP and the glazes cycle
   through the three, so no two neighbours drink out of the same thing. That is
   the room's argument sitting in a list, and it is what the mismatched lamps
   were doing before this room moved indoors and into the afternoon. */
.seats { list-style: none; margin: 24px 0 0; padding: 0; display: flex; flex-direction: column; gap: 24px; }
.seat { display: flex; gap: 18px; align-items: flex-start; max-width: 74ch; }
.seat__lamp { flex: 0 0 auto; margin: 7px 0 0; width: 20px; height: 15px; border: 2px solid var(--cov-delft); border-top: 0; border-radius: 0 0 8px 8px; }
.seat__lamp::after { content: ""; display: block; width: 7px; height: 7px; margin: 2px 0 0 18px; border: 2px solid var(--cov-delft); border-left: 0; border-radius: 0 6px 6px 0; }
.seat:nth-child(3n+2) .seat__lamp, .seat:nth-child(3n+2) .seat__lamp::after { border-color: var(--cov-sage); }
.seat:nth-child(3n+2) .seat__lamp { border-top: 0; }
.seat:nth-child(3n) .seat__lamp, .seat:nth-child(3n) .seat__lamp::after { border-color: var(--cov-rose); }
.seat:nth-child(3n) .seat__lamp { border-top: 0; }
.seat__body { flex: 1 1 auto; min-width: 0; background: var(--cov-sun); padding: 18px 20px; border-radius: 3px; }
.seat__said { margin: 9px 0 0; color: var(--cov-ink); }
.seat__whose { margin: 8px 0 0; font-size: 14px; color: var(--cov-ink-2); }
.seat__argued { margin: 13px 0 0; padding: 12px 0 0; border-top: 1px solid var(--cov-ink-2); font-size: 15.5px; }
.seat__argued b { color: var(--cov-delft); }
.seat__note { margin: 13px 0 0; }

/* THE QUOTATIONS. Set larger than the room's own prose and in the display
   serif, because on this page they are the tenet rather than an illustration of
   it — the commentary underneath is the thing that is secondary. Each carries
   its own attribution rather than sharing a footnote at the bottom of the room:
   a cite that sits once at the foot of a page is a cite nobody reads beside the
   words it belongs to. */
.seat__quote { margin: 14px 0 0; padding: 2px 0 2px 18px; border-left: 3px solid var(--cov-rose); }
.seat__quote p { margin: 0; font-family: 'Petrona', Georgia, serif; font-size: 18.5px; line-height: 1.5; color: var(--cov-ink); }
.seat__quote cite { display: block; margin: 8px 0 0; font-family: 'Asap', system-ui, sans-serif; font-style: normal; font-size: 14px; color: var(--cov-ink-2); }
.seat__quote--more { border-left-color: var(--cov-ink-2); }
.seat__quote--more p { font-size: 17px; }

/* §38 ── ROOM: Looming Rocks Amphitheatre (turning 03 in The Outskirts) ──────
   AN OPEN-AIR VENUE AT THE FOOT OF ENORMOUS ROCK FACES, AFTER DARK. Turning 03
   off The Outskirts, and it earns that road rather than the campsite: a venue
   is crowds, volume and staying out late, which is what this area is for and is
   the opposite of what the field past the other end of the street is for.

   THE LIGHT IS THROWN UPWARD AND NOTHING ELSE HERE DOES THAT. Floods stand on
   the ground and point UP the rock, so a face is brightest at its foot and goes
   dark towards the top, and there is nothing overhead at all. That is the exact
   inverse of Sithen two turnings back, where a full moon lights everything from
   directly above -- and of Black Leather Lagoon one turning back, where a
   single lit rectangle throws flat frontal light across water at eye level.
   Three rooms on one road, three directions of light, and the vertical is the
   one nobody had taken.

   AND WHAT GLOWS IS NOT THE LAMP. The lichen FLUORESCES: it takes invisible
   light and gives back visible, which is emission rather than reflection. This
   street already has two kinds of transmitted light -- Swaying Sweetgrass lit
   THROUGH grass blades, The Feed lit through a mask -- and this is the third
   and the strangest, because the source and the colour are not the same thing.
   The lamps are violet; the rocks come back cyan-green.

   THE ROOM IT MUST NOT COLLAPSE INTO IS THE LAGOON, one turning along the same
   road, since both are music rooms with a running order in them. The
   separations are structural: that room is HORIZONTAL -- a horizon, water, a
   screen at eye level - and this is VERTICAL, with the rock going up out of
   frame and the visitor at the bottom of it. That room's acid is a YELLOW-green
   and this lichen is a CYAN-green, far apart in blue. THIS IS THE PAIR TO
   WATCH: if the lichen ever warms towards yellow, the two music rooms on this
   road have started sharing a colour.

   IT IS ALSO NOT THE SOLARPUNK HERMITAGE, although both run on the sun. That
   room is a LIT GROUND under low morning sun, where the panels are how somebody
   LIVES. Here the array charges batteries all day so the floods can run after
   dark: the same technology, the opposite hour, and infrastructure for a show
   rather than for a life. A solar panel is not a style.

   THE SET IS THE HERMITAGE'S MECHANISM AND THE PROMISES COME WITH IT. Tuning is
   not playing: while the stage is dark, previous and next are silent and
   nothing is fetched. See looming.js, which says the rest. */

.looming { background: var(--lr-rock); color: var(--lr-dim); font-family: 'Archivo', system-ui, sans-serif; }
.looming a { color: var(--lr-uv); }
.looming a:hover { color: var(--lr-lichen); }
.looming p, .looming li { font-size: 16.5px; line-height: 1.68; }
.looming .backlink { font-family: 'Archivo', system-ui, sans-serif; font-size: 15px; letter-spacing: 0; color: var(--lr-uv); }
.looming .trailmark { margin: 0; font-size: 14px; color: var(--lr-dim); }
.looming h2 { font-family: 'Bevan', Georgia, serif; font-weight: 400; font-size: 23px; color: var(--lr-bone); margin: 0 0 13px; }
.looming h3 { font-family: 'Bevan', Georgia, serif; font-weight: 400; font-size: 21px; line-height: 1.24; color: var(--lr-bone); margin: 0; }
.looming .lede { font-size: 19.5px; line-height: 1.6; color: var(--lr-bone); max-width: 62ch; margin: 24px 0 0; }

.amphi { margin: 26px 0 0; }
.amphi__over { margin: 0; font-size: 13px; letter-spacing: 2.2px; text-transform: uppercase; color: var(--lr-dim); }
.looming h1 {
  font-family: 'Bevan', Georgia, serif; font-weight: 400;
  font-size: clamp(38px, 7.2vw, 74px); line-height: 1.06;
  color: var(--lr-bone); margin: 10px 0 0;
}
.amphi__sub { margin: 10px 0 0; font-size: clamp(17px, 2.6vw, 23px); line-height: 1.34; color: var(--lr-lichen); }
.amphi__art { margin: 20px 0 0; line-height: 0; }
.amphi__art svg { display: block; width: 100%; height: auto; }

/* A panel is a rock face with a flood on it: lighter at the FOOT, because that
   is where the lamp is. A flat colour sits under the gradient and it is the
   lighter end, which is the worse case for the type standing on it — The Rabbit
   Hole's rule, and the reason both ends are measured. */
.scree {
  margin: 32px 0 0; padding: 22px 26px; max-width: 68ch;
  background: var(--lr-face);
  background-image: linear-gradient(to top, var(--lr-face) 0%, var(--lr-rock) 100%);
  border-bottom: 3px solid var(--lr-uv); border-radius: 3px 3px 0 0;
}
.scree p { margin: 0 0 13px; }
.scree p:last-child { margin-bottom: 0; }
.scree ul { margin: 0; padding: 0 0 0 20px; }
.scree li { margin: 0 0 10px; }
.scree li:last-child { margin-bottom: 0; }
.scree li::marker { color: var(--lr-lichen); }

/* THE STAGE. A dark apron with the rock behind it, and the picture appears in
   the middle of it. The glass is a different black from the room, which is the
   Arcade's trick and is here for the same reason: a screen that is the same
   colour as what it stands in is not a screen. */
.apron { margin: 24px 0 0; }
.apron__glass {
  position: relative; aspect-ratio: 16 / 9; width: 100%;
  background: #0C0A09; border: 3px solid var(--lr-face); border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
}
.apron__glass iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.apron__off { padding: 22px 24px; text-align: center; max-width: 52ch; }
.apron__dark { margin: 0; font-family: 'Bevan', Georgia, serif; font-size: 13px; letter-spacing: 2.4px; color: var(--lr-uv); }
.apron__now { margin: 10px 0 0; font-family: 'Bevan', Georgia, serif; font-size: 21px; line-height: 1.24; color: var(--lr-bone); }
.apron__go { display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: center; justify-content: center; margin: 14px 0 0; }
.apron__runs { font-size: 14.5px; color: var(--lr-dim); }
.apron__play, .apron__door {
  font-family: 'Archivo', system-ui, sans-serif; font-weight: 700; font-size: 15px;
  padding: 9px 16px; border-radius: 3px; cursor: pointer;
  background: var(--lr-face); color: var(--lr-lichen); border: 2px solid var(--lr-lichen);
  text-decoration: none;
}
.apron__play:hover, .apron__door:hover { background: var(--lr-rock); }

/* The lighting desk: previous and next, with the label between them saying
   where it is going and how long that runs BEFORE it is pressed. */
.desk { margin: 18px 0 0; display: flex; flex-wrap: wrap; gap: 10px 18px; align-items: center; justify-content: space-between; padding: 14px 18px; background: var(--lr-face); border-radius: 3px; }
.desk__btn { font-family: 'Archivo', system-ui, sans-serif; font-weight: 700; font-size: 14.5px; padding: 8px 14px; border-radius: 3px; cursor: pointer; background: var(--lr-rock); color: var(--lr-bone); border: 2px solid var(--lr-dim); }
.desk__btn:hover { border-color: var(--lr-lichen); color: var(--lr-lichen); }
.desk__what { margin: 0; flex: 1 1 24ch; text-align: center; font-size: 14.5px; color: var(--lr-dim); }

/* THE RUNNING ORDER, COLLAPSIBLE. A <details>, so it opens and closes with no
   script at all — which is the guild's rule about its escapes, arriving on a
   listing. It ships OPEN, because a set list somebody has to discover is a set
   list most people will not find. */
.setlist { margin: 26px 0 0; }
.setlist > summary { cursor: pointer; font-family: 'Bevan', Georgia, serif; font-size: 18px; color: var(--lr-bone); padding: 12px 16px; background: var(--lr-face); border-radius: 3px; border-left: 4px solid var(--lr-lichen); }
.setlist > summary::marker { color: var(--lr-lichen); }
.setlist__note { margin: 12px 0 0; max-width: 66ch; font-size: 15.5px; }
.acts { list-style: none; margin: 16px 0 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.act { padding: 16px 18px; background: var(--lr-face); border-radius: 3px; border-left: 3px solid var(--lr-rock); }
.act--on { border-left-color: var(--lr-lichen); }
.act__no { margin: 0; font-family: 'Bevan', Georgia, serif; font-size: 12px; letter-spacing: 2px; color: var(--lr-uv); }
.act h3 { font-size: 18px; line-height: 1.26; margin: 7px 0 0; }
.act__by { margin: 6px 0 0; font-size: 14px; color: var(--lr-dim); }
.act p { margin: 10px 0 0; }
.tuneto { margin: 12px 0 0; font-family: 'Archivo', system-ui, sans-serif; font-weight: 700; font-size: 14.5px; padding: 8px 14px; border-radius: 3px; cursor: pointer; background: var(--lr-rock); color: var(--lr-lichen); border: 2px solid var(--lr-lichen); }
.tuneto:hover { background: var(--lr-face); }
.scree__go { font-size: 14.5px; color: var(--lr-dim); }

/* THE LICHEN ITSELF, in the space beside the paragraph that explains it. The
   panels in this room are capped at 68ch for reading, which on a wide screen
   leaves the right-hand column empty — so the thing the section is ABOUT goes
   there. Three growth forms, drawn rather than photographed: crustose rosettes
   with the rock cracking through them, foliose lobes, and little fruticose
   stalks with fruiting bodies on the ends.

   IT IS AT ONE OPACITY AND IT DOES NOT MOVE. A glow that pulsed would be the
   obvious next thought and it is refused for Club Chronic's reason, which this
   room's own door policy repeats: nothing in the rig flashes at any setting.
   It carries no text, is aria-hidden, and names no species — see
   tools/make-looming.py on why that last one is a rule rather than a habit. */
.glowwall { display: flex; flex-wrap: wrap; gap: 10px 28px; align-items: center; }
.glowwall .scree { flex: 1 1 46ch; margin-top: 32px; }
.glowwall__art { flex: 1 1 200px; max-width: 320px; line-height: 0; }
.glowwall__art svg { display: block; width: 100%; height: auto; }

/* §39 ── THE ADDRESS THAT IS NOT ON THE STREET (404.html) ────────────────────
   WHAT NETLIFY SERVES AT ANY ADDRESS NOBODY BUILT, WITH A 404 STATUS. It is
   not a room and not a premises, and it is not in the sitemap, on the job
   board or on a share card, because it has no address of its own to list,
   post a job at or unfurl: it is whichever address somebody arrived at by
   mistake. It is still a world, because on this street a page with nothing of
   its own would be the one place the architecture quietly gave up. Before this
   existed a missing address got Netlify's own teal "Page not found" and no way
   back, which is the default this site exists to refuse.

   FOG. A HOUSE-NUMBER PLATE ON A POST, AND NO HOUSE BEHIND IT. The number is
   here; the building is not. Everything else is rooftops going back into the
   air until they are gone.

   THE LIGHT IS FROM EVERYWHERE, AND NO OTHER WORLD HERE IS LIT THAT WAY.
   Every room on this street is lit from somewhere or from nowhere: above
   through leaves, from one side at desk height, from behind at a hundred feet,
   through a mask, from under the floor, from the ground up, by headlights, by
   a moon directly overhead, by one sodium lamp. Fog scatters light until it
   arrives from every direction at once, so nothing has a lit face and nothing
   casts a shadow, and DISTANCE IS CARRIED BY PALENESS AND BY NOTHING ELSE.

   THE PALE ROOMS ARE THE ONES TO WATCH, and each is held off by something
   physical rather than by a palette:
     · the Adventurer's Guild is lit from NOWHERE and has NO DEPTH -- a
       photocopy, manila, made of ruled lines. Fog is lit from EVERYWHERE and
       is nothing but depth: layer behind layer, each paler than the last, and
       not one ruled line.
     · the Foundry is mid-grey iron under north light with brass in it. This is
       paler than the Foundry's one proof sheet, cold, and has nothing warm in
       it at all. IF A WARM VALUE EVER APPEARS IN THIS SECTION, the fog has
       burned off and it is a grey room with a lamp in it.
     · the Doomscroll is warm foxed newsprint lying on a dark desk you can see
       the edges of. There are no edges here and nothing is lying on anything.
     · the Hermitage, the Garden and Covenstead are daylit, each from ONE
       direction, and all three have shadows. Fog has no direction.
   Danny the Street and The Outskirts are the other two outdoor places at
   ground level, and both are night with one light in them. This is day with
   no light you could point at.

   ONE FACE, TWO WEIGHTS. Work Sans sets the plate, the heading and every word,
   because fog takes contrast out of everything it touches and a page about an
   address that is not there has nothing to shout about. The plate is its one
   loud thing and it is loud because it is NEAR, not because it is a display face.

   NOTHING MOVES AT ANY SETTING, AND THERE IS NO TRANSFORM IN THIS SECTION.
   Drifting fog is a pleasant screensaver and a room where the words seem to
   swim, which is the wrong thing to hand somebody who has just been let down
   by a link. The drawing is flat layers standing still.

   THE LINK COLOUR AND THE FOCUS RING ARE DECIDED HERE, AT THE ROOM. This is a
   pale ground on a dark street: the base's link pink and its yellow focus ring
   were both chosen for near-black and would fall through onto the fog, which
   is the Doomscroll's hole and the Playhouse's. The ring is the ink, 11.04 on
   the fog.

   EVERY PATH ON THE PAGE STARTS WITH A SLASH, and the page says why in its own
   head: it is served at whatever address somebody mistyped, including ones
   several directories deep, so `love.css` would resolve against a directory
   that does not exist. */

.room-fog {
  background: var(--fg-fog);
  color: var(--fg-ink);
  font-family: 'Work Sans', var(--sans);
  font-size: 17px;
  line-height: 1.65;
}
.room-fog a { color: var(--fg-link); text-decoration: underline; text-underline-offset: 3px; }
.room-fog a:hover,
.room-fog a:focus-visible { color: var(--fg-ink); }
.room-fog :focus-visible { outline-color: var(--fg-ink); }
/* The dial keeps its yellow ring from §3, because it is a dark box. THE SKIP
   LINK DOES NOT: it is a yellow box whose ring falls on the fog outside it,
   and the first draft of this section exempted it along with the dial on the
   theory that it carried its own ground. It does, and the ring is not on it. */

.fg-main {
  width: min(680px, calc(100% - 32px));
  margin: 0 auto;
  padding: 18px 0 64px;
}

/* THE FOG BANK. In the flow, never behind a word: the rooftops are 1.22 and
   1.53 against the air and nothing is ever set on them. Rather than a
   background layer, which would put an unmeasured ground under the heading on
   any screen narrow enough for the two to meet. */
.fg-bank {
  display: block;
  width: 100%;
  height: clamp(110px, 20vw, 190px);
  margin: 10px 0 0;
  /* The bank has no edges, because fog has none: the rooftops go on into the
     air sideways and upwards until they are gone, rather than stopping at the
     column like a picture pasted onto the page. A mask, not a transform or an
     opacity animation -- it is painted once and never moves. */
  -webkit-mask-image: linear-gradient(to right, transparent, #000 16%, #000 84%, transparent),
                      linear-gradient(to bottom, transparent, #000 32%);
  -webkit-mask-composite: source-in;
          mask-image: linear-gradient(to right, transparent, #000 16%, #000 84%, transparent),
                      linear-gradient(to bottom, transparent, #000 32%);
          mask-composite: intersect;
}

/* The sign. A plate and a post, standing in the near foreground, flat: no
   shadow, no highlight, no bevel, because in fog nothing has a lit side. */
/* POSITIONED SO IT PAINTS OVER THE BANK. A masked element gets its own
   stacking context and is painted with the positioned ones, above every
   ordinary block after it in the source -- so without this the fog bank drew
   itself over the top of the plate the moment it was given soft edges. */
.fg-sign {
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  margin: -34px 0 26px;
}
.fg-plate {
  margin: 0;
  background: var(--fg-plate);
  color: var(--fg-enamel);
  border: 3px solid var(--fg-enamel);
  outline: 3px solid var(--fg-plate);
  border-radius: 10px;
  padding: 10px 26px 12px;
  font-weight: 600;
  font-size: clamp(40px, 9vw, 64px);
  line-height: 1;
  letter-spacing: .02em;
  font-variant-numeric: tabular-nums;
}
.fg-plate__no {
  font-size: .42em; letter-spacing: .08em;
  vertical-align: .9em; margin-right: .18em;
}
.fg-post {
  width: 12px; height: 88px;
  background: var(--fg-post);
}

.room-fog h1 {
  font-weight: 600;
  font-size: clamp(30px, 6vw, 44px);
  line-height: 1.12;
  letter-spacing: -.01em;
  margin: 0 0 14px;
  text-align: center;
  text-wrap: balance;
}
.fg-lede {
  font-size: 19px; text-align: center; margin: 0 auto 36px; max-width: 34em;
  text-wrap: pretty;
}
.room-fog h2 {
  font-weight: 600; font-size: 21px; line-height: 1.3;
  margin: 34px 0 8px;
}
.fg-list { padding-left: 1.2em; margin: 0; }
.fg-list li { margin: 0 0 10px; }
.fg-note { color: var(--fg-dim); font-size: 15px; margin: 34px 0 0; }
.room-fog code { font-size: .92em; }
.fg-dial { max-width: 400px; margin: 40px 0 0; }


/* §40 ── ROOM: Dead Tired Society (a shopfront on the street) ────────────────
   A BORROWED ROOM AFTER HOURS, WITH THE BIG LIGHTS OFF AND THE DOOR LEFT AJAR.
   Peer support by and for the burnt out, and the name is a play on Dead Poets
   Society -- which takes the shape of the name and nothing else from the film.

   THE LIGHT IS OUTSIDE THE ROOM AND NOBODY IS SITTING IN IT. Every other world
   on this street is lit by something in it or over it -- a lamp, a candle, the
   floor, the sun, a screen, a moon, a sodium head, a flood. Here the only light
   is a corridor's strip lights coming through a gap in a door, lying on the
   floor as one hard-edged wedge, and EVERY WORD ON THE PAGE STAYS IN THE SHADE.
   That is not a mood. Masking is performing under a light, and this is the one
   room where nothing has to stand in it: --dts-hall is drawn and never carries
   text, and nothing in this section may put a word on it. If a panel in here is
   ever lit to make it "pop", the room has lost the one thing it is about.

   THESE ARE THE COLLISIONS TO WATCH, and every one is structural:
     · THE LATIBULUM is also for burnouts, and it is a burrow for being
       unfindable in ALONE: brown earth, a lamp at knee height, and almost every
       word dark on lit plaster. This is a room you share, it is plum and not
       brown, every word is pale on the dark, and the one lit surface in it
       carries nothing at all.
     · THE HEALING CHECKPOINT is also about not being made to earn anything,
       and its light comes UP out of the floor, soft, green-blue, so that you
       could put your hand in it. This light arrives SIDEWAYS through a door and
       lies flat on the floor with a hard edge, and there is no bed.
     · COVENSTEAD is also a group meeting on purpose, and its light also comes
       in from one side. That room is daylit throughout, its patch is 1.12 from
       its wall, and it sets its words IN the patch. This one is dark, its patch
       is fourteen times brighter than anything near it, and keeps every word
       out of it. A kitchen with the good china out, and a room with the chairs
       pushed back.
     · THE MOPERY is the collision the NAME invites, because Dead Poets Society
       is the film dark academia is named after. No candle, no book, no stone,
       no tweed and nothing old: the light is a fluorescent tube in a corridor,
       and the most academic thing in here is a school blazer hung up by the
       door and left there. If a candle ever appears in this room it has become
       the Mopery with fewer books.

   THE CORRIDOR'S TUBES DO NOT FLICKER. A strip light is a flickering object
   nearly by definition, and Club Chronic's rule holds here for Club Chronic's
   reason: nothing flashes on this street at any setting. The only motion in the
   room is the dust in the doorway, which drifts at MAX, stands still at Regular
   and is taken away by §3 at Gentle, and it moves with a translate because
   rotation and skew are all check-gentle.py can read.

   AND THERE ARE NO PANELS. Nothing here is boxed: the text sits on the room's
   own ground, the pegs hang on the wall, and sections are parted by space and a
   hairline. The Feed is the one room on this street whose furniture is darker
   than its room, and a box of --dts-deep under the pegs would have been that
   room's claim arriving in this one. */

.dead-tired { background: var(--dts-room); color: var(--dts-text); font-family: 'Lexend', system-ui, sans-serif; }
.dead-tired a { color: var(--dts-exit); text-underline-offset: 3px; }
.dead-tired a:hover { color: var(--dts-pale); }
/* :where() so this base is (0,1,0) and every component below it wins by order.
   Written as `.dead-tired p` it was (0,1,1), and it quietly set the est. line,
   the over-line and the trail at body size -- the Playhouse's `.toy--orange
   span` lesson, caught by looking at the page. */
.dead-tired :where(p, li) { font-size: 17px; line-height: 1.7; }
.dead-tired strong { color: var(--dts-pale); font-weight: 600; }
.dead-tired code { font-size: .9em; color: var(--dts-pale); }
.dead-tired .backlink { font-family: 'Lexend', system-ui, sans-serif; font-size: 15px; letter-spacing: 0; color: var(--dts-exit); }

.dts-topline { display: flex; flex-wrap: wrap; gap: 14px; justify-content: space-between; align-items: baseline; }
.dts-trail { margin: 0; font-size: 14px; color: var(--dts-dim); }

/* THE NAME, set like a founding charter, which is the joke: the grandest name on
   the street for a society whose members are lying on the floor. Goudy's italic
   is spent on the one word of pomp under it and nowhere else. */
.dts-head { margin: 34px 0 0; }
.dts-over { margin: 0; font-size: 13px; letter-spacing: 2.4px; text-transform: uppercase; color: var(--dts-dim); }
.dead-tired h1 {
  font-family: 'Sorts Mill Goudy', Georgia, serif; font-weight: 400;
  font-size: clamp(46px, 9vw, 96px); line-height: 1.02;
  color: var(--dts-pale); margin: 12px 0 0;
}
.dts-est { margin: 8px 0 0; font-family: 'Sorts Mill Goudy', Georgia, serif; font-size: clamp(20px, 2.6vw, 26px); line-height: 1.3; color: var(--dts-dim); }
.dts-art { margin: 22px 0 0; line-height: 0; }
.dts-art svg { display: block; width: 100%; height: auto; }

.dts-lede { font-size: 20px; line-height: 1.62; color: var(--dts-pale); max-width: 62ch; margin: 28px 0 0; }
.dts-worse { margin: 20px 0 0; max-width: 62ch; padding: 2px 0 2px 16px; border-left: 3px solid var(--dts-exit); font-size: 16px; }

.dts-part { margin: 56px 0 0; max-width: 72ch; }
.dts-part > :where(p) { margin: 0 0 14px; }
.dead-tired h2 { font-family: 'Sorts Mill Goudy', Georgia, serif; font-weight: 400; font-size: clamp(29px, 4vw, 38px); line-height: 1.15; color: var(--dts-pale); margin: 0 0 14px; }
.dead-tired h3 { font-family: 'Sorts Mill Goudy', Georgia, serif; font-weight: 400; font-size: 27px; line-height: 1.15; color: var(--dts-pale); margin: 0; }

/* THE STANDING ORDERS, which nobody is standing for. Hairlines rather than
   bullets, because a bullet in front of each is the start of a checklist and
   these are not things to do. */
.dts-orders { list-style: none; margin: 18px 0 0; padding: 0; }
.dts-orders li { margin: 0; padding: 12px 0; border-top: 1px solid var(--dts-edge); }
.dts-orders li:last-child { border-bottom: 1px solid var(--dts-edge); }

/* The two lines that define the thing. In the reading face, larger and paler:
   Goudy is kept for names and never set as a sentence, because the Mopery owns
   a text serif and the yurt owns a high-contrast one. */
.dts-said { margin: 20px 0 22px; padding: 4px 0 4px 20px; border-left: 2px solid var(--dts-edge); }
.dts-said p { margin: 0; font-size: 20px; line-height: 1.5; color: var(--dts-pale); }
.dts-said cite, .dts-peg__quote cite { display: block; margin: 8px 0 0; font-size: 14px; font-style: normal; line-height: 1.5; color: var(--dts-dim); }

/* THE PEGS BY THE DOOR. One rail and one kind of peg all the way along, because
   it is one wall, and never the same thing hanging on two of them. The drawing
   is aria-hidden; the line beginning "On the peg" says the same thing in words. */
.dts-intro { margin: 0; }
.dts-pegs { list-style: none; margin: 30px 0 0; padding: 0; display: grid; gap: 38px; }
.dts-peg { display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 24px; align-items: start; }
.dts-peg__art { display: block; width: 120px; height: auto; }
.dts-peg__on { margin: 8px 0 0; }
.dts-peg__label { font-size: 12.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--dts-dim); }
.dts-peg__quote { margin: 14px 0 0; padding: 2px 0 2px 16px; border-left: 2px solid var(--dts-exit); }
.dts-peg__quote p { margin: 0; color: var(--dts-pale); }
.dts-peg__note { margin: 12px 0 0; }
.dts-peg__entry { margin: 10px 0 0; font-size: 15px; }
.dts-more { margin: 34px 0 0; max-width: 72ch; }

/* THE TALKING PIECE. Pass comes first and is the same size as speaking, because
   a piece that made passing look like the lesser option would be the thing peer
   support exists to undo. It ships hidden; see dead-tired.js. */
.dts-piece { margin: 20px 0 0; }
.dts-piece__row { display: flex; flex-wrap: wrap; gap: 12px; }
.dts-piece__btn {
  min-height: 48px; min-width: 132px; padding: 10px 22px; cursor: pointer;
  font-family: 'Lexend', system-ui, sans-serif; font-weight: 600; font-size: 16px;
  color: var(--dts-pale); background: transparent;
  border: 2px solid var(--dts-edge); border-radius: 999px;
}
.dts-piece__btn:hover { border-color: var(--dts-exit); }
.dts-say { margin: 16px 0 0; display: grid; gap: 10px; max-width: 60ch; }
.dts-say__label { font-size: 15px; line-height: 1.55; }
.dts-say__box {
  width: 100%; min-height: 128px; padding: 12px 14px; resize: vertical;
  font-family: 'Lexend', system-ui, sans-serif; font-size: 17px; line-height: 1.6;
  color: var(--dts-pale); background: transparent;
  border: 2px solid var(--dts-edge); border-radius: 6px;
}
.dts-say .dts-piece__btn { justify-self: start; }
.dts-piece__said { margin: 14px 0 0; min-height: 1.7em; color: var(--dts-pale); }

.dts-nots { margin: 0; padding: 0 0 0 1.1em; }
.dts-nots li { margin: 0 0 12px; }
.dts-nots li::marker { color: var(--dts-exit); }
.dts-further { font-size: 15px; color: var(--dts-dim); }
.dts-thanks { border-top: 1px solid var(--dts-edge); padding-top: 28px; }
.dead-tired .quest { margin-top: 44px; }

/* The dust in the doorway, at MAX only. A translate and nothing else. */
html[data-intensity="max"] .dts-dust circle { animation: dts-drift 13s ease-in-out infinite alternate; }
html[data-intensity="max"] .dts-dust circle:nth-child(2) { animation-duration: 17s; animation-delay: -4s; }
html[data-intensity="max"] .dts-dust circle:nth-child(3) { animation-duration: 11s; animation-delay: -7s; }
html[data-intensity="max"] .dts-dust circle:nth-child(4) { animation-duration: 19s; animation-delay: -2s; }
html[data-intensity="max"] .dts-dust circle:nth-child(5) { animation-duration: 15s; animation-delay: -9s; }
@keyframes dts-drift { from { transform: translate(0, 0); } to { transform: translate(14px, -10px); } }

/* A PEG IS A DRAWING BESIDE ITS WORDS, and on a phone the drawing gets smaller
   rather than going away: hiding it to save room would be the lite version
   arriving through a breakpoint. Written last in the section on purpose, after
   every rule it overrides -- the Playhouse's half-a-breakpoint lesson. */
@media (max-width: 560px) {
  .dts-peg { grid-template-columns: 70px minmax(0, 1fr); gap: 14px; }
  .dts-peg__art { width: 70px; }
  .dts-lede { font-size: 18px; }
}


/* §41 ── ROOM: Laughingstock (a shopfront on the street) ─────────────────────
   A COMEDY CELLAR SEEN FROM THE BACK OF THE HOUSE. Disabled comics on their own
   terms, in their own voice, controlling the frame -- which is the write-up
   this room is built on, and the reason the light works the way it does.

   THE LIGHT COMES FROM BEHIND YOU, AND ONLY WHAT A COMIC SAID STANDS IN IT. One
   follow spot in the lighting box over the audience's heads throws one hard-
   edged pool onto a brick wall. Nothing else on this street is lit from behind
   the person looking at it: the Lagoon's light is a screen in front of you, the
   Outskirts' is a low, level beam sweeping many signs at the roadside, the
   Checkpoint's rises out of the floor, Looming Rocks' climbs the rock, the
   Garden's falls through leaves. So every shadow in the drawing falls straight
   back onto the brick, and the pool has an edge you could trace.

   --ls-spot IS THAT LIGHT AND THE ONLY WORDS EVER SET IN IT ARE THE COMICS'.
   Each of their lines stands in an oval of it, dark ink on the light, with the
   comic's name under it; our context for the line sits OUTSIDE the oval, in the
   house. Everything of ours is out there with the audience. Do not put a word of
   ours in the light to make it "pop" -- that is the room handing the frame back
   to whoever is writing about the comics, which is the thing the write-up is
   against.

   THESE ARE THE COLLISIONS TO WATCH, and every one is structural:
     · DEAD TIRED SOCIETY is one door along and its light also lies on a surface
       with a hard edge. That room's whole rule is that NOBODY sits in the light,
       because masking is performing under one, and it keeps every word out of
       it. This one puts exactly one kind of word in it, on purpose, because the
       person in the light chose to be and is holding the mic. The same light,
       refused there and taken here, and neither room is wrong.
     · CLUB CHRONIC is the other club with a stage, and is a WALL with no light
       source anywhere in it: flat, frontal, a hundred rectangles of paper pasted
       onto black. There is no paper in here and there is one light.
     · BLACK LEATHER LAGOON is the other dark room with one bright shape in it,
       and its bright shape is the SOURCE, a screen standing in the water in
       front of you. Here the bright shape is where the light LANDS.
     · THE DEN is the room the brick would collapse into if it browned: panelled,
       lamplit at knee height, a carpet brighter than the walls. The brick here is
       red, the light is overhead and behind, and the brightest thing in the room
       is a pool on a wall. If --ls-brick or --ls-wall ever go brown, this room
       moves.

   THE NEON DOES NOT FLICKER. A neon sign in a cellar is a flickering object
   nearly by definition, and Club Chronic's rule holds here for Club Chronic's
   reason: nothing flashes on this street at any setting. Its glow is a static
   text-shadow. The only motion in the room is the glass of water on the stool,
   which is sparkling at MAX -- four bubbles rising with a translate -- still at
   Regular, and taken away by §3 at Gentle. Rotation and skew are all
   check-gentle.py can read, and nothing here asks it to take the room's word.

   THE SPOT IS AN ELLIPSE AND THE TEXT INSIDE IT HAS TO STAY INSIDE IT. A line is
   centred, padded 13% by 17% of the oval's width, which keeps the corners of the
   text box inside the curve at every width a line is set at -- measured on a
   phone and on a desk, because the contrast checkers measure against the
   element's background-color and cannot see a letter that has fallen off the
   edge of the light onto the dark. Keep the lines short; the tool caps them. */

.laughingstock { background: var(--ls-house); color: var(--ls-text); font-family: 'Bricolage Grotesque', system-ui, sans-serif; }
.laughingstock a { color: var(--ls-neon); text-underline-offset: 3px; }
.laughingstock a:hover { color: var(--ls-cream); }
/* :where() so this base is (0,1,0) and every component below it wins by order --
   Dead Tired Society's day-one lesson, taken before it could happen here. */
.laughingstock :where(p, li) { font-size: 17px; line-height: 1.68; }
.laughingstock strong { color: var(--ls-cream); font-weight: 700; }
.laughingstock code { font-size: .9em; color: var(--ls-cream); }
.laughingstock .backlink { font-family: 'Bricolage Grotesque', system-ui, sans-serif; font-size: 15px; letter-spacing: 0; color: var(--ls-neon); }

.ls-topline { display: flex; flex-wrap: wrap; gap: 14px; justify-content: space-between; align-items: baseline; }
.ls-trail { margin: 0; font-size: 14px; color: var(--ls-dim); }

/* THE SIGN OVER THE STAGE. Blue tube on a dark cellar, glowing and not
   flickering. The name is a script because a neon sign is copied from a
   sign-writer's hand; nothing you have to read is set in it. */
.ls-head { margin: 34px 0 0; }
.ls-over { margin: 0; font-size: 13px; font-weight: 700; letter-spacing: 2.4px; text-transform: uppercase; color: var(--ls-dim); }
.laughingstock h1 {
  font-family: 'Yellowtail', cursive; font-weight: 400;
  font-size: clamp(56px, 14vw, 148px); line-height: 1.05;
  color: var(--ls-neon); margin: 4px 0 0;
  text-shadow: 0 0 8px rgba(134, 220, 255, .55), 0 0 30px rgba(134, 220, 255, .28);
}
.ls-tonight { margin: 4px 0 0; font-weight: 700; font-size: clamp(19px, 2.6vw, 25px); line-height: 1.3; color: var(--ls-cream); }
.ls-art { margin: 24px 0 0; line-height: 0; }
.ls-art svg { display: block; width: 100%; height: auto; }

.ls-lede { margin: 30px 0 0; max-width: 64ch; }
.ls-lede p { margin: 0 0 16px; font-size: 20px; line-height: 1.6; color: var(--ls-cream); }
.laughingstock .ls-from { font-size: 15px; line-height: 1.6; color: var(--ls-dim); max-width: 70ch; }

.ls-part { margin: 64px 0 0; }
.ls-part > :where(p, ul) { max-width: 70ch; }
.ls-part > :where(p) { margin: 0 0 14px; }
.laughingstock h2 { font-weight: 700; font-size: clamp(28px, 4vw, 38px); line-height: 1.15; letter-spacing: -.01em; color: var(--ls-cream); margin: 0 0 16px; }
.ls-rule-note { margin: 0 0 8px; }

/* THE ACTS. Their names are in lights, which is the one place the neon sets a
   word that is not the club's own. */
.ls-act { margin: 40px 0 0; }
.ls-act > p { max-width: 70ch; margin: 10px 0 0; }
.ls-act h3 {
  font-family: 'Yellowtail', cursive; font-weight: 400; font-size: 46px; line-height: 1.1;
  color: var(--ls-neon); margin: 0; text-shadow: 0 0 8px rgba(134, 220, 255, .45);
}

/* THE LINES IN THE LIGHT. Each is its own pool, because each was its own laugh. */
.ls-lines { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); gap: 30px 26px; margin: 26px 0 0; }
.ls-line { margin: 0; display: flex; flex-direction: column; align-items: center; }
.ls-spot {
  margin: 0; width: 100%; border-radius: 50%; padding: 13% 17%;
  background: var(--ls-spot); color: var(--ls-ink); text-align: center;
  box-shadow: 0 0 0 5px rgba(251, 240, 220, .1), 0 0 44px rgba(251, 240, 220, .12);
}
.ls-spot p { margin: 0; font-weight: 700; font-size: 21px; line-height: 1.3; color: var(--ls-ink); }
.ls-spot cite { display: block; margin: 8px 0 0; font-style: normal; font-weight: 700; font-size: 13px; letter-spacing: .14em; text-transform: uppercase; color: var(--ls-ink-2); }
.laughingstock .ls-line__ctx { margin: 14px 0 0; font-size: 15px; line-height: 1.5; color: var(--ls-dim); text-align: center; max-width: 34ch; }

/* THE PRESSES. The shared plate, dressed for a cellar: the house's own dark,
   one hairline, and the label in the neon. Styled on `.facade` rather than on
   `button.facade`, so the pressed player is dressed the same as the button it
   replaced -- love-embed.js hands back a bare div, and a class on the button
   does not survive the press. */
.laughingstock .facade {
  background: var(--ls-deep); border: 2px solid var(--ls-edge); border-radius: 6px;
  color: var(--ls-cream); font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-weight: 700; font-size: 17px;
}
.laughingstock .facade:hover { border-color: var(--ls-neon); }
.laughingstock .facade__play { font-family: 'Bricolage Grotesque', system-ui, sans-serif; font-weight: 700; font-size: 12px; letter-spacing: .14em; color: var(--ls-neon); }
.laughingstock .facade iframe { border-radius: 4px; }

.ls-stageplate { margin: 18px 0 0; max-width: 900px; }
.ls-stageplate__note { margin: 0 0 14px; }
.laughingstock .ls-stageplate__credit { margin: 10px 0 0; font-size: 14px; color: var(--ls-dim); }

/* THE BILL. In the playlist's own order, and nothing on it bigger than anything
   else: nobody headlines. The comic's name is in lights on every set. */
.ls-bill { list-style: none; margin: 22px 0 18px; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 34px 26px; }
.ls-set { display: flex; flex-direction: column; gap: 8px; }
.ls-set__title { margin: 0; font-weight: 700; font-size: 20px; line-height: 1.25; color: var(--ls-cream); }
.laughingstock .ls-set__who { margin: 0; font-family: 'Yellowtail', cursive; font-size: 28px; line-height: 1.1; color: var(--ls-neon); }
.laughingstock .ls-set__note { margin: 0; font-size: 15px; line-height: 1.5; }
.ls-set .facade { margin-top: auto; }
.laughingstock .ls-set__credit { margin: 0; font-size: 14px; color: var(--ls-dim); }

/* What the laughs are doing, and the house rules: hairlines rather than bullets,
   because neither is a list of things to do. */
.ls-doing, .ls-rules { list-style: none; margin: 18px 0 16px; padding: 0; }
.ls-doing li, .ls-rules li { margin: 0; padding: 13px 0; border-top: 1px solid var(--ls-edge); }
.ls-doing li:last-child, .ls-rules li:last-child { border-bottom: 1px solid var(--ls-edge); }
.ls-questions { margin: 16px 0 18px; padding: 0 0 0 1.2em; }
.laughingstock .ls-questions li { margin: 0 0 12px; font-size: 19px; line-height: 1.55; color: var(--ls-cream); }
.ls-questions li::marker { color: var(--ls-neon); }

.ls-thanks { border-top: 1px solid var(--ls-edge); padding-top: 30px; }
.laughingstock .ls-further { font-size: 15px; color: var(--ls-dim); }
.ls-dialbox { max-width: 380px; }
.laughingstock .quest { margin-top: 44px; }

/* The water on the stool, sparkling at MAX only. A translate and a fade, never
   a flash: four bubbles, each a pixel or two across, rising. */
html[data-intensity="max"] .ls-fizz circle { animation: ls-fizz 2.8s linear infinite; }
html[data-intensity="max"] .ls-fizz circle:nth-child(2) { animation-duration: 3.4s; animation-delay: -1.1s; }
html[data-intensity="max"] .ls-fizz circle:nth-child(3) { animation-duration: 2.3s; animation-delay: -1.8s; }
html[data-intensity="max"] .ls-fizz circle:nth-child(4) { animation-duration: 3.1s; animation-delay: -.6s; }
@keyframes ls-fizz { from { transform: translate(0, 0); opacity: .95; } to { transform: translate(0, -18px); opacity: 0; } }

/* A LINE IN THE LIGHT STAYS A POOL ON A PHONE, one to a row, and the type comes
   down a step rather than the oval going square: a rectangle of light is a
   window, and a window is a different room. Written last in the section on
   purpose, after every rule it overrides -- the Playhouse's half-a-breakpoint
   lesson. */
@media (max-width: 560px) {
  .ls-lines { grid-template-columns: minmax(0, 1fr); }
  .ls-spot p { font-size: 19px; }
  .ls-lede p { font-size: 18px; }
  .ls-act h3 { font-size: 40px; }
}


/* §42 ── ROOM: The Lightbulb Picture House (a shopfront on the street) ───────
   A PICTURE HOUSE WHERE EVERY SCREENING IS A RELAXED SCREENING. Two screens of
   films about autism, ADHD and neurodiversity, most of them made by the people
   they are about, and a rack with a card for every film on the first.

   THE HOUSE LIGHTS STAY UP, AND THAT IS THE ROOM. Every other room on this
   street with a bright rectangle in it keeps the rectangle in the dark --
   Black Leather Lagoon's screen stands in black water, Laughingstock's pool of
   light is on a brick wall in a dark house. This one is lit ALL OVER, by bare
   bulbs in brass sconces down both walls, which is what a relaxed screening
   actually is: nobody sits in the dark who did not ask to. So the ground is lit
   velvet, the seats are a colour rather than a silhouette, and there is no
   beam. The screen is the palest thing in the room and not the only lit one.

   NOTHING IS BLUE. Not the bulbs, not a link, not a shadow. The page says so,
   and make-picture-house.py reads this section and the room's :root colours
   and refuses a blue or cyan hue, because a sentence can be made false by one
   colour somebody thought looked nice. The ornament is the gold infinity and
   never the rainbow one.

   THESE ARE THE COLLISIONS TO WATCH, and every one is structural:
     · LAUGHINGSTOCK is also red and also faces something lit. It is a dark
       house with one spot from behind you; this is a lit house with no spot.
     · THE CHAPPELL is also gold ornament in a devotional building. It is
       votive indigo, arches and glass; there is no indigo in here and there
       cannot be.
     · THE ARCADE has bulbs too, on a marquee round a cabinet, and they are its
       chrome. The bulbs here are house lights on the walls and in a static row
       on the door, and they never chase.
     · THE DEN is the warm lamplit room this would collapse into if the velvet
       browned. It is panelling lit at knee height; this is velvet lit from
       every wall at once.

   NO BULB FLICKERS, DIMS OR CHASES, at any setting, for Club Chronic's reason.
   The only motion is the popcorn in the second row, which pops at MAX with a
   translate, stands still at Regular and is taken away by §3 at Gentle.

   A PRESS-TO-PLAY PLATE IS A SMALL SCREEN, pale with dark ink, and is dressed
   from `.facade` rather than `button.facade` so the player that replaces it
   keeps the frame -- love-embed.js hands back a bare div. */

.picture-house { background: var(--lph-velvet); color: var(--lph-text); font-family: 'Outfit', system-ui, sans-serif; }
.picture-house a { color: var(--lph-gold); text-underline-offset: 3px; }
.picture-house a:hover { color: var(--lph-cream); }
.picture-house :where(p, li) { font-size: 17px; line-height: 1.66; }
.picture-house strong { color: var(--lph-cream); font-weight: 700; }
.picture-house .backlink { font-family: 'Outfit', system-ui, sans-serif; font-size: 15px; letter-spacing: 0; color: var(--lph-gold); }

.lph-topline { display: flex; flex-wrap: wrap; gap: 14px; justify-content: space-between; align-items: baseline; }
.lph-trail { margin: 0; font-size: 14px; color: var(--lph-dim); }

.lph-head { margin: 34px 0 0; }
.lph-over { margin: 0; font-size: 13px; font-weight: 700; letter-spacing: 2.4px; text-transform: uppercase; color: var(--lph-dim); }
.picture-house h1 {
  font-family: 'Limelight', Georgia, serif; font-weight: 400;
  font-size: clamp(40px, 7.4vw, 84px); line-height: 1.08;
  color: var(--lph-cream); margin: 10px 0 0;
}
.lph-tagline { margin: 10px 0 0; font-weight: 700; font-size: clamp(18px, 2.4vw, 23px); line-height: 1.35; color: var(--lph-gold); }
.lph-art { margin: 24px 0 0; line-height: 0; }
.lph-art svg { display: block; width: 100%; height: auto; border-radius: 4px; }

.lph-lede { margin: 30px 0 0; max-width: 66ch; }
.lph-lede p { margin: 0 0 16px; font-size: 20px; line-height: 1.6; color: var(--lph-cream); }

.lph-part { margin: 64px 0 0; }
.lph-part > :where(p, ul) { max-width: 70ch; }
.lph-part > :where(p) { margin: 0 0 14px; }
.picture-house h2 { font-family: 'Limelight', Georgia, serif; font-weight: 400; font-size: clamp(26px, 3.6vw, 36px); line-height: 1.2; color: var(--lph-cream); margin: 0 0 16px; }

.lph-rules { list-style: none; margin: 18px 0 20px; padding: 0; }
.lph-rules li { margin: 0; padding: 12px 0; border-top: 1px solid var(--lph-brass); }
.lph-rules li:last-child { border-bottom: 1px solid var(--lph-brass); }
.lph-blue { margin-top: 24px; }
.lph-said { margin: 18px 0 0; max-width: 64ch; padding: 4px 0 4px 20px; border-left: 3px solid var(--lph-gold); }
.lph-said p { margin: 0; font-size: 19px; line-height: 1.5; color: var(--lph-cream); }
.lph-said cite { display: block; margin: 8px 0 0; font-size: 14px; font-style: normal; color: var(--lph-dim); }

/* THE SCREENS. A stepped Deco frame in brass round a pale screen, which is the
   press-to-play plate until it is pressed and the player after. */
.lph-screen__num { display: block; font-size: .62em; letter-spacing: .12em; text-transform: uppercase; color: var(--lph-gold); }
.lph-proscenium { margin: 18px 0 0; max-width: 900px; padding: 12px; border: 3px solid var(--lph-brass); border-radius: 18px 18px 4px 4px; background: var(--lph-deep); }
.picture-house .facade {
  background: var(--lph-screen); color: var(--lph-ink);
  border: 2px solid var(--lph-brass); border-radius: 4px;
  font-family: 'Outfit', system-ui, sans-serif; font-weight: 700; font-size: 17px;
}
.picture-house .facade:hover { border-color: var(--lph-gold); }
.picture-house .facade__play { font-family: 'Outfit', system-ui, sans-serif; font-weight: 700; font-size: 12px; letter-spacing: .14em; color: var(--lph-ink-2); }
.picture-house .facade iframe { border-radius: 2px; }
.picture-house .lph-screen__note { margin: 0; }
.picture-house .lph-screen__credit { margin: 10px 0 0; font-size: 14px; color: var(--lph-dim); max-width: 70ch; }
.picture-house .lph-two__h { margin: 22px 0 6px; font-weight: 700; color: var(--lph-cream); }
.lph-two { margin: 0; padding: 0 0 0 1.2em; max-width: 72ch; }
.picture-house .lph-two li { margin: 0 0 6px; font-size: 15.5px; }
.lph-two__t { color: var(--lph-cream); font-weight: 700; }
.lph-two li::marker { color: var(--lph-gold); }

/* THE RACK. One card per film, in the order it plays, on the seats' own deep
   velvet with a brass hairline. What is in a film is said on the card, before
   the press, in the same place on every card. */
.lph-rack { list-style: none; margin: 22px 0 18px; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 26px 22px; }
.lph-card { display: flex; flex-direction: column; gap: 8px; padding: 18px 18px 16px; background: var(--lph-deep); border: 1px solid var(--lph-brass); border-radius: 4px; }
.picture-house .lph-card__n { margin: 0; font-family: 'Limelight', Georgia, serif; font-size: 22px; line-height: 1; color: var(--lph-gold); }
.lph-card__title { margin: 0; font-weight: 700; font-size: 20px; line-height: 1.25; color: var(--lph-cream); }
.picture-house .lph-card__makers { margin: 0; font-size: 14px; line-height: 1.45; color: var(--lph-dim); }
.picture-house .lph-card__about { margin: 0; font-size: 16px; line-height: 1.55; }
.picture-house .lph-card__content { margin: 0; font-size: 15px; line-height: 1.5; color: var(--lph-cream); padding-left: 10px; border-left: 3px solid var(--lph-gold); }
.lph-card__label { font-weight: 700; color: var(--lph-gold); }
.lph-card .facade { margin-top: auto; }
.picture-house .lph-card__credit { margin: 0; font-size: 14px; color: var(--lph-dim); }
.picture-house .lph-card__ours { margin: 0; font-size: 14px; }
.picture-house .lph-from { font-size: 15px; color: var(--lph-dim); }

.lph-thanks { border-top: 1px solid var(--lph-brass); padding-top: 30px; }
.picture-house .lph-further { font-size: 15px; color: var(--lph-dim); }
.lph-dialbox { max-width: 380px; }
.picture-house .quest { margin-top: 44px; }

/* The popcorn, at MAX only: four kernels hopping, a translate and nothing else. */
html[data-intensity="max"] .lph-pop circle { animation: lph-pop 1.6s ease-in-out infinite; }
html[data-intensity="max"] .lph-pop circle:nth-child(2) { animation-delay: -.5s; animation-duration: 1.9s; }
html[data-intensity="max"] .lph-pop circle:nth-child(3) { animation-delay: -1.1s; animation-duration: 1.4s; }
html[data-intensity="max"] .lph-pop circle:nth-child(4) { animation-delay: -.8s; animation-duration: 2.2s; }
@keyframes lph-pop { 0%, 70%, 100% { transform: translate(0, 0); } 80% { transform: translate(0, -9px); } }

/* ON A PHONE the rack is one card to a row and the frame round each screen gets
   thinner rather than going: a screen with no frame is a video on a page, and
   that is a different room. Last in the section, after every rule it overrides. */
@media (max-width: 560px) {
  .lph-rack { grid-template-columns: minmax(0, 1fr); }
  .lph-proscenium { padding: 7px; border-width: 2px; border-radius: 12px 12px 4px 4px; }
  .lph-lede p { font-size: 18px; }
}


/* §43 ── ROOM: Dance, Punks (turning 04 in The Outskirts) ────────────────────
   A SILENT DISCO ON AN OLD AIRSTRIP, and the light is the whole separation. It
   is WORN: every dancer has a small steady glow at head height in the colour of
   their channel, and it lights them and whoever is beside them and nothing
   else. There is no source anywhere else on the runway -- no rig, no runway
   lights, no moon -- so a crowd seen from the road is a field of small coloured
   lights with nobody's face in any of them.

   THE ROAD ALREADY HAS THREE LIGHTS AND THIS IS NONE OF THEM. The Lagoon is lit
   by one screen in front of you across water; Sithen from directly overhead by
   the moon; Looming Rocks from the ground up by floods. Nothing there moves with
   the people in it. Here the light goes wherever somebody walks.

   THESE ARE THE COLLISIONS TO WATCH, and every one is structural:
     · CLUB CHRONIC is the other dancefloor and its whole house rule is that a
       loud room is an access barrier. This room is the answer to that sentence,
       which is exactly how it could turn into that room's sequel. The club is a
       WALL: flat, frontal, no light in it, paper pasted on black. This has no
       wall, no stage and no paper -- it is a crowd standing on open tarmac.
     · LOOMING ROCKS is the other music venue on this road. It has a stage, a
       rig and a bill, and everybody faces one way. Here there is no stage and
       nobody faces anywhere in particular.
     · PINK PONY CLUB is flat hot pink. None of these three inks is pink, and
       the ground is the darkest thing on the page rather than the loudest.

   NOTHING MOVES ON ITS OWN, AT ANY DIAL SETTING, and make-dance-punks.py refuses
   @keyframes or an animation anywhere in this section. A dancefloor is the room
   most likely to grow a pulse, a chase or a strobe, and the headsets glow
   steadily or not at all. MAX makes the page no louder here; that is the room.

   THE HEADSET IS DRESSED FROM ITS CONTAINER, and the channel colour arrives as a
   custom property set by a class on that container, so the player that goes in
   the glass keeps the band round it. The frame is built by love-embed.js. */

.dance-punks { background: var(--dp-tarmac); color: var(--dp-text); font-family: 'Manrope', system-ui, sans-serif; }
.dance-punks a { color: var(--dp-pale); text-decoration-color: var(--dp-dim); text-underline-offset: 3px; }
.dance-punks a:hover { text-decoration-color: var(--dp-pale); }
.dance-punks :where(p, li) { font-size: 17px; line-height: 1.66; }
.dance-punks strong { color: var(--dp-pale); font-weight: 700; }
.dance-punks code { font-size: .92em; color: var(--dp-pale); }
.dance-punks .backlink { font-family: 'Manrope', system-ui, sans-serif; font-size: 15px; letter-spacing: 0; color: var(--dp-pale); }

.dp-topline { display: flex; flex-wrap: wrap; gap: 14px; justify-content: space-between; align-items: baseline; }
.dp-trail { margin: 0; font-size: 14px; color: var(--dp-dim); }

.dp-head { margin: 34px 0 0; }
.dp-over { margin: 0; font-size: 13px; font-weight: 700; letter-spacing: 2.4px; text-transform: uppercase; color: var(--dp-dim); }
.dance-punks h1 {
  font-family: 'Unbounded', system-ui, sans-serif; font-weight: 700;
  font-size: clamp(42px, 9vw, 104px); line-height: 1.02; letter-spacing: -1px;
  color: var(--dp-pale); margin: 12px 0 0;
}
.dp-sub { margin: 14px 0 0; max-width: 46ch; font-size: clamp(18px, 2.3vw, 22px); line-height: 1.45; color: var(--dp-text); }
.dp-art { margin: 26px -8px 0; line-height: 0; }
.dp-art svg { display: block; width: 100%; height: auto; }

.dp-lede { margin: 26px 0 0; max-width: 64ch; }
.dp-lede p { margin: 0; font-size: 20px; line-height: 1.6; color: var(--dp-pale); }

.dp-part { margin: 60px 0 0; }
.dp-part > :where(p) { max-width: 68ch; margin: 0 0 14px; }
.dance-punks h2 {
  font-family: 'Unbounded', system-ui, sans-serif; font-weight: 700;
  font-size: clamp(22px, 3.2vw, 32px); line-height: 1.2; letter-spacing: -.3px;
  color: var(--dp-pale); margin: 0 0 16px;
}

/* THE CHANNEL COLOUR IS ONE CUSTOM PROPERTY, set by the channel's class, so the
   headset band, the button on it and each channel's own card read one value. */
.dp-headset--blue,   .dp-channel--blue   { --dp-ch: var(--dp-blue); }
.dp-headset--orange, .dp-channel--orange { --dp-ch: var(--dp-orange); }
.dp-headset--white,  .dp-channel--white  { --dp-ch: var(--dp-white); }

/* THE HEADSET. A dark box whose top edge is the band, in the tuned channel's
   colour, round a glass that is the screen when the headset is on. */
.dp-headset {
  margin: 26px 0 0; max-width: 880px; padding: 16px 16px 14px;
  background: var(--dp-deep); border-radius: 22px 22px 8px 8px;
  border-top: 8px solid var(--dp-ch, var(--dp-dim));
}
/* 16:9 IS A MINIMUM AND NOT A CAGE. The panel shown while the headset is off is
   in the flow, so on a phone, where the channel's name and the button wrap, the
   glass grows to hold them; the first draft pinned it inside a fixed box and cut
   the button's label in half at 375px. Nothing clips it, so the corners are put
   on the player instead of on an overflow. */
.dp-glass { position: relative; display: grid; aspect-ratio: 16 / 9; background: var(--dp-tarmac); border-radius: 12px; }
.dp-glass iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; border-radius: 12px; }
.dp-off {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 8px; padding: 20px; text-align: center;
}
.dance-punks .dp-off__state { margin: 0; font-family: 'Unbounded', system-ui, sans-serif; font-weight: 700; font-size: 13px; letter-spacing: 2.6px; color: var(--dp-dim); }
.dance-punks .dp-off__ch { margin: 0; font-family: 'Unbounded', system-ui, sans-serif; font-weight: 700; font-size: clamp(22px, 3.4vw, 34px); line-height: 1.15; color: var(--dp-ch, var(--dp-pale)); }
.dance-punks .dp-off__opens { margin: 0; font-size: 16px; color: var(--dp-text); max-width: 40ch; }
.dp-on, .dp-offbtn {
  margin: 8px 0 0; padding: 12px 20px; border: 0; border-radius: 999px; cursor: pointer;
  background: var(--dp-ch, var(--dp-pale)); color: var(--dp-tarmac);
  font-family: 'Manrope', system-ui, sans-serif; font-weight: 700; font-size: 16px;
}
.dp-offbtn { background: transparent; color: var(--dp-pale); border: 2px solid var(--dp-dim); margin: 12px 0 0; }
.dance-punks .dp-band { margin: 12px 4px 0; font-weight: 700; font-size: 15px; color: var(--dp-ch, var(--dp-pale)); }

/* THE CHANNELS. One card per channel, its colour along the top edge and on its
   name, and its number printed beside the name every time: the colour is never
   the only thing telling one from another. */
.dp-channels { list-style: none; margin: 26px 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 22px; }
.dp-channel { display: flex; flex-direction: column; gap: 10px; padding: 18px; background: var(--dp-deep); border-top: 6px solid var(--dp-ch); border-radius: 4px; }
.dance-punks .dp-channel__no { margin: 0; font-family: 'Unbounded', system-ui, sans-serif; font-weight: 700; font-size: 14px; letter-spacing: 1.6px; color: var(--dp-dim); }
.dp-channel__name { color: var(--dp-ch); font-size: 1.5em; letter-spacing: 0; }
.dance-punks .dp-channel__opens { margin: 0; font-size: 16px; }
.dp-channel__opens b { color: var(--dp-pale); }
.dance-punks .dp-channel__about { margin: 0; font-size: 15px; color: var(--dp-dim); }
.dance-punks .dp-channel__go { margin: auto 0 0; font-size: 15px; }
.dp-tune {
  display: block; margin: 0 0 10px; padding: 9px 14px; cursor: pointer; border-radius: 999px;
  background: transparent; color: var(--dp-ch); border: 2px solid var(--dp-ch);
  font-family: 'Manrope', system-ui, sans-serif; font-weight: 700; font-size: 15px;
}
.dp-tune[aria-pressed="true"] { background: var(--dp-ch); color: var(--dp-tarmac); }
.dance-punks .dp-noscript { margin: 16px 0 0; color: var(--dp-dim); }

.dp-rules { list-style: none; margin: 0; padding: 0; max-width: 72ch; }
.dp-rules li { margin: 0; padding: 12px 0 12px 18px; border-left: 3px solid var(--dp-paint); }
.dp-rules li + li { margin-top: 8px; }
.dance-punks .quest { margin-top: 44px; }


/* §44 ── ROOM: The Small Hours (turning 05 in The Outskirts) ────────────────
   AN ALL-NIGHT DINER SEEN FROM THE CAR PARK, and the light is the whole
   separation. It comes from INSIDE ONE LONG BOX, evenly, from tubes, and you
   are outside it in the dark: the building is a band of bright glass with the
   light lying out across the tarmac in rectangles, and everything the diner has
   to say is written inside a window. Nothing out on the lot is lit except the
   sign on the roof and what the windows throw.

   THE ROAD'S OTHER LIGHTS ARE ALL SOMEWHERE ELSE. The Lagoon's screen stands
   in black water in front of you; Sithen is moonlit from overhead; Looming
   Rocks is lit from the ground up; Dance, Punks is lit by what people wear.
   This is the first light on the road that is a ROOM with people inside it.

   THESE ARE THE COLLISIONS TO WATCH, and every one is structural:
     · DEAD TIRED SOCIETY is also tubes, and also a shape of light on a floor.
       There you sit inside the dark and the light is in the corridor, and
       nobody stands in it. Here the light is inside and you are the one out
       in the dark. Same tube, opposite side of the glass.
     · THE LIGHTBULB PICTURE HOUSE is also lit all over and has red seats. It is
       velvet and brass, lit warm from sconces, and you are inside it. There is
       no velvet here and the light is cold and even; the only red is vinyl.
     · THE GARDEN'S pale surfaces are tinted green by leaves. This glass is a
       neutral cool white with a little blue in it, and there is no green in the
       building but the formica, which carries no word.

   THE TUBES DO NOT FLICKER. Nothing in this section moves at any setting: a
   stuttering fluorescent tube is the sound and sight of half the waiting rooms
   any of us has sat in, and the page says it is gone. The neon sign is steady. */

.small-hours { background: var(--sh-lot); color: var(--sh-text); font-family: 'Libre Franklin', system-ui, sans-serif; }
.small-hours a { color: var(--sh-neon); text-underline-offset: 3px; }
.small-hours a:hover { color: var(--sh-pale); }
.small-hours :where(p, li) { font-size: 17px; line-height: 1.65; }
.small-hours strong { color: var(--sh-pale); font-weight: 700; }
.small-hours code { font-size: .92em; color: var(--sh-pale); }
.small-hours .backlink { font-family: 'Libre Franklin', system-ui, sans-serif; font-size: 15px; letter-spacing: 0; color: var(--sh-neon); }

.sh-topline { display: flex; flex-wrap: wrap; gap: 14px; justify-content: space-between; align-items: baseline; }
.sh-trail { margin: 0; font-size: 14px; color: var(--sh-dim); }

.sh-head { margin: 34px 0 0; }
.sh-over { margin: 0; font-size: 13px; font-weight: 700; letter-spacing: 2.4px; text-transform: uppercase; color: var(--sh-dim); }
.small-hours h1 {
  font-family: 'Righteous', system-ui, sans-serif; font-weight: 400;
  font-size: clamp(42px, 8.4vw, 96px); line-height: 1.02;
  color: var(--sh-pale); margin: 10px 0 0;
}
.sh-sub { margin: 12px 0 0; max-width: 48ch; font-size: clamp(18px, 2.3vw, 22px); line-height: 1.45; color: var(--sh-text); }
.sh-art { margin: 24px -8px 0; line-height: 0; }
.sh-art svg { display: block; width: 100%; height: auto; }
.small-hours .sh-sign { margin: 8px 0 0; font-size: 16px; color: var(--sh-dim); }
.sh-sign__word { font-family: 'Righteous', system-ui, sans-serif; font-size: 22px; letter-spacing: 2px; text-transform: uppercase; color: var(--sh-neon); margin-right: 4px; }

.sh-lede { margin: 26px 0 0; max-width: 64ch; }
.sh-lede p { margin: 0; font-size: 20px; line-height: 1.6; color: var(--sh-pale); }

/* A WINDOW. Plate glass in a chrome frame set in the dark wall, lit evenly
   from inside. Everything the diner says is in one of these, dark on the light,
   and the light it throws lies on the lot underneath it in the gap before the
   next thing -- where there is no word to stand on it. */
.sh-window {
  position: relative; margin: 56px 0 72px; max-width: 900px; padding: 26px 28px 22px;
  background: var(--sh-glass); color: var(--sh-ink);
  border: 12px solid var(--sh-wall); box-shadow: inset 0 0 0 3px var(--sh-chrome);
}
.sh-window::after {
  content: ""; position: absolute; left: 4%; right: 4%; top: calc(100% + 12px); height: 60px;
  background: linear-gradient(var(--sh-glass), transparent); opacity: .08; pointer-events: none;
}
.small-hours .sh-window :where(p, li) { color: var(--sh-ink); }
.small-hours .sh-window strong { color: var(--sh-ink); }
.small-hours .sh-window a { color: var(--sh-teal); }
.small-hours .sh-window a:hover { color: var(--sh-ink); }
.sh-window :focus-visible { outline-color: var(--sh-ink); }
.sh-window > p { max-width: 66ch; margin: 0 0 14px; }
.small-hours h2 {
  font-family: 'Righteous', system-ui, sans-serif; font-weight: 400;
  font-size: clamp(24px, 3.4vw, 34px); line-height: 1.2; color: var(--sh-pale); margin: 0 0 16px;
}
.small-hours .sh-window h2 { color: var(--sh-teal); }

.sh-said { margin: 6px 0 20px; padding: 2px 0 2px 18px; border-left: 4px solid var(--sh-aqua); max-width: 60ch; }
.small-hours .sh-said p { margin: 0; font-size: 20px; line-height: 1.5; color: var(--sh-ink); }
.sh-said cite { display: block; margin: 8px 0 0; font-size: 14px; font-style: normal; color: var(--sh-ink-2); }
.small-hours .sh-said cite a { color: var(--sh-teal); }

/* THE MENU BOARD. One dish to a row, hairline between, no prices. */
.small-hours .sh-menu__note { font-size: 15px; color: var(--sh-ink-2); }
.sh-menu { list-style: none; margin: 8px 0 22px; padding: 0; }
.sh-dish { padding: 12px 0; border-top: 1px solid var(--sh-chrome); }
.sh-dish:last-child { border-bottom: 1px solid var(--sh-chrome); }
.small-hours .sh-dish__name { margin: 0; font-family: 'Righteous', system-ui, sans-serif; font-size: 20px; color: var(--sh-ink); }
.small-hours .sh-dish__note { margin: 4px 0 0; font-size: 16px; color: var(--sh-ink-2); max-width: 64ch; }

.sh-part { margin: 56px 0 0; }
.sh-part > p { max-width: 68ch; margin: 0 0 14px; }
.sh-rules { list-style: none; margin: 0; padding: 0; max-width: 72ch; }
.sh-rules li { margin: 0; padding: 12px 0; border-top: 1px solid var(--sh-line); }
.sh-rules li:last-child { border-bottom: 1px solid var(--sh-line); }
.small-hours .quest { margin-top: 44px; }

/* THE RECORD AND THE JUKEBOX. Both sit in windows, so everything here is dark
   ink on the lit glass. A press-to-play button is dressed from the WINDOW,
   because love-embed.js hands back a bare shell and the button's own classes
   do not survive the press; the player that replaces it is the browser's own. */
.small-hours .sh-record__by { margin: -8px 0 14px; font-size: 15px; font-weight: 700; color: var(--sh-ink-2); }
.small-hours .sh-record__meta { margin: 0 0 10px; font-size: 15px; color: var(--sh-ink-2); }
.small-hours .sh-window .facade--audio { margin: 0 0 14px; }
.small-hours .sh-window button.facade--audio {
  display: inline-block; width: auto; border: 2px solid var(--sh-ink); border-radius: 999px;
  padding: 8px 16px; background: var(--sh-ink); color: var(--sh-glass);
  font-family: 'Libre Franklin', system-ui, sans-serif; font-weight: 700; font-size: 15px;
}
.small-hours .sh-window button.facade--audio:hover { background: var(--sh-teal); border-color: var(--sh-teal); }
.sh-credits { margin: 6px 0 20px; display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 8px 20px; }
.sh-credits dt { font-weight: 700; color: var(--sh-ink); }
.sh-credits dd { margin: 0; font-size: 15px; color: var(--sh-ink-2); }
.small-hours .sh-window .sh-lyric__h { margin: 10px 0 8px; font-family: 'Righteous', system-ui, sans-serif; font-weight: 400; font-size: 22px; color: var(--sh-teal); }
.sh-lyric { margin: 0 0 16px; padding: 4px 0 4px 18px; border-left: 4px solid var(--sh-aqua); columns: 2 18ch; column-gap: 32px; }
.small-hours .sh-lyric p { margin: 0 0 14px; font-size: 17px; line-height: 1.55; color: var(--sh-ink); break-inside: avoid; }
.sh-lyric cite { display: block; column-span: all; margin: 4px 0 0; font-size: 14px; font-style: normal; color: var(--sh-ink-2); }
.small-hours .sh-record__more { font-size: 15px; }

.sh-album { margin: 22px 0 0; padding: 18px 0 0; border-top: 2px solid var(--sh-chrome); }
.small-hours .sh-window .sh-album__h { margin: 0; font-family: 'Righteous', system-ui, sans-serif; font-weight: 400; font-size: 26px; color: var(--sh-ink); }
.small-hours .sh-album__meta { margin: 4px 0 12px; font-size: 15px; color: var(--sh-ink-2); }
.sh-album__all {
  display: inline-block; margin: 0 0 12px; padding: 10px 18px; cursor: pointer; border-radius: 999px;
  border: 2px solid var(--sh-teal); background: var(--sh-teal); color: var(--sh-glass);
  font-family: 'Libre Franklin', system-ui, sans-serif; font-weight: 700; font-size: 15px;
}
.sh-album__now { margin: 0 0 12px; }
.small-hours .sh-album__line { margin: 0 0 8px; font-weight: 700; font-size: 15px; color: var(--sh-ink); }
.sh-tracks { list-style: none; margin: 0; padding: 0; }
.sh-track { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; padding: 8px 0; border-top: 1px solid var(--sh-chrome); }
.sh-track__n { min-width: 2ch; font-weight: 700; color: var(--sh-ink-2); }
.sh-track__t { flex: 1 1 14ch; font-weight: 700; color: var(--sh-ink); }
.small-hours .sh-track .facade--audio { margin: 0; }
.sh-track div.facade--audio { flex: 1 1 100%; }

@media (max-width: 560px) {
  .sh-window { padding: 20px 18px 16px; border-width: 8px; }
  .sh-lede p { font-size: 18px; }
}


/* §45 ── ROOM: The Repeater (turning 06 in The Outskirts) ────────────────────
   A RADIO MAST ON THE RIDGE AT THE FAR END OF THE ROAD, and everything in it is
   a silhouette. Nothing up there is lit. The cloud is, faintly, from beneath,
   by every lit thing on the road and the town past it, so the mast, the hut and
   the hill are black shapes against a sky the colour of somebody else's light.
   It is the only room on this street lit by light that has bounced off the sky.

   THE ROAD'S OTHER LIGHTS ARE ALL NEAR SOMETHING. A screen in water, a moon
   overhead, floods at the foot of a rock, lights people wear, a lit room seen
   from its car park. This one is lit by everything else, from a long way off,
   and by nothing close at all.

   THESE ARE THE COLLISIONS TO WATCH, and every one is structural:
     · THE CAMPGROUNDS is the other place with the sky on it and nothing lit in
       it. That sky is cold and blue, the field is open, and everything in it is
       evenly dim and seen. This sky is warm and lit from underneath, and
       nothing in the room is seen at all -- only its outline.
     · THE LATIBULUM has a wireless in it. That is a piece of furniture in a
       burrow you go to be unfindable; this is a structure you climb to be
       reached, and the room is outside.
     · SITHEN is grey-violet under a moon from directly overhead, and every
       object in it has a lit top. Nothing here has a lit face of any kind.

   THE LAMPS ON THE MAST ARE STEADY, and make-repeater.py refuses @keyframes or
   an animation anywhere in this section. A blinking red light is the ambient
   effect this room would grow first. */

.repeater { background: var(--rp-cloud); color: var(--rp-text); font-family: 'IBM Plex Sans', system-ui, sans-serif; }
.repeater a { color: var(--rp-amber); text-underline-offset: 3px; }
.repeater a:hover { color: var(--rp-pale); }
.repeater :where(p, li) { font-size: 17px; line-height: 1.66; }
.repeater strong { color: var(--rp-pale); font-weight: 700; }
.repeater .backlink { font-family: 'IBM Plex Sans', system-ui, sans-serif; font-size: 15px; letter-spacing: 0; color: var(--rp-amber); }

.rp-topline { display: flex; flex-wrap: wrap; gap: 14px; justify-content: space-between; align-items: baseline; }
.rp-trail { margin: 0; font-size: 14px; color: var(--rp-dim); }

.rp-head { margin: 34px 0 0; }
.rp-over { margin: 0; font-size: 13px; font-weight: 700; letter-spacing: 2.4px; text-transform: uppercase; color: var(--rp-dim); }
.repeater h1 {
  font-family: 'Syncopate', system-ui, sans-serif; font-weight: 700;
  font-size: clamp(32px, 7vw, 78px); line-height: 1.08; letter-spacing: 2px;
  color: var(--rp-pale); margin: 12px 0 0;
}
.rp-sub { margin: 14px 0 0; max-width: 46ch; font-size: clamp(18px, 2.3vw, 22px); line-height: 1.45; color: var(--rp-text); }
.rp-art { margin: 22px -8px 0; line-height: 0; }
.rp-art svg { display: block; width: 100%; height: auto; }

.rp-lede { margin: 22px 0 0; max-width: 64ch; }
.rp-lede p { margin: 0 0 16px; font-size: 19px; line-height: 1.62; color: var(--rp-pale); }

.rp-part { margin: 58px 0 0; }
.rp-part > p { max-width: 68ch; margin: 0 0 14px; }
.repeater h2 {
  font-family: 'Syncopate', system-ui, sans-serif; font-weight: 700;
  font-size: clamp(20px, 2.8vw, 28px); line-height: 1.25; letter-spacing: 1.2px;
  color: var(--rp-pale); margin: 0 0 16px;
}
.rp-said { margin: 6px 0 20px; padding: 2px 0 2px 18px; border-left: 3px solid var(--rp-amber); max-width: 60ch; }
.repeater .rp-said p { margin: 0; font-size: 20px; line-height: 1.5; color: var(--rp-pale); }
.rp-said cite { display: block; margin: 8px 0 0; font-size: 14px; font-style: normal; color: var(--rp-dim); }

/* THE OPEN LINE. A plain panel with a state line, one button that opens and
   another that closes, and a slider whose top is a quiet line. */
.rp-set {
  margin: 20px 0 0; max-width: 560px; padding: 20px 22px 18px;
  background: var(--rp-deep); border-left: 4px solid var(--rp-amber); border-radius: 2px;
}
.repeater .rp-set__state { margin: 0 0 12px; font-family: 'Syncopate', system-ui, sans-serif; font-weight: 700; font-size: 13px; letter-spacing: 2.4px; color: var(--rp-pale); }
.rp-set__open, .rp-set__close {
  display: inline-block; padding: 11px 18px; border-radius: 2px; cursor: pointer;
  font-family: 'IBM Plex Sans', system-ui, sans-serif; font-weight: 700; font-size: 16px;
  background: var(--rp-amber); color: var(--rp-cloud); border: 2px solid var(--rp-amber);
}
.rp-set__close { background: transparent; color: var(--rp-amber); }
.rp-set__lab { display: block; margin: 18px 0 6px; font-weight: 700; font-size: 15px; color: var(--rp-pale); }
.rp-set__level { width: 100%; max-width: 360px; accent-color: var(--rp-amber); }
.repeater .rp-set__note { margin: 12px 0 0; font-size: 15px; color: var(--rp-dim); }
.repeater .rp-noscript { color: var(--rp-dim); }

/* THE LOG. One card per kind of contact, printed the way a confirmation card
   is: the call across the top in red capitals, a line saying the contact is
   confirmed, and one line of ours. Square, straight, nothing rotated. */
.rp-log { list-style: none; margin: 22px 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 18px; }
.rp-card { padding: 16px 18px 18px; background: var(--rp-card); color: var(--rp-ink); border-top: 6px solid var(--rp-call); border-radius: 2px; }
.repeater .rp-card__call { margin: 0; font-family: 'Syncopate', system-ui, sans-serif; font-weight: 700; font-size: 17px; letter-spacing: 1.4px; color: var(--rp-call); }
.repeater .rp-card__ok { margin: 4px 0 10px; font-size: 12px; font-weight: 700; letter-spacing: 1.6px; text-transform: uppercase; color: var(--rp-ink-2); }
.repeater .rp-card__line { margin: 0; font-size: 16px; line-height: 1.55; color: var(--rp-ink); }

.rp-rules { list-style: none; margin: 0 0 18px; padding: 0; max-width: 72ch; }
.rp-rules li { margin: 0; padding: 12px 0; border-top: 1px solid var(--rp-glow); }
.rp-rules li:last-child { border-bottom: 1px solid var(--rp-glow); }
.repeater .quest { margin-top: 44px; }


/* §46 ── ROOM: Nothing For Sale (turning 07 in The Outskirts) ──────────────
   A FREE MARKET IN A LAY-BY, lit by a ring of parked cars with their
   headlights left on and pointed at the middle. Everything is lit from every
   side, and every object throws as many shadows as there are cars.

   THE ROAD'S OWN LIGHT, TURNED INWARD. The Outskirts is lit by the visitor's
   headlights, one beam from behind, so a sign has a bright face and no back.
   This is the same kind of lamp from everybody at once, so nothing has a back
   at all. That is the room's argument drawn in light and it is why it is on
   this road rather than the street: it is what happens when people who each
   brought a little pull up together.

   THESE ARE THE COLLISIONS TO WATCH, and every one is structural:
     · THE 404 is lit from every side too, by fog, and nothing in it casts a
       shadow. Here every object casts several, hard, in slightly different
       colours. If the shadows ever go, this has become the fog with tables in it.
     · DANCE, PUNKS is the other room lit by many small sources. Those move with
       the people wearing them; these are parked and point one way each.
     · THE PEBBLE BOARD is the other place where people bring each other things.
       It is a noticeboard on the street, pinned edition by edition; this is a
       ring of tables under the sky, and nothing on it is ever taken down.

   NOTHING IN THE RING MOVES, and make-nothing-for-sale.py refuses @keyframes
   or an animation in this section. Headlights that swept would be a car
   leaving. */

.nothing-for-sale { background: var(--nfs-gravel); color: var(--nfs-text); font-family: 'Figtree', system-ui, sans-serif; }
.nothing-for-sale a { color: var(--nfs-fog); text-underline-offset: 3px; }
.nothing-for-sale a:hover { color: var(--nfs-pale); }
.nothing-for-sale :where(p, li) { font-size: 17px; line-height: 1.66; }
.nothing-for-sale strong { color: var(--nfs-pale); font-weight: 700; }
.nothing-for-sale .backlink { font-family: 'Figtree', system-ui, sans-serif; font-size: 15px; letter-spacing: 0; color: var(--nfs-fog); }

.nfs-topline { display: flex; flex-wrap: wrap; gap: 14px; justify-content: space-between; align-items: baseline; }
.nfs-trail { margin: 0; font-size: 14px; color: var(--nfs-dim); }

.nfs-head { margin: 34px 0 0; }
.nfs-over { margin: 0; font-size: 13px; font-weight: 700; letter-spacing: 2.4px; text-transform: uppercase; color: var(--nfs-dim); }
.nothing-for-sale h1 {
  font-family: 'Patrick Hand', system-ui, sans-serif; font-weight: 400;
  font-size: clamp(46px, 9vw, 104px); line-height: 1; color: var(--nfs-pale); margin: 10px 0 0;
}
.nfs-sub { margin: 12px 0 0; max-width: 48ch; font-size: clamp(18px, 2.3vw, 22px); line-height: 1.45; color: var(--nfs-text); }
.nfs-art { margin: 22px -8px 0; line-height: 0; }
.nfs-art svg { display: block; width: 100%; height: auto; }

.nfs-lede { margin: 22px 0 0; max-width: 64ch; }
.nfs-lede p { margin: 0 0 16px; font-size: 19px; line-height: 1.62; color: var(--nfs-pale); }

.nfs-part { margin: 58px 0 0; }
.nfs-part > p { max-width: 68ch; margin: 0 0 14px; }
.nothing-for-sale h2 {
  font-family: 'Patrick Hand', system-ui, sans-serif; font-weight: 400;
  font-size: clamp(28px, 3.8vw, 40px); line-height: 1.15; color: var(--nfs-pale); margin: 0 0 14px;
}
.nfs-said { margin: 6px 0 20px; padding: 2px 0 2px 18px; border-left: 3px solid var(--nfs-halogen); max-width: 60ch; }
.nothing-for-sale .nfs-said p { margin: 0; font-size: 20px; line-height: 1.5; color: var(--nfs-pale); }
.nfs-said cite { display: block; margin: 8px 0 0; font-size: 14px; font-style: normal; color: var(--nfs-dim); }

/* THE TABLES. One per free thing, each with its cardboard sign and its top edge
   lit by one car's lamp; no two neighbours are lit by the same one twice in a
   row, and none is lit by a colour no car brought. */
.nfs-table--halogen { --nfs-beam: var(--nfs-halogen); }
.nfs-table--led     { --nfs-beam: var(--nfs-led); }
.nfs-table--fog     { --nfs-beam: var(--nfs-fog); }
.nfs-tables { list-style: none; margin: 22px 0 22px; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 20px; }
.nfs-table { display: flex; flex-direction: column; gap: 8px; padding: 16px 18px 18px; background: var(--nfs-table); border-top: 5px solid var(--nfs-beam); border-radius: 2px; }
.nothing-for-sale .nfs-table__sign { margin: 0; font-family: 'Patrick Hand', system-ui, sans-serif; font-size: 22px; letter-spacing: 1px; color: var(--nfs-beam); }
.nfs-table__what { margin: 0; font-family: 'Figtree', system-ui, sans-serif; font-weight: 700; font-size: 19px; line-height: 1.3; }
.nfs-table__what a { color: var(--nfs-pale); text-decoration-color: var(--nfs-beam); }
.nothing-for-sale .nfs-table__line { margin: 0; font-size: 16px; line-height: 1.55; }
.nothing-for-sale .nfs-notlaid { color: var(--nfs-text); }

.nfs-rules { list-style: none; margin: 0; padding: 0; max-width: 72ch; }
.nfs-rules li { margin: 0; padding: 12px 0; border-top: 1px solid var(--nfs-lit); }
.nfs-rules li:last-child { border-bottom: 1px solid var(--nfs-lit); }
.nothing-for-sale .quest { margin-top: 44px; }


/* §47 ── ROOM: Samefood Cafe (a shopfront on the street) ────────────────────
   A CAFE SEEN FROM DIRECTLY ABOVE THE TABLE, UNDER ONE EVEN LIGHT THAT DOES NOT
   CHANGE WITH THE HOUR, WHERE NOTHING ON ANY PLATE TOUCHES ANYTHING ELSE. For
   samefoods, safe foods and food aversions, understood rather than corrected,
   with Matthew Broberg-Moffitt's Color Taste Texture on the counter and the
   regulars' own samefoods on trays of their own.

   NOTHING TOUCHES UNLESS YOU WANT IT TO, AND THAT IS THE ROOM. Separation is
   OFFERED here and never imposed: a bowl is one person's dish as they eat it and
   its parts may touch (Ryan does not mind; Ronan likes everything apart), and
   the tool keeps its walker off them. Every plate is divided; every food
   sits in its own well with room round it; every object on the table stands
   apart from every other; and the page is built the same way -- the menu, the
   book and each regular's list are each on a plate of their own, each regular's
   samefood of the moment is in a bowl of its own, Ronan's ketchup is in a
   ramekin because that is how Ronan has red things -- his way, not the house's:
   THE HOUSE DEFAULTS TO STRUCTURE, SEPARATION AND PREDICTABILITY AND
   ACCOMMODATES EVERY GUEST INDIVIDUALLY, and nobody's way imposes on anybody
   else's plate -- and every item
   on a tray has a well of its own with a gap of plate between it and the next.
   make-samefood.py walks every coordinate of the drawing in the window and
   refuses a food that comes within a gap of its well's wall or of another
   food. NOTHING IN THIS SECTION MAY OVERLAP ANYTHING: no negative margin, no
   absolute positioning of one thing over another, no rotation. Club Chronic is
   a hundred rectangles pasted over each other and the Jungle Room is a canopy
   where everything overlaps something; this is the other end of that line.

   THE LIGHT IS STRAIGHT OVERHEAD AND DIFFUSE, so every object throws a soft
   even ring of shade all round itself, with no offset -- box-shadow with a
   spread and nothing else -- and that ring is the light drawing a gap round each
   thing. There is no window, so the hour never shows and nothing on the plate
   ever looks different from the last time: a samefood is the same colour at
   midnight as at noon. THESE ARE THE COLLISIONS TO WATCH, and each is structural:
     · DANNY THE STREET is the other plan view, seen from directly above under
       one sodium lamp, and under sodium NOTHING HAS A COLOUR OF ITS OWN. This
       lamp was chosen so that EVERYTHING KEEPS ITS OWN COLOUR, exactly, every
       time -- the opposite promise, which is the samefood's.
     · THE GARDEN is also lit from overhead, through leaves: green, dappled,
       hard little shadows, outdoors. This is indoors, soft, not green, and
       nothing is dappled, because a light that moved would be a surprise.
     · THE ADVENTURER'S GUILD is the other orderly pale room, and it is lit from
       nowhere, casts nothing, and is ruled into square rows. Here everything
       casts its ring and there is no straight rule anywhere -- every well is a
       moulded round-cornered hollow, and nothing is filed.
     · COVENSTEAD is the other room with crockery in it, one door along, and
       NOBODY'S CUP THERE IS ANYBODY ELSE'S, which is its subject. EVERY PLATE
       HERE IS THE SAME PLATE -- one colour, one mould, one component used for
       every panel on the page -- and that is this room's. If the plates ever
       start to differ from each other, it has become Covenstead with a menu.
     · THE SMALL HOURS is the other place that serves food, and it is a diner
       seen from the car park at night through glass. You are sitting at this
       table, looking down at it, and it is lit the same all day.

   THE TABLE IS LILAC BECAUSE ALMOST NOTHING ON THE MENU IS, so nothing on the
   table can be mistaken for the table. NO BLUE, for the Lightbulb Picture
   House's reason. NOTHING MOVES AT ANY SETTING except the drawing's shade rings
   deepening a touch on hover at MAX, which is a colour change and not a
   movement: a cafe for people who need their plate to be the same as last
   time does not rearrange itself while they look at it. */

.samefood { background: var(--sf-table); color: var(--sf-ink); font-family: 'Inclusive Sans', system-ui, sans-serif; font-synthesis: none; }
.samefood :where(i, em, cite) { font-style: normal; }
.samefood a { color: var(--sf-sauce); text-underline-offset: 3px; }
.samefood a:hover { color: var(--sf-ink); }
/* THE RING IS THE ROOM'S OWN INK, 12.14 on the table and 15.07 on a plate.
   §2's yellow ring was chosen for a near-black street and is nearly invisible
   on anything this pale -- the Guild's lesson, decided here at the room. */
.samefood :focus-visible { outline-color: var(--sf-ink); }
/* :where() so this base is (0,1,0) and every component below wins by order --
   Dead Tired Society's day-one lesson, taken before it could happen here. */
.samefood :where(p, li) { font-size: 17px; line-height: 1.65; }
.samefood strong { font-weight: 700; color: var(--sf-ink); }
.samefood code { font-size: .9em; color: var(--sf-ink); }
.samefood .backlink { font-family: 'Inclusive Sans', system-ui, sans-serif; font-size: 15px; letter-spacing: 0; color: var(--sf-sauce); }

.sf-topline { display: flex; flex-wrap: wrap; gap: 14px; justify-content: space-between; align-items: baseline; }
.sf-trail { margin: 0; font-size: 14px; color: var(--sf-ink-2); }

.sf-head { margin: 34px 0 0; }
.sf-over { margin: 0; font-family: 'Fredoka', system-ui, sans-serif; font-weight: 600; font-size: 13px; letter-spacing: 2.4px; text-transform: uppercase; color: var(--sf-ink-2); }
.samefood h1 {
  font-family: 'Fredoka', system-ui, sans-serif; font-weight: 600;
  font-size: clamp(48px, 9.4vw, 104px); line-height: 1; letter-spacing: -.01em;
  color: var(--sf-ink); margin: 10px 0 0;
}
/* THE SPECIALS LINE, which is the room's one joke and the answer to its job. */
.sf-special { margin: 14px 0 0; font-family: 'Fredoka', system-ui, sans-serif; font-weight: 400; font-size: clamp(21px, 2.8vw, 27px); line-height: 1.3; color: var(--sf-ink); }
.sf-special b { font-weight: 600; color: var(--sf-sauce); }
.sf-art { margin: 26px 0 0; line-height: 0; }
.sf-art svg { display: block; width: 100%; height: auto; }
.samefood .sf-window { margin: 12px 0 0; max-width: 70ch; font-size: 15px; color: var(--sf-ink-2); }

.sf-lede { margin: 30px 0 0; max-width: 62ch; font-size: 20px; line-height: 1.6; }

.sf-part { margin: 60px 0 0; }
.sf-part > :where(p) { margin: 0 0 14px; max-width: 70ch; }
.samefood h2 { font-family: 'Fredoka', system-ui, sans-serif; font-weight: 600; font-size: clamp(30px, 4.2vw, 40px); line-height: 1.12; color: var(--sf-ink); margin: 0 0 14px; }
.samefood h3 { font-family: 'Fredoka', system-ui, sans-serif; font-weight: 600; font-size: 25px; line-height: 1.15; color: var(--sf-ink); margin: 0; }

/* THE HOUSE RULES, on the bare table. Each one has a dot beside it that does
   not touch its words, which is the whole rule of the room at the size of a
   bullet. */
.sf-rules { list-style: none; margin: 18px 0 0; padding: 0; max-width: 70ch; display: grid; gap: 14px; }
.sf-rules li { position: relative; padding-left: 30px; }
.sf-rules li::before { content: ""; position: absolute; left: 4px; top: .55em; width: 11px; height: 11px; border-radius: 50%; background: var(--sf-plate); box-shadow: 0 0 0 3px var(--sf-shade); border: 1.5px solid var(--sf-rim); }

/* THE PLATE. ONE COMPONENT, USED FOR EVERY PANEL ON THE PAGE -- the three
   dishes, the book and every regular's tray -- because every plate here is the
   same plate. Its shade is an even ring with NO OFFSET, because the light is
   straight overhead: a spread and nothing else. */
.sf-plate {
  background: var(--sf-plate); color: var(--sf-ink);
  border: 1.5px solid var(--sf-rim); border-radius: 30px;
  box-shadow: 0 0 0 9px var(--sf-shade);
  padding: 24px 26px;
}
.sf-plates { list-style: none; margin: 34px 0 0; padding: 0; display: grid; gap: 40px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); }
.sf-plate h3 { margin: 0 0 10px; }
.sf-plate p { margin: 0 0 12px; }
.sf-plate > :last-child { margin-bottom: 0; }
.sf-quote { margin: 14px 0; padding: 14px 16px; background: var(--sf-well); border-radius: 18px; }
.sf-quote p { margin: 0; font-size: 18px; line-height: 1.55; }
.sf-quote cite { display: block; margin: 8px 0 0; font-size: 14px; font-style: normal; line-height: 1.5; color: var(--sf-ink-2); }
.sf-quote .sf-checked { display: block; margin: 4px 0 0; }
.sf-entry { font-size: 15px; }

/* THE BOOK ON THE COUNTER. The same plate, because it is the same plate. */
.sf-book { margin: 30px 0 0; max-width: 780px; }
.sf-book__title { margin: 0; font-family: 'Fredoka', system-ui, sans-serif; font-weight: 600; font-size: 30px; line-height: 1.1; }
.sf-book__sub { margin: 6px 0 0; font-size: 17px; }
.sf-book__by { margin: 10px 0 0; font-size: 15px; color: var(--sf-ink-2); }
.sf-book__get { list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 12px; }
.sf-book__get a { display: inline-block; padding: 8px 16px; background: var(--sf-well); border-radius: 999px; font-size: 15px; }

/* THE REGULARS' TRAYS. One plate per person and one well per food, with a gap
   of plate round every well, so that nobody's samefood touches anybody else's
   -- or the next one on their own list. The words in a well are theirs,
   exactly as given, so nothing in here restyles them: no capitals added, no
   title case, nothing crossed out. */
.sf-trays { list-style: none; margin: 34px 0 0; padding: 0; display: grid; gap: 44px; }
.sf-tray h3 { margin: 0 0 14px; }
.sf-wells { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 170px), 1fr)); }
.sf-wells li { margin: 0; padding: 14px 16px; background: var(--sf-well); border-radius: 18px; font-size: 17px; line-height: 1.4; text-transform: none; }
.sf-tray__given { margin: 14px 0 0; font-size: 14px; color: var(--sf-ink-2); }

/* THE SAMEFOOD OF THE MOMENT: one bowl on the tray, beside its name in words.
   Every bowl is the same bowl, as every plate is the same plate. A grid rather
   than a float, so the bowl and its caption sit side by side and never overlap. */
.sf-moment { margin: 0 0 20px; display: grid; grid-template-columns: 190px minmax(0, 1fr); gap: 24px; align-items: center; }
.sf-bowl { display: block; width: 190px; height: auto; }
.sf-moment figcaption { font-size: 16px; line-height: 1.5; }
.sf-moment__label { display: block; font-family: 'Fredoka', system-ui, sans-serif; font-weight: 600; font-size: 13px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--sf-ink-2); }
.sf-moment__item { display: block; font-family: 'Fredoka', system-ui, sans-serif; font-weight: 600; font-size: 22px; line-height: 1.2; margin: 2px 0 4px; }
.sf-moment__said { display: block; font-size: 15px; color: var(--sf-ink-2); }

.sf-nots { margin: 0; padding: 0 0 0 1.1em; max-width: 70ch; }
.sf-nots li { margin: 0 0 12px; }
.sf-nots li::marker { color: var(--sf-sauce); }
.sf-further { font-size: 15px; color: var(--sf-ink-2); }
.sf-thanks { padding-top: 6px; }
.samefood .quest { margin-top: 48px; }

/* The one thing that answers a hover, and only at MAX: the shade ring deepens.
   A colour, not a movement -- nothing on this table moves at any setting. */
html[data-intensity="max"] .sf-plate:hover { box-shadow: 0 0 0 9px var(--sf-rim); }

/* On a phone the plates stack and the wells go two across and then one, and
   nothing is hidden to save room -- the lite version arriving through a
   breakpoint. Written last in the section, after every rule it overrides. */
@media (max-width: 560px) {
  .sf-plate { padding: 20px 18px; border-radius: 24px; }
  .sf-lede { font-size: 18px; }
  .sf-wells { grid-template-columns: repeat(auto-fill, minmax(min(100%, 130px), 1fr)); }
  .sf-moment { grid-template-columns: 120px minmax(0, 1fr); gap: 14px; }
  .sf-bowl { width: 120px; }
}


/* §48 ── Small screens ───────────────────────────────────────────────────────
   The street stacks; nothing is dropped. Every room reads at 360px. */

@media (max-width: 720px) {
  body { font-size: 16px; }
  .wrap { width: calc(100% - 32px); }
  .masthead { flex-direction: column; gap: 22px; }
  .masthead__dial { flex: 1 1 auto; width: 100%; }
  .tagline { gap: 8px 12px; }
  .zine-cols { columns: 1; }
  .door { min-height: 0; }
  /* Stacked but NOT centred. Helen centred this card on small screens because
     her version had a portrait above the text; with two paragraphs and no
     picture, centred body copy is just harder to read, and this is a Disabled
     people's site. The short card below, which does have a drawing, keeps it. */
  .welcome { flex-direction: column; }
  /* Helen centred the whole card here; the portrait is what she was centring. */
  .welcome .portrait-frame { align-self: center; width: 168px; }
  .whereabouts { flex-direction: column; text-align: center; }
  .yurt { width: calc(100% - 28px); }
  /* Two 120px vines leave about 100px of column between them at 360px, and the
     eyebrow runs right up against the leaves. They are ivy, so they can be
     smaller ivy; the alternative was fading them, which is a change to how
     Helen's room looks rather than to how it fits. */
  .vine { width: 74px; }
  /* The arch gets shallower rather than narrower: 42px of top padding under a
     170px curve is a lot of empty sky on a 328px screen. */
  .gardengate__arch { padding: 30px 18px 18px; border-radius: 120px 120px 5px 5px; }
  .signpost__arm { padding-right: 30px; clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 50%, calc(100% - 16px) 100%, 0 100%); }
  /* The pad grows on a phone rather than shrinking: it is the only way to steer
     without a keyboard, and 44px is the floor everywhere on this site. */
  /* A squarer screen on a phone. At 8:5 and 343px wide the playfield is 214px
     tall, and the attract screen -- the game's name, the coin, and how to steer
     -- needs about 230. It was clipped top and bottom, which is the one screen
     a visitor sees before deciding whether to press anything. arcade.js reads
     the aspect off the element rather than assuming one, so the game moves
     correctly at both shapes. */
  .field, .bay { aspect-ratio: 1 / 1; }
  .attract { gap: 12px; }
  .dpad { grid-template-columns: repeat(3, 64px); grid-template-rows: repeat(3, 52px); margin-inline: auto; }
  .controls { justify-content: center; }
  .knobs { flex: 1 1 100%; }
  .screen { margin-inline: 10px; }
  .cabinet { border-width: 4px; }
  .burrow { width: calc(100% - 20px); padding: 0 14px 56px; }
  /* The arch is the room's whole silhouette, and at 332px a 260px radius eats
     the first two lines of every panel it is on. It gets shallower rather than
     square: a smial with a flat top is a shed. */
  .room-latibulum .wall--arched { border-radius: 120px 120px 22px 22px; padding: 70px 24px 26px; }
  .wireless .thing__case { border-radius: 100px 100px 14px 14px; }
  .jungle { width: calc(100% - 20px); padding: 0 14px 56px; }
  /* A 40px leaf corner on a 300px card eats the first line of the name. The
     aperture keeps the shape; the card behind it relaxes rather than going
     square, because a rectangle here would stop being a leaf and start being
     a spreadsheet cell. */
  .cam { border-radius: 26px 6px 26px 6px; padding: 14px 15px 18px; }
  .cams { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .den { width: calc(100% - 20px); padding: 0 14px 56px; }
  /* A 10px teak border on a 332px carpet is most of the carpet. The frame
     stays — a rug with no edge is a wall — it just stops being furniture. */
  .carpet { border-width: 6px; padding: 18px 16px 22px; }
  .cuts { grid-template-columns: minmax(0, 1fr); gap: 14px; }
  /* THE LEAF RAN 53px OFF THE RIGHT-HAND EDGE OF THE PAPER onto the desk, and
     the page did not scroll: a 310px leaf inside a 255px column happened to
     stop at 373.76 in a 375px window, so scrollWidth never tripped and
     everything that asks the document a question said the room was fine. It
     was measured instead -- the leaf's own rectangle against the sheet's --
     which is the 0x0 iframe's lesson in a different shape: the DOM was right
     and the paint was wrong. One column below 720px, and the sheet gives up
     its margin before the book gives up its page. */
  .room-zibaldone .zb-flyleaf, .room-zibaldone .zb-sheet { padding: 22px 16px 26px 32px; }
  .room-zibaldone .zb-quire { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .room-zibaldone .zb-rule__n { font-size: 33px; }
}


/* The Mopery, the Oracle Deck and the Doomscroll (§22-§24). The nook is two
   columns on a desk and one on a phone; the shelves already wrap on their own,
   and the spines stay upright because a spine that lay down would stop being a
   spine. */
@media (max-width: 760px) {
  .mop-scan { padding: 20px 16px 18px; }
  .mop-plate { margin: 22px auto 26px; }
  .mop-parlour { padding: 20px 14px 18px; }
  .mop-hearth { gap: 10px; }
  .mop-drip { flex-basis: 14px; }
  .mop-sign { padding: 18px 24px 20px; }
  .mop-shelf, .mop-card, .mop-card + p, .mop-records { margin-left: 14px; margin-right: 14px; }
  .mop-spine { padding: 14px 8px; font-size: 15px; }
  .orc-index { grid-template-columns: 1fr; }
  .dsc-sheet { padding: 24px 18px 30px; }
}

/* Swaying Sweetgrass (§25). The two grids collapse on their own — auto-fit
   with a 240–270px floor — but the readings are a CSS column count rather than
   a grid, and two columns of chapter titles on a phone is a stack of two-word
   lines. The bands scale with the viewport and get shorter as they narrow,
   which is a meadow seen from further off rather than a fault. */
@media (max-width: 620px) {
  .swg-doors { columns: 1; }
  .swg-door { padding: 9px 0; }
  .swg-quote { padding-left: 16px; }
  .swg-plot { padding: 18px 16px; }
  .swg-clip { max-width: 100%; }
}

/* The Adventurer's Guild. A FORM STOPS BEING A FORM AT 375px, and this room
   shipped with no rule here at all — which on a street whose §48 says every
   room reads at 360px is a room that was never looked at on a phone. The class
   column is 82px of an available 339, so the posting was being squeezed into
   173px: three-line titles and a body reading as a ribbon, with the stamp
   column collapsed to nothing. On a narrow screen the class goes ABOVE the job
   rather than beside it, and the numeral and its "on the street" sit on one
   line, which is what a docket line is anyway. The row keeps its padding,
   because the alternating band is what made the missing padding visible in the
   first place. */
@media (max-width: 620px) {
  .guild { padding: 0 16px 56px; }
  .job { grid-template-columns: 1fr; gap: 12px 0; padding: 18px 14px; }
  .job__class { display: flex; align-items: baseline; gap: 10px; font-size: 22px; }
  .job__where { display: inline; margin-top: 0; }
  .job__stamp { justify-self: start; align-self: start; }
  .job__hint[open] { padding-left: 10px; }
  .hand, .guild-rules { padding: 16px 14px; }
  .hand__in { flex: 1 1 100%; }
  .guild-desk__half .dial { max-width: none; }
}

/* The Garden (§28). The beds are flex rows that wrap on their own, which means
   the drawing lands ABOVE its own label rather than beside it -- a bed seen
   from the end of the path instead of across it, which is the right way round:
   the plant is what you see first either way. The drawing is CAPPED rather
   than stretched, because a plant drawn 340px wide on a phone is a plant
   looming over its own name, and it is never hidden -- a room whose pictures
   disappear on a phone is the lite-version mistake arriving through a
   breakpoint, which is the call the Playhouse's sound board already made when
   it gave up its grid instead of its words. */
@media (max-width: 620px) {
  .gd-bed { gap: 14px 24px; }
  .gd-bed__art { flex: 1 1 100%; max-width: 280px; align-self: flex-start; }
  .gd-over { gap: 22px; }
  .gd-plot__art { max-width: 280px; }
  .gd-plank, .gd-spider { padding: 16px 16px 18px; }
  .gd-spider__art { flex: 1 1 100%; max-width: 220px; }
  .gd-drill { padding-left: 16px; }
}

/* The Rabbit Hole. THE PRESS GIVES WAY RATHER THAN THE WORDS, which is the
   sound board's rule: half of 375px is about 135 pixels, and a 16/9 player and
   a paragraph of prose cannot both live in that. The first draft held the two
   columns and squeezed the note into a ribbon. So the button goes above the
   plate, full width, and both get the whole column.

   WRITTEN AFTER §30 ON PURPOSE. A media block placed above the rules it
   overrides loses exactly the declarations the base rule also sets and keeps
   the rest -- half a breakpoint, rendering as a layout nobody wrote, and it
   looks like a cache problem. That happened to the sound board's phone block.
   These are the last room rules in the file for that reason. */
@media (max-width: 620px) {
  .rh-press { grid-template-columns: minmax(0, 1fr); gap: 16px; padding: 18px; }
  .rh-ledge { padding: 20px 18px 22px; }
  .rh-cut__mat { padding: 14px; }
  .rh-cut__cap { padding: 0 14px 16px; }
  /* The engravings are the point of that section, so they get the width the
     mat's padding was taking rather than being shrunk to keep the frame. */
  .rh-cut__mat img { max-height: 380px; }
  /* The trail's deepest step is 96px in, which on a phone leaves a nine-
     character column. The stepping is the drawing and the words are the
     content, so the stepping is what gives way. */
  .rh-step { padding-left: calc(var(--step) * 5px); }
  .rh-step > a { margin-left: 12px; font-size: 19px; }
  .rh-step > p { margin-left: 12px; }

  /* The Healing Checkpoint (§31). The alcoves keep their arch at every width --
     it is the one shape that tells this room from the job board one link away,
     so the radius gives up proportion rather than existing. A slip's label and
     its note stack, because "Retry-After: the weekend" plus a clause is two
     lines of a 343px column and setting them side by side would leave four
     words to a line. */
  .hc-room { width: calc(100% - 32px); padding-bottom: 54px; }
  .hc-panel, .hc-desk { padding: 24px 20px 26px; border-radius: 32px 32px 18px 18px; }
  .hc-plate { font-size: 32px; padding: 12px 24px 14px; }
  .hc-voice { padding-left: 14px; }
  .hc-held, .hc-slip { border-radius: 20px; }
  .hc-slip__mark { padding: 16px 18px; }
  .hc-slip__after { flex: 1 1 100%; }
  .hc-slip__note { flex: 1 1 100%; margin-left: 18px; }
  .hc-slip__panel { padding: 0 18px 18px; }
  .hc-slip__text { padding: 16px 16px; font-size: 15.5px; }
  .hc-hold { padding: 18px 18px; }
}


/* The Foundry (§32). The bench already collapses on its own -- every control is
   a flex item with a basis rather than a fixed column -- so what is left here is
   the nameplate and the specimen grid. THIS BLOCK IS LAST IN ITS SECTION and
   after §32 in the file, which is not a formality: a media block written above
   the rules it overrides loses exactly the declarations the base rule also sets
   and keeps the rest, which is half a breakpoint and looks like a cache
   problem. The sound board taught this file that one.
   THE SPECIMEN NAMES DO NOT SHRINK. A face set too small to see is a specimen
   that is not doing its job, so the grid gives way to one column instead --
   the call the sound board made when a third of 375px turned out to be about
   seventy pixels of text column. */
/* Danny the Street (§33). THE RUNNING ORDER GIVES UP ITS COLUMN RATHER THAN ITS
   WORDS. A 104px date beside a 1fr entry leaves about 210px of text column on a
   375px phone, which sets a book title four words to a line; the date goes
   above its entry instead. The sound board's call, and this block is LAST in
   its section and after §33 in the file for that section's reason: a media
   block written above the rules it overrides loses exactly the declarations the
   base rule also sets and keeps the rest, which looks like a cache problem and
   is source order. The kerbs narrow rather than going, because they are the
   edge of the road and a road without one is a field. */
@media (max-width: 620px) {
  .dn-road { padding-left: 20px; padding-right: 20px; }
  .dn-road::before, .dn-road::after { width: 7px; }
  .dn-plate { padding: 16px 18px 18px; }
  .dn-when > li { grid-template-columns: 1fr; gap: 6px; }
  .dn-said { padding: 14px 16px; }
  .dn-note { padding: 16px 16px; }
}

@media (max-width: 620px) {
  .fo-plate { padding: 20px 18px 22px; gap: 16px; }
  .fo-galley { width: 124px; }
  .fo-bench, .fo-desk { padding: 18px 16px; }
  .fo-proof { padding: 26px 18px; }
  .fo-sorts { grid-template-columns: 1fr; }
  .fo-knob input[type="range"] { width: calc(100% - 58px); }
}

/* §49 ── Print ───────────────────────────────────────────────────────────────
   The zine room's own rule, applied site-wide: if it needs colour to make
   sense, it does not go in the zine. Ink on paper, decoration dropped. */

@media print {
  /* Fix the sheet ourselves. Left to the browser's margin setting the zine's
     one-sheet promise depends on a print dialog we do not control. */
  @page { size: letter; margin: 0.4in; }

  /* THE JOB MARKER DOES NOT PRINT. It is a control, like a play button: a
     disclosure you press, whose whole content is a code to type into a page
     you cannot type into on paper. The zine room's claim is that it prints to
     ONE SHEET -- check-print.py renders a real PDF and fails if it does not,
     and it has been pushed over that limit twice by a single paragraph -- so
     an extra object on every page is exactly the kind of thing that breaks a
     promise nobody was watching. It is also ink a photocopier would have to
     find room for, in a room whose other claim is black and white. */
  .quest { display: none !important; }

  /* NOR DOES THE SIGN-OFF, for the same reason and one more. It is a row of
     links, and a link on paper is an underlined word that goes nowhere; "Back
     to top" printed at the foot of a sheet is simply false. It also pushed
     issue #2 of the zine onto a second sheet the day it arrived, which
     check-print.py caught -- the third time a single addition has broken that
     room's promise, and the first time the addition was on every page. */
  .signoff { display: none !important; }

  /* Ink on paper, everywhere, with no exceptions by class.
     This used to reset backgrounds on a LIST of components, which meant every
     box not on the list kept its colour: the ransom note printed in full yellow,
     cyan and red, and .pullquote plus the dark credit boxes kept a near-black
     ground while the rules below forced their text to #000 -- black on
     #15121f, 1.14:1, invisible on paper. The most prominent quotation on each
     zine sheet and the whole attribution box were lost that way, and about a
     third of every sheet was solid toner.
     Colour and text are therefore reset TOGETHER and universally. Doing either
     alone breaks the other: white grounds under pale text (the .pullquote
     <cite> at #b9b2a3) would read 1.9:1 just as badly the other way. */
  *, *::before, *::after {
    background: #fff !important;
    background-image: none !important;
    color: #000 !important;
    box-shadow: none !important;
    text-shadow: none !important;
  }
  body { font-size: 11pt; }
  .sparkle, .glow, .grain, .marquee, .dial, .bunting, .floor, .fringe,
  .niche__glass, .seam, .votive__candles, .gd-dapple { display: none !important; }
  .door, .panel, .card, .qcard, .toy, .rules, .keeps, .niche, .votive, .gloria { border: 1pt solid #000 !important; background: #fff !important; color: #000 !important; break-inside: avoid; }
  a { color: #000 !important; text-decoration: underline; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; word-break: break-all; }
  h1, h2, h3, p, li, blockquote { color: #000 !important; text-shadow: none !important; }
  * { transform: none !important; }

  /* The zine room promises one sheet out of a bad printer, so it gets the only
     room-specific print rules on the street. On paper the two columns must stay
     two columns -- at 7.7in they would otherwise wrap and run to three pages --
     and the glossary row prints its shared prefix once instead of seven times. */
  .zine-sheet { display: grid !important; grid-template-columns: 1fr 1fr; gap: 0 16px !important; align-items: start; margin-top: 14px !important; }
  .zine-sheet > div { max-width: none !important; gap: 10px !important; }
  .room-zine p, .room-zine li, .room-zine dd { font-size: 8.6pt !important; line-height: 1.28 !important; }
  .room-zine h2 { font-size: 9.6pt !important; margin-bottom: 5px !important; }
  .room-zine section, .room-zine figure { padding: 8px 10px !important; }
  .room-zine .ransom span { font-size: 26pt !important; padding: 0 5px !important; }
  .room-zine .pullquote blockquote { font-size: 12pt !important; line-height: 1.2 !important; }
  .room-zine .pullquote cite { font-size: 7.6pt !important; }
  .room-zine .zine-cols { columns: 1 !important; }
  .room-zine .wrap { width: 100% !important; padding: 0 !important; }
  .room-zine main { padding-bottom: 0 !important; }
  .room-zine .ransom { margin: 4px 0 0 !important; }
  .zine-dialwrap { display: none !important; }
  .zine-footrow { display: grid !important; grid-template-columns: 1fr 1fr; gap: 10px !important; }
  .zine-footrow > section { flex: none !important; }
  .zine-glossary a[href^="http"]::after { content: none; }
  .zine-glossary::after { content: "\2014 all of them at stimpunks.org/glossary/"; display: block; font-size: 7.6pt; }

  /* THE FOUNDRY PRINTS THE PROOF AND NOTHING ELSE. What a foundry hands you is
     a sheet with the type on it, so the bench, the shelves, the notes and the
     way back to the street all stay off the paper -- there is nothing on any of
     them anybody could use once it is printed, and the shelves alone are every
     typeface on the street at 27px.
     THE COLOPHON IS THE HALF THAT MATTERS AND IT IS NOT DECORATION. It names the
     family, the person who drew it, the licence it travels under and every
     setting the proof was pulled at, which is the credit travelling with the
     thing rather than staying on a page nobody printed. It is the reason this
     rule hides everything EXCEPT .fo-pulled rather than only keeping .fo-proof.
     The ink is black on white by the universal rule above, whatever pair is on
     the screen: paper colour is a screen decision, and a printer would spend
     somebody's toner on it. The font, the size, the leading, the tracking and
     the measure are inline on the proof itself and survive, which is the whole
     point -- a proof that printed in the browser's default face would be a
     piece of paper. */
  .room-foundry .fo-light,
  .room-foundry .fo-topline,
  .room-foundry .fo-plate,
  .room-foundry .fo-lede,
  .room-foundry .fo-bench,
  .room-foundry .fo-notes,
  .room-foundry .fo-desk,
  .room-foundry .fo-cases,
  .room-foundry .fo-pulled__h { display: none !important; }
  .room-foundry .fo-shop { padding: 0 !important; max-width: none !important; }
  .room-foundry .fo-pulled { margin: 0 !important; }
  .room-foundry .fo-proof { padding: 0 !important; }
  .room-foundry .fo-colophon { margin-top: 18pt !important; padding-top: 6pt !important;
    border-top: 0.5pt solid #000 !important; font-size: 8pt !important; }
}

