/* Project Shift — shared stylesheet for the index and the five book pages.
   Extracted from the inline <style> block so one copy is cached across the site. */

:root{
  --ink: #262C38;
  --paper: #FFFFFF;
  --amber: #F5B23E;
  --amber-2: #FFD68A;
  --amber-wash: #FBEFDA;   /* gold at about 12% over paper */
  --white: #FFFFFF;
  --cyan: #77DDFD;
  --cyan-2: #9CE7FE;       /* hover */
  --cyan-deep: #4B7C91;    /* the settle mid-tone in the mark animation */
  --error: #E4736B;
  --muted-light: #7A7364;
  --line-dark: rgba(227,167,60,0.22);
  --line-light: rgba(27,31,39,0.14);
  --max: 1080px;
  --fr-mark: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20111%20100%22%3E%3Cpath%20fill%3D%22%23fff%22%20fill-rule%3D%22evenodd%22%20d%3D%22M%200%200%20H%20109%20V%2022%20H%2073%20V%2040%20H%2095%20C%20105%2040%20111%2047%20111%2058%20V%2080%20C%20111%2091%20105%20100%2094%20100%20H%2051%20V%2076%20H%2090%20V%2061%20H%2021%20V%20100%20H%200%20Z%20M%2021%2022%20H%2049%20V%2040%20H%2021%20Z%22%2F%3E%3C%2Fsvg%3E");
}

*{ box-sizing:border-box; }
html{ scroll-behavior:smooth; }
body{
  margin:0;
  background: var(--paper);
  color: var(--ink);
  font-family:'Inter',sans-serif;
  font-size:16.5px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}
a{ color:inherit; text-decoration:none; }
.wrap{ max-width:var(--max); margin:0 auto; padding:0 32px; }

h1,h2,h3{
  font-family:'Archivo', sans-serif;
  font-weight:900;
  letter-spacing:-0.01em;
  margin:0;
}
em{
  font-style:normal;
  color: var(--amber);
}
/* the hero is the one place the accent is cyan rather than gold */
.hero h1 em{ color: var(--cyan); }
/* The headline ships as plain text and a script splits it into per-letter spans
   that start hidden. Paint and that script are both gated on the same stylesheets,
   so which one wins is a race — losing it flashed the whole headline for an instant
   before it vanished for the 2.25s lead-in. Hiding it up front removes the race.
   Keyed off html.js so that with no JS at all the headline just stays visible. */
html.js .hero h1{ opacity:0; }
html.js .hero h1.is-split{ opacity:1; }

/* ---------- bands ---------- */
.band{ padding: 90px 0; }
.band--dark{ background: var(--ink); color: var(--white); }
.band--paper{ background: var(--paper); color: var(--ink); }

/* ---------- corner-bracket frame (signature, shared with FocusReport family) ---------- */
.ff{
  position:relative;
  display:inline-block;
  padding: 22px;
  line-height:0;
}
.ff img{
  display:block;
  width:100%;
  height:auto;          /* let the width/height attrs supply the ratio, not a fixed height */
  border-radius:2px;
}
.ff .c{
  position:absolute;
  width:26px; height:26px;
  border-color: var(--amber);
  border-style:solid;
  border-width:0;
}
.ff .tl{ top:0; left:0; border-top-width:3px; border-left-width:3px; }
.ff .tr{ top:0; right:0; border-top-width:3px; border-right-width:3px; }
.ff .bl{ bottom:0; left:0; border-bottom-width:3px; border-left-width:3px; }
.ff .br{ bottom:0; right:0; border-bottom-width:3px; border-right-width:3px; }

