/* The envelope (roadmap 29) in the one-bit art bible (studio/ART-BIBLE.md): ink and paper only, Bayer dither, stepped motion
   at 15 fps, classic window chrome. Sentences in the sentence font at 16 px or more, numbers in Jersey 10, both thresholded to
   one bit by the page's #onebit filter (index.html), so there are no grey fringes. Markup: client/envelope.js; the words are COPY
   in game/envelope.js; the envelope drawing is client/envelope-closed.svg and -open.svg (studio/tools/envelope-art.js).
   #envelope data-state: dim (the room darkens) -> slide (the envelope comes under the door) -> open (the letter zooms out of it,
   ranks 10 to 1 appear) -> done. data-motion: full | none (reduced motion: the last frame at once) | still (a demo frame). */
@font-face{font-family:"Atkinson Hyperlegible";src:url(fonts/AtkinsonHyperlegible-Regular.woff2) format("woff2");font-weight:400;font-style:normal;font-display:block}
:root{
  /* Bayer 4x4 at 2 px a cell (the stage's 2x pixels): ink at 25, 50, 75 and 87.5%, transparent between */
  --env-d25:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' shape-rendering='crispEdges'%3E%3Cpath d='M0 0h2v2h-2zM4 0h2v2h-2zM0 4h2v2h-2zM4 4h2v2h-2z'/%3E%3C/svg%3E");
  --env-d50:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' shape-rendering='crispEdges'%3E%3Cpath d='M0 0h2v2h-2zM4 0h2v2h-2zM2 2h2v2h-2zM6 2h2v2h-2zM0 4h2v2h-2zM4 4h2v2h-2zM2 6h2v2h-2zM6 6h2v2h-2z'/%3E%3C/svg%3E");
  --env-d75:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' shape-rendering='crispEdges'%3E%3Cpath d='M0 0h2v2h-2zM2 0h2v2h-2zM4 0h2v2h-2zM6 0h2v2h-2zM2 2h2v2h-2zM6 2h2v2h-2zM0 4h2v2h-2zM2 4h2v2h-2zM4 4h2v2h-2zM6 4h2v2h-2zM2 6h2v2h-2zM6 6h2v2h-2z'/%3E%3C/svg%3E");
  --env-d87:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' shape-rendering='crispEdges'%3E%3Cpath d='M0 0h2v2h-2zM2 0h2v2h-2zM4 0h2v2h-2zM6 0h2v2h-2zM0 2h2v2h-2zM2 2h2v2h-2zM6 2h2v2h-2zM0 4h2v2h-2zM2 4h2v2h-2zM4 4h2v2h-2zM6 4h2v2h-2zM2 6h2v2h-2zM4 6h2v2h-2zM6 6h2v2h-2z'/%3E%3C/svg%3E");
  /* a title bar's stripes: 2 px ink, 2 px paper */
  --env-stripes:repeating-linear-gradient(#000 0 2px,#fff 2px 4px);
}

/* ---------- the live line during a night shift (client/ui.js fills #race from the snapshot's race) ---------- */
/* colour look: a plain bar in the flow under the stage */
#race{margin:6px auto 0;max-width:640px;padding:6px 10px;color:#fff;background:#000;border:2px solid #fff;font:18px/24px "Atkinson Hyperlegible",Verdana,sans-serif}
/* one-bit desktop: a paper plate lying on the floor under the door (ui.js placeRace puts its bottom edge on the layout's),
   a title-bar stripe cap on the left; the plate grows upwards when the line wraps */
html[data-look="one-bit"] #race{position:absolute;z-index:4;max-width:none;margin:0;box-sizing:border-box;transform:translateY(-100%);
  padding:4px 10px 4px 32px;color:#000;background:#fff var(--env-stripes) 8px 6px/14px calc(100% - 12px) no-repeat;
  border:2px solid #000;box-shadow:0 0 0 2px #fff;font:16px/20px "Atkinson Hyperlegible",Verdana,sans-serif;filter:url(#onebit)}
/* sprint 33 item 3, a level 2 night door: the same one-bit plate, drawn in the night ink and its cream */
html[data-look="one-bit"][data-door="night"] #race{filter:url(#onebitnight)}
/* one-bit phone: a band fixed just above the disclaimer strip (ui.js fitPhone sets its bottom and shrinks the play area) */
html.portrait[data-look="one-bit"] #race{position:fixed;left:0!important;right:0;top:auto!important;width:auto!important;transform:none;
  z-index:5;border-width:2px 0 0;box-shadow:none;padding:6px 10px 6px 32px;background-position:8px 8px;background-size:14px calc(100% - 16px)}

