/* ===========================================================================
   ASTRUM — the site.
   One stylesheet for five pages, on the app's own tokens. The product and the
   page selling it share a palette or the page is a promise the app breaks.
   =========================================================================== */
:root{
  /* THIS PAGE HAS DECIDED WHAT COLOUR IT IS.
     A page that says nothing is a page a browser may re-theme, and several
     now offer "dark mode for every website" — they take silence as consent.
     Astrum on a forced-dark browser is not a darker Astrum: the ground goes
     black, the near-black buttons vanish into it, and the wordmark — dark navy
     on transparency — would disappear too, so the browser paints a pale plate
     behind it and the logo ends up in a grey box. Measured on an iPad: the
     lockup is 91% transparent and 0% opaque, so that box is the browser's, not
     the file's.
     There is no dark variant of this stylesheet to fall back to, which is the
     whole reason this line has to be here rather than a @media block. */
  color-scheme: only light;
  /* THE GROUND TWICE. Two surfaces sit ON the ground and have to let it
     through — the sticky bar, and the wash that fades the hero plate back
     into the page — so they need the ground WITH an alpha, which a hex
     cannot give them. Same colour, stated as channels. Change one, change
     the other. */
  --bg:#fbfaf8; --bg-rgb:251,250,248;
  --bg2:#f3f1ee; --card:#fff; --line:#e6e3dd;
  --ink:#131a28; --muted:#5f6472; --faint:#8b8f9b;
  --accent:#141b2a; --on-accent:#f4f2ef;
  --brass:#8a713e; --good:#3f7b55;

  /* ---- AND THE FIVE THAT ARE NOT COLOURS, WHICH LIVED IN THE WRONG BLOCK.
     The type, the gutter, the rail and the lift were declared only inside
     :root[data-theme="dark"] — a block that is dormant and gated behind an
     attribute nothing sets. Every colour above has a light value and a dark
     one; these five had exactly one, in the half that never runs. So on the
     site everybody actually sees:

       --sans and --serif  undefined, so `font-family:var(--sans)` on body was
                           invalid, fell back through to the browser default,
                           and the whole marketing site rendered in TIMES NEW
                           ROMAN. Measured, not guessed: computed body font
                           on the built page was "Times New Roman".
       --pad               undefined, so `.wrap{padding:0 var(--pad)}` was 0
                           and there was no side gutter at any width — on a
                           phone the copy ran into both edges of the screen.
       --rail              undefined, so `max-width` was none and a section
                           spanned the whole of a 1440px monitor.
       --lift              undefined, so the shadow under a card was missing.

     They are theme-independent — the dark block's own comment said so, "the
     same lift as the app's, so the two halves of Astrum stay one product" —
     so they belong here, where both themes inherit them. */
  --serif:ui-serif,Georgia,'Iowan Old Style','Times New Roman',serif;
  --sans:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;
  --lift:0 2px 6px rgba(20,27,42,.06),0 22px 60px rgba(20,27,42,.13);
  --pad:clamp(20px,4.6vw,72px);
  --rail:1320px;
}

/* ===========================================================================
   THE SITE AT NIGHT — the same tokens, and the sun falling into a night sky
   rather than into cream.

   DORMANT, like the app's. Gated on data-theme="dark" rather than on the
   system setting, and the declaration above still says "only light", because
   a site with a night hero and a cream footer is worse than a cream site.
   The gate moves when the rest of these pages have been walked through.

   The hue is carried, not replaced: brass at #8a713e is 2.4:1 on a dark card
   and a dim brass is not a brass at all. The same lift as the app's, so the
   two halves of Astrum stay one product.
   =========================================================================== */