/* ---------- header ---------- */
header.topbar{
  position:sticky; top:0; z-index:10;
  background: rgba(27,31,39,0.92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line-dark);
}
.topbar-in{
  max-width:var(--max); margin:0 auto; padding: 18px 32px;
  display:flex; align-items:center; justify-content:space-between;
}
.brand-lock{
  display:flex; align-items:center; gap:12px;
  font-family:'Archivo', sans-serif;
}
.brand-logo{
  width:44px; height:44px;
  border-radius:4px;
  display:block;
}
/* the header carries the wordmark alone; the icon is the animated mark below */
.topbar-in .brand-logo{ display:none; }
.brand-text{
  font-weight:700;
  font-size:26px;
  color: var(--white);
}
nav.auth{ display:flex; align-items:center; gap:14px; }
.nav-sep{ color: var(--amber); font-family:'IBM Plex Mono', monospace; font-size:15px; }
.nav-toggle-input{ display:none; }
.nav-toggle-btn{
  display:none;
  flex-direction:column;
  justify-content:center;
  gap:5px;
  width:28px; height:28px;
  cursor:pointer;
  flex:none;
}
.nav-toggle-btn span{
  display:block;
  width:100%;
  height:2px;
  background: var(--cyan);
  border-radius:1px;
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.nav-toggle-input:checked ~ .nav-toggle-btn span:nth-child(1){ transform: translateY(7px) rotate(45deg); }
.nav-toggle-input:checked ~ .nav-toggle-btn span:nth-child(2){ opacity:0; }
.nav-toggle-input:checked ~ .nav-toggle-btn span:nth-child(3){ transform: translateY(-7px) rotate(-45deg); }
nav.auth a.link{
  font-family:'IBM Plex Mono', monospace;
  font-size:15px;
  letter-spacing:0.08em;
  text-transform:uppercase;
  color: var(--white);
}
nav.auth a.link:hover{ color: var(--amber); }
.btn{
  display:inline-block;
  font-family:'IBM Plex Mono', monospace;
  font-size:15px;
  letter-spacing:0.06em;
  text-transform:uppercase;
  padding: 7px 22px;
  border-radius:3px;
  font-weight:500;
}
.btn--amber{ background: var(--amber); color: var(--ink); }
.btn--amber:hover{ background: var(--amber-2); }

/* ---------- hero ---------- */
.hero .wrap{
  display:grid;
  grid-template-columns: 0.8fr 1.2fr;
  gap: 60px;
  align-items:center;
}
.hero h1{
  font-size: clamp(41px, 5vw, 61px);
  line-height:1.35;
  margin-top: 4px;
}
.hero-sub{
  margin-top:22px;
  max-width: 60ch;
  color: var(--white);
  font-size:17px;
}
.hero-sub + .hero-sub{ margin-top:16px; }

/* ---------- animated hero mark (mobile only; desktop keeps the wordmark) ----------
   Six bars are clipped to the letterform, so however the timing is tuned the last
   frame is the logo exactly. --u is one mask unit in px and must stay a whole
   number: the mask viewBox is 111x100, so an integer unit keeps every bar edge on
   a whole pixel and the mask's own edges land on the same integers. Fractional
   edges make the mask clip some columns and not others, which shows as notching. */
.hero-mark{
  --u:3px;                        /* whole number - see note above */
  display:block;
  position:relative;
  width:calc(var(--u)*111);
  height:calc(var(--u)*100);
  -webkit-mask-image:var(--fr-mark); mask-image:var(--fr-mark);
  -webkit-mask-size:100% 100%;    mask-size:100% 100%;
  -webkit-mask-repeat:no-repeat;  mask-repeat:no-repeat;
}
.hero-mark i{ position:absolute; display:block; background:var(--cyan); }
/* Each bar reaches 2 units BACK under the stroke that arrived before it. Bars that
   merely touch leave a hairline wherever the browser can't put the shared edge on a
   whole device pixel - fractional DPR, or browser zoom off 100% - and that shows as
   a dark line across the mark. The overlap can never be seen, because earlier
   strokes have the higher z-index and the settle darkens the fill rather than
   fading its alpha, so an opaque bar always hides whatever sits beneath it.
   b-top stays exactly 22 tall: anything more and the mask clips it over the counter
   but not over the stem and bridge, which is what caused notching. */
.b-top   { left:calc(var(--u)*0);  top:calc(var(--u)*0);  width:calc(var(--u)*111); height:calc(var(--u)*22); transform-origin:left center;  z-index:6; }
.b-stem  { left:calc(var(--u)*0);  top:calc(var(--u)*20); width:calc(var(--u)*21);  height:calc(var(--u)*80); transform-origin:top center;   z-index:5; }
.b-link  { left:calc(var(--u)*49); top:calc(var(--u)*20); width:calc(var(--u)*24);  height:calc(var(--u)*20); transform-origin:top center;   z-index:5; }
.b-mid   { left:calc(var(--u)*19); top:calc(var(--u)*38); width:calc(var(--u)*92);  height:calc(var(--u)*23); transform-origin:left center;  z-index:4; }
.b-right { left:calc(var(--u)*90); top:calc(var(--u)*59); width:calc(var(--u)*21);  height:calc(var(--u)*17); transform-origin:top center;   z-index:3; }
.b-low   { left:calc(var(--u)*51); top:calc(var(--u)*74); width:calc(var(--u)*60);  height:calc(var(--u)*26); transform-origin:right center; z-index:2; }

.b-top  { animation: fr-growX 900ms cubic-bezier(.3,0,.6,.85)    0ms both, fr-settle 760ms ease-in-out  900ms forwards; }
.b-stem { animation: fr-growY 650ms linear                     900ms both, fr-settle 760ms ease-in-out 1550ms forwards; }
.b-link { animation: fr-growY 150ms linear                     900ms both, fr-settle 760ms ease-in-out 1050ms forwards; }
.b-mid  { animation: fr-growX 750ms linear                     900ms both, fr-settle 760ms ease-in-out 1650ms forwards; }
.b-right{ animation: fr-growY 300ms linear                    1500ms both, fr-settle 760ms ease-in-out 1800ms forwards; }
.b-low  { animation: fr-growX 500ms cubic-bezier(.2,.62,.3,1) 1650ms both, fr-settle 760ms ease-in-out 2150ms forwards; }

@keyframes fr-growX{ from{ transform:scaleX(0); opacity:0; } 22%{ opacity:1; } to{ transform:scaleX(1); opacity:1; } }
@keyframes fr-growY{ from{ transform:scaleY(0); opacity:0; } 22%{ opacity:1; } to{ transform:scaleY(1); opacity:1; } }
/* the settle darkens the fill rather than fading alpha - a translucent bar would
   let the stroke beneath show through as bright notches */
@keyframes fr-settle{ 0%{ background:var(--cyan); } 40%{ background:var(--cyan-deep); } 100%{ background:var(--cyan); } }
@keyframes fr-letter{ from{ opacity:0; } to{ opacity:1; } }
.hero h1 .ch{
  display:inline-block;
  opacity:0;
  animation: fr-letter 340ms ease-out both;      /* fades in place, no movement */
}
.hero-sub{
  opacity:0;
  animation: fr-copy 700ms ease-out 3540ms both; /* as the last letter lands */
}
@keyframes fr-copy{ from{ opacity:0; } to{ opacity:1; } }

/* desktop hero: the mark takes the left column and the wordmark moves across to
   sit above the copy on the right. display:contents flattens the two wrappers so
   all three can be placed on one grid without touching the markup. */
@media (min-width: 861px){
  .hero{ padding-top:44px; }        /* sits the mark up closer to the header */
  /* Two rows: the first is the wordmark's own height, the second takes whatever is
     left. The mark spans both and sets the block's height, so pinning the wordmark
     to the top of row 1 and the copy to the bottom of row 2 makes their outer edges
     line up with the top and bottom of the mark. */
  .hero .wrap{
    grid-template-columns: auto 1fr;
    grid-template-rows: auto 1fr;
    column-gap: 60px;
    row-gap: 0;
    align-items:stretch;
  }
  .hero-copy, .hero-sub-wrap{ display:contents; }
  /* --u:4 makes the mark 444x400, taller than the wordmark+copy stack, so the
     second row has slack for the copy to be pushed down onto the mark's baseline */
  .hero-mark{ --u:4px; grid-column:1; grid-row:1 / span 2; align-self:start; }
  .hero h1{ grid-column:2; grid-row:1; align-self:start; margin:0; }
  .hero-sub{ grid-column:2; grid-row:2; align-self:end; margin:0; }
}

/* ---------- section head ---------- */
.sec-head{ margin-bottom: 20px; }
.sec-title{ font-size: clamp(28px, 3.6vw, 40px); line-height:1.08; }
.sec-lead{
  max-width: 62ch;
  color: var(--cyan);
  font-size: 18.5px;
  margin: 18px 0 0;
}

/* ---------- books ---------- */
.book-row{
  display:grid;
  grid-template-columns: 182px 1fr;
  gap: 30px;
  padding: 34px 0;
  align-items:start;
}
.book-row + .book-row{ border-top:1px solid var(--line-dark); }
.book-row .ff{ padding:12px; }
.book-row .ff .c{ width:18px; height:18px; border-color:var(--cyan); }
.book-row h3{
  font-size:22px;
  font-weight:700;
  font-family:'Archivo', sans-serif;
}
.book-credit{
  font-family:'IBM Plex Mono', monospace;
  font-size:15.5px;
  color: var(--cyan);
  letter-spacing:0.04em;
  margin-top:4px;
}
.book-row p{ margin-top:12px; max-width:62ch; color: var(--white); }
.book-buy{
  display:inline-block;
  margin-top:14px;
  font-family:'IBM Plex Mono', monospace;
  font-size:15px;
  color: var(--cyan);
  border-bottom: 1px solid currentColor;
  padding-bottom:2px;
}
.book-buy:hover{ color: var(--amber-2); }

/* ---------- Bands that slide over one another ----------
   Each band gets a higher z-index than the one before, so a later band always
   rides up over an earlier one. Which edge a band pins to depends on whether it
   fits on screen:

   .hero and #about are shorter than the viewport, so top:0 holds them in place
   while the next band covers them.

   #books is about three viewports tall, so neither plain offset works: top:0
   pins it at its first screenful and strands books 2-5 below the fold, and
   bottom:0 pins it the moment it appears and shows only its tail. The band has
   to hold at (viewport height - band height) — a negative offset that puts its
   bottom edge on the viewport bottom — so the list scrolls through under its
   own steam and only settles once its end is on screen, with #film riding up
   over it from there. CSS cannot read an element's own height, so that offset
   is measured in script and written to --pin; see .is-pinned below. */
.hero{ position:relative; z-index:1; }
#focus-report{ position:relative; z-index:2; }
#books{ position:relative; z-index:3; }
#film{ position:relative; z-index:4; }
#about{ position:relative; z-index:5; }
#contact{ position:relative; z-index:6; }
footer.site-footer{ position:relative; z-index:7; }

/* One rule drives every sliding band. --pin is measured in script as
   min(0, viewport height - band height):

     band shorter than the screen -> 0, so it pins the moment it reaches the top
       and the next band rides straight over it (.hero, #about on desktop)
     band taller than the screen  -> negative, so it scrolls through under its own
       steam and only settles once its end is on screen (#books everywhere, and
       .hero / #about on phones)

   That second case is what previously forced these off on mobile: at top:0 a band
   taller than the phone screen pins at its first screenful and strands everything
   below the fold. Measuring the offset fixes it, so mobile now gets the effect too.
   With no JS nothing is pinned and the page reads as plain stacked bands. */
/* listed per band rather than as a bare .is-pinned: the base rules above are ID
   selectors, which outrank a lone class and would leave these at position:relative */
.hero.is-pinned,
#books.is-pinned,
#about.is-pinned{
  position:sticky;
  top: var(--pin, 0px);
}
/* Phones also hold the Focus Report band so #books rides over it. Desktop leaves
   it in flow — there the band is short enough that pinning it would stall the
   scroll right under the hero. */
