/* ===========================================================================
   Enclave Press
   ---------------------------------------------------------------------------
   The rules the plates are cut under, applied to a shop:

     * two inks. Every tone is an ordered dither at fat-pixel scale, never a
       flat grey and never a gradient.
     * the fat pixel is 2 CSS px, because the plates compose at 240x300 and
       double. Rules are 2 px. Dither cells are 2 px.
     * the copy number is set in the house grid alphabet; everything read as
       language is set in type. That split is the identity.
     * plates are shown at 1x or 0.5x and nothing between, because 0.5x is
       exactly the composition resolution and every other scale smears the
       lattice.
   ========================================================================= */

:root{
  --ink:#000;
  --paper:#fff;
  --fat:2px;

  --d12:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" shape-rendering="crispEdges"><rect width="8" height="8" fill="%23ffffff"/><rect x="0" y="0" width="2" height="2" fill="%23000000"/><rect x="4" y="4" width="2" height="2" fill="%23000000"/></svg>');
  --d25:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" shape-rendering="crispEdges"><rect width="8" height="8" fill="%23ffffff"/><rect x="0" y="0" width="2" height="2" fill="%23000000"/><rect x="4" y="4" width="2" height="2" fill="%23000000"/><rect x="4" y="0" width="2" height="2" fill="%23000000"/><rect x="0" y="4" width="2" height="2" fill="%23000000"/></svg>');

  --chrome:Inter,"Inter var",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --book:Literata,"Iowan Old Style","Palatino Linotype",Palatino,"Book Antiqua",Georgia,serif;
}

*{box-sizing:border-box}
/* The masthead, the nav and the footer must land on the same pixel on every
   page: a shop whose furniture moves as you walk through it is a shop that
   looks unbuilt. Only the content between them may change.
   The one thing that moved was the scrollbar — a short page had none and a
   long one did, so every page without a scrollbar sat 15 px wider and the
   whole site breathed at each click. The track is therefore always reserved,
   never hidden: `overflow-y:scroll` for engines that have no gutter, and the
   gutter itself where it exists, so the bar still appears only when it has
   something to scroll. */
html{-webkit-text-size-adjust:100%;overflow-y:scroll}
@supports (scrollbar-gutter:stable){
  html{overflow-y:auto;scrollbar-gutter:stable}
}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font-family:var(--chrome);font-size:16px;line-height:1.55;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;display:block}
a{color:inherit}
/* Centred, and centred on a WHOLE pixel. Half of an odd number is a half, so
   an auto margin puts the sheet at x.5 on any viewport of odd width — and a
   1bpp plate painted on a half pixel has its edge column rounded away by the
   compositor, differently in different boxes. That is why the same plate on
   two pages was not the same picture. The offset is floored instead. */
