/* sigouin.net hub, round 17 no scroll lane. Ink ground, paper type, one signal colour.
   Every page is exactly one pane tall. The only motion that moves the layout is the
   opening overture, and it collapses into the header strip instead of scrolling away. */
:root{
  --ink:#0a0a0b;
  --ink-2:#121215;
  --ink-3:#1b1b20;
  --line:#2c2c33;
  --paper:#ece7dd;
  --dim:#8d887e;
  --signal:#ff5b23;
  --live:#c6f53c;
  --serif:"Instrument Serif",Georgia,"Times New Roman",serif;
  --mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --pad:clamp(1.1rem,3.4vw,3.2rem);
  --padv:clamp(.6rem,1.5svh,1.1rem);
  color-scheme:dark;
}
*,*::before,*::after{box-sizing:border-box}
/* The whole no scroll rule lives here: the document is never taller than the pane. */
html,body{margin:0;padding:0;height:100%;max-height:100%;overflow:hidden}
html{-webkit-text-size-adjust:100%}
body{
  background:var(--ink);
  color:var(--paper);
  font-family:var(--mono);
  font-size:15px;
  line-height:1.45;
  display:grid;
  grid-template-rows:auto minmax(0,1fr);
}
body.proc-page{grid-template-rows:auto minmax(0,1fr) auto}
img,video,model-viewer,iframe{display:block;max-width:100%}
a{color:inherit}
button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer;text-align:left}
:focus-visible{outline:2px solid var(--signal);outline-offset:3px}
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}

/* ---------- the ground: clip A, fixed, under every pane on both pages ----------
   Round 18. The starfield loop replaces the static waveform still as the page ground.
   Two scrims keep the ink look and the contrast. First the clip is darkened at source
   (brightness .34), then a flat .62 ink wash sits on the whole ground, then each pane
   that carries text adds its own .66 ink wash on top. Worst case for contrast is a pure
   white video frame: 0.34 encoded is 0.0946 relative luminance, the ground wash takes it
   to 0.0378, the pane wash to 0.0148. Paper #ece7dd then reads 13.2:1 and even the dim
   #8d887e meta reads 4.60:1, both above 4.5:1, with no frame of either clip able to do
   worse. Solid black behind contained media in the stage is untouched. */
.ground{position:fixed;inset:0;z-index:0;overflow:hidden;background:var(--ink)}
.ground video{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  filter:grayscale(.42) contrast(1.42) saturate(.82) brightness(.62);
}
.ground::after{content:"";position:absolute;inset:0;background:rgba(10,10,11,.4)}
/* Everything the visitor reads or clicks sits in its own layer above the ground. */
.overture,.hub,.proc-strip,.scenes,.stepper{position:relative;z-index:1}

/* ---------- grain and vignette, one shared skin ---------- */
.grain{
  position:fixed;inset:0;z-index:60;pointer-events:none;opacity:.34;mix-blend-mode:overlay;
  background-image:radial-gradient(circle at 1px 1px,rgba(255,255,255,.55) .6px,transparent .7px);
  background-size:3px 3px;
}

/* ---------- overture: the kinetic name, then the header strip ---------- */
.overture{
  position:relative;
  min-height:100svh;
  display:grid;
  grid-template-rows:auto 1fr auto;
  padding:var(--padv) var(--pad);
  overflow:hidden;
  border-bottom:1px solid var(--line);
  animation:curtain 1050ms cubic-bezier(.76,0,.16,1) 1500ms both;
}
.overture__bed{
  position:absolute;inset:0;z-index:0;
  object-fit:cover;width:100%;height:100%;
  filter:grayscale(.35) contrast(1.12) brightness(.44);
  transform:scale(1.08);
  animation:bed 2600ms cubic-bezier(.2,.7,.2,1) both;
}
.overture::after{
  content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(190deg,rgba(10,10,11,.5) 0%,rgba(10,10,11,.2) 40%,rgba(10,10,11,.93) 100%);
}
/* Round 20: no settled state override. The strip keeps the round 17 overture gradient so
   the waveform bed reads through it behind the name, instead of the flat .78 ink wash that
   round 18 put there. The bed is opaque and sits inside the overture, above the ground, so
   the ground clip never washes it out. */
/* Clip B hands off to the waveform bed under it: it fades over 900 ms, then JS pauses and
   removes it. Both beds are z-index 0 inside the overture, so DOM order decides: the still
   is written first and clip B paints over it until the fade. */