@media (max-width: 860px){
  #focus-report.is-pinned{
    position:sticky;
    top: var(--pin, 0px);
  }
}



/* ---------- film ---------- */
.film-grid{ display:grid; grid-template-columns:1fr 1fr; gap:40px; margin-top: 44px; }
.film-card{
  border:1px solid var(--line-light);
  border-radius:4px;
  padding:28px;
}
.film-card h3{ font-size:19px; margin-bottom:12px; }
.film-card p{ color: var(--muted-light); font-size:15px; }
.film-card p + p{ margin-top:12px; }
.film-card .book-buy{ color: var(--amber); }
.yt-embed{
  position:relative;
  width:100%;
  aspect-ratio: 16/9;
  border-radius:3px;
  overflow:hidden;
  margin-bottom:16px;
  background: #000;
}
.yt-embed iframe{
  position:absolute; inset:0;
  width:100%; height:100%;
  border:0;
}
.film-footnote{
  margin-top:14px;
  color: var(--muted-light);
  font-size:15px;
}
.film-footnote a{
  color: var(--amber);
  border-bottom:1px solid currentColor;
  padding-bottom:1px;
}
.film-footnote a:hover{ color: var(--amber-2); }

/* ---------- about ---------- */
.about-grid{
  display:grid;
  grid-template-columns: 221px 1fr;   /* portrait 15% down from 260 */
  gap:44px;
  align-items:start;
}
.about-grid .ff{ padding:12px; }
.about-portrait{ aspect-ratio: 680/762; object-fit:cover; filter: grayscale(1); }
.about-body{ max-width: 64ch; }
.about-heading{
  font-size: clamp(26px, 3.4vw, 38px);
  font-weight:400;
  color:var(--cyan);
  line-height:1.08;
  text-align:left;
  margin:0 0 18px;
}
.network-row--about{
  margin-top:24px;
  padding-top:16px;
  border-top:1px solid var(--line-dark);
}
.network-row--about .network-logo{ opacity:0.92; }
.about-body p{ font-size:16.5px; color: var(--white); }
@media (min-width: 861px){
  .about-body p{ font-size:15.5px; }   /* a point down again, desktop only */
}

