/* ============================================================
   Grieving the average
   Visual style: early CLI terminal, inverted to white.
   Nothing eases. Everything snaps on a character grid.
   ============================================================ */

:root{
  --ink: #0a0a0a;
  --paper: #ffffff;
  --dim: #8a8a8a;

  /* VT220-era bitmap face; Courier is the fallback that still
     predates anything geometric. */
  --term: "VT323", "Courier New", Courier, monospace;

  /* a typewriter, not a terminal — Courier is the machine itself */
  --type: "Courier Prime", "Courier New", Courier, monospace;

  --bar: 30px;              /* height of the top/bottom rails */
  --cell: 18px;             /* base character size */
  --move: 760ms;

  /* full colour, washed flat so the white mask and the white
     ABSENTMIND still read on top of the photographs */
  --wash: contrast(0.28) brightness(1.28) saturate(1.5);
}

*{ box-sizing: border-box; margin: 0; padding: 0; }

html, body{
  height: 100%;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--term);
  font-size: var(--cell);
  line-height: 1.1;
  text-rendering: geometricPrecision;
  -webkit-font-smoothing: none;
  font-smooth: never;
}

body{ overflow: hidden; }

#site{ display: none; }

/* ------------------------------------------------------------
   Top and bottom rails — the window furniture
   ------------------------------------------------------------ */

#topbar,
#chrome{
  position: fixed;
  left: 0;
  right: 0;
  height: var(--bar);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 10px;
  background: var(--paper);
  text-transform: uppercase;
  letter-spacing: .04em;
  z-index: 40;
}

#topbar{
  top: 0;
  border-bottom: 2px solid var(--ink);
}

/* ---- the bottom rail ----
   Not a status line any more. A warning strip, and warning strips
   blink. Hard steps rather than a fade, so it reads as a lamp
   switching rather than as something dissolving. */
#chrome{
  bottom: 0;
  border-top: 2px solid #6d0a18;
  background: #c8102e;
  color: #fff;
  justify-content: flex-start;
  animation: warnbar 1.06s steps(1) infinite;
}

#chrome b{
  font-weight: 700;
  letter-spacing: .3em;
  padding-left: 4px;
}

@keyframes warnbar{ 0%,54%{ opacity: 1 } 55%,100%{ opacity: .16 } }

/* a run of box-drawing dashes that eats the slack */
/* ---- the navigation ----
   Two icons and nothing else. There were only ever two controls,
   and the words around them were the site describing itself. */

#topbar button{
  display: inline-flex;
  align-items: center;
  font: inherit;
  color: var(--ink);
  background: transparent;
  border: 0;
  padding: 2px 6px;
  cursor: pointer;
}

.ico{
  display: block;
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: square;
  stroke-linejoin: miter;
}

/* the hamburger, turned on its side */
.ico.bars{ transform: rotate(90deg); }

#chrome button{
  font: inherit;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--ink);
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
}

#chrome button:hover,
#chrome button:focus-visible,
#chrome button[aria-expanded="true"]{
  background: var(--ink);
  color: var(--paper);
  outline: none;
}

/* ------------------------------------------------------------
   The strip of frames
   ------------------------------------------------------------ */

#rail{
  display: flex;
  height: 100vh;
  width: 100vw;
  will-change: transform;
  /* Steps, not easing. A terminal does not glide. */
  transition: transform var(--move) steps(8, end);
}

#rail.cut{ transition: none; }

.frame{
  flex: 0 0 100vw;
  width: 100vw;
  height: 100vh;
  position: relative;
  padding: calc(var(--bar) + 18px) 10px calc(var(--bar) + 18px);
  border-right: 2px solid var(--ink);
  overflow: hidden;
}

/* ---- home frame: backdrop, plate, eyes ---- */

.home{
  padding: 0;
  display: block;
  overflow: hidden;
  background: var(--paper);
}

/* the photographs behind everything. they do not slide, they
   just appear, one every BACKDROP_MS. */

#bg{
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: 0;
  background: var(--paper);
}

#bg > img{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  filter: var(--wash);
  /* deliberately NOT will-change: every frame rewrites filter and
     transform anyway, so promotion buys nothing, and hinting it on
     all twelve pins twelve full-screen layers in GPU memory at once */
}

