/* Eden Online — the site. THEME.md is law: cream, sage, honey, apricot,
   charcoal. Porch light. Quiet chrome. If it looks like a crypto app, it
   failed. */

:root {
  --meadow-h: clamp(64px, 11vh, 108px);
  /* The signs sit in the four true corners on one inset. They overlap the
     grass at the bottom on purpose (Wick, 2026-08-18); the meadow is scenery,
     not a boundary. Change these two and all four corners move together. */
  --corner-x: 20px;
  --corner-y: 20px;
  --cream: #f4ece0;
  --paper: #faf5ec;
  --offwhite: #f6efe4;
  --charcoal: #3a342c;
  --faded: #6f6759;
  --honey: #c4a060;
  --honey-deep: #a87f1e;
  --apricot: #e0a46a;
  --sage: #5c7248;
  --line: rgba(58, 52, 44, 0.14);
  --shadow: 0 14px 42px rgba(42, 30, 18, 0.14);
}

* { box-sizing: border-box; }

html {
  background: var(--cream) url(/assets/frame/meadow-tile.png) repeat;
  background-size: 320px 320px;
}

html, body {
  margin: 0;
  padding: 0;
  background-color: transparent;
  color: var(--charcoal);
  font-family: ui-rounded, "SF Pro Rounded", "Hiragino Sans", Nunito, system-ui, sans-serif;
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--honey-deep); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }

img { max-width: 100%; }

.wrap { max-width: 760px; margin: 0 auto; padding: 0 22px; }

/* --- landing ------------------------------------------------------------ */

.hero { background: #6b924e; text-align: center; line-height: 0; }
.hero img { display: block; width: 100%; height: auto; }
.hero canvas { display: inline-block; }
.heroBox { position: relative; line-height: 0; max-width: 100%; max-height: 100%; }
.hero { position: relative; }

.tagline {
  text-align: center;
  font-size: clamp(19px, 3.2vw, 26px);
  padding: 44px 22px 6px;
  margin: 0 auto;
  max-width: 640px;
}

.tagline-sub {
  text-align: center;
  color: var(--faded);
  font-size: 15px;
  margin: 10px 0 0;
}

section.prose { padding: 30px 0 6px; }
section.prose p { margin: 0 0 1.1em; }
section.prose p.last { margin-bottom: 0; }

.glass {
  background: rgba(250, 245, 236, 0.87);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow);
  padding: 26px 30px;
}
.glass.chip {
  display: inline-block;
  padding: 14px 22px;
  max-width: 560px;
}

.dissolve {
  height: 42px;
  background: url(/assets/frame/dissolve.png) repeat-x top left / auto 42px;
  margin-top: -2px;
}

.divider {
  display: block;
  width: min(100%, 1280px);
  height: auto;
  margin: 26px auto;
}

.verbs {
  text-align: center;
  padding: 14px 22px 22px;
}
.verbs .label {
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--faded);
  margin-bottom: 10px;
}
.verbs .list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px 22px;
  align-items: flex-end;
}
.verbs .list img { height: 30px; width: auto; }

.plate { margin: 22px 0 0; }
.plate img { display: block; width: 100%; height: auto; }
.plate figcaption {
  text-align: center;
  font-size: 14px;
  color: var(--faded);
  padding: 12px 22px 0;
}

.people { text-align: center; padding: 30px 22px 8px; }
.people p { margin: 0 auto 1.2em; }
.people img.sheet {
  width: 100%;
  max-width: 960px;
  border-radius: 16px;
  box-shadow: var(--shadow);
}
.people img.one {
  width: 128px;
  image-rendering: pixelated;
  margin-bottom: 6px;
}

.door {
  display: block;
  background: rgba(250, 245, 236, 0.85);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  border: 1px solid var(--line);
  border-radius: 18px;
  box-shadow: var(--shadow);
  padding: 30px 34px;
  margin: 52px auto 0;
  max-width: 560px;
  color: var(--charcoal);
}
.door:hover { text-decoration: none; border-color: var(--honey); }
.door h2 { margin: 0 0 6px; font-size: 21px; }
.door p { margin: 0 0 12px; color: var(--faded); font-size: 15px; }
.door .go { color: var(--honey-deep); font-weight: 600; }