.overture__bed.is-out{opacity:0;transition:opacity 900ms ease}
.overture__top,.overture__mid,.overture__foot{position:relative;z-index:2}
.overture__top{align-self:start;display:flex;justify-content:space-between;gap:.6rem 1rem;flex-wrap:wrap;
  font-size:.66rem;letter-spacing:.2em;text-transform:uppercase;color:var(--dim)}
.about-btn{color:var(--signal);border-bottom:1px solid currentColor;letter-spacing:.2em;text-transform:uppercase;font-size:.66rem}
/* The tagline lives in a row that shuts with the curtain, so the strip is name only. */
.overture__mid{display:grid;align-content:end;overflow:hidden;max-height:52svh;
  animation:shutter 1050ms cubic-bezier(.76,0,.16,1) 1500ms both}
.overture__foot{align-self:end;display:grid}
.wordmark{
  font-family:var(--serif);
  font-weight:400;
  font-size:clamp(3.4rem,15.5vw,13.5rem);
  line-height:.84;
  letter-spacing:-.03em;
  margin:0;
  display:flex;flex-wrap:wrap;
  animation:settle 900ms cubic-bezier(.76,0,.16,1) 1550ms both;
}
.wordmark span{display:inline-block;overflow:hidden}
.wordmark b{
  display:inline-block;font-weight:inherit;
  transform:translateY(105%) rotate(5deg);
  animation:rise 900ms cubic-bezier(.16,1,.3,1) both;
  animation-delay:calc(var(--i) * 52ms + 180ms);
}
.wordmark .dot{color:var(--signal)}
.tagline{
  margin:0 0 .6rem;max-width:62ch;
  font-size:clamp(.74rem,1.05vw,.9rem);
  letter-spacing:.12em;text-transform:uppercase;color:var(--dim);
  opacity:0;animation:fade 700ms ease 900ms both;
}
.tagline strong{color:var(--paper);font-weight:400}
@keyframes rise{to{transform:translateY(0) rotate(0)}}
@keyframes fade{to{opacity:1}}
@keyframes settle{from{font-size:clamp(3.4rem,15.5vw,13.5rem)}to{font-size:clamp(2.1rem,7vw,4rem)}}
@keyframes bed{from{transform:scale(1.22)}to{transform:scale(1.08)}}
@keyframes curtain{from{min-height:100svh}to{min-height:0}}
@keyframes shutter{from{max-height:52svh;opacity:1}to{max-height:0;opacity:0}}

/* ---------- the about toggle, secondary copy without a second screen ---------- */
.about-panel{
  position:fixed;z-index:70;right:var(--pad);top:calc(var(--padv) + 2.2rem);
  width:min(38ch,calc(100vw - var(--pad) * 2));
  background:var(--ink-2);border:1px solid var(--line);
  padding:1rem 1.1rem;display:grid;gap:.7rem;
  font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;color:var(--dim);
}
.about-panel[hidden]{display:none}
.about-panel p{margin:0}
.about-panel strong{color:var(--paper);font-weight:400}
.about-panel button{color:var(--signal);justify-self:start;border-bottom:1px solid currentColor;font-size:.64rem;letter-spacing:.2em;text-transform:uppercase}

/* ---------- hub: uneven index rail plus stage, one pane ---------- */
.hub{
  display:grid;
  grid-template-columns:minmax(320px,36vw) 1fr;
  height:100%;min-height:0;
  border-bottom:0;
}
.rail-col{display:grid;grid-template-rows:minmax(0,1fr) auto;min-height:0;border-right:1px solid var(--line);
  background:rgba(10,10,11,.72)}
/* Ten rows, fixed fractions of the rail height. Uneven on purpose: every third row
   takes the largest share, the row after it the smallest. The rail cannot overflow
   because the tracks always add up to the rail height. */
