/* Alien Worlds — the pitch site.

   The architecture is the Zoe site's: a two-column spread whose halves scroll
   independently, a cluster that rides the foot of the window, and an overture
   of sticky scenes. The skin is not. Cormorant and Inter are gone; the ground
   is bone rather than cream, the ink is near-black rather than indigo, and the
   one accent is the colour of a K-dwarf.

   The type is Spectral over IBM Plex Sans, and the division is by role rather
   than by size: Spectral speaks — the cover, the page titles, the ledes, the
   scene statements, the pull quotes, the contents list — and Plex Sans does the
   work, carrying every paragraph of prose and every piece of furniture. So a
   page opens in a voice and then settles into a document, which is the shape of
   the pitch itself. Spectral was drawn for screens and is faintly technical in
   the serifs, which is as much personality as a scientific pitch wants: it has
   to survive being read for twenty minutes rather than win the first three
   seconds. */
/* fonts are linked from each page's <head> — an @import here made the
   browser fetch site.css, parse it, and only then go for the font CSS: a
   second blocking round trip, which on a phone connection is what left the
   type reflowing after the layout had already settled. */

:root{
  --paper:#F2EFE7;         /* bone, not cream — cooler than the zoe paper */
  --ink:#161B26;           /* near-black, with just enough blue to sit on bone */
  --ink-quiet:#6B7080;
  --rule:#161B26;
  --rule-soft:#D3CEC0;
  --warm:#C25A2B;          /* the star: K5V, and the only colour on the site */
  --menu:#161B26;
  --menu-ink:#F2EFE7;
  --edge:clamp(18px,4vw,64px);
  --measure:64ch;            /* the words, and nothing else */
  --night:#12141A;           /* the one dark band, on page 01 */
  --night-ink:#E8E4D8;
  --col-l:41%;
  --head:206px;   /* head block height = lead image offset */
  --gap:clamp(104px,7.5vw,168px);
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font:400 17px/1.68 'IBM Plex Sans',system-ui,sans-serif;
  -webkit-font-smoothing:antialiased;
}
img,video{display:block;max-width:100%}
a{color:inherit}

/* ---------- contents control ---------- */
.topbar{position:fixed;top:26px;left:26px;z-index:60;
  display:flex;align-items:center;gap:16px}
/* two arrows, opposite directions — page back / page on */
.pagenav{position:fixed;top:26px;right:26px;z-index:60;display:flex;gap:14px;
  align-items:center;font-size:11px}
.pagenav .nav{display:inline-flex;color:var(--ink);text-decoration:none;padding:2px}
.pagenav svg{width:auto;height:.72em;display:block;overflow:visible}
.pagenav .nav:hover{opacity:.55}
.pagenav .nav:focus-visible{outline:2px solid var(--ink);outline-offset:3px}

.contents-btn{
  z-index:60;
  display:flex;align-items:center;gap:16px;
  background:none;border:0;padding:6px;cursor:pointer;color:var(--ink);
  font:600 11px/1 'IBM Plex Sans',system-ui,sans-serif;letter-spacing:.12em;text-transform:uppercase;
}
/* a square mark: .72em wide and .72em tall — the cap height of CONTENTS */
/* stack height = the cap height of CONTENTS (0.72em), in em so it tracks the label */
/* Three bars of unequal length, which is what an absorption spectrum looks
   like when it is printed small — the mark of a project about reading
   atmospheres, and not the hamburger the zoe site used. */
.contents-btn .bars{display:grid;gap:.1em;width:.8em}
.contents-btn .bars i{display:block;height:.16em;background:currentColor;
  transition:width .2s}
.contents-btn .bars i:nth-child(1){width:100%}
.contents-btn .bars i:nth-child(2){width:58%}
.contents-btn .bars i:nth-child(3){width:82%}
.contents-btn:hover .bars i:nth-child(2){width:100%}
.contents-btn:hover .bars i:nth-child(3){width:64%}
.contents-btn:focus-visible{outline:2px solid var(--ink);outline-offset:3px}