/* a wrapping flex row left the last line short and hard against the left edge,
   which read as scattered; an even grid keeps every logo on its own centred cell */
.network-row{
  display:grid;
  grid-template-columns: repeat(6, 1fr);
  align-items:center;
  justify-items:center;
  gap:30px 24px;
  margin-top:38px;
  padding-top:32px;
  border-top:1px solid var(--line-light);
}
.network-logo{
  height:37px;
  width:auto;
  display:block;
  opacity:0.88;
}
.network-logo--boost{ height:46px; }
.network-logo--guild{ height:63px; }
.network-lockup{
  display:flex;
  align-items:center;
  gap:9px;
}
.network-lockup-text{
  font-family:'Archivo', sans-serif;
  font-weight:900;
  font-size:26px;
  letter-spacing:0.01em;
  color: var(--white);
  opacity:0.88;
  line-height:1;
}

/* ---------- contact ---------- */
.contact-wrap{ max-width:560px; margin:0 auto; text-align:center; }
.contact-wrap h2{ font-size:32px; }
.contact-wrap > p{ color: var(--muted-light); margin-top:14px; }
form.contact-form{ text-align:left; margin-top: 34px; }
.row2{ display:grid; grid-template-columns:1fr 1fr; gap:14px; }
form.contact-form input,
form.contact-form textarea{
  width:100%;
  font-family:'Inter', sans-serif;
  font-size:15px;
  padding: 13px 14px;
  border:1px solid var(--line-light);
  border-radius:3px;
  background: var(--white);
  color: var(--ink);
  margin-top: 14px;
  resize:vertical;
}
form.contact-form input::placeholder,
form.contact-form textarea::placeholder{ color: var(--muted-light); }
form.contact-form input:first-child{ margin-top:0; }
form.contact-form button{
  margin-top:18px;
  width:100%;
  background: var(--cyan);
  color: var(--ink);
  border:none;
  padding:14px;
  font-family:'IBM Plex Mono', monospace;
  font-size:13px;
  letter-spacing:0.06em;
  text-transform:uppercase;
  border-radius:3px;
  cursor:pointer;
}
form.contact-form button:hover{ background: var(--cyan-2); }

/* a line break that only applies on small screens */
.mob-break{ display:none; }

/* ---------- FocusReport spotlight ---------- */
/* desktop: the mockup is meant to meet the band below it flush */
#focus-report{ padding-bottom:0; }
.fr-logo-lockup{
  display:flex; align-items:center; gap:14px;
  color: var(--ink);
  font-family:'Archivo', sans-serif;
  font-weight:900;
  font-size: clamp(33px, 4.2vw, 47px);   /* 5pt up */
  width:100%;
  margin-bottom:36px;
}
.fr-logo-lockup svg{ width:1em; height:1em; flex:none; color: var(--amber); }
/* desktop only — mobile sets its own size further down */
@media (min-width: 861px){
  .fr-logo-lockup svg{ width:2em; height:2em; }
}
/* Each corner is one 60-unit path drawn from its own start point, and the four are
   ordered top-left, top-right, bottom-right, bottom-left - so running them in
   sequence sweeps clockwise from the left corner. The dot arrives last. */