/* ---------- the dim: a Bayer veil steps down over the room, the scene still faintly there ---------- */
#envelope{position:fixed;inset:0;z-index:20;overflow:auto;box-sizing:border-box;padding:max(16px,4vh) 12px 132px;color:#000;
  background:var(--env-d87) 0 0/8px 8px;font:18px/24px "Atkinson Hyperlegible",Verdana,sans-serif}
#envelope[data-motion="full"][data-state="dim"]{animation:env-dim 600ms linear both}
@keyframes env-dim{0%{background-image:none}12%{background-image:var(--env-d25)}37%{background-image:var(--env-d50)}62%{background-image:var(--env-d75)}87%,100%{background-image:var(--env-d87)}}
/* the disclaimer stays in view over the dim (its strip is fixed to the bottom, onebit.css) */
html:has(#envelope:not([hidden])) #strip{display:block!important;z-index:21}

/* ---------- the envelope: slides up from under the door in 9 stepped frames, then lies open below the letter ---------- */
#envelope .env-mail{position:fixed;left:50%;bottom:48px;width:192px;height:192px;margin-left:-96px;z-index:0;
  background:url(envelope-closed.svg) center/192px 192px no-repeat;image-rendering:pixelated}
#envelope[data-state="dim"] .env-mail{visibility:hidden}
#envelope[data-motion="full"][data-state="slide"] .env-mail{animation:env-slide 600ms steps(9,end) both}
@keyframes env-slide{from{transform:translateY(calc(100% + 64px))}to{transform:none}}
#envelope[data-state="open"] .env-mail,#envelope[data-state="done"] .env-mail{background-image:url(envelope-open.svg)}
/* one-bit desktop (ui.js placeMail, mailSpot in envelope.js): the envelope lies under the door's centre at the stage's own pixel
   size (--env-px), its body on the floor just out from under the threshold. data-at="door": it slides out from under the door
   in 10 stepped frames of 4 art rows (whole pixels, no grey), clipped at the threshold so it is never seen above it while it moves. data-at="foot" (a window too short
   for the floor under the door): it lies on the window's bottom edge below the door and slides up into view. */
#envelope[data-at] .env-mail{left:var(--env-x);top:var(--env-top);bottom:auto;width:calc(64 * var(--env-px));height:calc(64 * var(--env-px));
  margin-left:calc(-32 * var(--env-px));background-size:100% 100%}
/* a still demo frame mid-slide: --env-under (envelope.js slideUnder) is the part still under the door, 0 once it is out */
#envelope[data-at="door"][data-state="slide"] .env-mail{transform:translateY(calc(-40 * var(--env-px) * var(--env-under,0)));
  clip-path:inset(calc((24 + 40 * var(--env-under,0)) * var(--env-px)) 0 0 0)}
#envelope[data-at="door"][data-motion="full"][data-state="slide"] .env-mail{animation:env-under 600ms steps(10,end) both}
@keyframes env-under{from{transform:translateY(calc(-40 * var(--env-px)));clip-path:inset(calc(64 * var(--env-px)) 0 0 0)}
  to{transform:none;clip-path:inset(calc(24 * var(--env-px)) 0 0 0)}}
/* the letter beside the door, clear of the envelope (data-paper), zooming out from its lower left, towards the envelope;
   with no room beside the door it stays centred and the envelope hides once it is open, as on a phone */