#bg > img.on{ opacity: 1; }

/* single-frame flashes on the joins — the oldest trick there is
   for making a cut land harder than the cut itself */
#flash{
  position: absolute;
  inset: 0;
  z-index: 3;
  opacity: 0;
  pointer-events: none;
}

/* The intrusion. One frame of the thing the piece is about: the
   eye, blown up until it fills the screen and stares straight
   out — cut in among photographs of people not looking at each
   other, under an instruction not to look back. */
#intrude{
  position: absolute;
  inset: 0;
  z-index: 6;                  /* over the stage — a real cut, mask and all */
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
  background: var(--paper);
}

#intrude.neg{ background: var(--ink); }

#intrude img{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform-origin: 63.74% 41.12%;   /* the left eyeball's centre */
}

#intrude.neg img{ filter: invert(1); }

#intrude p{
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  margin: 0;
  font-family: var(--type);
  font-size: 5.2vw;
  line-height: 1;
  white-space: nowrap;
  color: var(--ink);
}

#intrude.neg p{ color: var(--paper); }

/* the artwork sits on its own 1024.5x576 stage, so the eye
   coordinates taken from the SVG map straight onto it */

#stage{
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(100vw, calc(100vh * 1024.5 / 576));
  aspect-ratio: 1024.5 / 576;
  pointer-events: none;
  /* so type on the mask can be sized against the artwork itself
     rather than the window, and stays put at any stage size */
  container-type: inline-size;
}

#stage img{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

#plate{ z-index: 3; }          /* mask + ABSENTMIND, stationary */

/* The eyeball is cut in two: a sclera that stays put, and the
   iris disc that travels across it — which is how an eye actually
   moves. Both squash about the globe centre so a blink closes on
   one line.

   The sclera sits behind the mask and is only ever seen through
   its eye holes. The iris rides above the mask, so it is never
   clipped by them and can wander out onto the face. */

.sclera{
  z-index: 1;                  /* behind the mask, seen through the holes */
  will-change: transform;
}

.iris{
  z-index: 4;                  /* over the mask — free to leave the eye hole */
  will-change: transform;
  /* no transition — eased per frame in app.js, so a moving cursor
     does not keep restarting a CSS tween */
}

#sclera-l, #iris-l{ transform-origin: 63.74% 41.12%; }
#sclera-r, #iris-r{ transform-origin: 79.08% 41.54%; }

/* Spoken out of the mouth. The mouth hole is the lowest gap in
   the mask: x 679 -> 781, y 406.5 -> 439, so its centre is
   (730, 423) and the bubble hangs to its left with the tail
   reaching back to the lip. Sized in cqw against #stage, so it
   stays glued to the mouth at any window size. */
#speech{
  position: absolute;
  z-index: 5;
  right: 37.5%;                 /* right edge at x ~= 640 */
  top: 73.44%;                  /* the mouth's centre line */
  transform: translateY(-50%);
  align-items: center;
  gap: 0.6cqw;
  padding: 0.85cqw 1.25cqw;
  background: var(--paper);
  border: 0.22cqw solid var(--ink);
  font-family: var(--type);
  font-size: 1.55cqw;
  line-height: 1;
  white-space: nowrap;
  color: var(--ink);
  display: none;
}

#speech.on{ display: flex; }     /* it appears; nothing eases here */

/* the tail: an ink triangle with a paper one laid over it, so the
   2px outline carries round the point */
#speech::before,
#speech::after{
  content: "";
  position: absolute;
  top: 50%;
  left: 100%;
  width: 0;
  height: 0;
  border: solid transparent;
  transform: translateY(-50%);
}

#speech::before{
  border-width: 1.5cqw 3.9cqw;   /* reaches the lip at x ~= 679 */
  border-left-color: var(--ink);
}

#speech::after{
  border-width: 1.12cqw 3.1cqw;
  border-left-color: var(--paper);
  margin-left: -0.28cqw;
}

/* keycaps. the deep bottom edge is what reads as a key */
#speech kbd{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.3cqw;
  height: 2.3cqw;
  border: 0.18cqw solid var(--ink);
  border-bottom-width: 0.5cqw;
  border-radius: 0.28cqw;
  background: var(--paper);
}