/* ---------- contents overlay ---------- */
.contents{position:fixed;inset:0;z-index:50;display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);visibility:hidden}
.contents[data-open="true"]{visibility:visible}
.contents .panel{
  background:var(--menu);color:var(--menu-ink);
  display:flex;flex-direction:column;justify-content:center;padding:5vh 0 5vh 8vw;
  transform:translateX(-100%);transition:transform .42s cubic-bezier(.4,0,.15,1);
}
.contents[data-open="true"] .panel{transform:none}
/* the empty half of the overlay is not empty: one dim disc, low and right,
   the same orange the rest of the site spends sparingly */
.contents .stage{background:var(--paper);position:relative;overflow:hidden}
.contents .stage::after{content:"";position:absolute;right:-14vh;bottom:-22vh;
  width:60vh;height:60vh;border-radius:50%;
  background:radial-gradient(circle at 34% 30%,
    rgba(194,90,43,.30),rgba(194,90,43,.10) 58%,transparent 72%)}
.contents ol{list-style:none;margin:0;padding:0}
.contents li{line-height:43px}
.contents a{display:flex;gap:1.4rem;align-items:baseline;text-decoration:none;
  font:300 25px/43px Spectral,Georgia,serif;
  color:var(--menu-ink);opacity:.95}
.contents a:hover{opacity:1;text-decoration:underline;text-underline-offset:6px}
.contents .num{min-width:3em;opacity:.55;
  font:400 13px/1 'IBM Plex Sans',system-ui,sans-serif;letter-spacing:.08em;
  font-variant-numeric:tabular-nums}
.contents li[aria-current="page"] a{opacity:.45;cursor:default}
.contents li[aria-current="page"] a:hover{text-decoration:none}

/* ---------- the page ----------
   One column, and a grid whose middle track is the measure. Everything sits in
   that track; anything marked .full spans the window instead. That is the whole
   layout — no spread, no sticky picture column, no second scroll. The words run
   down the middle of the page and the renders interrupt them at full width,
   which is the arrangement a project whose argument is pictures deserves. */
.page{
  display:grid;
  grid-template-columns:
    [full-start] minmax(var(--edge),1fr)
    [measure-start] minmax(0,var(--measure)) [measure-end]
    minmax(var(--edge),1fr) [full-end];
  row-gap:0;
}
.page > *{grid-column:measure}
.page > .full{grid-column:full}

.head{display:flex;align-items:baseline;gap:20px;
  padding:clamp(96px,16vh,150px) 0 18px}
.head .num{font:500 12px/1 'IBM Plex Sans',system-ui,sans-serif;letter-spacing:.16em;
  color:var(--warm);font-variant-numeric:tabular-nums}
.head h1{margin:0;font:300 clamp(30px,4.4vw,44px)/1.08 Spectral,Georgia,serif;
  letter-spacing:-.002em;text-wrap:balance}
/* two hairlines rather than one bar: the second is the accent, and it is the
   only place on a page where the star's colour runs the full measure */
.topline{border:0;height:5px;margin:0;
  background:linear-gradient(var(--rule) 0 1px,var(--paper) 1px 4px,var(--warm) 4px 5px)}
.lede{font:300 clamp(21px,2.1vw,26px)/1.42 Spectral,Georgia,serif;
  margin:30px 0 0;color:var(--ink);text-wrap:pretty}
.lede em{font-style:italic}
.lede strong{font-weight:500}

/* ---------- pictures that leave the measure ---------- */
.plate{margin:clamp(44px,7vh,86px) 0 0}
.plate img,.plate video{width:100%;height:auto;display:block;
  max-height:82vh;object-fit:cover}
.plate figcaption{max-width:var(--measure);margin:14px auto 0;
  font:400 13px/1.55 'IBM Plex Sans',system-ui,sans-serif;color:var(--ink-quiet)}
.plate.lead{margin-top:clamp(34px,5vh,60px)}
/* a page made of scenes: the rule under the title is the last thing in the
   measure before the window takes over */