:root[data-theme="dark"]{
  --bg:#0e1014; --bg-rgb:14,16,20;
  --bg2:#161920; --card:#15181e; --line:#2a2e37;
  --ink:#f2f3f6; --muted:#a3a8b4; --faint:#7e838f;
  --accent:#f2f3f6; --on-accent:#0e1014;
  --brass:#cdae74; --good:#6fbf8c;
  /* THE TYPE, THE GUTTER, THE RAIL AND THE LIFT ARE NOT COLOURS, so they are
     not in here any more. See :root above. */
}
*{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--sans);
  font-size:16px;line-height:1.6;-webkit-font-smoothing:antialiased;overflow-x:hidden}
img{max-width:100%}
a{color:inherit;text-decoration:none}
.wrap{max-width:var(--rail);margin:0 auto;padding:0 var(--pad)}

h1,h2,h3{font-family:var(--serif);font-weight:400;color:var(--ink);
  letter-spacing:-.018em;line-height:1.08;text-wrap:balance;margin:0}
h1{font-size:clamp(38px,4.9vw,68px)}
h2+p,h3+p{margin-top:12px}
h2{font-size:clamp(28px,3.5vw,46px);line-height:1.12}
h3{font-size:clamp(19px,1.5vw,23px);line-height:1.25}
p{margin:0 0 1.1em}
.eyebrow{font-size:11px;letter-spacing:3.2px;text-transform:uppercase;
  font-weight:600;color:var(--faint);margin:0 0 20px}
.lede{font-size:clamp(17px,1.35vw,20px);line-height:1.62;color:var(--muted);max-width:30em}
.fine{font-size:13px;line-height:1.6;color:var(--faint)}

/* ---- brand lockup ----
   THE WORDMARK IS ARTWORK, NOT TYPE. This set "ASTRUM" as letter-spaced
   Helvetica beside the mark — but the A of the wordmark is the same pointed,
   crossbar-less form as the A inside the compass, and no system font has it.
   Typing the word broke the one relationship the lockup is built on.
   astrum-header.png carries mark and wordmark together; the strapline stays as
   text beneath, which is what the app's own gate does. */
.lockup{display:flex;flex-direction:column;align-items:flex-start;gap:6px}
.lockup img{width:158px;height:auto;display:block}
.lockup .strap{font-size:8px;letter-spacing:2.1px;color:var(--muted);white-space:nowrap}
.lockup.sm img{width:126px}
.lockup.sm .strap{font-size:6.8px;letter-spacing:1.7px}

/* ---- top bar ---- */
.top{position:sticky;top:0;z-index:40;backdrop-filter:saturate(1.6) blur(14px);
  background:rgba(var(--bg-rgb),.72);border-bottom:1px solid transparent;transition:border-color .2s}
.top.stuck{border-bottom-color:var(--line)}
.top .wrap{display:flex;align-items:center;gap:26px;height:92px}
.topnav{display:flex;gap:34px;margin:0 auto;font-size:14.5px;color:var(--ink)}
.topnav a{padding:6px 0;border-bottom:1.5px solid transparent}
.topnav a:hover{border-bottom-color:var(--brass)}
.topnav a[aria-current]{border-bottom-color:var(--ink)}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;
  height:50px;padding:0 30px;border-radius:999px;background:var(--accent);color:var(--on-accent);
  font-size:15px;font-weight:600;letter-spacing:.2px;white-space:nowrap;
  box-shadow:0 1px 2px rgba(20,27,42,.16);transition:transform .15s,box-shadow .15s}
.btn:hover{transform:translateY(-1px);box-shadow:0 6px 18px rgba(20,27,42,.2)}
.btn.ghost{background:transparent;color:var(--ink);border:1px solid var(--line);box-shadow:none}
.btn.ghost:hover{border-color:var(--ink);box-shadow:none}
.btn.sm{height:44px;padding:0 24px;font-size:14px}

/* ---- the hero ---- */
.hero{position:relative;overflow:hidden;isolation:isolate}
.hero .wrap{position:relative;z-index:2;display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1.05fr) auto;
  align-items:center;gap:40px;padding-top:56px;padding-bottom:0;min-height:640px}