.rail{
  list-style:none;margin:0;padding:0;
  display:grid;
  grid-template-rows:1.34fr 1fr .88fr 1.34fr 1fr .88fr 1.34fr 1fr .88fr 1.34fr;
  min-height:0;
}
.rail li{border-bottom:1px solid var(--line);min-height:0;overflow:hidden;display:grid}
.rail li:last-child{border-bottom:0}
.row{
  display:grid;
  grid-template-columns:3.2rem 1fr auto;
  gap:.1rem .9rem;
  align-content:center;
  width:100%;height:100%;
  padding:.2rem var(--pad) .2rem calc(var(--pad) * .7);
  transition:background 180ms ease,padding-left 260ms cubic-bezier(.2,.8,.2,1);
}
.row__num{font-size:.66rem;color:var(--dim);letter-spacing:.14em;align-self:center}
.row__title{
  font-family:var(--serif);
  font-size:clamp(1.15rem,2.6svh,2.1rem);
  line-height:1;letter-spacing:-.015em;
  margin:0;display:block;
}
.rail li:nth-child(3n+1) .row__title{font-size:clamp(1.4rem,3.5svh,2.9rem)}
.rail li:nth-child(4n) .row__title{font-style:italic}
.row__meta{font-size:.62rem;letter-spacing:.16em;text-transform:uppercase;color:var(--dim);white-space:nowrap;align-self:center}
.row__word{
  grid-column:2;font-size:.62rem;letter-spacing:.2em;text-transform:uppercase;color:var(--signal);
  opacity:0;transform:translateY(-3px);transition:opacity 220ms ease,transform 220ms ease;
  height:0;overflow:hidden;
}
.row:hover,.row:focus-visible{background:rgba(18,18,21,.82);padding-left:calc(var(--pad) * .7 + 10px)}
.row:hover .row__word,.row:focus-visible .row__word,[aria-current="true"] .row__word{opacity:1;transform:none;height:auto}
[aria-current="true"] .row{background:rgba(27,27,32,.88)}
[aria-current="true"] .row__num{color:var(--signal)}
[aria-current="true"] .row__title{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.16em}

/* ---------- stage ---------- */
.stage{height:100%;min-height:0;display:grid;grid-template-rows:auto minmax(0,1fr);background:rgba(18,18,21,.82);overflow:hidden}
.stage__media{position:relative;overflow:hidden;background:#000;min-height:0}
/* whole capture visible, never cropped. Black ground makes the letterbox read as intent. */
.stage__media > :not(.stage__tag){position:absolute;inset:0;width:100%;height:100%;object-fit:contain}
.stage__media model-viewer{object-fit:unset;background:radial-gradient(circle at 50% 40%,#232329,#0a0a0b 72%)}
.stage__media iframe{border:0}
.stage__pair{position:absolute;inset:0;display:grid;grid-template-columns:1fr 1fr}
.stage__pair img{position:static;width:100%;height:100%;object-fit:contain}
.stage__pair img:first-child{border-right:1px solid var(--signal)}
.stage__tag{
  position:absolute;z-index:3;left:0;bottom:0;margin:0;
  font-size:.6rem;letter-spacing:.2em;text-transform:uppercase;
  background:var(--ink);color:var(--dim);padding:.38rem .8rem;border-top:1px solid var(--line);border-right:1px solid var(--line);
}
.stage__body{padding:var(--padv) var(--pad);display:grid;gap:.4rem;border-bottom:1px solid var(--line);align-content:start;overflow:hidden}
.stage__kicker{display:flex;gap:1rem;flex-wrap:wrap;margin:0;font-size:.64rem;letter-spacing:.2em;text-transform:uppercase;color:var(--dim)}
.stage__kicker .n{color:var(--signal)}
.stage__title{font-family:var(--serif);font-size:clamp(1.6rem,3.6svh,3rem);line-height:.98;margin:0;letter-spacing:-.02em}
.stage__fact{margin:0;max-width:56ch;color:var(--paper);font-size:.76rem}
.chips{display:flex;flex-wrap:wrap;gap:.3rem;list-style:none;margin:0;padding:0}
.chips li{
  font-size:.58rem;letter-spacing:.13em;text-transform:uppercase;color:var(--paper);
  border:1px solid var(--line);padding:.2rem .45rem;background:var(--ink);
}
.chips li.is-model{border-color:var(--signal);color:var(--signal)}
.stage__out{display:flex;gap:1rem;flex-wrap:wrap;align-items:center;margin:0;font-size:.64rem;letter-spacing:.16em;text-transform:uppercase}
.stage__out a{color:var(--signal);text-decoration:none;border-bottom:1px solid currentColor;padding-bottom:2px}
.stage__out span{color:var(--dim)}
.stage__live{color:var(--live)}
.stage__live.stale{color:var(--dim)}
.stage__back{display:none;color:var(--signal);border:1px solid var(--line);padding:.3rem .7rem;
  font-size:.6rem;letter-spacing:.2em;text-transform:uppercase;justify-self:start}

/* ---------- footer, now the last line of the rail column ---------- */
.foot{
  display:flex;flex-wrap:wrap;gap:.2rem 1.2rem;align-items:baseline;
  padding:.45rem var(--pad) .5rem calc(var(--pad) * .7);
  border-top:1px solid var(--line);
  font-size:.58rem;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);
}
.foot dl{display:flex;flex-wrap:wrap;gap:.2rem 1.2rem;margin:0}
.foot div{display:flex;gap:.4rem;align-items:baseline}
.foot dt{white-space:nowrap}
.foot dd{margin:0;color:var(--live)}
.foot dd.stale{color:var(--dim)}
.foot p{margin:0}
.foot a{color:var(--paper);text-decoration:none;border-bottom:1px solid var(--line)}
.sample-note{color:var(--signal)}

/* ---------- process page: a stepper, one scene per pane ---------- */
.proc-strip{
  position:relative;overflow:hidden;
  display:flex;flex-wrap:wrap;gap:.4rem 1.4rem;align-items:baseline;justify-content:space-between;
  padding:var(--padv) var(--pad);border-bottom:1px solid var(--line);
}
.proc-strip video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;filter:grayscale(.4) brightness(.32)}
/* Round 20: back to the round 17 wash, so the canvas clip reads in the strip again. */
.proc-strip::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(10,10,11,.5),rgba(10,10,11,.88))}
.proc-strip > *{position:relative;z-index:2}
.proc-strip h1{font-family:var(--serif);font-size:clamp(1.5rem,4.6svh,2.9rem);line-height:.9;margin:0;letter-spacing:-.03em}
.proc-strip .meta{font-size:.64rem;letter-spacing:.2em;text-transform:uppercase;color:var(--dim);display:flex;gap:1.1rem;flex-wrap:wrap;align-items:baseline}
.proc-strip .meta a{color:var(--signal);text-decoration:none;border-bottom:1px solid currentColor}
.proc-strip .meta button{color:var(--signal);border-bottom:1px solid currentColor;letter-spacing:.2em;text-transform:uppercase;font-size:.64rem}