.page.scroll .topline{margin-bottom:0}
.reel-set{margin:0}
.page.scroll .pager{margin-top:clamp(40px,6vh,72px)}
/* a portrait keeps to the measure and is ranged left, like a plate in a book */
.plate.tall{max-width:min(44ch,100%)}
.plate.tall img,.plate.tall video{max-height:none}
.plate.tall figcaption{padding:0;margin-left:0}
/* the picture is followed by words, and they need the same air the picture got */
.plate + h2,.plate + p,.plate + ul,.plate + blockquote,
.orbs + h2,.orbs + p,.orbs + ul,.orbs + blockquote{margin-top:clamp(40px,6vh,72px)}

/* ---------- the nine, on the one dark band in the site ---------- */
.orbs{background:var(--night);padding:clamp(44px,7vh,80px) var(--edge);
  margin:clamp(44px,7vh,86px) 0 0}
.orbrow{max-width:940px;margin:0 auto;display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:clamp(28px,4vh,52px) clamp(20px,3vw,46px)}
.orb{margin:0;display:flex;flex-direction:column;align-items:center;gap:14px}
.orb .disc{width:100%;aspect-ratio:1;border-radius:50%;overflow:hidden;
  position:relative;box-shadow:inset 0 0 0 1px rgba(242,239,231,.14)}
.orb .disc img,.orb .disc video{width:100%;height:100%;object-fit:cover;display:block}
.orb figcaption{text-align:center;color:var(--night-ink)}
.orb figcaption b{display:block;font:500 11px/1.3 'IBM Plex Sans',system-ui,sans-serif;
  letter-spacing:.14em;text-transform:uppercase}
.orb figcaption i{display:block;margin-top:5px;
  font:300 italic 15px/1.3 Spectral,Georgia,serif;opacity:.72}

/* ---------- prose furniture ---------- */
.page h2{
  font:500 11px/1 'IBM Plex Sans',system-ui,sans-serif;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink-quiet);
  margin:clamp(40px,6vh,64px) 0 18px;padding-top:15px;
  border-top:1px solid var(--rule-soft);
}
.page > p{margin:0 0 20px}
.page > p:first-of-type{margin-top:34px}
.page ul{list-style:none;margin:0 0 28px;padding:0}
.page li{position:relative;padding-left:1.5em;margin:0 0 12px}
.page li::before{
  content:"";position:absolute;left:.3em;top:.66em;
  width:5px;height:5px;border-radius:50%;background:var(--warm);
}
/* the pull quote is not indented: it takes the full measure and is held by a
   short rule above it, so it reads as the page raising its voice rather than
   as something quoted from elsewhere */
.page blockquote{margin:clamp(36px,5vh,56px) 0;padding:22px 0 0;border:0;
  position:relative}
.page blockquote::before{content:"";position:absolute;top:0;left:0;
  width:64px;height:1px;background:var(--warm)}
.page blockquote p{font:300 clamp(20px,2vw,25px)/1.4 Spectral,Georgia,serif;margin:0}
.page .notice{
  font-size:15.5px;line-height:1.6;color:var(--ink-quiet);
  border-top:1px solid var(--rule-soft);border-bottom:1px solid var(--rule-soft);
  padding:16px 0;margin:0 0 28px;
}
/* a footnote sits below the run of the text, not in it */
.page .note{color:var(--ink-quiet);font-size:15px;line-height:1.6;margin:0 0 26px}
/* Plex Sans carries a real 600; a name set in it reads as a name */
.page strong{font-weight:600}
.page .btnrow{margin:26px 0 30px;display:flex;flex-wrap:wrap;gap:10px}
.page a.btn,.say p.cta a.btn{
  font:500 10px/1 'IBM Plex Sans',system-ui,sans-serif;letter-spacing:.1em;
  text-transform:uppercase;text-decoration:none;
  color:var(--paper);background:var(--ink);
  border:1px solid var(--ink);padding:12px 16px;
}
.page a.btn:hover,.say p.cta a.btn:hover{background:var(--warm);border-color:var(--warm)}
.page a.btn:focus-visible,.say p.cta a.btn:focus-visible{outline:2px solid var(--ink);outline-offset:3px}

.diagram{margin:clamp(34px,5vh,56px) 0 36px}
.diagram svg{width:100%;height:auto;display:block}

.pager{display:flex;justify-content:space-between;gap:16px;align-items:end;
  margin-top:clamp(52px,9vh,110px)}