.hero-copy{max-width:38rem}
.hero h1{margin-bottom:26px}
/* ONE PARAGRAPH OR SEVERAL, WITHOUT EDITING THIS AGAIN. A single 34px bottom
   margin was written when the lede was one paragraph; a three-paragraph draft
   then put three button-sized gaps inside one thought. The 34px belongs
   between the LAST line and the buttons, and any paragraphs above it take an
   ordinary interval. With the lede back to one, both rules land on the same
   element and the spacing is what it always was. */
.hero .lede{margin-bottom:17px}
.hero .lede:last-of-type{margin-bottom:34px}
.hero-acts{display:flex;gap:14px;flex-wrap:wrap}

/* THE DEMONSTRATION LINE, under the buttons rather than beside them. A third
   button splits one click three ways at the moment you most want one of them
   to win; a line of text is read after the pair has been considered, which is
   the order it deserves. Brass, because it is the one link on the page that
   leads somewhere nobody has to sign in to reach. */
/* THE INVITATION TO CHECK, where the claim is made rather than where it is
   sold. It was also under the hero buttons for a few hours and is not any
   more: the demonstration opens on a NULL result, which reads as integrity to
   somebody who has just read the method and as a broken product to somebody
   who has just read a headline. Science earns it; the hero does not.

   UNDERLINED ON HOVER ONLY, which is what .topnav already does. A rule under
   it at rest was drawn edge to edge on whichever line happened to fill. */
.check{margin:26px 0 0;font-size:15px;line-height:1.6}
.check a{color:var(--brass);text-decoration:none;
  border-bottom:1px solid transparent;transition:border-color .15s}
.check a:hover{border-bottom-color:var(--brass)}

/* The sky behind it. NOT the app's photograph: that is a rocky seascape with
   hard shapes filling the frame, and grading it warm produced sepia while
   grading it split-toned produced something cold. tools/hero-plate.py builds
   the light instead — a low bronze sun off the upper right — and uses the
   photograph only for texture, blurred past recognition. The plate is already
   high-key, so the mask here only has to clear the left for the serif. */