.scenes{position:relative;height:100%;min-height:0;overflow:hidden;touch-action:pan-y}
.scene{position:absolute;inset:0;opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity 380ms ease,visibility 0s linear 380ms}
.scene.is-on{opacity:1;visibility:visible;pointer-events:auto;transition:opacity 380ms ease,visibility 0s}
.scene__grid{display:grid;grid-template-columns:1fr minmax(290px,31vw);height:100%;min-height:0}
.scene:nth-child(even) .scene__grid{grid-template-columns:minmax(290px,31vw) 1fr}
.scene:nth-child(even) .scene__frame{order:2}
.scene__frame{position:relative;overflow:hidden;background:#000;min-height:0}
.scene__frame img,.scene__frame video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.scene__frame.contain img{object-fit:contain;background:var(--ink-2)}
.scene__note{display:grid;gap:.6rem;align-content:start;overflow:hidden;min-height:0;background:rgba(10,10,11,.8);
  padding:clamp(.8rem,2.4svh,1.7rem) var(--pad);border-left:1px solid var(--line)}
.scene:nth-child(even) .scene__note{border-left:0;border-right:1px solid var(--line)}
.scene__id{margin:0;font-size:.64rem;letter-spacing:.24em;color:var(--signal)}
.scene h2{font-family:var(--serif);font-size:clamp(1.4rem,3.6svh,2.7rem);line-height:1;margin:0;letter-spacing:-.02em}
.scene p{margin:0;font-size:.76rem;color:var(--paper);max-width:46ch}
.scene pre{margin:0;font-size:.58rem;line-height:1.45;color:var(--dim);white-space:pre-wrap;
  border-left:1px solid var(--line);padding-left:.7rem}

.stepper{display:flex;align-items:center;gap:.8rem 1.1rem;flex-wrap:wrap;
  padding:.5rem var(--pad);border-top:1px solid var(--line);
  font-size:.64rem;letter-spacing:.18em;text-transform:uppercase;color:var(--dim)}
.stepper__count{color:var(--paper);white-space:nowrap}
.stepper__dots{display:flex;gap:.45rem;margin-left:auto}
.stepper__dots button{width:11px;height:11px;border:1px solid var(--line);border-radius:50%}
.stepper__dots button[aria-current="true"]{background:var(--signal);border-color:var(--signal)}
.step-btn{border:1px solid var(--line);padding:.28rem .7rem;letter-spacing:.18em;text-transform:uppercase;color:var(--paper)}
.step-btn[disabled]{opacity:.32;cursor:default}

.ledger{position:absolute;inset:0;z-index:30;background:var(--ink);overflow:hidden;
  padding:clamp(.8rem,2.2svh,1.6rem) var(--pad);display:grid;gap:.7rem;align-content:start}
.ledger[hidden]{display:none}
.ledger h2{font-family:var(--serif);font-size:clamp(1.4rem,3.6svh,2.6rem);margin:0;letter-spacing:-.02em}
.ledger__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(215px,1fr));gap:1px;background:var(--line);border:1px solid var(--line)}
.ledger__cell{background:var(--ink);padding:.5rem .7rem;display:grid;gap:.15rem;align-content:start}
.ledger__cell b{font-family:var(--serif);font-weight:400;font-size:1.1rem;letter-spacing:-.01em;line-height:1.1}
.ledger__cell span{font-size:.58rem;letter-spacing:.11em;text-transform:uppercase;color:var(--dim);line-height:1.3}
.ledger__cell.is-model b{color:var(--signal)}
.ledger p{margin:0;font-size:.66rem;color:var(--dim);max-width:78ch}
.ledger .close{color:var(--signal);border-bottom:1px solid currentColor;justify-self:start;
  font-size:.62rem;letter-spacing:.2em;text-transform:uppercase}