.pager.solo{justify-content:flex-start}
.pager a{
  font:500 11px/1 'IBM Plex Sans',system-ui,sans-serif;letter-spacing:.1em;
  text-transform:uppercase;text-decoration:none;color:var(--ink);
  border:1px solid var(--rule-soft);padding:11px 15px;
}
.pager a:hover{border-color:var(--warm);color:var(--warm)}

footer.site{
  margin-top:52px;padding:16px 0 40px;border-top:1px solid var(--rule-soft);
  font:500 10px/1.6 'IBM Plex Sans',system-ui,sans-serif;letter-spacing:.09em;
  text-transform:uppercase;color:var(--ink-quiet);
}

/* iOS paints its own play glyph over any film it has not started, and it is
   the one piece of chrome on the whole site that the reader did not ask for.
   The films are muted, looping wallpaper — they carry no controls and want
   none. This is the only way to refuse the overlay. */
video::-webkit-media-controls{display:none!important}
video::-webkit-media-controls-start-playback-button{
  display:none!important;-webkit-appearance:none}
video::-webkit-media-controls-panel{display:none!important}
/* ---------- overture ---------- */
/* the cover is one full frame of film, the words set on it */
.overture{background:var(--paper);position:relative}
.cover{position:relative;height:100vh;z-index:1}
/* the film is fixed to the window and narrows into the image column as the
   reader leaves the cover — the same picture, not a second copy of it */
.reel{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:0;overflow:hidden;
  /* graded, not re-encoded: the renders run warm and a shade flat */
  filter:saturate(1.06) contrast(1.06) brightness(.94)}
/* img as well as video: the cover of this site is a still, and without a
   height of its own a picture kept its natural proportions while the reel
   narrowed — so it lost height as it went and read as the cover sliding
   upward out of the window instead of closing into the column. Every other
   holder on the site already named both. */
.reel img,.reel video{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover}
/* A cover that goes rather than holds. The reel is mounted on the page instead
   of on the window, so it leaves upward with everything else and the first
   scene arrives on clean paper. The narrowing is the other site's signature
   move; this is the plainer reading of the same cover. */
.reel.plain{position:absolute;top:0;left:0;width:100%;height:100vh}
/* the iridescence: a few broad bands drifting across the film on the
   diagonal, laid on soft-light so it reads as light rather than as colour */
/* Not the zoe site's iridescence. Two things: a vignette that holds the title
   in the middle of the frame, and a very slow warm band drifting across it,
   the colour of the star the whole system orbits. */
.sheen{position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(ellipse 78% 62% at 50% 46%,
      rgba(10,12,20,.28) 0%, rgba(10,12,20,.48) 72%, rgba(10,12,20,.72) 100%);}
.sheen::after{content:"";position:absolute;inset:-40% -60%;
  mix-blend-mode:soft-light;opacity:.26;
  background:repeating-linear-gradient(-24deg,
    rgba(194,90,43,0) 0px, rgba(194,90,43,.55) 150px,
    rgba(255,232,200,.42) 300px, rgba(120,140,200,.34) 430px,
    rgba(194,90,43,0) 580px);
  animation:drift 34s linear infinite}
@keyframes drift{from{transform:translate3d(0,0,0)}
  to{transform:translate3d(580px,-258px,0)}}   /* one band, along the -24° */

.cover .plate{position:absolute;inset:auto 0 auto 0;top:50%;
  transform:translateY(-50%);text-align:center;
  padding:0 clamp(28px,6vw,80px);color:var(--paper);
  text-shadow:0 2px 30px rgba(8,10,18,.5)}
.overture .eyebrow{
  margin:0 0 clamp(16px,2.6vh,26px);
  font:500 11px/1 'IBM Plex Sans',system-ui,sans-serif;letter-spacing:.2em;
  text-transform:uppercase;color:rgba(242,239,231,.8);
}
/* the title is set light and open — it is a long word twice over, and the
   letterspacing is what keeps it from reading as a headline. Spectral's 200 is
   light enough to take it without the letters coming apart. */