.sheet{max-width:1160px;margin:0 auto;padding:0 28px;width:100%}
@supports (margin-left: round(down, 50%, 1px)){
  .sheet{margin-left:round(down, max(0px, (100% - 1160px) / 2), 1px);
         margin-right:auto}
}
.skip,.off-screen{position:absolute;left:-9999px}
.skip:focus{left:8px;top:8px;background:#000;color:#fff;padding:8px 12px;z-index:99}

/* ── masthead ───────────────────────────────────────────────────────────── */
.bar{border-bottom:var(--fat) solid var(--ink)}
.bar-foot{border-bottom:0;border-top:var(--fat) solid var(--ink);margin-top:72px}
.bar-in{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px 24px;
        min-height:64px;padding-top:12px;padding-bottom:12px}
.house{display:flex;align-items:center;gap:12px;text-decoration:none}
.mark{display:block;width:45px;height:42px}
.mark svg{display:block;width:100%;height:auto}
.house-name{display:flex;flex-direction:column;line-height:1.05}
.house-name b{font-size:10px;font-weight:600;letter-spacing:.25em}
.bar-nav{display:flex;gap:26px;font-size:11px;letter-spacing:.2em;text-transform:uppercase;font-weight:600}
.bar-nav a{text-decoration:none;padding-bottom:2px;border-bottom:var(--fat) solid transparent}
.bar-nav a:hover,.bar-nav a[aria-current]{border-bottom-color:var(--ink)}
.bar-foot .bar-in{font-size:11px;letter-spacing:.06em}
.bar-foot a{text-decoration:none;border-bottom:1px solid var(--ink)}

/* ── the front: one sentence, one object ────────────────────────────────── */
.hero{display:grid;grid-template-columns:minmax(0,1fr) 584px;gap:40px;
      align-items:center;padding:64px 0 78px}
.hero-txt h1{margin:0 0 20px;font-size:42px;line-height:1.06;letter-spacing:-.018em;font-weight:600}
.hero-lede{margin:0;font-size:19px;line-height:1.5;max-width:27em}
.hero-lede+.hero-lede{margin-top:14px}
.hero .acts{margin-top:30px}

/* ── the device, drawn rather than photographed ─────────────────────────── */
/* It was an elevation: a front-on slab, correct and flat. It is now an object.
   `assets/flex-shell.png` is an oblique extrusion — the body pushed back, up
   and to the right, so the top face and the right face come into view — shaded
   per pixel and quantised by the plates' own Bayer matrix. It is made of the
   same material as the covers and contains no grey, no gradient and no blur.
   `make-device.py` draws it; the reasoning is in its docstring.

   The panel stays frontal, which is the whole point of choosing an oblique
   projection over a rotation: the plate is never turned, never squashed and
   never resampled. The shell is laid under it and the plate sits in the recess
   at 1x, or at exactly 0.5x when the page narrows, like every other plate in
   the shop. */
.hero-obj{justify-self:end}
.flex{position:relative;width:584px;height:704px}
.flex-shell{position:absolute;left:0;top:0;width:584px;height:704px;max-width:none;
            image-rendering:pixelated;image-rendering:crisp-edges}
.flex-plate{position:absolute;left:28px;top:52px}

.shelf-head{display:flex;align-items:baseline;gap:16px;margin:52px 0 26px;
            border-bottom:var(--fat) solid var(--ink);padding-bottom:12px}
.shelf-head h2{margin:0;font-size:11px;letter-spacing:.26em;text-transform:uppercase;font-weight:600}

/* ── the questions ──────────────────────────────────────────────────────── */
/* They collapse, and they start closed. A wall of questions is a shop stating
   what it is prepared to be asked; a wall of answers is a manual. Nothing is
   hidden — every answer is one click and no scroll away, and the awkward ones
   are worded so the question itself gives the answer's direction.

   <details>, so it needs no script and keeps its keyboard behaviour. The row
   is the grid: the question holds the left column and the answer opens into
   the right one, which is exactly where it sat when it was always open. */
.head-flush{margin-bottom:0}
.faq{border-top:0}
.faq-item{padding:22px 0 24px;border-bottom:var(--fat) solid var(--ink)}
/* The question keeps the whole measure whether it is open or shut, and its
   mark is ranged hard right against that measure — so the mark the eye is
   fixed on at the moment of the click does not move by one pixel when the
   answer arrives. The answer opens BELOW the question, indented to the column
   where it used to sit beside it. That is the price of stillness, and it is
   worth it. */
.faq-item>summary{position:relative;padding-right:34px;cursor:pointer;list-style:none}
.faq-item>summary::-webkit-details-marker{display:none}
.faq-item>summary::marker{content:""}
/* the marker is drawn, not borrowed: two fat-pixel bars, and the upright one
   goes away when the answer is out */
.faq-item>summary::before,.faq-item>summary::after{content:"";position:absolute;
  background:var(--ink);right:0}
.faq-item>summary::before{top:10px;width:14px;height:var(--fat)}
.faq-item>summary::after{top:4px;right:6px;width:var(--fat);height:14px}
.faq-item[open]>summary::after{display:none}
.faq-item>summary:hover h3{text-decoration:underline;text-decoration-thickness:var(--fat);
  text-underline-offset:5px}
.faq-item>summary:focus-visible{outline:var(--fat) solid var(--ink);outline-offset:6px}
.faq-item h3{margin:0;font-size:17px;line-height:1.28;font-weight:600;letter-spacing:-.005em}
/* the answer takes the whole of the column it opens into: a measure inside a
   measure reads as a paragraph pinned to the left of an empty panel */
.faq-a{margin:16px 0 0 356px;max-width:none}
.faq-a p{margin:0;font-size:16px;line-height:1.6}
.faq-a p+p{margin-top:12px}
.faq-a a{text-decoration:none;border-bottom:var(--fat) solid var(--ink)}
.faq-a a:hover{background:var(--ink);color:var(--paper)}
.acts-end{margin-top:46px}

/* ── the collection ─────────────────────────────────────────────────────── */
/* The plates and nothing else: no heading, no standfirst, no rule. What a
   release has to say that a plate cannot is four short facts, and they sit
   beside the title rather than under it. */
.shelf{display:grid;grid-template-columns:repeat(auto-fill,480px);
       column-gap:96px;row-gap:104px;justify-content:space-between;
       margin:52px 0 0;padding-bottom:16px}
/* A plate gets an edge, because a page has to make two very different plates
   read as the same kind of object, and because a plate has one when it is cut.
   On a book's own page it goes back to full bleed. */
.rel{text-decoration:none;display:block;width:480px}
.rel .plate-box{box-shadow:0 0 0 var(--fat) var(--ink)}
.rel:hover .plate-box{box-shadow:0 0 0 var(--fat) var(--ink),0 0 0 8px var(--paper),0 0 0 10px var(--ink)}
.rel-line{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:2px 24px;
          align-items:baseline;margin-top:24px}
.rel-title{font-size:15px;line-height:1.3;font-weight:600}
.rel-by{font-size:15px;line-height:1.3;font-weight:400}
.rel-run,.rel-date{font-size:10px;letter-spacing:.2em;text-transform:uppercase;
                   line-height:1.3;text-align:right}
.rel-run{font-weight:600}

/* ── the spread: a book's own page ──────────────────────────────────────── */
.spread{display:grid;grid-template-columns:520px minmax(0,1fr);gap:56px;padding:52px 0 24px}
.rail-stick{position:sticky;top:32px}
.rail-cap{margin:14px 0 0;font-size:10px;letter-spacing:.22em;text-transform:uppercase;font-weight:600}

/* ── the device, which is also the plate ────────────────────────────────── */
/* The bezel is added OUTSIDE the screen, never inside it, so a plate is
   always drawn at exactly 1x or 0.5x and the lattice never smears. */
.device{
  width:-moz-fit-content;width:fit-content;background:var(--paper);padding:0;
  transition:padding .32s steps(8,end),margin .32s steps(8,end),
             background-color .32s steps(2,end);
}
/* The bezel grows OUTWARD from the screen: the padding that draws it is
   cancelled by an equal negative margin above and to the left, so the plate
   keeps its exact position and size when the device switches on. The plate is
   the fixed point of this site; the chrome is what may move around it. */
.device.is-on{padding:20px 20px 40px;margin:-20px 0 0 -20px;background:var(--ink)}
.device .screen{width:480px;height:600px;position:relative;overflow:hidden;
                background:var(--paper);box-shadow:0 0 0 var(--fat) var(--ink)}
/* the bezel is an edge, so it replaces the plate's own rather than doubling it */
.device.is-on .screen{box-shadow:none}
.device.is-on::after{content:"";display:block;width:96px;height:6px;background:#fff;margin:17px auto 0;opacity:.5}
.board{width:480px;height:600px;transform-origin:0 0;position:absolute;top:0;left:0}
/* max-width:none matters: a plate is scaled by transform, never by layout, so
   the reset's max-width:100% must not clamp it inside a half-size box. */
.plate{width:480px;height:600px;max-width:none;image-rendering:pixelated;image-rendering:crisp-edges}

.plate-box{display:block;width:480px;height:600px;position:relative;overflow:hidden}

/* the copy number, where the generator puts it: x 380..455, y 532..555,
   cell 4 px, ranged hard right against the 432 px measure */


/* ── the device's own screens ───────────────────────────────────────────── */
.os{position:absolute;inset:0;background:#fff;font-family:var(--chrome);
    display:flex;flex-direction:column;padding:26px 24px;text-align:center}
.os h4{margin:0;font-size:23px;font-weight:600;line-height:1.25}
.os p{margin:6px 0 0;font-size:19px;line-height:1.35}
.os .os-rule{height:1px;background:#000;margin:18px 0}
.os .os-rows{margin-top:8px;text-align:left;flex:1}
.os .os-row{padding:13px 0;border-bottom:1px solid #000}
.os .os-row span{display:block;font-size:15px;letter-spacing:.06em;text-transform:uppercase}
.os .os-row b{display:block;font-size:21px;font-weight:600;word-break:break-all}
.os .os-btns{margin-top:auto;display:flex;flex-direction:column;gap:12px}
.os .os-hint{font-size:14px;letter-spacing:.12em;text-transform:uppercase;margin-top:14px;opacity:.7}


.os-prog{width:300px;height:16px;margin:0 auto;box-shadow:inset 0 0 0 2px #000}
.os-prog i{display:block;height:100%;width:0;background:#000}

/* the count on the device rather than beside it: the number belongs to the
   thing that is filling up */
.os-bignum{display:flex;align-items:flex-end;justify-content:center;gap:12px}
.os-bignum .glyphs svg{height:84px;width:auto}
.os-bignum small{font-size:34px;font-weight:600;line-height:1;padding-bottom:6px}


.os-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:22px;padding:34px 30px;align-content:start}
.os-app{display:flex;flex-direction:column;align-items:center;gap:10px;cursor:pointer;background:none;border:0;font:inherit}
.os-app i{width:96px;height:96px;background:#000;display:grid;place-items:center;border-radius:20px;overflow:hidden}
.os-app i img{width:76px;height:76px;image-rendering:pixelated}
.os-app i em{color:#fff;font:600 30px/1 var(--chrome);font-style:normal}
.os-app span{font-size:17px;line-height:1.2}
.os-app:hover i{outline:3px solid #000;outline-offset:3px}

/* the colophon is a reading surface, so it is set in the book's face */

/* ── the step column ────────────────────────────────────────────────────── */
.eyebrow{margin:0 0 18px;font-size:10px;letter-spacing:.26em;text-transform:uppercase;font-weight:600;
         display:flex;align-items:center;gap:12px}
.eyebrow::after{content:"";flex:1;height:var(--fat);background:var(--ink)}
h1{margin:0 0 18px;font-size:44px;line-height:1.05;letter-spacing:-.015em;font-weight:600}
h1.tall{font-size:54px}
.byline{margin:-10px 0 22px;font-size:19px}
.lede{font-size:19px;line-height:1.5;margin:0 0 18px;max-width:34em}
.step p,.step ul{max-width:34em}
.step p+p{margin-top:14px}
.fine{font-size:12px;line-height:1.5}
.blurb{font-family:var(--book);font-size:18px;line-height:1.6;max-width:32em;margin:0 0 22px}
.blurb p{margin:0}
.blurb p+p{margin-top:12px}

.tick{border-top:var(--fat) solid var(--ink);border-bottom:var(--fat) solid var(--ink);
      display:flex;margin:26px 0;flex-wrap:wrap}
.tick div{padding:16px 22px 15px;flex:1;min-width:150px}
.tick div+div{border-left:var(--fat) solid var(--ink)}
.tick span{display:block;font-size:10px;letter-spacing:.22em;text-transform:uppercase;font-weight:600;margin-bottom:7px}
.tick b{display:block;font-size:26px;font-weight:600;line-height:1.05;letter-spacing:-.01em}

.acts{display:flex;gap:14px;flex-wrap:wrap;margin:26px 0 0;align-items:center}
.btn{display:inline-block;background:var(--ink);color:var(--paper);text-decoration:none;border:0;
     padding:16px 26px;font:600 12px/1 var(--chrome);letter-spacing:.22em;text-transform:uppercase;cursor:pointer}
.btn:hover{background:var(--paper);color:var(--ink);box-shadow:inset 0 0 0 var(--fat) var(--ink)}
.btn-ghost{background:var(--paper);color:var(--ink);box-shadow:inset 0 0 0 var(--fat) var(--ink)}
.btn-ghost:hover{background:var(--ink);color:var(--paper);box-shadow:none}
.btn[disabled],.btn.off{background:var(--paper);color:var(--ink);
  box-shadow:inset 0 0 0 var(--fat) var(--ink);cursor:default;pointer-events:none}
.btn.off::before{content:"";display:inline-block;width:8px;height:8px;background:var(--ink);
  margin-right:11px;animation:blink 1.1s steps(1,end) infinite}
@keyframes blink{0%,50%{opacity:1}50.01%,100%{opacity:0}}
.tlink{font:600 12px/1 var(--chrome);letter-spacing:.18em;text-transform:uppercase;text-decoration:none;
       border:0;border-bottom:var(--fat) solid var(--ink);padding-bottom:3px;cursor:pointer;
       background:none;color:inherit}
.tlink:hover{background:var(--ink);color:var(--paper)}

.note{margin-top:26px;padding:20px 22px;background-image:var(--d12);background-color:var(--paper);
      box-shadow:inset 0 0 0 var(--fat) var(--ink)}
.note>*{background:var(--paper);display:block}
.note p{margin:0;padding:2px 6px;max-width:none}
.note p+p{margin-top:10px}


.cells{display:flex;gap:4px;margin:24px 0 0}
.cells i{width:16px;height:16px;background-image:var(--d25);background-color:var(--paper);
         box-shadow:inset 0 0 0 var(--fat) var(--ink)}
.cells i.on{background:var(--ink);background-image:none}
.wait{font-size:11px;letter-spacing:.22em;text-transform:uppercase;font-weight:600;margin-top:12px}

.glyphs,.glyphs svg{display:block}



.sentence{font-family:var(--book);font-size:23px;line-height:1.45;margin:26px 0 0;max-width:26em;
          border-left:var(--fat) solid var(--ink);padding-left:22px}


/* ── the explainer, in two columns ──────────────────────────────────────── */
/* Line heights here are whole pixels, not ratios: a ratio on an 18 px body
   gives 28.8, the figures below it inherit the fraction, and a plate painted
   on a fractional row loses an edge row of its lattice to rounding. Type this
   size does not care about the tenth of a pixel; the lattice does.
   The text is the page and the figures are its margin. Each section is one
   row: heading and prose on the left at a measure of about 72 characters,
   whatever the section has to show on the right, both ranged to the top of the
   row so the eye can cross. A section with nothing worth drawing keeps an
   empty margin — that is honest, and a page of invented diagrams is not.
   The rule across the top of each row is what makes the two columns read as
   one thing rather than as a column of text beside a column of pictures. */
.doc{padding:44px 0 0}
.doc-row{display:grid;grid-template-columns:minmax(0,560px) minmax(0,488px);gap:0 56px;
         align-items:start;border-top:var(--fat) solid var(--ink);
         padding:34px 0 44px}
.doc-open{border-top:0;padding-top:12px}
.doc-txt{max-width:560px}
.doc-txt h1{font-size:44px;line-height:46px;margin-bottom:20px}
.doc-txt h2{margin:0 0 14px;font-size:26px;line-height:30px;font-weight:600;letter-spacing:-.01em}
.doc-txt p{margin:0 0 16px;font-size:18px;line-height:29px}
.doc-txt p:last-child{margin-bottom:0}
.doc-txt .lede{font-size:21px;line-height:30px;margin:0}
.doc-txt ul{margin:0;padding-left:20px;font-size:18px;line-height:29px}
.doc-txt li{margin-bottom:8px}
.doc-txt li:last-child{margin-bottom:0}
.doc-txt blockquote{margin:22px 0;padding-left:22px;border-left:var(--fat) solid var(--ink);
                    font-family:var(--book);font-size:21px;line-height:30px}
.doc-txt a{text-decoration:none;border-bottom:var(--fat) solid var(--ink)}
.doc-txt a:hover{background:var(--ink);color:var(--paper)}
.doc-fig{margin:0}
.doc-fig figcaption{margin-top:14px;font-size:12px;line-height:1.5;max-width:32em}

/* A window onto a plate, at 1x. A plate shown at some fraction of its size is
   a smeared lattice; a plate cropped is still the artefact, pixel for pixel.
   So the figures crop rather than scale. */
.win{display:block;position:relative;overflow:hidden;width:var(--ww);height:var(--wh);
     box-shadow:0 0 0 var(--fat) var(--ink)}
.win .plate{position:absolute;left:0;top:var(--wy)}
/* the number sits where the generator puts it: y 532 on the plate, and the
   window opens at 504, so 28 into it. Diffed against the numbered plate. */
.slot-win{top:28px}

/* The two ceremonies get a picture rather than a table, and it is drawn by
   the same script as the hero's device: real objects, in the plates' own
   material, several to a scene and quantised together so one lattice runs
   across the whole image. They are shown at half their raster, which is the
   composition resolution, so the plate inside each device is at exactly 0.5x.
   Below about 700 px the figure scrolls sideways rather than being resampled:
   a smeared lattice is worse than a scrollbar. */

/* ── narrow ─────────────────────────────────────────────────────────────── */
@media (max-width:1080px){
  .spread{grid-template-columns:1fr;gap:36px;padding:32px 0 16px}
  .rail-stick{position:static}
  .device .screen{width:240px;height:300px}
  .device.is-on{padding:10px 10px 20px;margin:-10px 0 0 -10px}
  .device.is-on::after{width:48px;height:4px;margin-top:8px}
  .board{transform:scale(.5)}
  .shelf{grid-template-columns:repeat(auto-fill,240px);column-gap:56px;row-gap:64px;margin-top:32px}
  .rel{width:240px}
  .plate-box{width:240px;height:300px}
  .plate-box .plate{transform:scale(.5);transform-origin:0 0}
  h1{font-size:34px}
  h1.tall{font-size:40px}
  /* the object at half scale: the shell and the plate halve together, so every
     fat pixel of both becomes one device pixel and neither lattice smears */
  .hero{grid-template-columns:1fr;gap:40px;align-items:start;padding:40px 0 56px}
  .hero-obj{justify-self:start}
  .hero-txt h1{font-size:32px}
  .hero-lede{font-size:17px}
  .flex,.flex-shell{width:292px;height:352px}
  .flex-plate{left:14px;top:26px}
  .doc-txt h1{font-size:34px}
}
/* The explainer wants the sheet at its full width: two columns plus a plate at
   1x need 1104 px, and the sheet stops being that wide at 1160. Below it the
   page is one column and the figure follows the text it belongs to — better
   than a figure squeezed narrower than the artefact it shows, which is what
   put a horizontal scrollbar on this page alone between 1080 and 1160. */
@media (max-width:1160px){
  .doc-row{grid-template-columns:minmax(0,1fr);gap:32px 0;padding:28px 0 36px}
}
@media (max-width:820px){
  .faq-a{margin-left:0}
}
@media (max-width:560px){
  .sheet{padding:0 18px}
  .tick{display:block}
  .tick div+div{border-left:0;border-top:var(--fat) solid var(--ink)}
  .bar-nav{gap:12px 14px;font-size:10px;letter-spacing:.1em;flex-wrap:wrap}
  .mark{width:30px;height:28px}
  .house-name b{font-size:9px;letter-spacing:.16em}
  h1{font-size:28px}
  h1.tall{font-size:34px}
  .hero-txt h1{font-size:28px}
  .faq-a p{font-size:15px}
  .lede{font-size:17px}
  /* the windows halve, like every other plate on a narrow page */
  .win{width:calc(var(--ww)/2);height:calc(var(--wh)/2)}
  .win .plate{transform:scale(.5);transform-origin:0 0;top:calc(var(--wy)/2)}
  .slot-win{top:14px;right:12px;height:12px}
  .slot-win svg{height:12px}
  .doc-txt p,.doc-txt ul{font-size:17px}
  .doc-txt .lede{font-size:19px}
  .doc-txt h2{font-size:22px}
  .receipt{grid-template-columns:1fr;gap:2px 0}
  .receipt dd{margin-bottom:9px}
  .btn{padding:15px 18px;letter-spacing:.16em}
  .stack a,.stack button{flex-direction:column;align-items:flex-start;gap:5px}
  .stack em{text-align:left}
  .bignum .glyphs svg{height:44px}
}