footer {
  text-align: center;
  color: var(--faded);
  font-size: 14px;
  padding: 72px 22px 46px;
}
footer .mark { color: var(--sage); }
footer .status {
  margin-top: 14px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.14em;
  color: var(--faded);
}

/* --- the space between things is the garden ------------------------------ */


.gcritter {
  position: fixed;
  z-index: 4;
  image-rendering: pixelated;
  pointer-events: none;
}

/* --- the temple, taken back ---------------------------------------------- */

.glass, .chapter { position: relative; }
.retired-ivy {
  content: "";
  position: absolute;
  top: -12px;
  right: -10px;
  width: 96px;
  height: 96px;
  background: url(/assets/frame/ivy-a.png) no-repeat top right / contain;
  pointer-events: none;
}


.liana {
  position: fixed;
  top: 0;
  z-index: 68;
  pointer-events: none;
  background-repeat: no-repeat;
  background-size: contain;
  transform-origin: top center;
  animation: sway 7s ease-in-out infinite alternate;
}
.liana.l1 { left: 9%; width: 26px; height: 122px; background-image: url(/assets/frame/liana-1.png); animation-duration: 8.5s; }
.liana.l2 { left: 46%; width: 26px; height: 170px; background-image: url(/assets/frame/liana-2.png); animation-delay: -3s; }
.liana.l3 { right: 7%; width: 26px; height: 206px; background-image: url(/assets/frame/liana-3.png); animation-duration: 9.5s; animation-delay: -6s; }
@keyframes sway {
  from { transform: rotate(-0.9deg); }
  to { transform: rotate(1.1deg); }
}
@media (max-width: 700px) {
  .liana.l1, .liana.l2 { display: none; }
  .liana.l3 { height: 140px; }
}
@media (prefers-reduced-motion: reduce) {
  .liana { animation: none; }
}

/* --- the garden engulfs the page ---------------------------------------- */

.frame {
  position: fixed;
  z-index: 70;
  pointer-events: none;
  image-rendering: pixelated;
}
.frame-top {
  top: 0; left: 0; right: 0; height: 34px;
  background: url(/assets/frame/canopy.png) repeat-x top left / auto 34px;
}
.frame-bottom {
  bottom: 0; left: 0; right: 0; height: 26px;
  background: url(/assets/frame/grass.png) repeat-x bottom left / auto 26px;
}
.frame-left, .frame-right { top: 0; bottom: 0; width: 22px; display: none; }
.frame-left { left: 0; background: url(/assets/frame/vine-left.png) repeat-y top left / 22px auto; }
.frame-right { right: 0; background: url(/assets/frame/vine-right.png) repeat-y top right / 22px auto; }
@media (min-width: 1100px) {
  .frame-left, .frame-right { display: block; }
}
@media (max-width: 700px) {
  .frame-top { height: 24px; background-size: auto 24px; }
  .frame-bottom { height: 18px; background-size: auto 18px; }
}

#life {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 65;
  pointer-events: none;
  image-rendering: pixelated;
}
@media (prefers-reduced-motion: reduce) { #life { display: none; } }

.stone { margin: 0 0 14px; }
.stone img { image-rendering: auto; width: auto; }

footer { padding-top: 26px; }

/* --- the world behind the page ------------------------------------------
   The loading fall's canvas does not die at handover any more. It moves out
   of the loader, becomes the page's own ground, and holds a camera seated at
   the shrine on the summit of the Hanging Gardens, so the monitor the page
   draws stands on the altar the world renders. index.html solves that seat.
   Everything the page owns sits above it in the layer order. */

#world {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  pointer-events: none;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}

/* the page's own layer, above the world and above the critters that walk
   between them, which is what keeps growth off the words */
body.one .stage { position: relative; z-index: 10; }

/* Once the world is up, the page stops drawing the two things the world now
   carries as objects: the monitor and the sentence. Both are hidden and not
   removed, on purpose and in three ways that matter.
   - hero.js keeps drawing. index.html copies its canvas, the demo, the play
     plate onto one picture every frame and hangs that picture on the glass
     of the monitor in the world. Stop the drawing and the tube goes dark.
   - `visibility`, never `display`. The boxes must still lay out, because
     index.html solves the camera against the monitor's own rect and reads
     the play plate's position out of it.
   - the click target is not in this list. `.crtplay-btn` is an empty box
     with no paint of its own, so it stays exactly where the solve has put
     its pixels in the world and the play control is still there to press.
   Every one of these rules needs html.world-on, which index.html sets only
   when the object is certainly on the screen. */
html.world-on .heroBox canvas,
html.world-on .crtdemo,
html.world-on .crtglass,
html.world-on .tagline img,
html.world-on .hero > img { visibility: hidden; }

/* Walking. The page steps out of the way, the world takes the screen, and
   only the way back stays lit. */
.stage, .corner, .frame, .liana, #life, .gcritter {
  transition: opacity 0.45s ease;
}
html.walking .stage,
html.walking .corner,
html.walking .frame,
html.walking .liana,
html.walking #life,
html.walking .gcritter {
  opacity: 0;
  pointer-events: none;
}
html.walking, html.walking body.one, html.walking body.one a, html.walking body.one button {
  cursor: grab;
}
html.walking.dragging, html.walking.dragging body.one { cursor: grabbing; }