.fr-logo-lockup svg path{ stroke-dasharray:60; stroke-dashoffset:60; }
.fr-logo-lockup svg circle{ opacity:0; }
.fr-logo-lockup.is-in svg path{ animation: fr-corner 320ms ease-out both; }
.fr-logo-lockup.is-in svg path:nth-of-type(1){ animation-delay:   0ms; }
.fr-logo-lockup.is-in svg path:nth-of-type(2){ animation-delay: 190ms; }
.fr-logo-lockup.is-in svg path:nth-of-type(3){ animation-delay: 380ms; }
.fr-logo-lockup.is-in svg path:nth-of-type(4){ animation-delay: 570ms; }
.fr-logo-lockup.is-in svg circle{ animation: fr-dot 380ms ease-out 880ms both; }
@keyframes fr-corner{ to{ stroke-dashoffset:0; } }
@keyframes fr-dot{ from{ opacity:0; } to{ opacity:1; } }
/* the name was a &nbsp; before it became two spans — keep it from wrapping */
.fr-lockup-name{ white-space:nowrap; }
.fr-tagrow{
  display:flex; align-items:center; gap:16px;
  margin-bottom:26px;
  flex-wrap:wrap;
}
.fr-badge{
  font-family:'IBM Plex Mono', monospace;
  font-size:13.5px;
  letter-spacing:0.1em;
  text-transform:uppercase;
  color: var(--ink);
  background: var(--amber);
  padding: 9px 16px;
  border-radius:3px;
  font-weight:500;
}
.fr-tag{
  font-family:'IBM Plex Mono', monospace;
  font-size:16px;
  letter-spacing:0.1em;
  text-transform:uppercase;
  color: var(--ink);
}
.fr-spot-grid{
  display:grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: 50px;
  align-items:stretch;
}
/* the one italic word inside the Focus Report headline */
.fr-shift{
  color: var(--amber);
  font-style:italic;
  font-weight:700;
  font-family:'Archivo', sans-serif;
}
.fr-learn-more{
  display:inline-block;
  margin-top:16px;
  color: var(--ink);
}
.fr-copy h3{
  font-size: clamp(28px, 3.6vw, 40px);
  color: var(--amber);
  line-height:1.1;
  letter-spacing:-0.015em;
  font-weight:400;
}
.fr-copy p{
  color: var(--muted-light);
  font-size:16px;
  margin-top:16px;
  max-width: 46ch;
}
.fr-media--stack{
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:space-between;
  overflow:visible;
}
.fr-mockup{
  max-width:100%;
  height:auto;
  display:block;
}
.fr-mockup--laptop{ width:130%; max-width:none; margin: 0 -15%; }
.fr-mockup--mobile{ width:98%; }
.fr-eyebrow-vert{
  font-family:'Archivo', sans-serif;
  font-weight:700;
  font-size:30px;
  letter-spacing:0.01em;
  color: var(--ink);
  text-align:right;
  width:76%;
  margin:0 auto;
  padding: 8px 0;
  line-height:1.9;
}
.fr-eyebrow-italic{ font-style:italic; }
.fr-signup{
  margin-top: 32px;
  padding-bottom: 30px;   /* air under the Learn more link */
}
/* button first, field beneath it, both the same width and joined */
.fr-signup-form{
  display:flex;
  flex-direction:column;
  align-items:stretch;
  gap:0;
  max-width:380px;
}
.fr-signup-form button{ order:-1; border-radius:3px 3px 0 0; }
.fr-signup-form input{
  width:100%;
  min-width:0;
  text-align:center;
  font-family:'Inter', sans-serif;
  font-size:15px;
  padding: 13px 16px;
  /* shorthand first, then the seam: the button sits on top, so this field gives up
     its top border and top corners to join the two into one control */
  border:1px solid var(--line-light);
  border-top:none;
  border-radius:0 0 3px 3px;
  background: var(--white);
  color: var(--ink);
}
.fr-signup-form input::placeholder{ color: var(--muted-light); }
.fr-signup-form button{
  background: var(--cyan);
  color: var(--ink);
  border:none;
  padding: 13px 22px;
  font-family:'IBM Plex Mono', monospace;
  font-size:12.5px;
  letter-spacing:0.05em;
  text-transform:uppercase;
  border-radius:3px;
  cursor:pointer;
  white-space:nowrap;
}
.fr-signup-form button:hover{ background: var(--cyan-2); }

footer.site-footer{ background: var(--ink); color: var(--white); border-top:1px solid var(--line-dark); }
.foot-inner{
  max-width:var(--max); margin:0 auto; padding: 70px 32px 40px;
  display:grid; grid-template-columns: 1.4fr 1fr 1fr; gap:40px;
}
.foot-brand{
  display:flex;
  flex-direction:column;
  justify-content:space-between;
}
.foot-brand p{ margin-top:14px; color:var(--white); font-size:14px; max-width:32ch; }
.foot-col h4{
  font-family:'IBM Plex Mono', monospace;
  font-size:14.5px;
  letter-spacing:0.1em;
  text-transform:uppercase;
  color: var(--amber);
  margin-bottom:16px;
  font-weight:500;
}
.foot-col a{ display:block; font-size:14.5px; color:var(--white); opacity:1; margin-bottom:10px; }
.foot-col a:hover{ color:var(--amber); }
.foot-copyright{
  text-align:left;
  font-family:'IBM Plex Mono', monospace;
  font-size:12px;
  color: var(--white);
  white-space:nowrap;
}

/* spam honeypot — hidden from people, irresistible to bots; Formspree drops
   any submission where _gotcha is filled in */
/* The field rules above are more specific than a lone class, so their width:100%
   was winning and inflating the honeypot to a full-width box — which is what was
   dragging the page sideways and why html had overflow-x:hidden on it. Matching
   their specificity keeps it 1px and the page free of a phantom scroll region. */
form.contact-form input.hp,
form.fr-signup-form input.hp{
  position:absolute;
  width:1px; height:1px;
  margin:-1px; padding:0; border:0;
  clip-path: inset(50%);
  overflow:hidden;
  white-space:nowrap;
  pointer-events:none;
}

