/* ===========================================================================
   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;
  /* One face on the whole site, and it is the device's own.
     There used to be two: a sans for the chrome and Literata for anything
     quoting a book, which was right while the reader was set in Literata. The
     reader is set in Inter now, so a serif blurb was the shop showing you a
     typeface the book no longer uses. `--book` is kept as a name because four
     rules read it, and it now points at the same stack. */
  --book:Inter,"Inter var",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-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;justify-content:center}
.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 */
/* The answer sits UNDER its question, not 356 px to the right of it. That
   indent belonged to a two-column FAQ; with the question ranged left and the
   answer ranged to the middle of the page, the two read as unrelated - and at
   the measure it left, a two-line answer wrapped where nothing asked it to. */
.faq-a{margin:16px 0 0;max-width:62ch}
.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}

/* ── the empty slot ─────────────────────────────────────────────────────── */
/* The last plate on the shelf, cut to the same 480x600 as a book and framed
   dashed rather than solid: the frame says the slot exists and is not filled,
   which is the whole of the invitation. Every other way of asking for this
   was a paragraph under the covers. */
.rel-ask{appearance:none;background:none;border:0;padding:0;font:inherit;
  color:inherit;cursor:pointer;text-align:left}
.rel-ask .ask-plate{display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:26px;background:var(--paper);
  box-shadow:none;outline:var(--fat) dashed var(--ink);outline-offset:calc(-1 * var(--fat))}
.rel-ask:hover .ask-plate{outline-style:solid;
  box-shadow:0 0 0 8px var(--paper),0 0 0 10px var(--ink)}
.rel-ask:focus-visible .ask-plate{outline-style:solid}
/* the plus is drawn in fat pixels, like every other mark on this site */
.ask-plus{position:relative;width:64px;height:64px}
.ask-plus::before,.ask-plus::after{content:"";position:absolute;background:var(--ink)}
.ask-plus::before{left:0;right:0;top:28px;height:8px}
.ask-plus::after{top:0;bottom:0;left:28px;width:8px}
.ask-say{font:600 13px/1 var(--chrome);letter-spacing:.22em;text-transform:uppercase}

/* The form it opens. Paper on a dimmed page, the house's own edge around it,
   and no rounded corner anywhere. */
.ask-box{width:min(560px,calc(100vw - 36px));padding:0;border:0;
  background:var(--paper);color:var(--ink);box-shadow:0 0 0 var(--fat) var(--ink)}
.ask-box::backdrop{background:rgba(0,0,0,.55)}
.ask-box form{padding:32px 32px 28px}
.ask-box h2{margin:0 0 22px;font-size:24px;font-weight:600;letter-spacing:-.01em}
.ask-box label{display:block;margin:0 0 16px;font:600 10px/1 var(--chrome);
  letter-spacing:.2em;text-transform:uppercase}
.ask-box label span{opacity:.5;letter-spacing:.14em}
.ask-box input,.ask-box textarea{display:block;width:100%;margin-top:8px;
  padding:12px 13px;font:400 16px/1.4 var(--chrome);color:var(--ink);
  background:var(--paper);border:0;box-shadow:0 0 0 var(--fat) var(--ink);
  border-radius:0;resize:vertical}
/* The focus mark thickens the field's own edge rather than drawing a second
   one outside it: an outline plus a box-shadow read as two frames. */
.ask-box input:focus,.ask-box textarea:focus{outline:0;
  box-shadow:0 0 0 calc(var(--fat) * 2) var(--ink)}
.ask-msg{margin:0 0 4px;min-height:20px;font-size:13px;line-height:1.5}
.ask-box .acts{margin-top:18px}

/* ── how many devices hold a book ───────────────────────────────────────── */
/* Beside the button, in the chrome face, quiet. Hidden at nought: a shop
   announcing that nobody has taken a book is telling a visitor nothing they
   can use. */
.tally{align-self:center;font:600 11px/1 var(--chrome);letter-spacing:.18em;
  text-transform:uppercase;opacity:.55}
/* and on the shelf, in the corner of the plate it belongs to */
.plate-count{position:absolute;left:0;bottom:0;z-index:2;padding:7px 11px;
  background:var(--ink);color:var(--paper);font:600 10px/1 var(--chrome);
  letter-spacing:.16em;text-transform:uppercase}
.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)}

/* The way out of a book. A visitor can land on a title from anywhere - a
   shared link, a search result - so this goes to the shelf rather than to
   whatever the browser happens to have behind it. */
.backlink{display:inline-block;margin:0 0 22px;font:600 11px/1 var(--chrome);
  letter-spacing:.2em;text-transform:uppercase;text-decoration:none;color:var(--ink);
  opacity:.6;transition:opacity .15s ease}
.backlink:hover{opacity:1}

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}
}


/* The reader in the hero's Flex. A frameless iframe at exactly the panel's
   size: any border, any scrollbar, any pixel of difference and it stops being
   the screen and starts being a window onto one. */
/* Full size. It was scaled to 98% to keep the rectangle out of the shell's
   rounded corners and the owner's verdict was that it looked worse: a panel
   that does not fill its recess reads as a screenshot pasted into a drawing,
   which is the one thing this must not read as. */
.plate-box .live{display:block;width:480px;height:600px;border:0;background:var(--paper)}


/* The hero's Flex is live, and nothing about a drawing says so. Three things
   say it together: the pointer becomes a finger over the glass, the shell
   lifts a little when the pointer is on it, and one line under the device
   states it in words for anyone who never moves a mouse over a picture. */
.plate-box .live{cursor:pointer}
.hero-obj .flex{transition:transform .18s ease}
.hero-obj .flex:hover{transform:translateY(-3px)}

