@@ -541,18 +541,47 @@ button, input { font-family: inherit; }
541541/* Apply the gooey threshold filter only while morphing.
542542 The filter snap is what creates the crisp dissolve from blurry pixels. */
543543.projector-topic-stage .is-morphing {
544+ --projector-topic-slide-distance : clamp (1.5rem , 3.2vw , 2.6rem );
544545 filter : none;
545546}
546547
548+ .projector-topic-stage .is-slide-morph {
549+ padding-left : clamp (0.6rem , 1.25vw , 1.1rem );
550+ }
551+
552+ .projector-topic-morph-shell {
553+ position : relative;
554+ min-height : 0 ;
555+ height : 100% ;
556+ overflow : hidden;
557+ }
558+
547559.projector-topic-morph {
548560 position : relative;
549561 min-height : 0 ;
550562 height : 100% ;
551563 overflow : hidden;
552564}
553565
554- .projector-topic-morph .is-morphing {
555- filter : url(# to pic- mor ph-threshold) blur(0.6px );
566+ .projector-topic-stage .is-gooey-morph .projector-topic-morph-shell .is-morphing {
567+ overflow : hidden;
568+ filter : none;
569+ -webkit-filter : none;
570+ pointer-events : none;
571+ }
572+
573+ .projector-topic-stage .is-gooey-morph .projector-topic-morph .is-morphing {
574+ overflow : hidden;
575+ filter : url ("#topic-morph-threshold" ) blur (0.6px );
576+ -webkit-filter : url ("#topic-morph-threshold" ) blur (0.6px );
577+ pointer-events : none;
578+ }
579+
580+ .projector-topic-morph-shell .is-slide-morph ,
581+ .projector-topic-morph .is-slide-morph {
582+ overflow : hidden;
583+ filter : none;
584+ -webkit-filter : none;
556585 pointer-events : none;
557586}
558587
@@ -587,6 +616,20 @@ button, input { font-family: inherit; }
587616 will-change : filter, opacity;
588617}
589618
619+ .projector-topic-stage .is-slide-morph .projector-topic-layer {
620+ will-change : transform, opacity;
621+ }
622+
623+ .projector-topic-stage .is-slide-morph .projector-topic-layer--from {
624+ animation : projector-topic-slide-out var (--topic-slide-duration , 560ms )
625+ cubic-bezier (0.22 , 0.78 , 0.24 , 1 ) both;
626+ }
627+
628+ .projector-topic-stage .is-slide-morph .projector-topic-layer--to {
629+ animation : projector-topic-slide-in var (--topic-slide-duration , 560ms )
630+ cubic-bezier (0.18 , 0.84 , 0.28 , 1 ) both;
631+ }
632+
590633/* Static (non-morphing) layer sits normally */
591634.projector-topic-layer--current {
592635 position : absolute;
@@ -687,6 +730,18 @@ button, input { font-family: inherit; }
687730 z-index : 1 ;
688731}
689732
733+ .projector-subtopic-measure {
734+ position : absolute;
735+ display : inline-block;
736+ left : 0 ;
737+ top : 0 ;
738+ width : max-content;
739+ max-width : none;
740+ white-space : nowrap;
741+ visibility : hidden;
742+ pointer-events : none;
743+ }
744+
690745.projector-subtopic-viewport ::before ,
691746.projector-subtopic-viewport ::after {
692747 content : "" ;
@@ -799,6 +854,32 @@ button, input { font-family: inherit; }
799854 to { transform : translateX (calc (-1 * var (--subtopic-pan-loop-distance , 0px ))); }
800855}
801856
857+ @keyframes projector-topic-slide-out {
858+ from {
859+ opacity : 1 ;
860+ transform : translateY (0 );
861+ }
862+ to {
863+ opacity : 0 ;
864+ transform : translateY (
865+ calc (-1 * var (--projector-topic-slide-direction , 1 ) * var (--projector-topic-slide-distance ))
866+ );
867+ }
868+ }
869+
870+ @keyframes projector-topic-slide-in {
871+ from {
872+ opacity : 0 ;
873+ transform : translateY (
874+ calc (var (--projector-topic-slide-direction , 1 ) * var (--projector-topic-slide-distance ))
875+ );
876+ }
877+ to {
878+ opacity : 1 ;
879+ transform : translateY (0 );
880+ }
881+ }
882+
802883/* Suppress CSS opacity transitions during morph — JS controls opacity directly */
803884.projector-topic-morph .is-morphing .projector-topic-card h2 ,
804885.projector-topic-morph .is-morphing .projector-topic-card li {
@@ -1330,23 +1411,33 @@ button, input { font-family: inherit; }
13301411 .projector-topic-stage {
13311412 border-left : 0 ;
13321413 border-top : 0 ;
1333- padding-left : 0 ;
1414+ padding-left : 0.35 rem ;
13341415 padding-top : 0.25rem ;
13351416 height : 100% ;
13361417 min-height : 0 ;
13371418 }
13381419
1420+ .projector-topic-stage .is-morphing {
1421+ --projector-topic-slide-distance : 1.3rem ;
1422+ }
1423+
1424+ .projector-topic-stage .is-slide-morph {
1425+ padding-left : 0.35rem ;
1426+ }
1427+
13391428 .projector-topic-stage ::after {
13401429 bottom : -3px ;
13411430 }
13421431
1432+ .projector-topic-morph-shell ,
13431433 .projector-topic-morph {
13441434 height : 100% ;
13451435 min-height : 0 ;
13461436 }
13471437
13481438 .projector-topic-layer {
1349- padding-top : 0.25rem ;
1439+ padding : 0.25rem 0.35rem
1440+ calc (var (--projector-content-end-gap ) + var (--projector-topic-scroll-end-gap )) 0.35rem ;
13501441 }
13511442
13521443 .projector-topic-heading {
@@ -1384,6 +1475,14 @@ button, input { font-family: inherit; }
13841475 filter : none;
13851476 }
13861477
1478+ .projector-topic-morph-shell .is-morphing ,
1479+ .projector-topic-morph .is-morphing ,
1480+ .projector-topic-morph-shell .is-slide-morph ,
1481+ .projector-topic-morph .is-slide-morph {
1482+ filter : none;
1483+ -webkit-filter : none;
1484+ }
1485+
13871486 .projector-topic-morph .is-morphing .projector-topic-layer h2 ,
13881487 .projector-topic-morph .is-morphing .projector-topic-layer li ,
13891488 .projector-topic-morph .is-morphing .projector-topic-layer .projector-topic-heading {
0 commit comments