/* confirmation shown after a successful fetch submit (see script at end of body) */
.sent-note{
  position:fixed;
  bottom:28px;
  /* left+right with auto margins, not left:50% — that caps shrink-to-fit
     width at half the viewport and wraps the text to a sliver on mobile */
  left:16px; right:16px;
  margin-inline:auto;
  width:fit-content;
  max-width: min(520px, calc(100vw - 32px));
  background: var(--ink);
  color: var(--white);
  border:1px solid var(--amber);
  border-radius:4px;
  padding: 14px 20px;
  font-family:'IBM Plex Mono', monospace;
  font-size:14px;
  line-height:1.45;
  text-align:center;
  box-shadow: 0 8px 28px rgba(0,0,0,0.28);
  z-index:50;
  /* visible is the resting state and the animation only supplies the entrance,
     so the note can never get stuck invisible if animations don't run */
  opacity:1;
  transform: translateY(0);
  animation: sent-note-in .28s ease;
}
.sent-note.is-out{ animation: sent-note-out .3s ease forwards; }
.sent-note.is-error{ border-color:var(--error); }
@keyframes sent-note-in{ from{ opacity:0; transform: translateY(16px); } }
@keyframes sent-note-out{ from{ opacity:1; transform: translateY(0); } to{ opacity:0; transform: translateY(16px); } }
@media (prefers-reduced-motion: reduce){
  .hero h1, .hero-mark i, .hero h1 .ch, .hero-sub{ animation:none !important; opacity:1 !important; transform:none !important; }
  .fr-logo-lockup svg path{ stroke-dashoffset:0 !important; }
  .fr-logo-lockup svg circle{ opacity:1 !important; }
  .sent-note{ animation:none; opacity:1; transform:none; }
  .sent-note.is-out{ animation:none; opacity:0; }
}