/* ---------- phone: one pane at a time, still no document scroll ---------- */
@media (max-width:900px){
  .overture{animation-name:curtain}
  /* The strip keeps one line at 390: the city drops, the rest fits beside the about toggle. */
  .overture__top{font-size:.56rem;letter-spacing:.1em;gap:.3rem .6rem;flex-wrap:nowrap}
  .overture__top span:nth-child(2){display:none}
  .overture__foot{margin-top:.35rem}
  .about-btn{font-size:.56rem;letter-spacing:.1em;white-space:nowrap}
  .proc-strip{gap:.25rem .8rem}
  .proc-strip .meta{font-size:.56rem;letter-spacing:.11em;gap:.8rem;flex-wrap:nowrap}
  .proc-strip .meta button{font-size:.56rem;letter-spacing:.11em;white-space:nowrap}
  .proc-strip .meta > span:first-child{display:none}
  .proc-strip .meta a{white-space:nowrap}
  .hub{grid-template-columns:1fr;grid-template-rows:minmax(0,1fr);position:relative;overflow:hidden}
  .rail-col,.stage{grid-area:1 / 1}
  .rail-col{border-right:0}
  .stage{transform:translateX(100%);visibility:hidden;transition:transform 380ms cubic-bezier(.2,.8,.2,1),visibility 0s linear 380ms}
  body.stage-open .stage{transform:none;visibility:visible;transition:transform 380ms cubic-bezier(.2,.8,.2,1),visibility 0s}
  .stage__back{display:block}
  .stage__title{font-size:clamp(1.4rem,3.2svh,2.2rem)}
  .stage__fact{font-size:.72rem}
  .row{grid-template-columns:2.4rem 1fr;padding-left:calc(var(--pad) * .6)}
  .row__meta{grid-column:2;white-space:normal}
  .row__title{font-size:clamp(1.05rem,2.5svh,1.8rem)}
  .rail li:nth-child(3n+1) .row__title{font-size:clamp(1.25rem,3.2svh,2.3rem)}
  .foot{font-size:.55rem;gap:.15rem .9rem}
  .scene__grid,.scene:nth-child(even) .scene__grid{grid-template-columns:1fr;grid-template-rows:minmax(0,40%) minmax(0,1fr)}
  .scene:nth-child(even) .scene__frame{order:0}
  .scene__note,.scene:nth-child(even) .scene__note{border-left:0;border-right:0;border-top:1px solid var(--line);gap:.45rem}
  .scene p{font-size:.7rem}
  .scene pre{font-size:.52rem}
  .ledger__grid{grid-template-columns:repeat(2,1fr)}
  .ledger__cell b{font-size:.86rem}
  .ledger__cell span{font-size:.5rem;letter-spacing:.06em}
  .ledger p{font-size:.56rem}
  .stepper{gap:.5rem .7rem;font-size:.58rem;padding:.4rem var(--pad)}
  .stepper__dots button{width:9px;height:9px}
}

@media (prefers-reduced-motion:reduce){
  .overture{animation:none;min-height:0}
  .overture__mid{animation:none;max-height:0;opacity:0}
  .overture__bed{animation:none;transform:none;filter:grayscale(.35) contrast(1.12) brightness(.5)}
  .overture__bed.is-out{transition:none}
  .wordmark{animation:none;font-size:clamp(2.1rem,7vw,4rem)}
  .wordmark b{animation:none;transform:none}
  .tagline{animation:none;opacity:1}
  .row,.row__word,.stage,.scene{transition:none}
  .row__word{opacity:1;height:auto;transform:none}
  *{scroll-behavior:auto !important}
}