/* arrows drawn, not typed — neither the terminal face nor the
   typewriter one can be trusted to carry an arrow glyph */
#speech kbd svg{
  width: 1.35cqw;
  height: 1.35cqw;
  display: block;
}

#speech kbd path{
  fill: none;
  stroke: currentColor;
  stroke-width: 2.6;
  stroke-linecap: square;
  stroke-linejoin: miter;
}

/* Struck on the forehead. Dead centre of it: the face runs from
   y 65.5 to the brow at y 184, and spans x 576 -> 875.3 at that
   height — so (725.6, 124.8) in artwork units. */
#dontlook{
  position: absolute;
  z-index: 5;
  left: 70.825%;
  top: 21.667%;
  transform: translate(-50%, -50%);
  margin: 0;
  font-family: var(--type);
  font-size: 1.22cqw;
  line-height: 1;
  white-space: nowrap;
  color: var(--ink);
}

/* ---- a project running in its frame ----

   The garden has no theme. A project keeps its own typeface and
   its own colours; the only thing the site imposes is the two
   rails. The page sits live behind a veil, frozen by
   pointer-events rather than by being a picture of itself, so
   what is teased is the real thing and it is ready the moment
   someone asks for it. */

.project.embedded{
  padding: 0;
  --fh: calc(100vh - var(--bar) * 2);   /* the frame between the rails */
}

/* ---- the puppet scene ----
   A 16:9 rack sized to cover the frame with overscan, so parts can
   drift without dragging an edge into shot. Every flat is the full
   canvas, so a pivot given in canvas coordinates lands correctly
   whatever the window is doing. */

.p-scene{
  position: absolute;
  left: 0;
  top: var(--bar);
  width: 100%;
  height: var(--fh);
  overflow: hidden;
  z-index: 1;
  /* the case has a back to it. without this, pitching the camera
     swings the flats off the top or the bottom of the frame and the
     project's own page shows through the gap, which is a hole in
     the world rather than a view of one. */
  background: #060d0f;
  /* the box the diorama sits in; the depth comes from here */
  perspective-origin: 50% 46%;
}

/* the flats swing further than they used to, so the rack carries
   more overscan or an edge walks into shot */

.project.live .p-scene{ display: none; }

/* the painted backcloth. out of focus, almost unlit, and nailed
   down: it is scenery, not a layer, so it never moves. */
.p-cyc{
  position: absolute;
  inset: -8%;
  z-index: 0;
  background-position: center;
  background-size: cover;
}

.p-rack{
  position: absolute;
  /* the flats are scenery. clicks pass through them to the things
     hanging in the room that are meant to be clicked. */
  pointer-events: none;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  /* the assets are 2688x1536, which is 7:4, not 16:9 */
  transform-style: preserve-3d;
  aspect-ratio: 2688 / 1536;
  /* whichever is larger: overscanned frame width, or the width that
     makes the rack tall enough to cover an overscanned frame */
  width: max(126%, calc(var(--fh) * 2.21));
}

.p-rack img,
.p-strings{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  will-change: transform;
  /* flats and their strings are leaves in the box: never put a
     filter on the rack itself or the whole thing goes flat */
}

/* The room is forced cold and blue-green by a colour-blend layer,
   and the only warmth in the frame is punched back through it by
   the two screens, which screen-blend over the top. That order is
   the whole look: drain everything, then let the phone and the
   television be the only things giving light. */