@media (max-width: 860px){
  .hero .wrap{ grid-template-columns:1fr; gap:20px; }
  .fr-spot-grid{ grid-template-columns:1fr; }
  .film-grid{ grid-template-columns:1fr; }
  /* cover centred and larger, with the title and copy beneath it */
  .book-row{ grid-template-columns: 1fr; gap:22px; }
  .book-row .ff{ width:220px; margin:0 auto; }
  /* centres the title, credit and the inline-block buy link together */
  .book-row > div:last-child{ text-align:center; }
  /* Explore and Connect sit side by side and stretch to a matching height;
     the logo lockup and copyright drop underneath, spanning both */
  /* Connect gets the wider share so the email addresses don't break mid-word */
  .foot-inner{ grid-template-columns:0.82fr 1.18fr; gap:30px 18px; }
  .foot-col{ order:0; }
  /* :last-child is DOM-based (order doesn't affect it) so this is Connect;
     Explore keeps the inherited left alignment */
  .foot-col:last-child{ text-align:right; }
  .foot-brand{
    order:1;
    grid-column:1 / -1;
    align-items:center;
    text-align:center;
    padding-top:26px;
    border-top:1px solid var(--line-dark);
  }
  .row2{ grid-template-columns:1fr; }
  .band{ padding: 60px 0; }
  .about-grid{ grid-template-columns: 1fr; }

  /* fix: laptop mockup was bleeding 15% past the viewport on each side, causing horizontal scroll */
  .fr-mockup--laptop{ width:100%; max-width:100%; margin:0; }

  /* mobile hero: the icon leaves the header (wordmark stays) and becomes the
     animated mark, centred, with the wordmark and copy arriving beneath it */
  .hero-copy{ display:block; text-align:center; }

  .hero-mark{ --u:2px; margin:0 auto 22px; }

  /* the three words read as one continuous run; the <br>s are desktop-only */
  /* nowrap on a grid child sets its min-content width, which would otherwise push
     the whole wrap past its own gutters and drag the copy out with it */
  .hero .wrap > *{ min-width:0; }
  .hero h1{
    font-weight:400;
    line-height:1.25;
    /* nowrap means the line can't reflow, so it has to be sized to fit: at this
       tracking the word measures about 13x its font-size, and anything wider than
       the column overflows and stops looking centred on narrower phones */
    font-size: min(24px, calc((100vw - 68px) / 13));
    margin:0;
    white-space:nowrap;
    /* tracked out until the word measures the same as the copy beneath it; the
       negative right margin cancels the trailing space after the final letter */
    letter-spacing:.068em;
    margin-right:-.068em;
  }
  .hero h1 br{ display:none; }

  .hero-sub{ text-align:left; }
  .hero{ padding-bottom:26px; }

  /* mobile nav: hamburger + dropdown instead of crammed inline links */
  .topbar-in{ position:relative; flex-wrap:nowrap; }
  /* the checkbox drives the menu with no JS, but display:none took it out of the
     tab order entirely — nobody on a keyboard could open the menu. Clipped rather
     than hidden, so it still focuses and Space still toggles it. */
  .nav-toggle-input{
    display:block;
    position:absolute;
    width:1px; height:1px; margin:-1px;
    clip-path: inset(50%);
    overflow:hidden;
  }
  .nav-toggle-input:focus-visible ~ .nav-toggle-btn{
    outline:2px solid var(--cyan);
    outline-offset:3px;
    border-radius:3px;
  }
  .nav-toggle-btn{ display:flex; }
  nav.auth{
    position:absolute;
    top:100%; left:0; right:0;
    flex-direction:column;
    align-items:stretch;
    gap:0;
    background: var(--ink);
    border-bottom:1px solid var(--line-dark);
    max-height:0;
    overflow:hidden;
    transition: max-height 0.25s ease;
  }
  nav.auth a.link{
    padding:16px 32px;
    border-top:1px solid var(--line-dark);
    text-align:left;
  }
  nav.auth a.btn{
    margin:16px 32px;
    text-align:center;
  }
  .nav-sep{ display:none; }
  .nav-toggle-input:checked ~ nav.auth{ max-height:400px; }

  /* anchor jumps were landing underneath the 74px sticky header */
  #focus-report, #books, #film, #about, #contact{ scroll-margin-top: 84px; }

  /* Focus Report, resequenced for mobile:
       lockup -> phone mockup -> blue headline panel -> copy -> laptop -> signup
     The copy and the mockups live in two separate containers, so display:contents
     flattens both into one column and `order` does the interleaving. Desktop,
     which keeps the two-column grid, is untouched. */
  /* the desktop 50px grid gap becomes a row-gap here and would push every
     item apart — spacing is set per item below instead */
  .fr-spot-grid{ display:flex; flex-direction:column; gap:0; }
  .fr-copy, .fr-media{ display:contents; }

  .fr-tagrow{ display:none; }               /* Coming Soon + "A Project Shift Original" */

  /* icon left, name stacked right, sized so the two lines match the icon height */
  .fr-logo-lockup{
    order:1;
    justify-content:center;
    align-items:center;
    gap:10px;
    font-size:14.1vw;              /* 15% down */
    line-height:1.02;
    /* uses the full screen width rather than the 32px page gutters, so the
       mark can run as large as it will go */
    width:calc(100% + 56px);
    margin:0 -28px 16px;
  }
  .fr-logo-lockup svg{ width:2.04em; height:2.04em; }
  .fr-lockup-name span{ display:block; }
  .fr-mockup--mobile{
    order:2;
    width:100%;
    margin:0;                               /* sits flush on the panel below */
    display:block;
  }
  .mob-break{ display:inline; }
  .fr-copy h3{
    order:3;
    background: var(--ink);
    color: var(--white);          /* the italic "shift" keeps its gold */
    font-size:39px;               /* 5pt up from 32px */
    letter-spacing:0.015em;       /* opened up from the -0.01em heading default */
    line-height:1.06;
    text-align:center;
    /* runs past the page gutters to the full width of the screen */
    width:calc(100% + 64px);
    margin:0 -32px 14px;
    padding: 16px 18px 14px;   /* shallower, and tighter underneath */
    border-radius:0;
  }
  /* first paragraph, then the stacked claims, then the rest */
  .fr-copy p:nth-of-type(1){ order:4; }
  .fr-copy p:nth-of-type(2){ order:7; }
  /* full-bleed past the page gutters so the laptop reads as large as it can */
  .fr-mockup--laptop{
    order:6;
    width:calc(100% + 64px);
    max-width:none;
    margin:0 -32px;
  }
  .fr-signup{ order:8; text-align:center; margin:26px 0 0; }
  .fr-signup-form{ max-width:none; }

  /* portrait 20% down, centred */
  .about-grid .ff{ width:68%; margin:0 auto; }   /* 15% down from 80% */
  .about-heading{
    font-size:29px;               /* 2pt up from 26px */
    font-weight:300;              /* lighter cut of Archivo */
  }

  /* network logos a further 15% down, and pulled up towards the bio */
  .network-logo{ height:28px; }
  .network-logo--boost{ height:35px; }
  .network-logo--guild{ height:48px; }
  .network-lockup-text{ font-size:20px; }
  .network-row--about{ margin-top:12px; padding-top:10px; }
  .network-row{ grid-template-columns: repeat(3, 1fr); gap:26px 18px; }

  /* prose justified, headlines centred */
  .hero-sub,
  .fr-copy p,
  .book-row p,
  .film-card p:not(.film-footnote),
  .about-body p,
  .sec-lead,
  .contact-wrap > p{
    text-align:left;
  }
  .hero h1,
  .sec-title,
  .about-heading,
  .contact-wrap h2{
    text-align:center;
  }

  /* the mockup ran straight into the dark band below it. The signup form is last
     in the stack again, and #books starts climbing the instant this band pins, so
     the bottom padding is what holds the form clear of that edge — enough to read
     and act on, without a dead gap you have to scroll through. */
  #focus-report{ padding-top:64px; padding-bottom:150px; }

  /* 28px card padding on top of 32px page gutters ate a third of the screen */
  .film-card{ padding:16px; }

  /* the video loses its card and runs the full width of the screen */
  .film-card--video{
    border:none;
    padding:0;
    background:none;
  }
  .film-card--video .yt-embed{
    width:calc(100% + 64px);
    margin:0 -32px 14px;
    border-radius:0;
  }

  /* --- 44px hit areas (targets were 23-38px) --- */
  /* keeps the bars 28px wide via border-box, only the hit area grows */
  .nav-toggle-btn{ width:44px; height:44px; padding:8px; }
  .brand-lock{ padding:4px 0; }
  .btn{ padding:12px 22px; }
  .foot-col a{ padding:11px 0; margin-bottom:0; }
  .fr-signup-form button{ padding:14px 22px; }
  /* invisible pad around the link so the underline stays tight to the text */
  .book-buy{ position:relative; }
  .book-buy::after{ content:''; position:absolute; inset:-9px -6px; }

  /* logo lockup and copyright line were touching */
  .foot-brand{ gap:14px; }

  /* was 30px, right-aligned in a 76% box with line-height 1.9 — floated away from
     the mockups it labels and got sliced by the header on the way past */
  .fr-eyebrow-vert{
    order:5;
    font-size:31px;               /* 2pt down again */
    text-align:center;
    line-height:1.1;
    /* solid cyan band running past both screen edges, ink on top — the same
       pairing as the logo, and it clears contrast comfortably */
    background: var(--cyan);
    color: var(--ink);
    width:calc(100% + 64px);
    /* The laptop sits the same distance below the band as the band sits below
       "just the math, shown." Above the box that gap is 30px, not 14 — the
       paragraph's own 16px bottom margin adds to the box's 14px rather than
       collapsing into it, because this is a flex column. So the box carries 30
       underneath to match what the eye sees on top. */
    margin:14px -32px 30px;
    padding: 12px 12px;           /* shallower, to suit the smaller type */
  }
}