/* Two lines of type used to stand here, one at the head of the screen to
   leave the seat and one at the foot to come back. Jack took them off on
   2026-08-20: the only flat things left on this screen are the signs in the
   corners. The way in is W, or a press held still on the world for half a
   second, which is the same gesture on a screen with no keyboard; the way
   out is Escape or simply walking back to the altar. Nothing is written
   down to say so. The rule below is what lets the held press work at all on
   a phone: without it, holding still on the page raises the system's own
   selection callout over the world. */
body.one {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

/* --- the arm ------------------------------------------------------------
   arm.js reaches an arm in from the bottom right corner and points it at
   the pointer. html.arm is set only once that canvas is drawing, so the
   native cursor is never hidden with nothing in its place: no second GL
   context, a coarse pointer or reduced motion all keep the pixel apple. */

/* The shadow is not decoration. Every skin tone that belongs in this
   palette sits a shade away from the sand and the stone the arm passes
   over, so without an edge the hand vanishes exactly where it is needed. */
#armcv {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 96;
  pointer-events: none;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  filter: drop-shadow(0 2px 0 rgba(20, 14, 6, 0.75))
          drop-shadow(0 0 7px rgba(20, 14, 6, 0.5));
}
/* :not(.walking) is load-bearing. While walking the arm is hidden and the
   grab cursor takes over, and these rules match the walking ones exactly on
   specificity, so without it the page walks with no pointer at all. */
html.arm:not(.walking) body.one,
html.arm:not(.walking) body.one a,
html.arm:not(.walking) body.one button,
html.arm:not(.walking) body.one button:not([disabled]) { cursor: none; }
html.walking #armcv { display: none; }
/* --- the CRT pane -------------------------------------------------------- */

.crt-scan { /* retired on the landing: the CRT is the monitor object now */
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  background: repeating-linear-gradient(0deg,
    rgba(16, 12, 6, 0.09) 0px, rgba(16, 12, 6, 0.09) 1px,
    transparent 1px, transparent 3px);
  animation: crtflicker 9s steps(1) infinite;
}
.crt-roll {
  position: fixed;
  left: 0;
  right: 0;
  top: -140px;
  height: 120px;
  z-index: 90;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(246, 239, 228, 0) 0%,
    rgba(246, 239, 228, 0.05) 45%,
    rgba(16, 12, 6, 0.04) 60%,
    rgba(246, 239, 228, 0) 100%);
  animation: crtroll 17s linear infinite;
}
.crt-vignette {
  position: fixed;
  inset: 0;
  z-index: 91;
  pointer-events: none;
  background: radial-gradient(115% 115% at 50% 48%,
    rgba(26, 22, 18, 0) 62%,
    rgba(26, 22, 18, 0.10) 86%,
    rgba(26, 22, 18, 0.30) 100%);
}
@keyframes crtroll {
  from { transform: translateY(0); }
  to { transform: translateY(calc(100vh + 280px)); }
}
@keyframes crtflicker {
  0%, 100% { opacity: 1; }
  7% { opacity: 0.92; }
  8% { opacity: 1; }
  43% { opacity: 0.95; }
  44% { opacity: 1; }
  71% { opacity: 0.9; }
  72% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .crt-scan { animation: none; }
  .crt-roll { display: none; }
}