.overture h1{margin:0;font:200 clamp(44px,7vw,98px)/1.02 Spectral,Georgia,serif;
  letter-spacing:.07em}
/* at the widest windows the title would otherwise run the full measure */
.cover .plate{max-width:1180px;margin:0 auto}
/* a hairline under the title, the width of the standfirst, in the star's colour */
.cover .plate::after{content:"";display:block;width:74px;height:1px;
  margin:clamp(20px,3vh,32px) auto 0;background:var(--warm);opacity:.85}
.cover .stand{margin:clamp(14px,2.4vh,26px) auto 0;
  font:400 clamp(12px,1.05vw,15px)/1.5 'IBM Plex Sans',system-ui,sans-serif;
  letter-spacing:.1em;white-space:nowrap;color:rgba(242,239,231,.88)}

/* One picture carried through the whole overture: it arrives in the middle of
   the column in the first scene and climbs to the top of it in the second.
   The same element throughout — never a second copy fading in. */
.carry{position:fixed;top:0;left:0;z-index:2;overflow:hidden;
  width:1px;height:1px;opacity:0;will-change:transform,width}
.carry img,.carry video{width:100%;height:100%;object-fit:cover;display:block}


/* ---------- the scenes ----------
   The section is tall; the frame inside it is one screen and sticks, so the
   reader's scroll is spent inside the scene instead of pushing it past. */
.scene{position:relative}
.frame{position:sticky;top:0;height:100vh;overflow:hidden;
  display:grid;grid-template-columns:1fr 1fr;z-index:1}

.say{position:relative;z-index:3;background:var(--paper);padding:0 clamp(28px,4.4vw,72px);
  display:flex;flex-direction:column;justify-content:center;
  gap:clamp(18px,2.6vh,30px)}
/* the paragraphs stack: each arrives on its own beat and then stays */
.say p{
  margin:0;font:300 clamp(20px,1.75vw,27px)/1.34 Spectral,Georgia,serif;max-width:31ch;
  opacity:0;will-change:transform,opacity;
}
/* a list set in from the line that introduces it */
.say p.in{padding-left:1.5em}
/* the overture ends on the same button the pages use */
.say p.cta{max-width:none}
/* The scientists who built the world. Two sit side by side and share the
   column; one sits alone on the same left edge rather than centring itself,
   so a scene with one name and a scene with two begin identically. Set in
   Plex Sans, because this is a credit, not a sentence. */
.say p.who{display:flex;gap:clamp(18px,2.4vw,40px);max-width:none;
  font-family:'IBM Plex Sans',system-ui,sans-serif;font-weight:400;
  font-size:clamp(12px,1.05vw,14px);line-height:1.45;color:var(--ink-quiet);
  margin-top:clamp(6px,1.4vh,18px)}
.say p.who .q{display:flex;flex-direction:column;flex:0 1 auto;min-width:0;
  max-width:24ch}
.say p.who[data-n="1"] .q{max-width:32ch}
.say p.who b{font-weight:600;color:var(--ink);letter-spacing:.005em}

.field{position:relative;overflow:hidden}
.bed{position:absolute;inset:0;will-change:transform}
.bed img,.bed video{width:100%;height:100%;object-fit:cover;display:block}
/* the film that carries across a boundary: one element, fixed over the
   picture column, so it is never started a second time */
.stay{position:fixed;top:0;z-index:0;overflow:hidden;opacity:0;pointer-events:none}
.stay img,.stay video{width:100%;height:100%;object-fit:cover;display:block}
/* the grid that closes over the bed: every cell covers its share of the column,
   so when the last one lands the picture underneath is gone */
.grid{position:absolute;inset:0;z-index:1;display:grid;
  grid-template-columns:repeat(var(--cols,4),1fr);
  grid-auto-rows:1fr}
.cell{position:relative;overflow:hidden;opacity:0;
  transform:scale(1.06);will-change:opacity,transform}
.cell img,.cell video{width:100%;height:100%;object-fit:cover;display:block}
/* a picture that comes out of a vanishing point at the centre of the column:
   it grows at a steady relative rate, which is what makes it read as an
   approach out of infinity rather than a box being scaled up */