/* The device has to look usable BEFORE anything is hovered. A cursor that
   changes and a shell that lifts are both rewards for a gesture somebody has
   to make first, and a visitor who does not know the drawing is live has no
   reason to make it.

   So it moves on its own: the glass breathes once every few seconds - a sheen
   crossing the panel, three seconds of travel in a nine-second cycle - which
   is the smallest thing that reads as "this is not a photograph". It stops on
   hover, because by then the point is made and a moving highlight under a
   pointer is just noise. */
@keyframes hero-sheen{
  0%   {transform:translateX(-120%) skewX(-14deg); opacity:0}
  8%   {opacity:.55}
  34%  {opacity:.55}
  46%  {transform:translateX(220%) skewX(-14deg); opacity:0}
  100% {transform:translateX(220%) skewX(-14deg); opacity:0}
}
.plate-box .sheen{position:absolute;top:-10%;bottom:-10%;width:36%;z-index:3;
  pointer-events:none;
  background:linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.55), rgba(255,255,255,0));
  animation:hero-sheen 9s ease-in-out 1.2s infinite}
.hero-obj .flex:hover .sheen{animation-play-state:paused;opacity:0}

/* The hero's Flex carries no word on it. There was one in the bezel ("Tap to
   read") and the owner cut it on 2026-08-07: on an object drawn this carefully
   a label is a caption, and the sheen crossing the glass already says the
   thing is alive. The rail on a book's page keeps its chip, where there is no
   drawn device around the panel to make the point. */

/* ── the same reader, in a book page's rail ─────────────────────────────── */
/* The hero holds a drawn Flex with a recess; the rail holds the panel on its
   own, so the live reader gets its own wrapper rather than borrowing
   `.plate-box`, whose narrow-screen rules would scale a second time inside
   `.board` (which is already at 0.5). Everything else is shared: the same
   iframe at exactly 480x600, the same sheen, the same word on the glass. */
.rail-live{display:block;width:480px;height:600px;position:relative;
  overflow:hidden;isolation:isolate}
.rail-live .live{display:block;width:480px;height:600px;border:0;
  background:var(--paper);cursor:pointer}
.rail-live .sheen{position:absolute;top:-10%;bottom:-10%;width:36%;z-index:3;
  pointer-events:none;
  background:linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.55), rgba(255,255,255,0));
  animation:hero-sheen 9s ease-in-out 1.2s infinite}
.rail-live:hover .sheen{animation-play-state:paused;opacity:0}
/* No bezel to sit in here, and what is behind the chip changes: a cover that
   is nearly black, then white paper the moment a visitor reads. So it is a
   paper chip with the house's own edge around it, which is the one treatment
   that holds against both. It leaves as soon as the pointer arrives. */
.rail-live .tapme{position:absolute;left:50%;bottom:16px;z-index:4;
  transform:translateX(-50%);background:var(--paper);color:var(--ink);
  box-shadow:0 0 0 var(--fat) var(--ink);
  padding:9px 14px;font:600 11px/1 var(--chrome);letter-spacing:.18em;
  text-transform:uppercase;pointer-events:none;transition:opacity .18s ease}
.rail-live:hover .tapme{opacity:0}

@media (prefers-reduced-motion: reduce){
  .plate-box .sheen,.rail-live .sheen{animation:none;opacity:0}
}


/* ── the device as an object ─────────────────────────────────────────────
   Two treatments, both faint. The panel is 1bpp and every pixel on it is a
   pixel the device would draw, so nothing here may touch the type: these sit
   OVER the glass as separate layers, and neither takes a click.

   The shadow is cast off the shell's own alpha with `drop-shadow`, not off its
   bounding box: the shell is a drawn extrusion with a rounded silhouette and a
   box shadow would put a rectangle under a rounded thing. Long, soft and very
   low in opacity - an object on a white page an arm's length away, not a card
   floating over it. */
/* NOT `drop-shadow` on the shell: that PNG has no alpha - it is drawn on its
   own white - so the filter cast a rectangle behind a rounded object, which is
   worse than no shadow at all. An ellipse under the device instead, blurred
   and low, the shape a thing this size actually throws on a white page. */
.hero-obj .flex{position:relative}
.hero-obj .flex::after{content:"";position:absolute;z-index:-1;
  left:8%;right:8%;bottom:-14px;height:34px;border-radius:50%;
  background:radial-gradient(closest-side, rgba(20,18,15,.30), rgba(20,18,15,0));
  filter:blur(6px)}

/* And the glass. Three things a real panel does under a room light, at the
   strength a matte e-ink screen does them - which is: barely.

   - a sheen falling across the top left corner, cut off hard partway down,
     because a flat sheet reflects a window rather than a bulb;
   - the faintest cool tint over the paper, since e-ink glass is never quite
     the colour of the ink under it;
   - a dark hairline inside the recess, which is the panel sitting UNDER the
     bezel rather than flush with it. That one does most of the work. */
.plate-box{isolation:isolate}
.plate-box .glass{position:absolute;inset:0;pointer-events:none;z-index:2;
  background:linear-gradient(148deg,
    rgba(255,255,255,.42) 0%,
    rgba(255,255,255,.16) 18%,
    rgba(255,255,255,0) 34%),
   linear-gradient(180deg, rgba(120,140,160,.05), rgba(120,140,160,0) 40%);
  box-shadow:inset 0 2px 5px rgba(20,18,15,.28),
             inset 0 -1px 3px rgba(20,18,15,.14),
             inset 2px 0 4px rgba(20,18,15,.16),
             inset -2px 0 4px rgba(20,18,15,.16)}
