/* Part Two opener - lifted from opener-wireframe.html.
   Icons: Lucide (ISC) https://lucide.dev */
.o2{background:linear-gradient(180deg,#061426 0%,#03101e 60%,#020914 100%);
    --blue-700:#1c50c8; font:400 clamp(1.02rem,.98rem + .25vw,1.13rem)/1.62
    'Inter',system-ui,-apple-system,sans-serif; color:var(--cream-50)}
.o2 h2{margin:0; line-height:1.14; text-wrap:balance}
/* ---------- slide shell ---------- */
/* navy gutter = the border around the whole thing */
.slide{
  min-height:100vh; min-height:100svh;
  display:grid; grid-template-columns:1fr 1fr; align-items:stretch; gap:0;
  padding:clamp(.9rem,2.4vw,2rem);
  position:relative;
}
/* alternate: even slides put the copy on the left, the art on the right.
   ponytail: order:1 pushes the art past the copy - order:-1 was a no-op,
   the art is already first in the DOM. */
.slide:nth-child(even) .slide__art{order:1}

.slide__art{
  display:grid; place-items:center; min-width:0;
  padding:clamp(2rem,5vw,4rem);
  background:
    radial-gradient(circle at 50% 38%, rgba(66,126,191,.14), transparent 62%),
    linear-gradient(180deg,#071730,#04101f);
}
.slide__copy{
  min-width:0; background:var(--cream-50); color:var(--navy-950);
  padding:clamp(2.2rem,5vw,4.5rem);
  display:flex; flex-direction:column; justify-content:center;
}
.slide__copy>*{max-width:34rem}

.kicker{
  font-size:.74rem; letter-spacing:.18em; text-transform:uppercase;
  color:var(--blue-700); margin:0 0 1.1rem;
}
.slide__copy h2{
  font-family:'Fraunces',Georgia,serif; font-weight:500;
  font-size:clamp(1.9rem,1.3rem + 2.2vw,3rem); margin-bottom:1.4rem;
}
.slide__copy p{margin:0 0 1.1rem; color:rgba(6,16,29,.76)}
.slide__copy p:last-child{margin-bottom:0}
.turn{font-family:'Fraunces',Georgia,serif; font-size:1.5em; line-height:1.3; color:var(--navy-950)}
.turn em{font-style:italic; color:var(--blue-700)}
.list{
  margin:0 0 1.5rem; padding:0; list-style:none;
  display:flex; flex-wrap:wrap; gap:.5rem .55rem;
}
.list li{
  font-size:.78rem; letter-spacing:.1em; text-transform:uppercase;
  border:1px solid rgba(28,80,200,.28); border-radius:999px;
  padding:.34rem .7rem; color:var(--blue-700);
}

/* ---------- icons ---------- */
svg.ico{width:min(100%,26rem); height:auto; overflow:visible}
.lot{width:min(100%,22rem); aspect-ratio:1}
.lot--globe{width:min(100%,26rem)}
.lot svg{width:100%!important; height:100%!important}
.ico path,.ico circle,.ico rect,.ico line{
  stroke:var(--blue-300); fill:none; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round;
}
.ico .hi{stroke:var(--blue-500); stroke-width:2.4}
.ico .dim{stroke:rgba(143,197,244,.28)}
.ico circle.fill{fill:var(--blue-500); stroke:none}
.ico text{fill:var(--blue-300); font:500 8px 'Inter',sans-serif; letter-spacing:.14em}

/* draw-on: pathLength="1" makes one rule cover every shape */
.js .ico:not(.disc):not(.grid9) :is(path,circle,rect,line){stroke-dasharray:1; stroke-dashoffset:1}
.js .ico:not(.disc):not(.grid9) :is(circle.fill,text){opacity:0}
.in .ico:not(.disc):not(.grid9) :is(path,circle,rect,line){animation:draw 1.1s cubic-bezier(.4,0,.2,1) forwards}
.in .ico:not(.disc):not(.grid9) :is(.fill,text){animation:pop .5s ease forwards}
@keyframes draw{to{stroke-dashoffset:0}}
@keyframes pop{from{opacity:0;transform:scale(.7)}to{opacity:1;transform:scale(1)}}
.ico .fill,.ico text{transform-box:fill-box; transform-origin:center}

/* ---------- slide 1: the disc ----------
   ponytail: the pie sweep is one circle with stroke-width = radius and an
   animated dashoffset. No path morphing, no JS, no library. */
.disc .d-base{fill:rgba(47,128,237,.42); stroke:none}
.disc .d-rim{fill:none; stroke:var(--blue-300); stroke-width:1.2; opacity:.55}
.disc .d-sweep{
  fill:none; stroke:#0a1e39; stroke-width:88;
  stroke-dasharray:276.46; stroke-dashoffset:276.46;
}
.disc .d-sliver{fill:var(--blue-500); stroke:none; opacity:0}
.disc .d-lead{fill:none; stroke:var(--blue-300); stroke-width:1.2;
  stroke-dasharray:92; stroke-dashoffset:92}
.disc .d-label{opacity:0}

.in .disc .d-sweep{animation:sweep 1.9s cubic-bezier(.65,0,.35,1) .45s forwards}
.in .disc .d-sliver{animation:fadein .5s ease 2.2s forwards}
.in .disc .d-lead{animation:draw-len .6s ease 2.4s forwards}
.in .disc .d-label{animation:fadein .4s ease 2.9s forwards}
/* the sweep stops 2.5% short of a full turn - that gap is the whole point */
@keyframes sweep{to{stroke-dashoffset:6.91}}
@keyframes draw-len{to{stroke-dashoffset:0}}
@keyframes fadein{to{opacity:1}}

/* stagger, cheap and generic */
.ico:not(.disc):not(.grid9)>*:nth-child(1){animation-delay:.05s}.ico:not(.disc):not(.grid9)>*:nth-child(2){animation-delay:.17s}
.ico:not(.disc):not(.grid9)>*:nth-child(3){animation-delay:.29s}.ico:not(.disc):not(.grid9)>*:nth-child(4){animation-delay:.41s}
.ico:not(.disc):not(.grid9)>*:nth-child(5){animation-delay:.53s}.ico:not(.disc):not(.grid9)>*:nth-child(6){animation-delay:.65s}
.ico:not(.disc):not(.grid9)>*:nth-child(7){animation-delay:.77s}.ico:not(.disc):not(.grid9)>*:nth-child(8){animation-delay:.89s}
.ico:not(.disc):not(.grid9)>*:nth-child(9){animation-delay:1.01s}.ico:not(.disc):not(.grid9)>*:nth-child(10){animation-delay:1.13s}
.ico:not(.disc):not(.grid9)>*:nth-child(n+11){animation-delay:1.25s}
.ico .g>*{animation-delay:inherit}

/* copy entrance */
.js .slide__copy>*{opacity:0; transform:translateY(14px)}
.in .slide__copy>*{animation:rise .7s cubic-bezier(.4,0,.2,1) forwards}
.in .slide__copy>*:nth-child(2){animation-delay:.09s}
.in .slide__copy>*:nth-child(3){animation-delay:.18s}
.in .slide__copy>*:nth-child(4){animation-delay:.27s}
.in .slide__copy>*:nth-child(5){animation-delay:.36s}
@keyframes rise{to{opacity:1;transform:none}}

/* the nine-fix grid on slide 4 lights up in sequence */
.grid9 :is(path,circle,rect,line,polyline,polygon){
  stroke:var(--blue-300); stroke-width:.85; fill:none;
  stroke-linecap:round; stroke-linejoin:round;
}
.grid9 .cell{opacity:.34}
.js .grid9 .cell{opacity:1}
.js .grid9 .cell>svg{opacity:0;transform-box:fill-box;transform-origin:center}
.in .grid9 .cell>svg{animation:cellin .6s cubic-bezier(.34,1.56,.64,1) forwards}
@keyframes cellin{0%{opacity:0;transform:scale(.2) rotate(-10deg)}70%{opacity:1;transform:scale(1.08) rotate(2deg)}100%{opacity:1;transform:scale(1)}}
.in .grid9 .cell:nth-child(1)>svg{animation-delay:.25s}.in .grid9 .cell:nth-child(2)>svg{animation-delay:.34s}
.in .grid9 .cell:nth-child(3)>svg{animation-delay:.43s}.in .grid9 .cell:nth-child(4)>svg{animation-delay:.52s}
.in .grid9 .cell:nth-child(5)>svg{animation-delay:.61s}.in .grid9 .cell:nth-child(6)>svg{animation-delay:.7s}
.in .grid9 .cell:nth-child(7)>svg{animation-delay:.79s}.in .grid9 .cell:nth-child(8)>svg{animation-delay:.88s}
.in .grid9 .cell:nth-child(9)>svg{animation-delay:.97s}
@media (prefers-reduced-motion:reduce){.js .grid9 .cell>svg{opacity:1;animation:none!important}}

/* ---------- mobile: stack, art on top, no alternation ---------- */
@media (max-width:880px){
  /* Part One's mobile grammar: planet band = top half, copy = bottom half,
     every slide registers identically. */
  .slide{grid-template-columns:1fr; grid-template-rows:50svh 1fr; position:relative}
  .slide:nth-child(even) .slide__art{order:0}
  .slide__art{height:100%; min-height:0; padding:3.6rem 1.4rem 1.2rem}
  svg.ico{width:min(100%,13rem); max-height:100%}
  .lot{width:min(72%,34svh)}
  .lot--globe{width:min(84%,38svh)}
  .slide__copy>*{max-width:none}
  .o2 .slide__copy{justify-content:flex-start; padding:1.6rem 1.4rem 2.6rem}
  .slide__copy h2{font-size:clamp(1.45rem,5.8vw,1.9rem); margin-bottom:1rem}
  .turn{font-size:1.2em}
  h2.squeeze{font-size:clamp(1.3rem,5.4vw,1.8rem)}
  /* masthead rides the navy art half, top-left, in the finale's colours -
     never over the copy, so it cannot collide with the kicker */
  .o2 .slide__copy{position:static}
  .o2 .sl-mh{top:1.05rem;left:1.15rem;right:auto;text-align:left}
  .o2 .slide__copy .sl-mh__s{color:var(--cream-50,#f6f3ed)}
  .o2 .slide__copy .sl-mh__c{color:var(--blue-300,#8fc5f4)}
}
@media (prefers-reduced-motion:reduce){
  .js .ico [stroke]{stroke-dashoffset:0}
  .js .ico .fill,.js .ico text,.js .slide__copy>*{opacity:1;transform:none}
  .grid9 .cell{opacity:1}
  *{animation:none!important}
}
html:not(.js) .grid9 .cell{opacity:1}

/* ---------- second hero: the cover, restaged ---------- */
.o2-finale{
  position:relative; min-height:100vh; min-height:100lvh; overflow:hidden;
  display:grid; place-items:center; isolation:isolate; color:var(--cream-50);
  background:
    radial-gradient(circle at 50% 24%, rgba(28,82,137,.52) 0%, rgba(8,27,50,.48) 34%, transparent 58%),
    linear-gradient(180deg, #061426 0%, #03101e 70%, #020914 100%);
}
.o2-scene{position:absolute; inset:0; z-index:0; pointer-events:none}
.o2-mast{position:relative; z-index:3; text-align:center; padding:0 1.5rem}
/* type lifted verbatim from Part One's .p7-eyebrow / .p7-chapter so the two finales match */
.o2-mast__series{
  margin:0 0 .45rem; font-family:'Fraunces','Iowan Old Style',Georgia,serif;
  font-weight:500; font-size:1.1rem; color:var(--cream-50);
}
.o2-mast__chapter{
  margin:0; font-size:.68rem; letter-spacing:.24em; text-transform:uppercase;
  color:var(--blue-300); font-weight:500;
}
.o2-continue{
  position:absolute; left:50%; bottom:5svh; translate:-50%; z-index:3;
  display:grid; justify-items:center; gap:.55rem;
  font-size:.66rem; letter-spacing:.26em; text-transform:uppercase; color:var(--blue-100);
  text-decoration:none; font-weight:500; white-space:nowrap;
}
.o2-continue .arr{font-size:1.25rem; line-height:1; color:var(--blue-300); transition:translate .25s ease}
.o2-continue:hover .arr,.o2-continue:focus-visible .arr{translate:0 4px}

/* ---------- scroll lock ----------
   Native CSS snap only. Part One shipped a wheel/touch stepper here and it had to be
   deleted - preventDefault plus scrollIntoView fought the sticky frame and produced the
   flicker. Position stays the single source of truth; JS only decides WHEN snap applies,
   so the article underneath still free-scrolls. */
html.o2-snap{scroll-snap-type:y mandatory}
html.o2-snap #cover,
html.o2-snap .o2 .slide,
html.o2-snap .o2-finale{scroll-snap-align:start; scroll-snap-stop:always}
html.o2-snap #article{scroll-snap-align:start}   /* the exit ramp */

/* flatten: one slide is exactly one viewport, so a snap always lands clean.
   Only where the content actually fits - see the short-screen release below. */
.o2 .slide{height:100svh; min-height:0}
@supports not (height:100svh){ .o2 .slide{height:100vh} }

/* phones: the art has to give way or slide 4 bleeds into slide 5 */
@media (max-width:880px){
  .o2 .slide__art{padding:1.5rem 1.6rem}
  .o2 svg.ico{width:min(100%,9rem)}
  .o2 .lot{width:min(100%,9rem)}
  .o2 .lot--globe{width:min(100%,10rem)}
  .o2 .slide__copy{padding:1.6rem}
  .o2 .slide__copy h2{font-size:clamp(1.6rem,1.2rem + 2.4vw,2.2rem); margin-bottom:1rem}
}

/* Short screens cannot hold a slide in one viewport, so they do not pretend to:
   flatten and snap both release and the opener scrolls normally. */
@media (max-height:699px){
  .o2 .slide{height:auto; min-height:100svh}
  html.o2-snap{scroll-snap-type:none}
}

/* short punch lines between paragraphs - a beat, not a heading.
   p.w2-beat, not .w2-beat: article.css carries `#article p` at equal
   specificity and loads later, so this must outrank it. */
#article p.w2-beat{
  font-family:'Fraunces','Iowan Old Style',Georgia,serif;
  font-size:clamp(1.18rem,1.08rem + .48vw,1.46rem);
  font-weight:600;line-height:1.34;color:var(--blue-600);
  margin:1.7rem 0 1.8rem;
}

/* 2026-08-10: one-line .turn on desktop + orphan control */
.slide__copy p{text-wrap:pretty}
@media (min-width:881px){
  .slide__copy>.turn{max-width:none}
}
.slide__copy h2 em{font-style:normal;color:var(--blue-700)}
.slide__copy h2{text-wrap:balance}
@media (min-width:881px){
  .slide__copy h2.squeeze{max-width:none;font-size:clamp(1.9rem,calc((50vw - 9rem)/14),3rem)}
}

h2.squeeze{text-wrap:wrap;min-height:2.5em;font-size:clamp(1.25rem,.75rem + 2.1vw,2.3rem)}
.slide__art h2.squeeze{color:#fff;margin:0;width:min(34rem,100%)}
.w2-type{color:var(--blue-300)}
/* one-shot type-in; caret is zero net width so the line never rewraps */
.w2-type.typing::after{content:"";display:inline-block;width:.45em;height:.82em;
  margin-left:.06em;margin-right:-.51em;background:var(--blue-300);vertical-align:-.06em}

/* masthead - exact replica of Part One's corner masthead (measured off the live
   page: Fraunces 500 .8rem / Inter 500 .53rem, ls .2em, blue-500), pinned in
   the OUTER top corner of each slide's cream panel. */
.slide__copy{position:relative}
.sl-mh{position:absolute;top:1.05rem;right:1.15rem;text-align:right;margin:0;pointer-events:none}
.sl-mh p{margin:0;max-width:none}
.slide__copy .sl-mh__s{font-family:'Fraunces','Iowan Old Style',Georgia,serif;font-weight:500;
  font-size:.8rem;letter-spacing:-.005em;line-height:1;color:#101820}
.slide__copy .sl-mh__c{margin-top:.26rem;font:500 .53rem/1.62 'Inter',system-ui,sans-serif;
  letter-spacing:.2em;text-transform:uppercase;color:#2f80ed}
.js .slide__copy>.sl-mh{opacity:1;transform:none;animation:none}