.sky{position:absolute;inset:0;z-index:0;pointer-events:none}
.sky .coast{position:absolute;inset:0;
  background:url('/site/hero-sky.jpg') 58% 46% / cover no-repeat;opacity:.88;
  -webkit-mask-image:linear-gradient(96deg,transparent 2%,rgba(0,0,0,.22) 20%,
    rgba(0,0,0,.66) 40%,#000 62%);
  mask-image:linear-gradient(96deg,transparent 2%,rgba(0,0,0,.22) 20%,
    rgba(0,0,0,.66) 40%,#000 62%)}
/* THE SUN DOES NOT MOVE. Both plates come from one recipe and one low sun off
   the upper right — tools/hero-plate.py, with and without --night — because
   the page's layout is arranged around where that light falls. Only the plate
   changes here: the mask, the position and the crop are the rule above's and
   stay there, so the two can never drift apart. */
:root[data-theme="dark"] .sky .coast{
  background-image:url('/site/hero-sky-night.jpg');opacity:1}
.sky .glow{position:absolute;right:-11%;top:-16%;width:min(760px,52vw);aspect-ratio:1;
  background:url('/saturn.png') center/contain no-repeat;opacity:.3;
  filter:blur(1.1px) grayscale(.55) brightness(1.5) contrast(.82)}
.sky .wash{position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(var(--bg-rgb),.5) 0%,rgba(var(--bg-rgb),0) 26%,
      rgba(var(--bg-rgb),0) 66%,rgba(var(--bg-rgb),.9) 98%),
    radial-gradient(112% 86% at 6% 50%,rgba(var(--bg-rgb),.8) 0%,rgba(var(--bg-rgb),0) 56%)}

/* ---- the phones, angled, as a pair ---- */
.rig{position:relative;justify-self:center;perspective:1700px;width:452px;
  padding:46px 0 0;transform-style:preserve-3d}
.rig .device{position:relative;width:300px;border-radius:44px;padding:11px;
  background:linear-gradient(152deg,#3b4358 0%,#171d2b 38%,#0b0f18 100%);
  box-shadow:0 3px 8px rgba(11,15,24,.3),0 40px 90px rgba(11,15,24,.42);
  transform:rotateY(-15deg) rotateX(4deg) rotateZ(-1deg)}
.rig .device::after{content:'';position:absolute;top:11px;left:50%;transform:translateX(-50%);
  width:96px;height:26px;border-radius:0 0 16px 16px;background:#0b0f18;z-index:2}
.rig .device img{display:block;width:100%;height:auto;border-radius:34px}
.rig .device.back{position:absolute;left:188px;top:0;width:264px;z-index:-1;
  transform:rotateY(-15deg) rotateX(4deg) translateZ(-70px) translateY(34px);
  filter:saturate(.96) brightness(1.01)}
.rig .device.back::after{width:84px;height:23px}

/* ---- the section rail, set vertically down the right ---- */
.rail{display:flex;flex-direction:column;gap:15px;padding-left:26px;font-size:10.5px;
  letter-spacing:2.6px;text-transform:uppercase;color:var(--ink);text-align:right;
  align-self:center;text-shadow:0 1px 12px rgba(253,250,244,.98),0 0 4px rgba(253,250,244,.95)}
.rail a{opacity:.62;transition:opacity .15s}
.rail a:hover{opacity:1}
.rail i{display:block;width:44px;height:1px;background:rgba(19,26,40,.28);margin:8px 0 0 auto;font-style:normal}

/* ---- the four marks ---- */
.marks{position:relative;z-index:2;border-top:1px solid var(--line);background:var(--bg)}
.marks .wrap{display:grid;grid-template-columns:repeat(4,1fr);padding-top:48px;padding-bottom:52px}
.mark{text-align:center;padding:0 22px;border-left:1px solid var(--line)}
.mark:first-child{border-left:0}
.mark svg{display:block;margin:0 auto 20px;color:var(--ink)}
.mark b{display:block;font-size:10.5px;letter-spacing:2.6px;text-transform:uppercase;
  font-weight:600;color:var(--ink);margin-bottom:12px}
.mark p{margin:0;font-family:var(--serif);font-size:17px;line-height:1.45;color:var(--muted)}

/* ---- ordinary sections ---- */
section{padding:clamp(64px,7vw,104px) 0}
section.tint{background:var(--bg2)}
.split{display:grid;grid-template-columns:1fr 1fr;gap:clamp(36px,5vw,84px);align-items:center}
.split.flip .copy{order:2}
.narrow{max-width:760px}
.centre{text-align:center;margin-left:auto;margin-right:auto}
.centre .lede{margin-left:auto;margin-right:auto}

.frame{width:100%;max-width:300px;border-radius:42px;padding:10px;margin:0 auto;
  background:linear-gradient(152deg,#3b4358,#171d2b 38%,#0b0f18);box-shadow:var(--lift)}
.frame img{display:block;width:100%;height:auto;border-radius:33px}

/* A REFERENCE LIST HANGS, which is the one piece of typography that makes a
   list of sources readable: the author's surname sits proud of the wrapped
   lines, so the eye runs down a column of names instead of a wall. No numbers
   and no bullets — an ordered list is the right ELEMENT because the order is
   alphabetical and meaningful, but a reference does not want a marker in front
   of the name it is sorted by. */
/* NUMBERED, BECAUSE SOMETHING POINTS AT IT. The list was set APA-style with
   no numerals, which is correct for a bibliography and wrong the moment a
   superscript in the prose above says "2": a reader following it lands on an
   entry with nothing to confirm they arrived. The counter puts the numeral in
   the hanging indent the citation already reserves, so nothing shifts. */
.refs{list-style:none;padding:0;margin:14px 0 0;counter-reset:ref}
.refs li{counter-increment:ref;padding-left:1.7em;text-indent:-1.7em;margin:0 0 .7em;line-height:1.55}
.refs li::before{content:counter(ref) ". ";color:var(--muted)}
.refs li:last-child{margin-bottom:0}
.refs li:target::before{color:var(--ink)}
/* A SOURCE YOU CAN GO AND READ. Links on this site are color:inherit and
   text-decoration:none, which is right for navigation and wrong here: a
   reference whose whole point is that somebody can check it has to look like
   something you can click. Underlined in the hairline colour, picking up to
   full strength on hover. */
.refs a{text-decoration:underline;text-decoration-thickness:1px;
  text-underline-offset:3px;text-decoration-color:var(--line)}
.refs a:hover{text-decoration-color:currentColor}

/* WHAT EACH SOURCE IS FOR. A list of books is a bibliography; a list that says
   which claim each book answers is a reference list, and only the second lets
   somebody check one sentence without reading all three. Set smaller and
   muted, on its own line, so it reads as an annotation rather than part of the
   citation. */
.refs .for{display:block;margin-top:.3em;font-size:.88em;color:var(--muted);text-indent:0}

/* THE SUPERSCRIPT THAT POINTS DOWN AT IT. Small, raised, and a real link —
   browsers open a <details> when a fragment inside it is navigated to, so the
   disclosure unfolds and scrolls to the entry. Where that is not supported the
   link still lands on the disclosure, which is the honest degradation.
   line-height:0 keeps the raised digit from pushing the paragraph's lines
   apart, which is the usual way a superscript ruins the prose it annotates. */
.cite{font-size:.62em;line-height:0;vertical-align:super;margin-left:.15em;
  color:var(--muted);text-decoration:none}
.cite + .cite{margin-left:.2em}
.cite:hover{color:var(--ink)}

.points{list-style:none;padding:0;margin:0}
.points li{padding:16px 0;border-top:1px solid var(--line);display:grid;
  grid-template-columns:104px 1fr;gap:18px;align-items:baseline}
.points li b{font-size:10.5px;letter-spacing:2.2px;text-transform:uppercase;color:var(--ink)}
.points li span{color:var(--muted)}

.stat{display:grid;grid-template-columns:repeat(4,1fr);border:1px solid var(--line);
  border-radius:16px;background:var(--card);overflow:hidden;margin:28px 0 14px}
.stat div{padding:20px 12px;text-align:center;border-left:1px solid var(--line)}
.stat div:first-child{border-left:0}
.stat b{display:block;font-family:var(--serif);font-size:27px;line-height:1;margin-bottom:7px}
.stat b.good{color:var(--good)}
.stat span{font-size:11.5px;letter-spacing:.4px;color:var(--faint)}

.quote{font-family:var(--serif);font-size:clamp(21px,2.3vw,28px);line-height:1.38;
  color:var(--ink);border-left:2px solid var(--brass);padding-left:22px;margin:0 0 26px}
/* the same voice, centred — a closing refrain has nothing to sit against, and
   a left rule under a centred heading reads as a stray mark. */
.centre-quote{border-left:0;padding-left:0;text-align:center;margin:30px auto 28px}

/* the three words the reader actually marks a month with, set as the app sets
   them rather than buried in a sentence */
.scale{font-size:12.5px;letter-spacing:2.6px;text-transform:uppercase;color:var(--ink);
  margin:22px 0}

.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(304px,1fr));gap:22px;margin-top:40px}
.card{background:var(--card);border:1px solid var(--line);border-radius:18px;padding:28px 26px}
.card h3{margin-bottom:10px}
.card p{margin:0;color:var(--muted);font-size:15.5px;line-height:1.62}

/* ---- a disclosure, for detail that would otherwise turn the page into a
   journal article. The citation is a CC BY condition, so it stays in the
   document and one click away — it just does not have to be the loudest thing
   in the section. */
details.method{margin-top:18px;border-top:1px solid var(--line);padding-top:14px}
details.method summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;
  gap:8px;font-size:11px;letter-spacing:2.2px;text-transform:uppercase;color:var(--muted)}
details.method summary::-webkit-details-marker{display:none}
details.method summary::after{content:"\2192";letter-spacing:0;transition:transform .2s}
details.method summary:hover{color:var(--ink)}
details.method[open] summary::after{transform:rotate(90deg)}
details.method .fine{margin-top:14px}

.cta{text-align:center}
.cta h2{margin-bottom:22px}

/* ---- foot ---- */
footer{border-top:1px solid var(--line);background:var(--bg);padding:38px 0 46px}
.fin{display:flex;align-items:center;gap:30px;flex-wrap:wrap}
.finnav{display:flex;gap:26px;margin-left:auto;font-size:14px;color:var(--muted)}
.finnav a:hover{color:var(--ink)}
footer .fine{margin:26px 0 0;max-width:62em}

/* ---- narrower ---- */
@media(max-width:1180px){
  .rail{display:none}
  .hero .wrap{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .rig{width:auto}
  .rig .device{width:264px}
  .rig .device.back{display:none}
}
@media(max-width:900px){
  .top .wrap{height:76px;gap:14px}
  /* the strapline is a second voice under the wordmark: at phone width the
     header has room for one, and the line is the hero's eyebrow anyway. */
  .top .lockup .strap{display:none}
  .top .lockup img{width:132px}
  /* the nav is gone at this width, and it was the nav's auto margins that held
     Get Astrum against the right gutter. Without them a narrow lockup lets the
     button drift into the middle of the bar. */
  .top .btn{margin-left:auto}
  /* Only the first of them takes the auto margin, or the pair is pushed apart
     to opposite ends of the bar. */
  .top .btn ~ .btn{margin-left:0}
  .topnav{display:none}
  .hero .wrap{grid-template-columns:1fr;min-height:0;padding-bottom:0;gap:8px}
  .hero-copy{max-width:none}
  .rig{padding:26px 0 0;justify-self:start;perspective:1200px}
  .rig .device.back{display:none}
  .rig .device{width:min(300px,78vw);transform:rotateY(-11deg) rotateX(3deg)}
  .sky .coast{width:100%;
    -webkit-mask-image:linear-gradient(170deg,transparent 0%,rgba(0,0,0,.3) 30%,#000 72%);
    mask-image:linear-gradient(170deg,transparent 0%,rgba(0,0,0,.3) 30%,#000 72%)}
  /* the planet is a wide-screen flourish: at phone width it clips to a grey
     lens that reads as a rendering fault, so it is not drawn at all. */
  .sky .glow{display:none}
  .marks .wrap{grid-template-columns:1fr 1fr;gap:34px 0;padding-top:40px;padding-bottom:42px}
  .mark:nth-child(odd){border-left:0}
  .split{grid-template-columns:1fr}
  .split.flip .copy{order:0}
  .stat{grid-template-columns:1fr 1fr}
  .stat div:nth-child(3){border-left:0}
  .stat div:nth-child(n+3){border-top:1px solid var(--line)}
  .finnav{margin-left:0;width:100%}
}

/* A band can carry more than one screen. Three phones at 300px each will not
   fit the column, so a group scales its frames down together and lets the
   bezel radius come down with them — a 42px radius on a 150px phone reads as
   a lozenge. The middle one sits proud so the group is a group and not a
   filmstrip. */
/* ARRANGED, NOT LINED UP. Three phones standing to attention in a row is a
   spec sheet. These overlap and lean: one face on and forward, the others
   turned a few degrees behind it so you catch part of a screen rather than
   all of one — which is what makes a group read as a group.

   The lean is small on purpose. Past about eight degrees a phone stops
   looking placed and starts looking dropped. */
.frames{display:flex;justify-content:center;align-items:center;gap:0;padding:34px 0 26px}
.frames .frame{max-width:none;min-width:0;margin:0;border-radius:26px;padding:6px;
  transform-origin:50% 60%;transition:transform .35s ease}
.frames .frame img{border-radius:20px}

.frames.three .frame{flex:0 0 38%}
.frames.three .frame:nth-child(1){transform:rotate(-7deg) translateY(26px) scale(.9);
  margin-right:-7%;z-index:1}
.frames.three .frame:nth-child(2){transform:translateY(-14px);z-index:3;
  box-shadow:0 26px 60px rgba(11,15,24,.28)}
.frames.three .frame:nth-child(3){transform:rotate(7deg) translateY(26px) scale(.9);
  margin-left:-7%;z-index:2}

/* A PAIR OVERLAPS LESS THAN A FAN. Three phones can hide each other's edges
   because the group is the subject. Two cannot: at -9% the front phone was
   covering the Oracle's probability — the one number that screen exists to
   show — leaving "% MODERATE CONFIDENCE" with nothing in front of it. */
.frames.two{gap:clamp(10px,1.4vw,20px)}
.frames.two .frame{flex:0 0 45%}
.frames.two .frame:nth-child(1){transform:rotate(-4deg) translateY(12px);z-index:2;
  box-shadow:0 26px 60px rgba(11,15,24,.28)}
.frames.two .frame:nth-child(2){transform:rotate(5deg) translateY(-18px) scale(.96);z-index:1}

/* The front phone comes level when the group is hovered — a small reward for
   looking, and it lets someone read the screen they were leaning in at. */
@media (hover:hover){
  .frames.three:hover .frame:nth-child(1){transform:rotate(-9deg) translateY(30px) scale(.9) translateX(-6%)}
  .frames.three:hover .frame:nth-child(3){transform:rotate(9deg) translateY(30px) scale(.9) translateX(6%)}
  .frames.three:hover .frame:nth-child(2){transform:translateY(-22px) scale(1.04)}
  .frames.two:hover .frame:nth-child(1){transform:rotate(-6deg) translateY(10px) scale(1.03)}
  .frames.two:hover .frame:nth-child(2){transform:rotate(6deg) translateY(-22px) scale(.99)}
}
/* On a phone, three phones side by side come out about 110px wide and nothing
   on them can be read — a montage where a screenshot was meant. So the group
   becomes a swipeable row at a size you can actually see, one phone and a
   glimpse of the next, which also says there is more than one without a
   caption saying so. */
@media (max-width:760px){
  /* flex-start, and it is not tidying. `justify-content:center` from the base
     rule survives into here, and a centred flex row that OVERFLOWS pushes its
     content past the left edge into space scrolling cannot reach: scrollLeft
     was 0 while the first phone sat at left:-178px. It looked like the row had
     been scrolled. It had not — that phone was simply gone. */
  .frames{display:flex;justify-content:flex-start;gap:14px;overflow-x:auto;scroll-snap-type:x mandatory;
    -webkit-overflow-scrolling:touch;padding:4px 16px;margin:0 -16px;
    scrollbar-width:none}
  .frames::-webkit-scrollbar{display:none}
  .frames .frame{flex:0 0 68%;scroll-snap-align:start;border-radius:30px;padding:7px}
  .frames .frame img{border-radius:23px}
  /* Flat here, and every child of them: a leaning phone inside a scroller is
     a phone you cannot read, and the arrangement above only works when all
     three are in view at once.

     AND IT HAS TO OUT-SPECIFY THE LEAN, WHICH IT DID NOT. The rotations are
     set on `.frames.two .frame:nth-child(1)` — three classes and a
     pseudo-class — and `.frames .frame` is two classes, so this rule lost
     every time and the phones went on leaning inside the scroller on every
     screen under 760px. The first one sat at left:-25px with the document
     16px wider than the window, so the page scrolled sideways on a phone and
     the lean was the reason. Matched on specificity now; `:nth-child(n)` is
     every child, and this rule comes after them. */
  .frames.two .frame:nth-child(n),
  .frames.three .frame:nth-child(n){transform:none;margin:0;box-shadow:var(--lift)}
  .frames.three .frame,.frames.two .frame{flex:0 0 68%}
}
