/* johnstoszkowski.com shared styles.
   Extracted from index.html so About and Contact can share one stylesheet
   instead of each carrying a duplicate copy.
   NB url()s resolve against THIS file: fonts are ../fonts/, images are siblings. */

@font-face{font-family:'Instrument Serif';src:url('../fonts/InstrumentSerif-Regular.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Instrument Serif';src:url('../fonts/InstrumentSerif-Italic.woff2') format('woff2');font-weight:400;font-style:italic;font-display:swap}
@font-face{font-family:'Source Serif 4';src:url('../fonts/SourceSerif4-Variable.woff2') format('woff2');font-weight:200 900;font-style:normal;font-display:swap}

/* ============ base ============ */
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box;border:0 solid}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  font-family:'Source Serif 4',Georgia,serif;
  font-weight:300;
  line-height:1.55;
  background:#000;
  color:#fff;
  -webkit-font-smoothing:antialiased;
}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;cursor:pointer}
input,textarea,select{font:inherit;color:inherit}
svg{display:block}
.serif{font-family:'Instrument Serif',serif;font-weight:400}

:focus-visible{outline:2px solid rgba(255,255,255,.7);outline-offset:2px;border-radius:9999px}

::selection{background:#fff;color:#000}
::-moz-selection{background:#fff;color:#000}

/* on-brand scrollbar (default light one is jarring against the black) */
html{scrollbar-color:rgba(255,255,255,.22) #000;scrollbar-width:thin}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:#000}
::-webkit-scrollbar-thumb{background:rgba(255,255,255,.18);border-radius:99px;border:3px solid #000}
::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.3)}

/* let the display face use its proper ligatures and kerning */
h1,h2,h3,.logo,.hero-line{
  text-rendering:optimizeLegibility;
  font-kerning:normal;
  font-feature-settings:"liga" 1,"clig" 1;
}

/* keyboard users land here first */
.skip{
  position:absolute;left:50%;top:0;transform:translate(-50%,-120%);
  z-index:60;background:#fff;color:#000;
  padding:.7rem 1.4rem;border-radius:0 0 .6rem .6rem;
  font-size:.85rem;font-weight:500;
  transition:transform .25s cubic-bezier(.22,1,.36,1);
}
.skip:focus{transform:translate(-50%,0)}

/* inline text links: underline sweeps in on hover */
.textlink{
  position:relative;color:#fff;
  background-image:linear-gradient(currentColor,currentColor);
  background-repeat:no-repeat;
  background-position:0 100%;
  background-size:100% 1px;
  padding-bottom:1px;
  transition:background-size .35s cubic-bezier(.22,1,.36,1),opacity .25s;
}
.textlink:hover{background-size:0% 1px;background-position:100% 100%;opacity:.72}

/* sections sit on solid black */
.about,.creed,.work,.contact,footer{position:relative;background:#000}

/* first-paint entrance */
@keyframes rise{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}
.hero-content h1{animation:rise 1.15s cubic-bezier(.22,1,.36,1) .12s both}
.nav{animation:rise .9s cubic-bezier(.22,1,.36,1) both}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .hero-content h1,.nav{animation:none}
}


/* ============ meme stack ============
   Ported from a pasted framer-motion component. The memes carry text right to
   their edges, so the component's object-cover on a fixed 5/7 card would crop
   the joke: these use object-fit:contain on a white card instead, which also
   reads as a pile of prints. Aspect ratios in the set run 0.8 to 1.46, so the
   card is square and the letterboxing is part of the look. */
.memes{position:relative;background:#000;padding:clamp(3.5rem,9vw,6rem) 1.5rem}
.memes-inner{max-width:64rem;margin:0 auto;display:flex;flex-direction:column;align-items:center}
.memes-head{text-align:center;margin-bottom:clamp(1.8rem,4vw,2.6rem)}
.memes-head h2{
  font-family:'Instrument Serif',serif;font-weight:400;
  font-size:clamp(2.2rem,4.6vw,3.2rem);line-height:1.15;letter-spacing:-.015em;
  margin-bottom:.7rem;
}
.memes-head h2 em{font-style:italic}
.memes-head .sub{color:rgba(255,255,255,.8);max-width:44ch;margin:0 auto}

.stack{
  position:relative;
  width:min(330px,80vw);aspect-ratio:1/1;
  margin:0 auto;
  outline:none;
  /* how far the pile fans. Rotating a square card widens its bounding box by
     w*(cos+sin-1)/2 per side, which on a phone pushed the deepest cards off the
     left edge, so the fan is scaled down rather than the cards being clipped. */
  --fan:1;
}
.stack:focus-visible{box-shadow:0 0 0 2px rgba(255,255,255,.7);border-radius:1rem}
.mcard{
  position:absolute;inset:0;margin:0;
  background:#000;border-radius:.9rem;overflow:hidden;
  /* the card is the page colour so a meme narrower than the square leaves no
     white strip. A hairline is then the only thing separating one card from the
     next, since a black shadow on a black section shows nothing. */
  border:1px solid rgba(255,255,255,.16);
  box-shadow:0 18px 40px -12px rgba(0,0,0,.9);
  /* pan-y keeps vertical page scroll working on a phone: only sideways
     movement is treated as a drag */
  touch-action:pan-y;
  will-change:transform;
  user-select:none;-webkit-user-select:none;
}
.mcard img{
  width:100%;height:100%;display:block;
  object-fit:contain;background:transparent;
  pointer-events:none;-webkit-user-drag:none;
}
.stack .mcard.is-top{cursor:grab}
.stack .mcard.is-top:active{cursor:grabbing}
@media (max-width:640px){
  .stack{width:min(278px,76vw);--fan:.55}
}

/* ============ liquid glass ============ */
.liquid-glass{
  background:rgba(255,255,255,0.01);
  background-blend-mode:luminosity;
  backdrop-filter:blur(4px);
  -webkit-backdrop-filter:blur(4px);
  border:none;
  box-shadow:inset 0 1px 1px rgba(255,255,255,0.1);
  position:relative;
  overflow:hidden;
}
.liquid-glass::before{
  content:'';
  position:absolute;
  inset:0;
  border-radius:inherit;
  padding:1.4px;
  background:linear-gradient(180deg,
    rgba(255,255,255,0.45) 0%,
    rgba(255,255,255,0.2) 20%,
    rgba(255,255,255,0.14) 40%,
    rgba(255,255,255,0.14) 60%,
    rgba(255,255,255,0.2) 80%,
    rgba(255,255,255,0.45) 100%);
  -webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
  -webkit-mask-composite:xor;
  mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
  mask-composite:exclude;
  pointer-events:none;
}

/* ============ hero ============ */
.hero{
  min-height:100svh;
  background:#000;
  position:relative;
}
.hero-stage{
  position:relative;
  min-height:100svh;
  overflow:hidden;
  display:flex;
  flex-direction:column;
}
/* ============ hero photograph ============
   Taller than the stage and hung above it, so the parallax drift always has
   cover to spare: 130lvh at top:-15lvh means translating down by 11.5% of its
   own height (= 15lvh) lands its top edge exactly at the stage top, never
   revealing a gap. The filter does the tonal work rather than a heavier scrim:
   this is a bright daylight photograph going onto a black site, and crushing it
   toward dusk keeps the photo readable where piling on more scrim just muddies
   it. */
.hero-photo{
  position:absolute;left:0;right:0;
  top:-15lvh;height:130lvh;
  z-index:0;pointer-events:none;
  will-change:transform;
}
@supports not (height:1lvh){.hero-photo{top:-15vh;height:130vh}}
.hero-photo img{
  width:100%;height:100%;display:block;
  object-fit:cover;object-position:center 56%;
  filter:brightness(.95) saturate(1.18) contrast(1.0);
}
@media (max-width:700px){
  .hero-photo img{object-position:center 60%;filter:brightness(.9) saturate(1.18) contrast(1.0)}
}
.hero-scrim{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    radial-gradient(44% 28% at 50% 50%,rgba(0,0,0,.32),rgba(0,0,0,0) 74%),
    linear-gradient(180deg,
      rgba(0,0,0,.42) 0%,
      rgba(0,0,0,.04) 22%,
      rgba(0,0,0,.08) 66%,
      rgba(0,0,0,.78) 100%);
}
@media (max-width:640px){
  .hero-scrim{
    background:
      radial-gradient(92% 32% at 50% 48%,rgba(0,0,0,.52),rgba(0,0,0,0) 78%),
      linear-gradient(180deg,
        rgba(0,0,0,.5) 0%,
        rgba(0,0,0,.12) 22%,
        rgba(0,0,0,.2) 64%,
        rgba(0,0,0,.8) 100%);
  }
}

/* nav */
.nav{position:relative;z-index:20;padding:1.5rem}
.nav-inner{
  border-radius:9999px;
  padding:.75rem 1.5rem;
  display:flex;align-items:center;
  /* the masthead is present on interior pages as the way home, and absent on
     the homepage where the h1 already says the name. margin-left:auto on the
     right group handles both without a :has() rule or a second class. */
  justify-content:flex-start;
  max-width:64rem;margin:0 auto;
}
.nav-left{display:flex;align-items:center}
/* masthead: the name tracked in the body face */
.logo{
  font-family:'Source Serif 4',serif;font-weight:600;
  color:#fff;font-size:.84rem;letter-spacing:.24em;text-transform:uppercase;
  display:inline-block;
}
.logo span{white-space:nowrap}
.nav-right{display:flex;align-items:center;gap:1rem;margin-left:auto}
/* the buttons sit back as quiet chrome, so the name leads */
.nav-right .plain{
  font-family:'Source Serif 4',serif;font-weight:600;
  font-size:.68rem;letter-spacing:.18em;text-transform:uppercase;
  color:rgba(255,255,255,.72);transition:color .15s;
}
.nav-right .plain:hover{color:#fff}
.pill{
  border-radius:9999px;
  padding:.62rem 1.35rem;
  font-family:'Source Serif 4',serif;font-weight:600;
  font-size:.68rem;letter-spacing:.18em;text-transform:uppercase;
  color:#fff;
  border:1px solid rgba(255,255,255,.34);   /* one plain ring, no glass, no fill */
  display:inline-block;
  transition:border-color .25s;
}
.pill:hover{border-color:rgba(255,255,255,.6)}
/* ---------- mobile menu ----------
   Same pattern as the Syntropise site: a two-bar button that becomes an X, and
   the link group turns into a full-screen panel sliding down from -100%. It
   replaces the old rule that simply hid the text links on mobile, which left
   About and Contact unreachable on a phone.
   The panel is position:fixed, which on the homepage means it must not sit
   inside a transformed ancestor: .hero-stage is overflow:hidden but carries no
   transform, so the panel escapes the hero correctly. Check this if the hero
   ever gains one. */
.nav-toggle{
  display:none;flex-direction:column;justify-content:center;gap:5px;
  width:34px;height:34px;padding:0;margin-left:auto;
  background:none;border:0;cursor:pointer;position:relative;z-index:60;
}
.nav-toggle span{
  display:block;width:23px;height:1.5px;background:#fff;margin:0 auto;
  transition:transform .4s cubic-bezier(.22,1,.36,1),opacity .3s;
}
.nav.open .nav-toggle span:first-child{transform:translateY(3.25px) rotate(45deg)}
.nav.open .nav-toggle span:last-child{transform:translateY(-3.25px) rotate(-45deg)}

@media (max-width:640px){
  .nav{padding:1rem}
  .nav-inner{padding:.6rem .9rem}
  .logo{font-size:.72rem;letter-spacing:.2em}
  .nav-toggle{display:flex}
  .nav-right{
    position:fixed;inset:0;height:100svh;overflow-y:auto;z-index:50;
    margin-left:0;gap:0;
    flex-direction:column;align-items:stretch;justify-content:flex-start;
    padding:5.6rem 1.6rem 2.6rem;background:#000;
    transform:translateY(-100%);
    transition:transform .55s cubic-bezier(.22,1,.36,1);
  }
  .nav.open .nav-right{transform:translateY(0)}
  .nav-right .plain{
    display:block;width:100%;
    font-family:'Instrument Serif',serif;font-weight:400;
    font-size:1.75rem;letter-spacing:0;text-transform:none;
    color:#fff;padding:1.15rem 0;
    border-top:1px solid rgba(255,255,255,.14);
  }
  .nav-right .plain:first-of-type{border-top:none}
  .nav-right .pill{
    margin-top:1.6rem;text-align:center;
    padding:1rem 1.4rem;font-size:.9rem;
  }
}
/* tracked capitals are wide: on the narrowest phones the masthead and the pill
   would otherwise meet in the middle */
@media (max-width:400px){
  .nav{padding:.9rem .7rem}
  .nav-inner{padding:.55rem .45rem}
  .logo{font-size:.64rem;letter-spacing:.14em}
  .pill{padding:.5rem .95rem;font-size:.62rem;letter-spacing:.14em}
}

/* hero content */
.hero-content{
  position:relative;z-index:10;
  flex:1 1 0%;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:3rem 1.5rem;
  text-align:center;
}
.hero-content h1{
  font-family:'Instrument Serif',serif;
  font-weight:400;
  font-size:clamp(3rem,8.4vw,6rem);
  line-height:1.02;
  color:#fff;
  letter-spacing:-.02em;
  margin-bottom:1.5rem;
  text-wrap:balance;
  text-shadow:0 1px 14px rgba(0,0,0,.7),0 2px 48px rgba(0,0,0,.6);
}
.hero-content h1 em{font-style:italic}
/* the second line sits under the display headline in the body face, so it
   reads as the qualifier rather than competing with it */
.hero-content .hero-line{
  color:rgba(255,255,255,.92);
  font-family:'Source Serif 4',Georgia,serif;font-weight:300;
  font-size:clamp(1.18rem,2.3vw,1.55rem);
  line-height:1.5;
  letter-spacing:.005em;
  max-width:52ch;
  margin:0 auto;
  text-wrap:balance;
  text-shadow:0 1px 12px rgba(0,0,0,.9),0 2px 34px rgba(0,0,0,.8);
}

.scroll-cue{
  position:absolute;left:50%;bottom:1.9rem;transform:translateX(-50%);
  z-index:10;color:rgba(255,255,255,.72);
  animation:cue 2.6s cubic-bezier(.4,0,.2,1) infinite;
}
@keyframes cue{0%,100%{transform:translate(-50%,0);opacity:.55}50%{transform:translate(-50%,7px);opacity:1}}
@media (prefers-reduced-motion:reduce){.scroll-cue{animation:none}}

/* ============ about ============ */
.about{
  padding:7rem 1.5rem 1.5rem;
}
.about-inner{
  max-width:64rem;margin:0 auto;
  display:grid;grid-template-columns:320px 1fr;
  gap:clamp(2.4rem,6vw,4.5rem);
  align-items:center;
}
.about-photo{position:relative;aspect-ratio:4/5}
.about-photo img{
  display:block;width:100%;height:100%;
  object-fit:cover;border-radius:.6rem;
}

.about-copy h2{
  font-family:'Instrument Serif',serif;font-weight:400;
  font-size:clamp(2.2rem,4.6vw,3.2rem);
  line-height:1.15;
  letter-spacing:-.015em;
  margin-bottom:1.3rem;
}
.about-copy h2 em{font-style:italic}
.about-copy p{
  color:rgba(255,255,255,.84);
  font-size:.98rem;line-height:1.75;
  max-width:34rem;
  margin-bottom:1rem;
}
.about-copy p:last-child{margin-bottom:0}
.about-copy b{color:#fff;font-weight:500}
@media (max-width:760px){
  .about{padding-top:5rem}
  .about-inner{grid-template-columns:1fr}
  .about-photo{max-width:300px;margin:0 auto}
  .about-copy{text-align:center}
  .about-copy p{margin-left:auto;margin-right:auto}
}

/* ============ creed ============ */
.creed{
  padding:5rem 1.5rem 1rem;
  text-align:center;
}
.creed-inner{max-width:44rem;margin:0 auto}
.creed .rule{
  display:block;width:44px;height:1px;margin:0 auto 2rem;
  background:rgba(250,161,161,.75);          /* Syntropise coral, as on the card icons */
}
.creed p{
  font-family:'Instrument Serif',serif;font-weight:400;
  font-size:clamp(1.5rem,3.4vw,2.35rem);
  line-height:1.32;
  letter-spacing:-.01em;
  color:rgba(255,255,255,.94);
  text-wrap:balance;
}
.creed p em{font-style:italic}
@media (max-width:760px){.creed{padding-top:4rem}}

/* ============ the work ============ */
.work{
  position:relative;
  padding:7rem 1.5rem 5rem;
}
.work-inner{max-width:64rem;margin:0 auto}
.work-head{margin-bottom:3.2rem;text-align:center}
.work-head .kicker{
  font-size:.78rem;font-weight:600;letter-spacing:.28em;text-transform:uppercase;
  color:rgba(255,255,255,.62);
  display:block;margin-bottom:1rem;
}
.work-head h2{
  font-family:'Instrument Serif',serif;font-weight:400;
  font-size:clamp(2.2rem,5vw,3.4rem);
  line-height:1.15;
  letter-spacing:-.015em;
}
.work-head h2 em{font-style:italic}
.cards{
  display:grid;grid-template-columns:repeat(2,1fr);gap:1.1rem;
}
@media (max-width:760px){.cards{grid-template-columns:1fr}}
.card{
  border-radius:1.4rem;
  padding:1.9rem 2rem 1.8rem;
  display:flex;flex-direction:column;gap:.55rem;
  transition:background-color .25s cubic-bezier(.4,0,.2,1),transform .35s cubic-bezier(.4,0,.2,1);
  --mx:50%;--my:50%;
}
.card:hover{background-color:rgba(255,255,255,.05);transform:translateY(-3px)}
.card::after{
  content:'';position:absolute;inset:0;z-index:0;
  border-radius:inherit;pointer-events:none;
  background:radial-gradient(360px circle at var(--mx) var(--my),rgba(255,255,255,.16),transparent 68%);
  opacity:0;transition:opacity .4s ease;
}
.card:hover::after{opacity:1}
.card>*{position:relative;z-index:1}
.card .cicon{
  color:rgba(250,161,161,.82);          /* Syntropise coral */
  margin-bottom:.35rem;
  transition:color .35s cubic-bezier(.4,0,.2,1),transform .5s cubic-bezier(.22,1,.36,1);
}
.card:hover .cicon{color:#faa1a1;transform:translateY(-2px)}
.card .title-row{display:flex;align-items:baseline;justify-content:space-between;gap:1rem}
.card h3{
  font-family:'Instrument Serif',serif;font-weight:400;
  font-size:1.85rem;line-height:1.2;letter-spacing:-.01em;color:#fff;
}
.card .arrow{
  color:rgba(255,255,255,.62);flex:none;align-self:center;
  transition:color .2s,transform .35s cubic-bezier(.4,0,.2,1);
}
.card:hover .arrow{color:#fff;transform:translate(3px,-3px)}
.card p{color:rgba(255,255,255,.82);font-size:.94rem;line-height:1.65}

/* ---- carousel (JS-enhanced; without .is-live the cards stay the plain grid) ---- */
.cards.is-live{
  display:block;position:relative;
  width:100vw;margin-left:calc(50% - 50vw);   /* full-bleed so the arc has room */
  height:var(--stage-h,420px);
  overflow:hidden;
  touch-action:pan-y;
}
.cards.is-live .card{
  position:absolute;left:50%;top:50%;
  width:var(--card-w,330px);
  height:var(--card-h,280px);
  margin:0;
  transform-origin:center center;
  transition:transform .65s cubic-bezier(.22,1,.36,1),
             opacity .65s cubic-bezier(.22,1,.36,1),
             background-color .25s cubic-bezier(.4,0,.2,1);
  will-change:transform,opacity;
}
.cards.is-live .card:hover{transform:none}   /* the JS transform owns position */
/* only the card at the front gets the cursor spotlight */
.cards.is-live .card:hover::after{opacity:0}
.cards.is-live .card.is-front:hover::after{opacity:1}
.cards.is-live.is-drag{cursor:grabbing}

.carou-ctrl{
  display:flex;align-items:center;justify-content:center;gap:1rem;
  margin-top:2.6rem;
}
.carou-arrow{
  width:2.6rem;height:2.6rem;border-radius:9999px;
  display:flex;align-items:center;justify-content:center;
  color:rgba(255,255,255,.7);
  transition:color .2s,background-color .2s,transform .3s cubic-bezier(.22,1,.36,1);
}
.carou-arrow:hover{color:#fff;background-color:rgba(255,255,255,.06);transform:scale(1.08)}
.carou-arrow:active{transform:scale(.95)}
.carou-dots{display:flex;align-items:center;gap:.42rem}
.carou-dot{
  height:6px;width:6px;border-radius:9999px;
  background:rgba(255,255,255,.22);
  transition:width .35s cubic-bezier(.22,1,.36,1),background-color .3s;
}
.carou-dot:hover{background:rgba(255,255,255,.45)}
.carou-dot.on{width:26px;background:rgba(250,161,161,.9)}   /* Syntropise coral */
@media (max-width:760px){
  .carou-ctrl{margin-top:2rem}
}

/* ============ contact ============ */
.contact{
  padding:5rem 1.5rem 4rem;
  text-align:center;
}
.contact h2{
  font-family:'Instrument Serif',serif;font-weight:400;
  font-size:clamp(2rem,4.6vw,3rem);
  line-height:1.15;
  letter-spacing:-.015em;
  margin-bottom:1rem;
}
.contact h2 em{font-style:italic}
.contact .sub{color:rgba(255,255,255,.8);font-size:.98rem;max-width:30rem;margin:0 auto 2.2rem;line-height:1.7}

/* ---- contact form ---- */
.c-form{max-width:32rem;margin:0 auto;text-align:left}
.c-field{margin-bottom:1.5rem}
.c-field label{
  display:block;font-size:.72rem;font-weight:600;letter-spacing:.22em;text-transform:uppercase;
  color:rgba(255,255,255,.66);margin-bottom:.7rem;
}
.c-field input,.c-field textarea{
  width:100%;
  background:rgba(255,255,255,.03);
  border:1px solid rgba(255,255,255,.14);
  border-radius:.6rem;
  padding:1rem 1.1rem;
  color:#fff;
  font-size:1.05rem;
  transition:border-color .25s,background-color .25s;
}
.c-field input::placeholder,.c-field textarea::placeholder{color:rgba(255,255,255,.52)}
.c-field input:focus,.c-field textarea:focus{
  outline:none;border-color:rgba(255,255,255,.4);background:rgba(255,255,255,.05);
}
.c-field textarea{min-height:9rem;resize:vertical;line-height:1.6}
.c-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
/* the primary action: same tracked chrome as the nav buttons, sized up a step */
.contact .c-submit{
  font-size:.78rem;letter-spacing:.18em;
  padding:.95rem 2.5rem;
  border:1px solid rgba(255,255,255,.34);
  border-radius:9999px;
  transition:border-color .25s,background-color .25s cubic-bezier(.4,0,.2,1),transform .3s cubic-bezier(.4,0,.2,1);
}
.contact .c-submit:hover{
  transform:translateY(-1px);
  border-color:rgba(255,255,255,.6);
  background-color:rgba(255,255,255,.06);
}
.c-note{
  margin-top:1.1rem;font-size:.85rem;color:rgba(255,255,255,.7);
  min-height:1.3em;
}
.c-note.is-ok{color:rgba(255,255,255,.85)}
.c-note.is-err{color:rgba(255,120,120,.85)}
.c-or{
  margin:2.8rem auto 0;max-width:32rem;
  padding-top:2.2rem;border-top:1px solid rgba(255,255,255,.1);
  font-size:.85rem;color:rgba(255,255,255,.68);letter-spacing:.02em;
}

/* ============ footer ============ */
.socials{
  display:flex;justify-content:center;gap:1rem;
  padding:2.5rem 1.5rem 1.6rem;
}
.socials a{
  border-radius:9999px;padding:1rem;
  color:rgba(255,255,255,.9);
  display:flex;align-items:center;justify-content:center;
  transition:color .15s cubic-bezier(.4,0,.2,1),background-color .15s cubic-bezier(.4,0,.2,1);
}
.socials a:hover{color:#fff;background-color:rgba(255,255,255,.05)}
.copyright{
  text-align:center;color:rgba(255,255,255,.55);
  font-size:.78rem;letter-spacing:.06em;
  padding:0 1.5rem 2.4rem;
}

/* reveal */
.reveal{opacity:0;transform:translateY(20px);transition:opacity .9s cubic-bezier(.22,1,.36,1),transform .9s cubic-bezier(.22,1,.36,1)}
.reveal.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none;transition:none}}

/* ============ books ============ */
.books{position:relative;background:#000;padding:clamp(3.5rem,9vw,6rem) 1.5rem}
.books-inner{max-width:64rem;margin:0 auto}
.books-head{text-align:center;margin-bottom:clamp(2.4rem,6vw,3.6rem)}
.books-head h2{
  font-family:'Instrument Serif',serif;font-weight:400;
  font-size:clamp(2.2rem,4.6vw,3.2rem);line-height:1.15;letter-spacing:-.015em;
  margin-bottom:.7rem;
}
.books-head h2 em{font-style:italic}
.books-head .sub{color:rgba(255,255,255,.8);max-width:46ch;margin:0 auto}
.book-grid{
  display:grid;grid-template-columns:repeat(3,1fr);
  gap:clamp(1.6rem,4vw,3rem);align-items:start;
}
.book{display:flex;flex-direction:column}
.book-cover{
  position:relative;display:block;
  border-radius:.4rem;overflow:hidden;
  box-shadow:0 22px 44px -16px rgba(0,0,0,.9);
  /* the covers are photographic and go right to the edge, so a hairline keeps
     the darker ones from bleeding into the black page */
  outline:1px solid rgba(255,255,255,.14);outline-offset:-1px;
  transition:transform .45s cubic-bezier(.22,1,.36,1),box-shadow .45s;
}
.book-cover img{display:block;width:100%;height:auto;aspect-ratio:900/1436;object-fit:cover}
.book:hover .book-cover{transform:translateY(-6px);box-shadow:0 30px 56px -16px rgba(0,0,0,.95)}
.book h3{
  font-family:'Instrument Serif',serif;font-weight:400;
  font-size:clamp(1.35rem,2.4vw,1.7rem);line-height:1.2;
  margin:1.5rem 0 .35rem;
}
.book .byline{
  font-size:.7rem;letter-spacing:.2em;text-transform:uppercase;
  color:rgba(255,255,255,.6);margin-bottom:.9rem;display:block;
}
.book .byline .flag{color:#f0b8a8}
.book p{color:rgba(255,255,255,.82);font-size:1rem;line-height:1.62}
@media (max-width:860px){
  /* one column width for books, essays and mixes so the page keeps one rhythm.
     The covers used to be capped at 16rem here, which was a guard against a
     2:3 portrait going full width, but it left the books visibly smaller than
     everything around them and reading as the least important thing on the
     page. They are the most important, so they get the same column. */
  .book-grid{grid-template-columns:1fr;gap:clamp(2.6rem,7vw,3.4rem);max-width:30rem;margin:0 auto}
}

/* ============ the reading room (1-2-1) ============ */
.rooms{position:relative;background:#000;padding:clamp(3.5rem,9vw,6rem) 1.5rem}
.rooms-inner{max-width:56rem;margin:0 auto;text-align:center}
.rooms h2{
  font-family:'Instrument Serif',serif;font-weight:400;
  font-size:clamp(2.2rem,4.6vw,3.2rem);line-height:1.15;letter-spacing:-.015em;
  margin-bottom:1.2rem;
}
.rooms h2 em{font-style:italic}
.rooms p{color:rgba(255,255,255,.84);max-width:52ch;margin:0 auto 1.1rem;font-size:1.06rem;line-height:1.68}
.rooms .rooms-note{color:rgba(255,255,255,.62);font-size:.95rem}
.rooms .rooms-cta{margin-top:2rem}

/* ============ interior pages ============
   About and Contact do not get the photographic hero: it belongs to the
   homepage and repeating it would flatten the difference between them. They get
   a quiet type-only header on black instead. */
.page-head{
  position:relative;background:#000;
  padding:calc(6.5rem + 4vh) 1.5rem clamp(2.6rem,6vw,4rem);
  text-align:center;
}
.page-head h1{
  font-family:'Instrument Serif',serif;font-weight:400;
  font-size:clamp(2.6rem,6.4vw,4.4rem);line-height:1.06;letter-spacing:-.02em;
  color:#fff;text-wrap:balance;margin-bottom:1rem;
}
.page-head h1 em{font-style:italic}
.page-head .lede{
  color:rgba(255,255,255,.84);
  font-size:clamp(1.05rem,1.9vw,1.28rem);line-height:1.6;
  max-width:52ch;margin:0 auto;text-wrap:balance;
}
.page-head .rule{
  display:block;width:56px;height:1px;margin:clamp(2rem,4vw,2.8rem) auto 0;
  background:rgba(255,255,255,.28);
}

/* long-form body copy */
.prose-page{background:#000;padding:clamp(2rem,5vw,3rem) 1.5rem clamp(4rem,9vw,6rem)}
.prose-col{max-width:38rem;margin:0 auto}
.prose-col h2{
  font-family:'Instrument Serif',serif;font-weight:400;
  font-size:clamp(1.7rem,3.4vw,2.3rem);line-height:1.18;letter-spacing:-.01em;
  margin:clamp(2.6rem,6vw,3.6rem) 0 1rem;
}
.prose-col h2:first-child{margin-top:0}
.prose-col h2 em{font-style:italic}
.prose-col p{color:rgba(255,255,255,.84);margin-bottom:1.15rem;line-height:1.72}
.prose-col p:last-child{margin-bottom:0}
.prose-col a.textlink{color:#fff}
.prose-col .aside{
  border-left:1px solid rgba(255,255,255,.2);
  padding:.2rem 0 .2rem 1.3rem;margin:2rem 0;
  color:rgba(255,255,255,.72);font-size:1.02rem;
}
.prose-col .facts{list-style:none;margin:1.4rem 0 0}
.prose-col .facts li{
  position:relative;padding-left:1.3rem;margin-bottom:.7rem;
  color:rgba(255,255,255,.84);line-height:1.6;
}
.prose-col .facts li::before{
  content:'';position:absolute;left:0;top:.62em;
  width:5px;height:5px;border-radius:50%;background:#f0b8a8;
}

/* ============ essays ============
   The Substack cards carry their own title in the artwork, so there is no text
   heading underneath: printing the title twice would look like a mistake. The
   accessible name comes from the link's aria-label and the alt text instead.
   Cropped 4:5 rather than shown at their native 9:16, which keeps every baked
   title (they all sit between 38% and 68% of the height), drops the redundant
   syntropology.com footer, and stops this reading as a second identical
   portrait grid directly under the book covers. */
.essays{position:relative;background:#000;padding:clamp(3.5rem,9vw,6rem) 1.5rem}
.essays-inner{max-width:64rem;margin:0 auto}
.essays-head{text-align:center;margin-bottom:clamp(2.4rem,6vw,3.6rem)}
.essays-head h2{
  font-family:'Instrument Serif',serif;font-weight:400;
  font-size:clamp(2.2rem,4.6vw,3.2rem);line-height:1.15;letter-spacing:-.015em;
  margin-bottom:.7rem;
}
.essays-head h2 em{font-style:italic}
.essays-head .sub{color:rgba(255,255,255,.8);max-width:46ch;margin:0 auto}
.essay-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(1.6rem,4vw,2.6rem)}
.essay{display:flex;flex-direction:column}
.essay-card{
  display:block;border-radius:.6rem;overflow:hidden;
  outline:1px solid rgba(255,255,255,.14);outline-offset:-1px;
  box-shadow:0 18px 40px -16px rgba(0,0,0,.9);
  transition:transform .45s cubic-bezier(.22,1,.36,1),box-shadow .45s;
}
.essay-card img{display:block;width:100%;height:auto;aspect-ratio:4/5;object-fit:cover;object-position:center}
/* height:auto is load bearing: the img carries a height attribute, which is a
   presentational hint, and it beats aspect-ratio unless height is set here. */
.essay:hover .essay-card{transform:translateY(-6px);box-shadow:0 28px 52px -16px rgba(0,0,0,.95)}
.essay p{color:rgba(255,255,255,.82);font-size:.98rem;line-height:1.6;margin:1.1rem 0 .8rem}
.essay .go{
  font-size:.7rem;letter-spacing:.2em;text-transform:uppercase;
  color:rgba(255,255,255,.66);transition:color .2s;
}
.essay:hover .go{color:#fff}
.essays-all{text-align:center;margin-top:clamp(2.4rem,6vw,3.4rem)}
@media (max-width:860px){
  .essay-grid{grid-template-columns:1fr;gap:clamp(2.4rem,7vw,3rem);max-width:30rem;margin:0 auto}
}

/* buy links under a book */
.book .buy{margin-top:1rem}
.book .buy a{
  font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;
  color:#fff;border-bottom:1px solid rgba(255,255,255,.34);
  padding-bottom:2px;transition:border-color .25s;
}
.book .buy a:hover{border-color:#fff}
.book .cause{
  display:block;margin-top:.8rem;
  color:rgba(255,255,255,.66);font-size:.92rem;line-height:1.55;
}
.book .cause b{color:#f0b8a8;font-weight:400}

/* ============ mixes ============
   Three SoundCloud embeds. Each is a full third-party player with its own
   scripts, so they are loading="lazy": on a page this long they are well below
   the fold and there is no reason to pay for them on first paint.
   The players' own default purple (#7756e3) is swapped for the site accent, and
   SoundCloud's inline-styled attribution line is replaced with our own markup
   rather than pasting their font stack and #ccc into the page. */
.mixes{position:relative;background:#000;padding:clamp(3.5rem,9vw,6rem) 1.5rem}
.mixes-inner{max-width:64rem;margin:0 auto}
.mixes-head{text-align:center;margin-bottom:clamp(2.4rem,6vw,3.6rem)}
.mixes-head h2{
  font-family:'Instrument Serif',serif;font-weight:400;
  font-size:clamp(2.2rem,4.6vw,3.2rem);line-height:1.15;letter-spacing:-.015em;
  margin-bottom:.7rem;
}
.mixes-head h2 em{font-style:italic}
.mixes-head .sub{color:rgba(255,255,255,.8);max-width:46ch;margin:0 auto}
.mix-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(1.4rem,3vw,2rem)}
.mix{display:flex;flex-direction:column}
.mix iframe{
  display:block;width:100%;height:300px;border:0;
  border-radius:.6rem;background:#111;
}
.mix .credit{
  margin-top:.7rem;
  font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(255,255,255,.6);
}
.mix .credit a{color:rgba(255,255,255,.82);transition:color .2s}
.mix .credit a:hover{color:#fff}
.mixes-all{text-align:center;margin-top:clamp(2.4rem,6vw,3.4rem)}
@media (max-width:860px){
  .mix-grid{grid-template-columns:1fr;gap:1.6rem;max-width:30rem;margin:0 auto}
}

/* ============ interior photo heroes ============
   About and Contact each get their own photograph. Heroes rather than page
   backgrounds: a fixed background behind a long scrolling column would fight
   the text the whole way down, where a hero states the page and then gets out
   of the way. Same portrait-in-a-landscape-band problem as the homepage, so
   the same solution: object-fit:cover with a per-page object-position, sized
   in lvh so the mobile address bar cannot rescale it mid-scroll. */
.page-head.has-photo{
  min-height:clamp(20rem,58svh,30rem);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  overflow:hidden;
  padding-top:calc(6.5rem + 4vh);
}
.page-head .ph-img{
  position:absolute;left:0;right:0;top:0;height:100%;
  z-index:0;pointer-events:none;
}
.page-head .ph-img img{
  width:100%;height:100%;display:block;object-fit:cover;
}
.page-head .ph-scrim{position:absolute;inset:0;z-index:1;pointer-events:none}
.page-head.has-photo > *:not(.ph-img):not(.ph-scrim){position:relative;z-index:2}
.page-head.has-photo h1{
  text-shadow:0 1px 14px rgba(0,0,0,.72),0 2px 48px rgba(0,0,0,.6);
}
.page-head.has-photo .lede{
  text-shadow:0 1px 12px rgba(0,0,0,.9),0 2px 34px rgba(0,0,0,.75);
}

/* the apple tree is busy edge to edge with no quiet corner, so it takes the
   heavier hand of the two */
.ph-apple img{object-position:center 46%;filter:brightness(.84) saturate(1.16) contrast(1.0)}
.ph-apple + .ph-scrim{
  background:
    radial-gradient(56% 60% at 50% 50%,rgba(0,0,0,.5),rgba(0,0,0,0) 78%),
    linear-gradient(180deg,rgba(0,0,0,.6) 0%,rgba(0,0,0,.16) 30%,rgba(0,0,0,.3) 76%,rgba(0,0,0,.86) 100%);
}
/* the cemetery has sky at the top and reads darker already, so it needs less */
.ph-cem img{object-position:center 52%;filter:brightness(.88) saturate(1.12) contrast(1.0)}
.ph-cem + .ph-scrim{
  background:
    radial-gradient(54% 56% at 50% 50%,rgba(0,0,0,.44),rgba(0,0,0,0) 78%),
    linear-gradient(180deg,rgba(0,0,0,.56) 0%,rgba(0,0,0,.12) 30%,rgba(0,0,0,.26) 76%,rgba(0,0,0,.86) 100%);
}
@media (max-width:700px){
  .ph-apple img{object-position:center 48%;filter:brightness(.8) saturate(1.16) contrast(1.0)}
  .ph-cem img{object-position:center 54%;filter:brightness(.84) saturate(1.12) contrast(1.0)}
}

/* the charity is a link now, so it needs to look like one without shouting */
.book .cause a{border-bottom:1px solid rgba(240,184,168,.4);transition:border-color .25s}
.book .cause a:hover{border-color:#f0b8a8}

/* ============ one-to-one ring ============
   Ported from a pasted p5.js + GSAP component. Neither library ships: p5 alone
   is ~1MB from a CDN for what is a ring of dots whose radius is driven by an
   eased pulse travelling around it, and this site loads no third-party JS at
   all. The two GSAP eases (elastic.in and back.in) are reimplemented in ~10
   lines each in site.js.
   The ring sits BEHIND the copy and the copy sits in its hole, so the canvas is
   deliberately larger than the text column. */
.rooms{
  position:relative;isolation:isolate;overflow:hidden;
  /* one variable drives both the ring and the room it needs. Without the
     min-height the section is only as tall as its ~450px of text and the ring
     was being sliced 119px off the top and bottom, which reads as a bug rather
     than a crop. */
  --ring:min(860px,92vw);
  min-height:calc(var(--ring) + 3rem);
  display:flex;flex-direction:column;justify-content:center;
}
.rooms-ring{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  z-index:0;pointer-events:none;
  width:var(--ring);aspect-ratio:1/1;
}
.rooms-ring canvas{display:block;width:100%;height:100%}
.rooms-inner{position:relative;z-index:1}
/* the dots pass behind the words at narrow widths, so the type gets a little
   help rather than the ring being switched off */
.rooms h2,.rooms p{text-shadow:0 1px 12px rgba(0,0,0,.75),0 2px 30px rgba(0,0,0,.6)}
@media (max-width:640px){
  /* fits the viewport rather than overhanging it: a ring clipped on both
     sides looks as wrong as one clipped top and bottom. It crosses behind
     the copy at this size, which is why the type carries a shadow and the
     ring is dropped back. */
  .rooms{--ring:92vw}
  .rooms-ring{opacity:.5}
}
@media (prefers-reduced-motion:reduce){
  .rooms-ring{opacity:.5}
}