.corner { position: fixed; z-index: 92; }
.corner.tl { top: var(--corner-y); left: var(--corner-x); }
.corner.tr { top: var(--corner-y); right: var(--corner-x); }
.corner.bl { bottom: var(--corner-y); left: var(--corner-x); }
.corner.br { bottom: var(--corner-y); right: var(--corner-x); }
.vh {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}
.online {
  border: 0;
  padding: 0;
  width: 112px;
  height: 32px;
  background: url(/assets/signs/online.png?v=2) no-repeat center / 100% 100%;
  image-rendering: pixelated;
  filter: drop-shadow(0 3px 5px rgba(42, 30, 18, 0.3));
}

.player {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  filter: drop-shadow(0 3px 5px rgba(42, 30, 18, 0.3));
}
.player .p-row { display: flex; gap: 6px; }
.player button {
  border: 0;
  padding: 0;
  width: 30px;
  height: 36px;
  background: no-repeat center / 100% 100%;
  image-rendering: pixelated;
  cursor: pointer;
}
.player .p-toggle { background-image: url(/assets/signs/btn-play.png); }
.player .p-toggle.on { background-image: url(/assets/signs/btn-pause.png); }
.player .p-skip { background-image: url(/assets/signs/btn-skip.png); }
.player .p-back { background-image: url(/assets/signs/btn-back.png); }
/* Back and skip mean nothing with one procedural hum and no playlist. */
.player .p-skip,
.player .p-back { display: none; }
.player.has-tracks .p-skip,
.player.has-tracks .p-back { display: block; }

/* The console is the plain readout until there are tracks, then it grows a
   second board for the times and the seek groove. */