.p-tint{
  position: absolute;
  inset: 0;
  z-index: 8;
  pointer-events: none;
  mix-blend-mode: color;
  background: linear-gradient(168deg, #0d4a5e 0%, #0d5046 48%, #06242c 100%);
}

.p-lights{
  position: absolute;
  inset: 0;
  z-index: 9;
  pointer-events: none;
  mix-blend-mode: screen;
}

/* the dark that arrives as the camera lifts off the floor */
.p-dark{
  position: absolute;
  inset: 0;
  z-index: 14;
  pointer-events: none;
  background: radial-gradient(ellipse 90% 80% at 50% 62%,
    rgba(3,10,12,.25) 0%, rgba(3,10,12,.72) 68%, rgba(3,10,12,.95) 100%);
  opacity: 0;
}

/* The grade. A vignette that breathes like something closing in,
   and a red bleed that rises out of the demon as he comes near.
   Both sit over the flats and under the veil. */
.p-grade,
.p-bleed{
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.p-grade{
  z-index: 11;
  background: radial-gradient(ellipse 78% 68% at 50% 48%,
    rgba(4,12,14,0) 44%, rgba(4,12,14,.34) 76%, rgba(4,12,14,.80) 100%);
}

.p-bleed{
  z-index: 10;
  mix-blend-mode: soft-light;
  opacity: 0;
}

/* A stage has a frame round it, and a diorama has a shallow focus
   because it is small. Both are Anderson and both are literally
   true of a puppet theatre. */
.p-pros{
  position: absolute;
  inset: 12px;
  z-index: 13;
  pointer-events: none;
  border: 1px solid rgba(146, 186, 190, .26);
  box-shadow: 0 0 0 1px rgba(40, 28, 20, .18);
}

.p-mini{
  position: absolute;
  left: 0;
  right: 0;
  height: 17%;
  z-index: 12;
  pointer-events: none;
  backdrop-filter: blur(2.4px);
  -webkit-backdrop-filter: blur(2.4px);
}

.p-mini.top{
  top: 0;
  mask-image: linear-gradient(to bottom, #000 0%, transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, transparent 100%);
}

.p-mini.bot{
  bottom: 0;
  mask-image: linear-gradient(to top, #000 0%, transparent 100%);
  -webkit-mask-image: linear-gradient(to top, #000 0%, transparent 100%);
}

/* The strings. Same red as the threads already running through the
   artwork, so the drawn ones and the painted ones are the same
   thing. Over the flats, because in rukada you see them. */
.p-strings{
  overflow: visible;
  pointer-events: none;
}

.p-strings .p-lid{
  fill: #0a1416;
  opacity: 0;
}

.p-strings path{
  fill: none;
  stroke: #b8503a;
  stroke-width: 1.3;
  opacity: .42;
  vector-effect: non-scaling-stroke;
}

.p-embed,
.p-veil{
  position: absolute;
  left: 0;
  top: var(--bar);
}

.p-veil{
  right: 0;
  bottom: var(--bar);
  z-index: 2;                      /* over the scene */
}

/* an iframe is a replaced element: with width:auto it takes its
   intrinsic 300x150 and ignores left/right, so it needs telling */
.p-embed{
  width: 100%;
  height: calc(100% - var(--bar) * 2);
  border: 0;
  display: block;
  background: var(--paper);
  pointer-events: none;            /* frozen */
}

.project.live .p-embed{ pointer-events: auto; }

/* ---- the veil ----
   A wash and nothing else. The words used to sit here on the glass,
   neatly, which was the problem: it read as a caption for the
   picture rather than as part of it. They are in the room now. All
   this does is take the top off the contrast and vanish when the
   project comes up. Nothing here takes a pointer. */

.p-veil{
  display: block;
  padding: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse 128% 96% at 50% 46%,
      rgba(4,12,14,0) 46%, rgba(4,12,14,.44) 100%),
    rgba(4,12,14,.10);
  color: #fff;
  font-family: "Futura", "Jost", "Century Gothic", var(--own, system-ui), sans-serif;
}

.project.live .p-veil{ display: none; }

/* ---- the type, hanging in the room ----

   Inside the box, at the back wall, so the man and the thing behind
   him pass in front of the words and the reading is never clean.
   Nothing is level and nothing lines up with anything else, because
   a set is painted, not typeset. */

/* The type is no longer in the box. It sits on the glass in front
   of everything, because the man and the demon were eating the
   words. Only the room moves behind it now. */
/* ---- the two faces the lending frame is set in ----

   Self hosted, not linked. This project's standing rule is that it
   uses nothing from Google, and a webfont link is a request to
   Google from every visitor's browser. These came off jsDelivr once,
   at build time, and are served from here. Both are SIL Open Font
   License.

   Only the weights actually in use are here. An unused @font-face
   costs nothing to a visitor, because the file is not fetched until
   something asks for it, but it costs the next person reading this
   a minute working out which of five files matter. */

@font-face{ font-family:"EB Garamond";
  src:url("assets/fonts/eb-garamond-600.woff2") format("woff2");
  font-weight:600; font-display:swap }
@font-face{ font-family:"Libre Franklin";
  src:url("assets/fonts/libre-franklin-400.woff2") format("woff2");
  font-weight:400; font-display:swap }

.p-type{
  position: absolute;
  inset: 0;
  z-index: 16;
  pointer-events: none;
}

.p-word{
  position: absolute;
  /* pinned at the top left corner, so a block goes where it is put */
  transform-origin: 0 0;
  pointer-events: none;
  will-change: transform;
  color: #f4efe6;
  line-height: 1.14;
  /* a newline in the copy is a break the writer chose */
  white-space: pre-line;
  font-family: "Futura", "Jost", "Century Gothic", var(--own, system-ui), sans-serif;
  /* the wall behind is lit in places, so the type carries its own
     dark rather than relying on a panel to sit on */
  text-shadow:
    0 0 .9em rgba(0,0,0,.98),
    0 1px 3px rgba(0,0,0,.95),
    0 0 2.6em rgba(0,0,0,.85);
}

/* The headline is a sentence, not a label, and it is a long one.
   Uppercase set it about fifteen percent wider for no gain in
   legibility and pushed it under the demon. Sentence case is also
   what the project's own copy rules ask for. */
.p-word.title{
  /* The headline, now a subheadline under the question. A gothic,
     set regular. It sits on a dark photograph with no plate behind
     it, so the weight it is not carrying has to come from the
     shadow underneath instead. */
  font-family: "Libre Franklin", "Franklin Gothic Medium", "Franklin Gothic",
               "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 400;
  letter-spacing: -0.004em;
  line-height: 1.10;
  color: #f2ece1;
}

.p-word.lead{ line-height: 1.12; color: #f6f1e6; }

.p-word.body{ line-height: 1.5; color: #dad3c7; }

/* what he said. lighter than the title and larger than the type
   around it, because it is the only voice on the page that is not
   the author's. */
.p-word.quote{
  /* The question he cannot answer. An old-style serif set in
     capitals, which needs positive tracking to breathe the way
     lowercase does not. */
  font-family: "EB Garamond", "Adobe Garamond Pro", Garamond,
               "Hoefler Text", Georgia, serif;
  font-weight: 600;
  text-transform: uppercase;
  line-height: 1.163;
  letter-spacing: .034em;
  color: #f6f0e4;
}

/* ---- the three ways in ----

   Pinned across the top of the frame, outside the perspective box,
   so nothing in the room can pass in front of them. Icon first,
   because these have to be found against a picture and a mark is
   quicker to read than a word at this size. */

.p-bar{
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  display: flex;
  align-items: stretch;
  gap: clamp(10px, 1.4vw, 22px);
  padding: clamp(14px, 1.8vh, 26px) clamp(24px, 4vw, 74px);
  pointer-events: none;      /* the gaps are not a target */
}

.p-way{
  pointer-events: auto;
  cursor: pointer;
  display: flex;
  align-items: flex-start;
  gap: 11px;
  max-width: 290px;
  font: inherit;
  font-size: 15px;
  line-height: 1.2;
  text-align: left;
  text-decoration: none;
  color: #f6efe2;
  /* nearly opaque. a translucent plate sits at whatever contrast the
     picture behind it happens to be, which for a control is not a
     decision anyone should be leaving to the artwork. */
  background: rgba(4,9,11,.93);
  border: 1px solid rgba(246,239,226,.5);
  padding: 10px 14px 11px;
  text-shadow: none;
  box-shadow: 0 6px 26px rgba(0,0,0,.55);
}

.p-way .l{ display: block; letter-spacing: .018em; }

.p-way .n{
  display: block;
  font-size: 11px;
  line-height: 1.35;
  letter-spacing: .01em;
  opacity: .72;
  margin-top: .34em;
}

.p-ico{
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  margin-top: 1px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .82;
}

.p-way:hover,
.p-way:focus-visible{
  outline: none;
  color: #0a1214;
  background: #f6efe2;
  border-color: #f6efe2;
  box-shadow: 0 6px 30px rgba(0,0,0,.6), 0 0 2.6em rgba(255,214,142,.22);
}

.p-way:hover .n,
.p-way:focus-visible .n{ opacity: .74; }

.p-way:hover .p-ico,
.p-way:focus-visible .p-ico{ opacity: 1; }

/* a short frame has no room for the second line */
@media (max-height: 760px), (max-width: 1150px){
  .p-way .n{ display: none; }
}

/* ---- the close-up ----
   A plane of dark hung between him and everything behind him. When
   he comes to the glass this comes up, and the room, the words and
   the thing in the corner all go under it, because they are behind
   it and he is not. */
.p-fog{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0;
  background:
    radial-gradient(ellipse 74% 74% at 50% 52%,
      rgba(3,9,11,.42) 0%, rgba(3,9,11,.88) 58%, #03090b 100%);
}

/* the fire in his eye. it rides in his own plane by wearing his
   exact transform, so it stays on the eye however near he comes.
   no blend mode: a blended leaf would flatten the whole box. */
.p-retina{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  will-change: transform;
}

.p-retina i{
  position: absolute;
  display: block;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  opacity: 0;
}

/* ---- what is on the television ----
   Lives in the set's own depth plane by wearing its transform. No
   blend modes: a blended leaf would flatten the whole box. */
.p-tv{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  will-change: transform;
}

.p-tv-box{
  position: absolute;
  overflow: hidden;
}

.p-snow,
.p-ghost{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* whatever is in the snow is mostly not there */
.p-ghost{ opacity: 0; }

/* the vertical hold. a bright band and the dark seam under it,
   walking down the picture and wrapping, forever. */
.p-roll{
  position: absolute;
  left: -2%;
  right: -2%;
  top: 0;
  height: 26%;
  display: block;
  background: linear-gradient(to bottom,
    rgba(255,255,255,0)   0%,
    rgba(255,255,255,.20) 38%,
    rgba(255,255,255,.28) 50%,
    rgba(0,0,0,.42)       62%,
    rgba(0,0,0,0)        100%);
}

/* the tear. brief, warm, and never twice inside a second. */
.p-flash{
  position: absolute;
  inset: 0;
  z-index: 20;
  pointer-events: none;
  opacity: 0;
  background: #fff4e2;
}

/* the single-button fallback, for any embedded frame with no words
   of its own. it belongs on the glass, because it is a control. */
.p-enter{
  pointer-events: auto;
  position: absolute;
  left: 50%;
  bottom: 8vh;
  transform: translateX(-50%);
  font: inherit;
  font-size: 15px;
  color: #fff;
  background: rgba(0,0,0,.45);
  border: 1px solid rgba(255,255,255,.72);
  border-radius: 4px;
  padding: 9px 18px;
  cursor: pointer;
}

.p-enter:hover,
.p-enter:focus-visible{
  background: #fff;
  color: #000;
  outline: none;
}

/* only once the project is live, and deliberately in the garden's
   voice rather than the project's: it belongs to the site */
.p-back{
  position: absolute;
  right: 10px;
  top: calc(var(--bar) + 10px);
  z-index: 6;
  display: none;
  font-family: var(--term);
  font-size: var(--cell);
  letter-spacing: .04em;
  color: var(--ink);
  background: var(--paper);
  border: 2px solid var(--ink);
  padding: 2px 8px;
  cursor: pointer;
}

.project.live .p-back{ display: block; }

.p-back:hover,
.p-back:focus-visible{
  background: var(--ink);
  color: var(--paper);
  outline: none;
}

/* ---- project frames ---- */

/* A project frame is one screen. Content is anchored top left on
   the character grid, the way the rest of the site is, and sized
   so it clears both rails at 1024x768 without scrolling. */

.project{
  display: block;
  padding: calc(var(--bar) + 24px) 10px calc(var(--bar) + 18px);
}

.project h2{
  font-size: 34px;
  font-weight: normal;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: .02em;
  max-width: 34ch;
}

.project .rule{
  color: var(--dim);
  overflow: hidden;
  white-space: nowrap;
  margin: 6px 0 10px;
}

/* the line the project leads with */
.p-line{
  font-size: 22px;
  line-height: 1.1;
  margin-bottom: 10px;
  max-width: 34ch;
}

.p-body{
  max-width: 68ch;
  margin-bottom: 6px;
  color: var(--dim);
  letter-spacing: .02em;
}

/* the project's own structure, drawn in box characters */
.p-plate{
  font: inherit;
  margin: 12px 0 10px;
  line-height: 1.15;
  white-space: pre;
  overflow: hidden;
}

.p-close{
  max-width: 68ch;
  margin-bottom: 12px;
}

.p-meta{
  display: grid;
  grid-template-columns: 13ch auto;
  gap: 2px 12px;
  margin: 0 0 14px;
  color: var(--dim);
  font-size: 15px;
  letter-spacing: .02em;
}

.p-meta dt{ text-transform: uppercase; }
.p-meta dd{ margin: 0; color: var(--ink); }

.p-out{
  display: inline-block;
  color: var(--ink);
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: .06em;
}

.p-out:hover,
.p-out:focus-visible{
  background: var(--ink);
  color: var(--paper);
  outline: none;
}

/* ------------------------------------------------------------
   Menu
   ------------------------------------------------------------ */

#menu{
  position: fixed;
  inset: var(--bar) 0;
  z-index: 30;
  background: var(--paper);
  padding: 18px 10px;
  overflow: auto;
}

#menu[hidden]{ display: none; }

.menu-head,
.menu-foot{
  color: var(--dim);
  text-transform: uppercase;
}

.menu-foot{ margin-top: 20px; }

#menu-list{
  list-style: none;
  margin: 14px 0 0;
  counter-reset: m;
}

#menu-list li{ counter-increment: m; }

#menu-list button{
  font: inherit;
  font-size: 30px;
  line-height: 1.15;
  text-transform: uppercase;
  letter-spacing: .02em;
  color: var(--ink);
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: left;
  display: block;
}

#menu-list button::before{
  content: counter(m, decimal-leading-zero) "  ";
  color: var(--dim);
}

#menu-list button:hover,
#menu-list button:focus-visible,
#menu-list li[data-current] button{
  background: var(--ink);
  color: var(--paper);
  outline: none;
}

#menu-list li[data-current] button::before{ color: var(--paper); }

/* The front page used to hide the top rail, because the top rail
   was words about whichever frame you were on. It carries the only
   two controls now, so it stays on every frame.

   The bottom rail does not. Nothing is down on the front page, and
   the montage runs the full height of the frame behind both rails,
   so hiding it uncovers the picture rather than leaving a gap. */
body[data-frame="0"] #chrome{ display: none; }

/* ------------------------------------------------------------
   Phosphor lines. Faint.
   ------------------------------------------------------------ */

#scan{
  position: fixed;
  inset: 0;
  z-index: 50;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0,0,0,.045) 0px,
    rgba(0,0,0,.045) 1px,
    transparent 1px,
    transparent 3px
  );
}