/* ============================================================
   Book pages (/books/<slug>/)
   ============================================================ */



/* ---------- book page masthead ---------- */
.bookpage-grid{
  display:grid;
  grid-template-columns: 300px 1fr;
  gap:52px;
  align-items:start;
}
.bookpage-grid .ff{ padding:14px; }
.bookpage-grid .ff .c{ border-color: var(--cyan); }
.bookpage-grid .ff img{ width:100%; }
.bookpage-title{
  font-size: clamp(32px, 4.4vw, 50px);
  line-height:1.06;
  letter-spacing:-0.015em;
}
.bookpage-sub{
  font-family:'Archivo', sans-serif;
  font-weight:400;
  font-size: clamp(19px, 2.2vw, 25px);
  color: var(--cyan);
  line-height:1.2;
  margin-top:12px;
}
.bookpage-byline{
  font-family:'IBM Plex Mono', monospace;
  font-size:15px;
  color: var(--white);
  opacity:0.82;
  margin-top:16px;
  line-height:1.6;
}
.bookpage-actions{ display:flex; align-items:center; gap:18px; flex-wrap:wrap; margin-top:26px; }

/* ---------- book page body ---------- */
.prose{ max-width:68ch; }
.prose p{ margin-top:18px; font-size:17px; }
.prose p:first-child{ margin-top:0; }
.prose h2{
  font-size: clamp(24px, 3vw, 32px);
  margin-top:52px;
  margin-bottom:6px;
}
.prose h2:first-child{ margin-top:0; }
.prose h3{
  font-family:'Archivo', sans-serif;
  font-size:19px;
  font-weight:700;
  margin-top:30px;
}
.band--paper .prose p{ color: var(--muted-light); }
.band--dark .prose p{ color: var(--white); }

/* contributor bios — the scholars are a big part of why these books exist */
.contrib{
  padding:22px 0;
  border-top:1px solid var(--line-light);
}
.contrib h3{ margin-top:0; color: var(--ink); }
.contrib p{ margin-top:8px; }

/* pull quotes from the published praise */
.praise{
  border-left:3px solid var(--amber);
  padding:4px 0 4px 22px;
  margin-top:26px;
  max-width:64ch;
}
.praise p{ font-size:17.5px; line-height:1.5; margin-top:0; }
.praise cite{
  display:block;
  margin-top:10px;
  font-family:'IBM Plex Mono', monospace;
  font-size:13.5px;
  font-style:normal;
  color: var(--muted-light);
}

/* ---------- specs ---------- */
.specs{
  display:grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap:1px;
  background: var(--line-light);
  border:1px solid var(--line-light);
  border-radius:4px;
  overflow:hidden;
  margin-top:26px;
}
.specs div{ background: var(--paper); padding:16px 18px; }
.specs .spec-wide{ grid-column: span 2; }
@media (max-width: 520px){ .specs .spec-wide{ grid-column: auto; } }
.specs dt{
  font-family:'IBM Plex Mono', monospace;
  font-size:12px;
  letter-spacing:0.09em;
  text-transform:uppercase;
  color: var(--amber);
}
.specs dd{ margin:6px 0 0; font-size:15.5px; color: var(--ink); }

/* ---------- more books strip ---------- */
.more-grid{
  display:grid;
  grid-template-columns: repeat(4, 1fr);
  gap:26px;
  margin-top:36px;
}
.more-card img{
  width:100%; height:auto; display:block;
  border-radius:2px;
  border:1px solid var(--line-dark);
}
.more-card h3{
  font-size:15.5px;
  font-weight:700;
  margin-top:12px;
  line-height:1.25;
}
.more-card span{
  display:block;
  font-family:'IBM Plex Mono', monospace;
  font-size:12.5px;
  color: var(--cyan);
  opacity:0.75;
  margin-top:5px;
}
.more-card:hover h3{ color: var(--amber); }

@media (max-width: 860px){
  .bookpage-grid{ grid-template-columns:1fr; gap:26px; }
  .bookpage-grid .ff{ width:230px; margin:0 auto; }
  .bookpage-title, .bookpage-sub, .bookpage-byline{ text-align:center; }
  .bookpage-actions{ justify-content:center; }
  .prose h2{ text-align:center; margin-top:40px; }
  .more-grid{ grid-template-columns: repeat(2, 1fr); gap:20px; }
  .praise{ margin-inline:auto; }
}

/* index book rows now carry two links: through to the book page, and out to Amazon */
.book-links{ display:flex; align-items:center; gap:24px; flex-wrap:wrap; margin-top:14px; }
.book-links .book-buy{ margin-top:0; }
.book-row h3 a{ border-bottom:1px solid transparent; }
.book-row h3 a:hover{ color: var(--amber-2); border-bottom-color: currentColor; }
@media (max-width: 860px){ .book-links{ justify-content:center; } }