.player .p-console {
  width: 150px;
  height: 36px;
  background: url(/assets/signs/plate-track.png) no-repeat center / 100% 100%;
  image-rendering: pixelated;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0 12px;
}
.player.has-tracks .p-console {
  width: 232px;
  height: 56px;
  background-image: url(/assets/signs/plate-console.png);
  justify-content: flex-start;
  padding: 7px 13px 0;
  gap: 4px;
}
.player .p-title {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 10px;
  letter-spacing: 0.14em;
  color: #d8cab2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  text-shadow: 0 1px 0 rgba(20, 14, 6, 0.85);
}
.player.playing .p-title { color: #e8d080; }

.player .p-bar { display: none; }
.player.has-tracks .p-bar {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  margin-top: 5px;
}
.player .p-elapsed,
.player .p-total {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 9px;
  letter-spacing: 0.04em;
  color: #b7a68c;
  text-shadow: 0 1px 0 rgba(20, 14, 6, 0.85);
  font-variant-numeric: tabular-nums;
  min-width: 22px;
}
.player .p-elapsed { text-align: right; }
.player .p-total { text-align: left; }

/* The groove is cut, not drawn on: a dark channel with the lit wall along
   its lower edge, the same low west sun as every carved letter. */
.player .p-seek {
  position: relative;
  flex: 1;
  height: 7px;
  cursor: pointer;
  background: linear-gradient(
    180deg,
    #241a10 0, #241a10 4px,
    #9a7a50 4px, #9a7a50 6px,
    #6a5232 6px, #6a5232 7px
  );
  touch-action: none;
}
.player .p-seek:focus-visible { outline: 1px solid var(--honey); outline-offset: 2px; }
.player .p-fill {
  position: absolute;
  left: 0;
  top: 0;
  height: 4px;
  width: 0;
  background: var(--honey);
}
.player .p-bead {
  position: absolute;
  top: -4px;
  left: 0;
  width: 7px;
  height: 15px;
  margin-left: -3px;
  background: url(/assets/signs/bead.png) no-repeat center / 100% 100%;
  image-rendering: pixelated;
  pointer-events: none;
}

@media (max-width: 700px) { .player .p-console { display: none; } }


body.one, body.one a, body.one button {
  cursor: url(/assets/cursors/apple.png?v=4) 4 2, auto;
}
body.one a, body.one button:not([disabled]) {
  cursor: url(/assets/cursors/apple-bite.png?v=4) 4 2, pointer;
}
.online .dot {
  width: 6px;
  height: 6px;
  background: #8a8478;
  animation: onlinepulse 3.4s ease-in-out infinite;
}
@keyframes onlinepulse {
  0%, 100% { opacity: 0.45; }
  50% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) { .online .dot { animation: none; } }
@media (max-width: 700px) { .online { top: 10px; right: 10px; font-size: 10px; } }

/* the hero's own resting scanline retires; the whole pane is the CRT now */
.hero .scan.rest { opacity: 0; }

/* --- the glass ------------------------------------------------------------

   Everything a live tube does that a still image cannot, sitting on the
   screen rect hero.js publishes. Layer order is the order light meets the
   eye: phosphor bloom deepest, then the shadow mask, then the two moving
   refresh bands, then flicker, then the reflection on the outside of the
   glass. Nothing here costs a canvas repaint; the bands are composited
   transforms. Keep every alpha low. The tube should feel alive, not busy.

   These layers are the fallback now. When the world is up the monitor is an
   object in it, and index.html composes the roll and the raster into the
   picture it hangs on that object's glass instead. This block is what a
   visitor sees whose browser could not give the page a world. */

/* the tube's play control and the demo it starts (demo.js). The plate and
   the demo ride under the glass; only the button takes the pointer. */
.crtplay { position: absolute; image-rendering: pixelated; pointer-events: none; }
.crtplay-btn {
  position: absolute;
  z-index: 5;
  display: block;
  background: none;
  border: 0;
  padding: 0;
}
.crtplay-btn:focus-visible { outline: 2px solid #6f6759; outline-offset: 3px; }
.crtdemo { position: absolute; overflow: hidden; pointer-events: none; }
.crtdemo canvas {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}
.crtdemo-raster { position: absolute; left: 0; top: 0; width: 100%; height: 100%; }
.crtdemo-cap { position: absolute; background: #14100a; }
.crtglass {
  position: absolute;
  z-index: 4;
  overflow: hidden;
  pointer-events: none;
}
.crtglass > * {
  position: absolute;
  inset: 0;
}

/* phosphor glow pooling at the centre, tube shadow closing the corners */
.crt-bloom {
  box-shadow:
    inset 0 0 26px rgba(6, 10, 4, 0.42),
    inset 0 0 70px rgba(120, 190, 100, 0.09);
}

/* the shadow mask: vertical triads, the tube's own grain. Only above a
   size where the stripes can resolve without moire against the raster. */
.crt-grille {
  background-image: repeating-linear-gradient(
    90deg,
    rgba(255, 40, 40, 0.045) 0 1px,
    rgba(40, 255, 90, 0.045) 1px 2px,
    rgba(60, 90, 255, 0.045) 2px 3px
  );
}
@media (max-width: 700px) { .crt-grille { display: none; } }

/* the slow refresh roll: a wide, soft brightening that walks down the
   glass, the artifact you get filming a CRT slightly out of sync */
.crt-roll {
  bottom: auto;
  height: 42%;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(214, 255, 214, 0.035) 34%,
    rgba(226, 255, 226, 0.07) 50%,
    rgba(214, 255, 214, 0.035) 66%,
    rgba(255, 255, 255, 0) 100%
  );
  will-change: transform;
  animation: crtroll 7.5s linear infinite;
}
@keyframes crtroll {
  from { transform: translateY(-100%); }
  to   { transform: translateY(238%); }   /* 100/42: clears the glass */
}

/* the fast sweep: the thin dark seam where the beam is between fields */
.crt-sweep {
  bottom: auto;
  height: 9%;
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, 0) 0%,
    rgba(2, 6, 2, 0.14) 48%,
    rgba(2, 6, 2, 0.05) 62%,
    rgba(0, 0, 0, 0) 100%
  );
  will-change: transform;
  animation: crtsweep 2.6s linear infinite;
}
@keyframes crtsweep {
  from { transform: translateY(-100%); }
  to   { transform: translateY(1111%); }  /* 100/9 */
}

/* Mains flicker. Deliberately slow and shallow: the swing is under two
   percent of luminance and nowhere near the 3-30 Hz photosensitive band.
   A faster strobe would be more "authentic" and is not worth the risk. */
