/* Same adaptive type scale as case page titles, available before the page body loads. */
:root{--intro-title-size:34px;--intro-title-leading:36px}
/* The loading curtain is the inverse of the destination page, independent of its controls. */
html body>.page-intro-screen{
 position:fixed;inset:0;z-index:2147483000;display:grid;place-items:center;
 padding:32px;background:var(--intro-surface,#000000);color:var(--intro-ink,#fff);
 cursor:wait;overflow:hidden;pointer-events:auto;isolation:isolate;
 transform:translateY(0);transition:transform 650ms cubic-bezier(.76,0,.24,1);
}
html body>.page-intro-screen.is-leaving{transform:translateY(-101%);pointer-events:none}
html body>.page-intro-screen .page-intro-title{
 margin:0;max-width:100%;text-align:center;
 font-family:'Neue Montreal',Arial,sans-serif!important;
 font-size:var(--intro-title-size)!important;line-height:var(--intro-title-leading)!important;font-weight:600!important;font-variation-settings:"wght" 600!important;font-synthesis:none!important;
 letter-spacing:normal!important;text-transform:none;color:inherit;
}
.page-intro-word{
 display:inline-block;white-space:nowrap;clip-path:inset(0);
 padding-block:.12em;margin-block:-.12em;
}
.page-intro-char{
 display:inline-block;position:relative;text-shadow:0 calc(1lh + .24em) currentColor;
 transform:translateY(0);transition:transform .6s cubic-bezier(.625,.05,0,1);
 transition-delay:var(--letter-delay,0ms);
}
.title-roll .page-intro-char{transform:translateY(calc(-1lh - .24em))}
html{scrollbar-gutter:stable}
html.page-intro-active{overflow-y:scroll!important;overflow-x:clip!important}
html.page-intro-active body>.site-cursor,html.page-intro-active body>.hover-tooltip{visibility:hidden!important}
@media(prefers-reduced-motion:reduce){html body>.page-intro-screen{display:none}html.page-intro-active{overflow:initial!important}}

/* A direct Home visit never paints the curtain, even before deferred scripts run. */
html:not(.page-intro-active) body>.page-intro-screen{display:none!important}
/* The background wipes through square cells; the title keeps its existing roll. */
html body>.page-intro-screen,
html body>.page-intro-screen:is(.is-leaving,.is-covering,.cover-complete){
 transform:none;border-radius:0;transition:none;will-change:clip-path;
}
html body>.page-intro-screen.is-leaving{pointer-events:none}
html body>.page-intro-screen.is-covering{display:grid!important}
html body>.page-intro-screen.is-covering .page-intro-title{opacity:0}
/* Keep the desktop scrollbar present throughout the curtain; never resize the page. */
@media(hover:hover) and (pointer:fine){html{overflow-y:scroll}}
html body>.page-intro-screen{touch-action:none;overscroll-behavior:none}

/* Destination titles share the case title scale. */
html body>.page-intro-screen .page-intro-title{font-size:var(--intro-title-size)!important;line-height:var(--intro-title-leading)!important}

/* Animated letter spans must keep the case title face. */
html body>.page-intro-screen .page-intro-title,
html body>.page-intro-screen .page-intro-title *{
 font-family:'Neue Montreal',Arial,sans-serif!important;
 font-size:var(--intro-title-size)!important;line-height:var(--intro-title-leading)!important;font-weight:600!important;font-variation-settings:"wght" 600!important;font-synthesis:none!important;
 letter-spacing:normal!important;text-transform:none;
}

/* Pixel cells animate across the entire surface, with empty cells revealing the page. */
html body>.page-intro-screen{background:var(--intro-surface,#000000);will-change:auto}
html body>.page-intro-screen.has-pixel-wipe{background:transparent}
html body>.page-intro-screen .page-intro-pixels{position:absolute;inset:0;width:100%;height:100%;z-index:-1;pointer-events:none;image-rendering:pixelated}
html body>.page-intro-screen.is-leaving .page-intro-title{opacity:1;transition:none;will-change:transform}

/* Hold content until its original entrance motion is prepared after the wipe. */
html.page-intro-active body>main{visibility:hidden}
/* Paint a solid initial backing before deferred transition code is ready. */
html.page-intro-active:not(:has(.page-intro-screen))::before{
 content:'';position:fixed;inset:0;z-index:2147482999;background:#000000;pointer-events:none;
}
html.page-intro-active:has(body.home-page,body.case-page[data-case-theme="dark"]):not(:has(.page-intro-screen))::before{background:#fff}
@media(prefers-reduced-motion:reduce){html.page-intro-active body>main{visibility:visible}html.page-intro-active::before{display:none}}

/* Reveal real page content under the tail, never an intermediate empty canvas. */
html.page-intro-active.page-intro-revealing body>main{visibility:visible}
html.page-intro-active:has(body.home-page),
html.page-intro-active body.home-page{background:#000000!important}
html.page-intro-active:has(body.case-page[data-case-theme="dark"]),
html.page-intro-active body.case-page[data-case-theme="dark"]{background:#000000!important}
.page-intro-char{transition-duration:360ms;transition-delay:calc(var(--letter-delay,0ms) * .5)}

/* The outgoing page remains painted while the first curtain covers it. */
html.page-intro-active body.curtain-covering>main{visibility:visible}

/* Carry the outgoing surface and settled title across the document handoff. */
html.page-intro-active:not(:has(.page-intro-screen))::before{
 background:var(--intro-boot-surface,#000000)!important;
}
html body>.page-intro-screen.title-settled .page-intro-char{transition:none}

/* Explicit word gaps stay stable through letter rolls and document handoff. */
.page-intro-space{display:inline-block;width:.3em;white-space:pre;letter-spacing:normal!important}
/* The next document paints the same settled title before deferred scripts execute. */
.portfolio-curtain-boot .page-intro-title,
.portfolio-curtain-boot .page-intro-title *{
 font-family:'Neue Montreal',Arial,sans-serif!important;
 font-size:var(--intro-title-size)!important;line-height:var(--intro-title-leading)!important;font-weight:600!important;font-variation-settings:"wght" 600!important;font-synthesis:none!important;
 letter-spacing:normal!important;text-transform:none;
}
.portfolio-curtain-boot .page-intro-title{margin:0;max-width:100%;text-align:center}
/* Same compositing as the live curtain, so text antialiasing does not change when it takes over. */
.portfolio-curtain-boot{isolation:isolate;transform:none;will-change:clip-path}
.portfolio-curtain-boot,html body>.page-intro-screen{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
.portfolio-curtain-boot .page-intro-char{transform:translateY(calc(-1lh - .24em));transition:none}

/* Preserve the completed curtain while the browser swaps same-origin documents. */
@view-transition{navigation:auto}
::view-transition-group(*){animation-duration:0s!important}
::view-transition-old(root),::view-transition-new(root){animation:none!important;mix-blend-mode:normal}
html.page-intro-active *{view-transition-name:none!important}

/* One backing only: no destination-colored placeholder may cover the carried curtain. */
html.page-intro-active:not(:has(.page-intro-screen,.portfolio-curtain-boot))::before{
 background:var(--intro-boot-surface,#000000)!important;
}

/* Keep the curtain raster opaque; only its torn edge contains transparent pixels. */
html body>.page-intro-screen,html .portfolio-curtain-boot {opacity:1!important;filter:none!important;mix-blend-mode:normal!important;}
html body>.page-intro-screen .page-intro-pixels {opacity:1!important;filter:none!important;mix-blend-mode:normal!important;}
html body>.page-intro-screen .page-intro-title,
html body>.page-intro-screen .page-intro-title *,
html .portfolio-curtain-boot .page-intro-title,
html .portfolio-curtain-boot .page-intro-title * {font-weight:600!important;font-variation-settings:'wght' 600!important;font-size:40px!important;line-height:1.2!important;}
.case-transition-letter-mask{display:inline-block;overflow:hidden;vertical-align:top;height:1.25em;line-height:1.25;white-space:pre;}
.case-transition-letter{display:inline-block;will-change:transform;}