/* ------------------------------------------------------------
   MOBILE: the archaic version
   ------------------------------------------------------------ */

#archaic{
  display: block;
  padding: 16px 14px 60px;
  font-family: "Times New Roman", Times, serif;
  font-size: 17px;
  line-height: 1.45;
  background: #fff;
  color: #000;
  height: 100%;
  overflow-y: auto;
}

#archaic h1{
  font-family: var(--term);
  font-size: 34px;
  font-weight: normal;
  line-height: 1;
  letter-spacing: .02em;
}

#archaic hr{
  border: 0;
  border-top: 1px solid #000;
  margin: 12px 0;
}

#archaic p{ margin: 10px 0; }

#archaic ul{
  list-style: square;
  padding-left: 26px;
  margin: 10px 0;
}

#archaic li{ margin: 10px 0; }

#archaic a{
  color: #0000ee;
  text-decoration: underline;
  font-size: 19px;
}

#archaic a:visited{ color: #551a8b; }

/* ------------------------------------------------------------
   Switch
   ------------------------------------------------------------ */

@media (min-width: 900px) and (pointer: fine){
  #archaic{ display: none; }
  #site{ display: block; }
}

@media (prefers-reduced-motion: reduce){
  #rail{ transition-duration: 1ms; }
  #chrome{ animation: none; }
}