.crt-flick {
  background: rgba(206, 255, 206, 0.035);
  animation: crtflick 1.1s ease-in-out infinite;
}
@keyframes crtflick {
  0%, 100% { opacity: 0.30; }
  40%      { opacity: 0.85; }
  70%      { opacity: 0.50; }
}

/* Power-on. One line of light that opens into the full field, once, when
   the loader hands the page over. html.booted is set for every visitor at
   reveal; if the glass is built after that (slow logo-grid fetch), the
   animation simply plays the moment the layer exists. Single flash, under
   a second, never repeated: nowhere near the photosensitive band. */
.crt-boot {
  opacity: 0;
  transform-origin: 50% 50%;
  will-change: transform, opacity;
  background:
    radial-gradient(100% 60% at 50% 50%,
      rgba(234, 255, 226, 0.95) 0%,
      rgba(190, 235, 178, 0.55) 55%,
      rgba(130, 200, 110, 0.18) 100%);
}
html.booted .crt-boot {
  animation: crtboot 0.8s cubic-bezier(0.2, 0.7, 0.3, 1) 1 forwards;
}
@keyframes crtboot {
  0%   { opacity: 0;   transform: scaleY(0.012); }
  14%  { opacity: 1;   transform: scaleY(0.03); }
  46%  { opacity: 0.6; transform: scaleY(1); }
  100% { opacity: 0;   transform: scaleY(1); }
}

/* the room, reflected in the outside of the glass */
.crt-glare {
  background:
    linear-gradient(148deg,
      rgba(255, 255, 255, 0.11) 0%,
      rgba(255, 255, 255, 0.035) 20%,
      rgba(255, 255, 255, 0) 44%),
    radial-gradient(120% 80% at 50% 0%,
      rgba(255, 255, 255, 0.05) 0%,
      rgba(255, 255, 255, 0) 60%);
}

@media (prefers-reduced-motion: reduce) {
  .crt-roll, .crt-sweep { display: none; }
  .crt-flick { animation: none; opacity: 0.4; }
  html.booted .crt-boot { animation: none; }
}

/* --- one screen ---------------------------------------------------------- */

body.one {
  height: 100dvh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* The stage owns the whole viewport and insets itself equally top and
   bottom by the meadow's height. Symmetric padding is what makes centering
   inside it land on the true middle of the screen, and it also keeps the
   monitor from growing down into the grass. */
body.one .stage {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--meadow-h) 18px;
}

/* The hero band is all the space between canopy and meadow. The monitor and
   the tagline live inside it as one column, centered, so the composition
   sits in the middle of the screen at every viewport. Pinning it to the
   bottom looked right only when the canvas filled the band; in a portrait
   window the canvas is width-limited and the group sank. hero.js subtracts
   the tagline's height from the canvas budget. */
body.one .hero {
  flex: 1;
  min-height: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(10px, 2.4vh, 26px);
  background: transparent;
}
body.one .hero > img { max-height: 100%; width: auto; max-width: 100%; }

body.one .tagline {
  padding: 0;
  margin: 0;
  line-height: 0;
  width: 100%;
  text-align: center;
}
/* The stone type now reads against lit stone instead of cream paper, so it
   carries its own shadow. Without one the altar washes the letterforms out. */
body.one .tagline img {
  width: min(92%, 620px);
  height: auto;
  image-rendering: pixelated;
  filter: drop-shadow(0 2px 3px rgba(20, 14, 6, 0.85));
}
body.one .whisper {
  margin: 0;
  color: var(--faded);
  font-size: clamp(12px, 1.8vh, 15px);
}

.doorsign {
  display: block;
  filter: drop-shadow(0 4px 7px rgba(42, 30, 18, 0.34));
}
.doorsign img {
  display: block;
  width: 186px;
  height: auto;
  image-rendering: pixelated;
}
.doorsign:hover { filter: drop-shadow(0 6px 10px rgba(42, 30, 18, 0.45)); }

/* The drawn meadow strip is retired (2026-08-20): the floor of the page is
   the summit of the real gardens now. --meadow-h stays because it is the
   stage's symmetric inset, and that symmetry is what puts the monitor on
   the true middle of the screen. */