.emerge{position:absolute;left:50%;top:50%;z-index:2;opacity:0;
  transform:translate(-50%,-50%) scale(0.02);transform-origin:50% 50%;
  will-change:transform,opacity}
.emerge.cover{width:100%;height:100%}
.emerge.plate{width:calc(var(--w,47) * 1%);aspect-ratio:var(--ar,1);height:auto}
.emerge img,.emerge video{width:100%;height:100%;object-fit:cover;display:block}
/* four pictures that arrive from the four corners and close into one tile */
.quad{position:absolute;left:50%;top:50%;z-index:2;
  width:calc(var(--w,60) * 1%);aspect-ratio:1;transform:translate(-50%,-50%);
  display:grid;grid-template-columns:1fr 1fr;grid-auto-rows:1fr}
.q{position:relative;overflow:hidden;will-change:transform,opacity;opacity:0}
.q img,.q video{width:100%;height:100%;object-fit:cover;display:block}
.grid{will-change:transform}

/* a stack of plates in the column: they slide in from the top or the foot
   and come to rest touching one another, the stack anchored at the top */
.plate-v{position:absolute;left:50%;z-index:2;width:calc(var(--w,74) * 1%);max-width:none;
  aspect-ratio:var(--ar,1);transform:translateX(-50%);
  will-change:transform;overflow:hidden;top:0}
.plate-v img,.plate-v video{width:100%;height:100%;object-fit:cover;display:block}


@media (max-width:900px){
  body{font-size:16px;line-height:1.66}
  .head{padding-top:clamp(74px,12vh,96px);gap:14px}
  .head h1{font-size:28px}
  .lede{max-width:none}
  .plate img,.plate video{max-height:62vh}
  .orbrow{grid-template-columns:repeat(2,1fr)}
  .contents{grid-template-columns:1fr}
  .contents .stage{display:none}

  /* ---- the overture on a phone ----
     A scene splits left/right on a desktop. On a narrow screen that leaves
     the words about nineteen characters wide, so the scene stacks instead:
     the film takes a band across the top and the words have the full width
     underneath it. */
  .frame{grid-template-columns:1fr;grid-template-rows:42vh 1fr}
  .field{grid-row:1}
  .say{grid-row:2;justify-content:flex-start;
       padding:clamp(22px,5vh,40px) clamp(20px,5.5vw,34px) 0;
       gap:clamp(12px,1.8vh,20px)}
  .say p{font-size:clamp(17px,4.4vw,22px);line-height:1.38;max-width:none}
  .say p.in{padding-left:1.1em}

  /* the cover's own type, which was sized for a wide window */
  .overture h1{font-size:clamp(34px,11.5vw,62px);letter-spacing:.05em}
  .cover .stand{font:400 clamp(11px,3.2vw,15px)/1.45 'IBM Plex Sans',system-ui,sans-serif;
    letter-spacing:.06em}
  .overture .eyebrow{margin-bottom:clamp(12px,2vh,20px);letter-spacing:.22em}
  /* the confidentiality line is held to one line on a wide screen; at phone
     width one line would be 626px, which is what was making the page slide
     sideways, so here it wraps */
  .overture .overture-note,
  .overture .overture-note p{font-size:11px;line-height:1.45;white-space:normal}
  .overture .overture-note{bottom:clamp(14px,2.4vh,22px)}

}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .sheen{animation:none}
  .contents .panel{transition:none}
}

/* the confidentiality line, at the foot of the cover — one line, ranged left */
.overture-note{
  position:absolute;left:0;right:0;bottom:clamp(18px,3vh,30px);margin:0;
  padding:0 clamp(28px,4.4vw,72px);text-align:left;
  color:rgba(242,239,231,.7);
  font-size:clamp(10px,1.02vw,14px);line-height:1.5;white-space:nowrap;
  text-shadow:0 1px 14px rgba(20,24,40,.55);
}
.overture-note p{margin:0}
.overture-note a{color:inherit;text-decoration:underline;text-underline-offset:3px}

/* the contents mark is cream while it sits on the film, indigo once past it */
.topbar.on-film .contents-btn,
.pagenav.on-film .nav{color:var(--paper)}