#envelope[data-at][data-paper] .env-paper{width:540px;margin:0 0 0 calc(var(--env-paper-left) - 12px)}
#envelope[data-at][data-paper][data-motion="full"][data-state="open"] .env-paper{animation:env-zoom-side 270ms steps(4,end) both}
@keyframes env-zoom-side{from{clip-path:inset(42% 76% 0 0)}to{clip-path:inset(0)}}
/* wherever the letter is not beside the door (phone, colour look, a narrow desktop) it would half cover the envelope: hide it */
#envelope:not([data-paper])[data-state="open"] .env-mail,#envelope:not([data-paper])[data-state="done"] .env-mail{visibility:hidden}

/* ---------- the letter: a classic one-bit window, zooming out of the envelope in four steps ---------- */
#envelope .env-paper{position:relative;z-index:1;box-sizing:border-box;width:100%;max-width:540px;margin:0 auto;padding:0 18px 16px;
  background:#fff;color:#000;border:2px solid #000;box-shadow:0 0 0 2px #fff,0 0 0 4px #000;filter:url(#onebit)}
#envelope[data-state="dim"] .env-paper,#envelope[data-state="slide"] .env-paper{visibility:hidden}
#envelope[data-motion="full"][data-state="open"] .env-paper{animation:env-zoom 270ms steps(4,end) both}
@keyframes env-zoom{from{clip-path:inset(42% 38% 0 38%)}to{clip-path:inset(0)}}

/* the title bar: stripes either side of the title, as on every window in the game */
.env-title{display:flex;align-items:center;gap:12px;margin:0 -18px;padding:7px 10px;border-bottom:2px solid #000;
  font:700 20px/24px "Atkinson Hyperlegible",Verdana,sans-serif;white-space:nowrap}
.env-title::before,.env-title::after{content:"";flex:1;height:14px;background:var(--env-stripes)}
.env-line{margin:12px 0 0}