@media (max-height: 600px) {
  body.one { overflow-y: auto; }
  body.one .whisper { display: none; }
}

/* the book is a reading room: gentler pane, no roll */
body.crt-lite .crt-scan {
  background: repeating-linear-gradient(0deg,
    rgba(16, 12, 6, 0.05) 0px, rgba(16, 12, 6, 0.05) 1px,
    transparent 1px, transparent 3px);
  animation: none;
}
body.crt-lite .crt-vignette {
  background: radial-gradient(120% 120% at 50% 45%,
    rgba(26, 22, 18, 0) 70%,
    rgba(26, 22, 18, 0.16) 100%);
}

/* --- book --------------------------------------------------------------- */

.book {
  display: grid;
  grid-template-columns: 235px minmax(0, 1fr);
  gap: 46px;
  max-width: 1060px;
  margin: 0 auto;
  padding: 30px 22px 70px;
}

.crumb {
  font-size: 14px;
  color: var(--faded);
  padding: 18px 22px 0;
  max-width: 1060px;
  margin: 0 auto;
}

.toc {
  position: sticky;
  top: 26px;
  align-self: start;
  font-size: 14.5px;
  line-height: 1.5;
}
.toc a { display: block; padding: 3.5px 0; color: var(--faded); }
.toc a:hover { color: var(--charcoal); text-decoration: none; }
.toc a.here { color: var(--honey-deep); font-weight: 600; }

.chapter {
  max-width: 720px;
  background: #f2e8d5 url(/assets/scroll/parchment-tile.png) repeat;
  border: 0;
  border-radius: 2px;
  box-shadow: 0 10px 34px rgba(42, 30, 18, 0.18);
  padding: 40px 42px 44px;
  margin: 22px 0 26px;
}
.chapter::before, .chapter::after {
  content: "";
  position: absolute;
  left: -8px;
  right: -8px;
  height: 22px;
  background-repeat: repeat-x;
  background-size: auto 22px;
  image-rendering: pixelated;
  pointer-events: none;
  filter: drop-shadow(0 3px 4px rgba(42, 30, 18, 0.22));
}
.chapter::before { top: -14px; background-image: url(/assets/scroll/scroll-top.png); }
.chapter::after { bottom: -14px; background-image: url(/assets/scroll/scroll-bottom.png); }
.chapter code { background: rgba(90, 68, 44, 0.12); }
.chapter th { background: rgba(90, 68, 44, 0.08); }
.chapter h1 { font-size: clamp(27px, 4vw, 33px); line-height: 1.2; margin: 8px 0 20px; }
.chapter h2 { font-size: 21px; margin: 34px 0 10px; }
.chapter h3 { font-size: 17.5px; margin: 26px 0 8px; }
.chapter p { margin: 0 0 1.05em; }
.chapter hr { border: 0; border-top: 1px solid var(--line); margin: 34px 0; }

.chapter code {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.86em;
  background: rgba(58, 52, 44, 0.07);
  border-radius: 6px;
  padding: 0.12em 0.38em;
}

.chapter table {
  border-collapse: collapse;
  width: 100%;
  margin: 18px 0 24px;
  font-size: 15px;
}
.chapter th {
  text-align: left;
  background: var(--paper);
  border-bottom: 2px solid var(--line);
  padding: 8px 12px;
}
.chapter td { border-bottom: 1px solid var(--line); padding: 8px 12px; vertical-align: top; }

.chapter ul, .chapter ol { margin: 0 0 1.1em; padding-left: 1.4em; }
.chapter li { margin: 0.28em 0; }

pre.mermaid {
  display: flex;
  justify-content: center;
  overflow-x: auto;
  margin: 26px 0 30px;
  background: transparent;
}

.prevnext {
  display: flex;
  justify-content: space-between;
  gap: 18px;
  margin-top: 54px;
  padding-top: 22px;
  border-top: 1px solid var(--line);
  font-size: 15px;
}

@media (max-width: 880px) {
  .book { display: block; }
  .toc {
    position: static;
    display: flex;
    overflow-x: auto;
    gap: 16px;
    white-space: nowrap;
    padding-bottom: 12px;
    margin-bottom: 26px;
    border-bottom: 1px solid var(--line);
  }
  .toc a { padding: 2px 0; }
}