/* ranks 10 to 1: each row prints in from the left in four steps; a row not yet shown keeps its place so nothing jumps */
.env-ranks{list-style:none;margin:10px 0 0;padding:6px 0;background:
  repeating-linear-gradient(90deg,#000 0 2px,transparent 2px 4px) 0 0/100% 2px no-repeat,
  repeating-linear-gradient(90deg,#000 0 2px,transparent 2px 4px) 0 100%/100% 2px no-repeat}
#envelope .env-row[hidden]{display:grid!important;visibility:hidden}
/* fixed number columns so the rows line up; the rows' SOL is rounded to 4 places (rowSol), the exact share is on the slab.
   The heads sit over the two number columns, in the sentence font, right-aligned like the numbers. */
.env-row,.env-head{display:grid;grid-template-columns:32px minmax(0,1fr) 64px 120px;gap:16px;align-items:center;min-height:32px;padding:0 8px}
.env-head{align-items:end;min-height:0;margin:10px 0 0;font:16px/20px "Atkinson Hyperlegible",Verdana,sans-serif;text-align:right}
.env-head-pts{grid-column:3}
.env-head-sol{grid-column:4}
.env-head + .env-ranks{margin-top:4px}
/* the player's own share before the slab has counted up to it: a dotted gap, never the number */
.env-row-sol[data-wait="true"]::before{content:"";display:inline-block;width:48px;height:4px;vertical-align:middle;
  background:repeating-linear-gradient(90deg,currentColor 0 4px,transparent 4px 8px)}
#envelope[data-motion="full"] .env-row:not([hidden]){animation:env-print 270ms steps(4,end) both}
@keyframes env-print{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0)}}
/* the player's own row: inverted, ink bar with paper words, like the board's own row */
.env-row[data-lit="true"]{background:#000;color:#fff}
.env-name{font:18px/24px "Atkinson Hyperlegible",Verdana,sans-serif;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.env-row[data-lit="true"] .env-name{font:700 18px/24px "Atkinson Hyperlegible",Verdana,sans-serif}
.env-rank,.env-pts,.env-row-sol,.env-sol{font:28px/30px "Jersey 10",monospace}
.env-rank{text-align:right}
.env-pts,.env-row-sol{text-align:right}

/* a neighbour who knocked in its own light this shift (sprint 21; client/envelope.js): a small pane of glass with its head and
   shoulders in the beam (client/lit-icon.js, ink and paper, 40x40 art pixels at 2x) in an ink frame, then the line in the
   sentence font. Below the ranks, one row per neighbour, none when none came. */
.env-looks{display:flex;align-items:center;gap:14px;margin:12px 0 0;font:18px/24px "Atkinson Hyperlegible",Verdana,sans-serif}
.env-looks + .env-looks{margin-top:8px}
.env-looks canvas.lit-icon{position:static;inset:auto;flex:none;display:block;width:80px;height:80px;image-rendering:pixelated;border:2px solid #000;box-shadow:0 0 0 2px #fff,0 0 0 4px #000;margin:4px}
.env-looks-line{min-width:0}

/* the finish, then the share counted up on an ink slab, the way the sum is chalked on the door */
.env-finish{margin:14px 0 0;font:700 20px/26px "Atkinson Hyperlegible",Verdana,sans-serif}
.env-share{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 10px;margin:10px 0 0;padding:6px 14px 4px;background:#000;color:#fff}
.env-label{flex:1 1 auto;font:18px/24px "Atkinson Hyperlegible",Verdana,sans-serif}
.env-sol{font:56px/56px "Jersey 10",monospace;font-variant-numeric:tabular-nums}
.env-unit{font:18px/24px "Atkinson Hyperlegible",Verdana,sans-serif}
.env-status,.env-devnet{margin:8px 0 0;font:16px/22px "Atkinson Hyperlegible",Verdana,sans-serif}

/* a square button with the default ring */
.env-close{display:block;margin:16px 4px 4px auto;min-height:44px;min-width:120px;padding:0 24px;background:transparent;color:#000;border:2px solid #000;
  box-shadow:0 0 0 2px #fff,0 0 0 4px #000;font:700 18px/24px "Atkinson Hyperlegible",Verdana,sans-serif;cursor:pointer}
.env-close:hover,.env-close:focus-visible{background:#000;color:#fff;outline:none}
/* Sprint 22 (readable text at fractional scaling and zoom): the letter's #onebit filter makes ink from 25% coverage so thin
   strokes survive 125% scaling and 90% zoom; bold words are thresholded first on their own clear layer at 50% (#bitb in
   index.html), so their small counters stay open. The button is clear over the paper (it looks the same) so its words can be. */
.env-title,.env-row[data-lit="true"] .env-name,.env-finish,.env-close{filter:url(#bitb)}
[hidden]{display:none!important}

/* a phone: the envelope at 2x, the letter edge to edge */
@media (max-width:640px){
  #envelope{padding:12px 6px 96px}
  #envelope .env-mail{width:128px;height:128px;margin-left:-64px;bottom:56px;background-size:128px 128px}
  #envelope[data-state="open"] .env-mail,#envelope[data-state="done"] .env-mail{visibility:hidden} /* the letter fills the screen */
  #envelope .env-paper{padding:0 12px 14px}
  .env-title{margin:0 -12px}
  .env-row,.env-head{grid-template-columns:26px minmax(0,1fr) 52px 84px;gap:12px;padding:0 6px}
  .env-head-sol{overflow-wrap:break-word}
  .env-rank,.env-pts,.env-row-sol{font:26px/30px "Jersey 10",monospace}
  .env-sol{font:48px/50px "Jersey 10",monospace}
}

/* no animation at all when there should be none: the viewer asks for less motion (client/envelope.js also skips straight to
   the last frame), or a demo holds a still frame */
#envelope[data-motion="none"],#envelope[data-motion="none"] *,#envelope[data-motion="still"],#envelope[data-motion="still"] *{animation:none!important}
@media (prefers-reduced-motion: reduce){#envelope,#envelope *{animation:none!important;transition:none!important}}
