2026-05-12 15:18:16 +08:00
<!DOCTYPE html>
< html lang = 'en' >
< head >
< meta charset = 'utf-8' />
< meta name = 'viewport' content = 'width=device-width, initial-scale=1' />
2026-07-10 17:41:47 +08:00
< title > Turn a Study into a Lab Meeting Deck like a Senior Postdoc - Academic research</ title >
< meta name = 'description' content = 'A gut-microbiome lab-meeting research deck on kami parchment. Warm parchment with ink-blue cover and chapter slides, serif at one weight, no italic.' />
2026-05-12 15:18:16 +08:00
< link rel = 'preconnect' href = 'https://fonts.googleapis.com' />
< link rel = 'preconnect' href = 'https://fonts.gstatic.com' crossorigin />
2026-06-16 16:41:04 +08:00
< link href = 'https://fonts.googleapis.com/css2?family=Source+Serif+4:wght@400;500&family=Source+Sans+3:wght@400;500&family=JetBrains+Mono:wght@400;500&display=swap' rel = 'stylesheet' />
2026-05-12 15:18:16 +08:00
< style >
/*
* kami-deck — single-file slide deck stylesheet.
*
* Kami token language (warm parchment, ink-blue accent, serif at one
* weight, no italic) — but laid out as a horizontal swipe deck. Macro
* tokens are scaled × ~1.6 vs. print baseline; letter-spacing scaled
* × ~0.6 (per design-systems/kami/DESIGN.md §3).
*
* Navigation model is borrowed from skills/guizang-ppt — same flex
* track + transform translateX, same key/wheel/touch handlers.
*/
: root {
/* surface */
--parchment : #f5f4ed ;
--ivory : #faf9f5 ;
/* brand (single chromatic accent) */
--brand : #1B365D ;
--brand-light : #2D5A8A ;
2026-06-16 16:41:04 +08:00
--brand-steel : #B5C8DC ; /* highlight ink on navy: cover/end .hl */
2026-05-12 15:18:16 +08:00
/* text */
--near-black : #141413 ;
--dark-warm : #3d3d3a ;
--olive : #504e49 ;
--stone : #6b6a64 ;
/* border */
--border : #e8e6dc ;
--border-soft : #e5e3d8 ;
/* tag tints (solid hex, NEVER rgba) */
--tag-08 : #EEF2F7 ;
--tag-14 : #E4ECF5 ;
/* type */
--serif : 'Source Serif 4' , Charter , Georgia , Palatino , 'Times New Roman' , serif ;
--sans : 'Source Sans 3' , - apple-system , BlinkMacSystemFont , 'Segoe UI' , system-ui , sans-serif ;
--mono : 'JetBrains Mono' , 'SF Mono' , 'Fira Code' , Consolas , Monaco , monospace ;
}
* { box-sizing : border-box ; margin : 0 ; padding : 0 ; }
html , body {
width : 100 % ; height : 100 % ;
overflow : hidden ;
background : var ( -- parchment );
color : var ( -- near - black );
font-family : var ( -- serif );
font-weight : 400 ;
-webkit- font-smoothing : antialiased ;
}
strong { font-weight : 500 ; }
/* ---------- deck flex track ---------- */
# deck {
position : fixed ; inset : 0 ;
height : 100 vh ;
display : flex ;
flex-wrap : nowrap ;
transition : transform 0.9 s cubic-bezier ( 0.77 , 0 , 0.175 , 1 );
z-index : 5 ;
will-change : transform ;
}
. slide {
width : 100 vw ; height : 100 vh ;
flex : 0 0 100 vw ;
position : relative ;
padding : 80 px 96 px ;
display : flex ;
flex-direction : column ;
overflow : hidden ;
background : var ( -- parchment );
color : var ( -- near - black );
}
. slide . dark {
background : var ( -- brand );
color : var ( -- ivory );
}
. slide-inner {
max-width : 1280 px ;
margin : 0 auto ;
width : 100 % ;
height : 100 % ;
display : grid ;
align-content : center ;
gap : 24 px ;
position : relative ;
min-height : 0 ;
}
/* ---------- per-slide chrome strip ---------- */
. slide-chrome {
position : absolute ;
top : 28 px ; left : 0 ; right : 0 ;
display : flex ;
justify-content : space-between ;
align-items : center ;
padding : 0 96 px ;
font-family : var ( -- sans );
font-size : 11 px ;
font-weight : 500 ;
letter-spacing : 0.6 px ;
text-transform : uppercase ;
color : var ( -- stone );
z-index : 4 ;
pointer-events : none ;
}
2026-06-16 16:41:04 +08:00
. slide . dark . slide-chrome { color : rgba ( 250 , 249 , 245 , 0.74 ); } /* 11px caps on navy: keep >= AA */
2026-05-12 15:18:16 +08:00
. slide-chrome b { color : var ( -- near - black ); font-weight : 500 ; }
. slide . dark . slide-chrome b { color : var ( -- ivory ); }
. slide-chrome . left { display : inline-flex ; align-items : center ; gap : 12 px ; }
. slide-chrome . right {
display : inline-flex ; align-items : center ; gap : 12 px ;
font-variant-numeric : tabular-nums ;
}
. slide-chrome . mark {
2026-06-16 16:41:04 +08:00
/* printer's mark: square hairline seal, not a generic pill chip */
height : 22 px ;
padding : 0 9 px ;
border-radius : 2 px ;
2026-05-12 15:18:16 +08:00
border : 1 px solid currentColor ;
display : inline-flex ;
align-items : center ;
justify-content : center ;
font-family : var ( -- serif );
font-weight : 500 ;
font-size : 11 px ;
2026-06-16 16:41:04 +08:00
letter-spacing : 0.5 px ;
text-transform : lowercase ;
2026-05-12 15:18:16 +08:00
opacity : 0.85 ;
}
. slide-foot {
position : absolute ;
bottom : 28 px ; left : 0 ; right : 0 ;
display : flex ;
justify-content : space-between ;
align-items : center ;
padding : 0 96 px ;
font-family : var ( -- mono );
font-size : 10.5 px ;
letter-spacing : 0.4 px ;
color : var ( -- stone );
font-variant-numeric : tabular-nums ;
z-index : 4 ;
pointer-events : none ;
}
2026-06-16 16:41:04 +08:00
. slide . dark . slide-foot { color : rgba ( 250 , 249 , 245 , 0.74 ); } /* 10.5px mono on navy: keep >= AA */
2026-05-12 15:18:16 +08:00
. slide-foot . counter {
font-family : var ( -- mono );
letter-spacing : 0.04 em ;
color : var ( -- near - black );
background : var ( -- ivory );
padding : 4 px 8 px ;
border : 1 px solid var ( -- border );
2026-06-16 16:41:04 +08:00
border-radius : 2 px ; /* match the square hairline language of the mark */
2026-05-12 15:18:16 +08:00
}
. slide . dark . slide-foot . counter {
color : var ( -- ivory );
background : rgba ( 250 , 249 , 245 , 0.08 );
border-color : rgba ( 250 , 249 , 245 , 0.22 );
}
/* ---------- progress bar ---------- */
. deck-progress {
position : fixed ;
left : 0 ; right : 0 ; bottom : 0 ;
height : 2 px ;
background : rgba ( 27 , 54 , 93 , 0.08 );
z-index : 30 ;
}
. deck-progress . bar {
height : 100 % ;
background : var ( -- brand );
width : 0 % ;
transition : width 0.6 s cubic-bezier ( 0.77 , 0 , 0.175 , 1 );
}
/* ---------- dot nav ---------- */
# nav {
position : fixed ;
left : 50 % ;
bottom : 40 px ;
transform : translateX ( -50 % );
z-index : 30 ;
display : flex ;
gap : 9 px ;
padding : 8 px 14 px ;
2026-06-16 16:41:04 +08:00
/* flat parchment strip with a hairline, square corners: the glassy
blurred pill was outside the kami print language */
border-radius : 2 px ;
background : rgba ( 245 , 244 , 237 , 0.92 );
2026-05-12 15:18:16 +08:00
border : 1 px solid var ( -- border );
}
# nav . dot {
width : 7 px ; height : 7 px ;
border-radius : 50 % ;
background : rgba ( 27 , 54 , 93 , 0.22 );
cursor : pointer ;
2026-06-16 16:41:04 +08:00
transition : background-color 0.3 s cubic-bezier ( 0.16 , 1 , 0.3 , 1 ),
width 0.3 s cubic-bezier ( 0.16 , 1 , 0.3 , 1 ),
transform 0.3 s cubic-bezier ( 0.16 , 1 , 0.3 , 1 );
2026-05-12 15:18:16 +08:00
border : 0 ;
padding : 0 ;
}
# nav . dot : hover {
background : rgba ( 27 , 54 , 93 , 0.5 );
transform : scale ( 1.15 );
}
# nav . dot . active {
background : var ( -- brand );
width : 22 px ;
2026-06-16 16:41:04 +08:00
border-radius : 1 px ; /* active marker reads as an ink dash, not a capsule */
2026-05-12 15:18:16 +08:00
}
# hint {
position : fixed ;
2026-06-16 16:41:04 +08:00
bottom : 64 px ; right : 28 px ;
2026-05-12 15:18:16 +08:00
z-index : 30 ;
font-family : var ( -- mono );
font-size : 10 px ;
letter-spacing : 0.4 px ;
text-transform : uppercase ;
color : var ( -- stone );
2026-06-16 16:41:04 +08:00
/* hint floats over both parchment and navy slides; bare stone text was
sub-AA on the dark cover/end, so it gets the same parchment hairline
chip language as the nav strip and counter */
background : rgba ( 245 , 244 , 237 , 0.92 );
border : 1 px solid var ( -- border );
border-radius : 2 px ;
padding : 5 px 9 px ;
2026-05-12 15:18:16 +08:00
}
/* ---------- COVER slide (dark) ---------- */
2026-06-16 16:41:04 +08:00
/* opening beat: transform+opacity only, ease-out, staggered 0.08s.
Scoped to the cover; the swipe track paints every slide at load, so
animating all of them would burn the effect off-screen. */
@ keyframes kami-rise {
from { opacity : 0 ; transform : translateY ( 18 px ); }
to { opacity : 1 ; transform : none ; }
}
. s-cover . slide-inner > * {
animation : kami-rise 0.7 s cubic-bezier ( 0.16 , 1 , 0.3 , 1 ) both ;
}
. s-cover . slide-inner > * : nth-child ( 2 ) { animation-delay : 0.08 s ; }
. s-cover . slide-inner > * : nth-child ( 3 ) { animation-delay : 0.16 s ; }
. s-cover . slide-inner > * : nth-child ( 4 ) { animation-delay : 0.24 s ; }
2026-05-12 15:18:16 +08:00
. s-cover . slide-inner {
grid-template-columns : 1 fr ;
text-align : left ;
align-content : center ;
gap : 28 px ;
max-width : 980 px ;
}
. s-cover . eyebrow {
font-family : var ( -- sans );
font-size : 12 px ;
font-weight : 500 ;
letter-spacing : 1.2 px ;
text-transform : uppercase ;
2026-06-16 16:41:04 +08:00
color : rgba ( 250 , 249 , 245 , 0.74 ); /* small caps on navy: keep >= AA */
2026-05-12 15:18:16 +08:00
}
. s-cover h1 {
font-family : var ( -- serif );
font-weight : 500 ;
font-size : clamp ( 60 px , 7 vw , 110 px );
line-height : 1.05 ;
letter-spacing : -1.2 px ;
color : var ( -- ivory );
margin : 0 ;
}
2026-06-16 16:41:04 +08:00
. s-cover h1 . hl { color : var ( -- brand - steel ); }
2026-05-12 15:18:16 +08:00
. s-cover . tagline {
font-family : var ( -- serif );
font-weight : 500 ;
font-size : 21 px ;
color : rgba ( 250 , 249 , 245 , 0.75 );
max-width : 50 ch ;
line-height : 1.45 ;
}
. s-cover . meta {
margin-top : 20 px ;
display : flex ;
align-items : center ;
2026-06-16 16:41:04 +08:00
flex-wrap : wrap ;
gap : 14 px 20 px ;
2026-05-12 15:18:16 +08:00
font-family : var ( -- mono );
font-size : 11 px ;
letter-spacing : 0.4 px ;
text-transform : uppercase ;
2026-06-16 16:41:04 +08:00
color : rgba ( 250 , 249 , 245 , 0.72 ); /* 11px mono on navy: keep >= AA */
2026-05-12 15:18:16 +08:00
font-variant-numeric : tabular-nums ;
}
. s-cover . meta . rule {
width : 56 px ; height : 1 px ;
background : rgba ( 250 , 249 , 245 , 0.4 );
display : inline-block ;
}
/* ---------- CHAPTER divider (dark) ---------- */
. s-chapter . slide-inner {
grid-template-columns : 1 fr ;
text-align : center ;
align-content : center ;
gap : 36 px ;
}
. s-chapter . num {
font-family : var ( -- serif );
font-weight : 500 ;
font-size : clamp ( 64 px , 8 vw , 130 px );
2026-06-16 16:41:04 +08:00
color : rgba ( 250 , 249 , 245 , 0.62 ); /* ghosted chapter numeral, kept >= 3:1 for large text */
2026-05-12 15:18:16 +08:00
letter-spacing : -0.5 px ;
line-height : 1 ;
font-variant-numeric : tabular-nums ;
}
. s-chapter h2 {
font-family : var ( -- serif );
font-weight : 500 ;
font-size : clamp ( 48 px , 5.4 vw , 84 px );
line-height : 1.1 ;
letter-spacing : -0.6 px ;
color : var ( -- ivory );
margin : 0 auto ;
max-width : 22 ch ;
}
. s-chapter . lede {
font-family : var ( -- serif );
font-weight : 500 ;
font-size : 19 px ;
2026-06-16 16:41:04 +08:00
color : rgba ( 250 , 249 , 245 , 0.78 );
2026-05-12 15:18:16 +08:00
max-width : 42 ch ;
margin : 0 auto ;
line-height : 1.5 ;
}
/* ---------- CONTENT slide ---------- */
. s-content . slide-inner {
grid-template-columns : 1 fr 2.4 fr ;
gap : 56 px ;
align-content : center ;
}
. s-content . layout-full . slide-inner { grid-template-columns : 1 fr ; max-width : 980 px ; }
. s-content . head { display : flex ; flex-direction : column ; gap : 16 px ; }
. s-content . num {
font-family : var ( -- serif );
font-weight : 500 ;
font-size : 14 px ;
letter-spacing : 0.4 px ;
color : var ( -- brand );
font-variant-numeric : tabular-nums ;
}
. s-content h2 {
font-family : var ( -- serif );
font-weight : 500 ;
font-size : clamp ( 36 px , 4 vw , 56 px );
line-height : 1.1 ;
2026-06-16 16:41:04 +08:00
letter-spacing : -0.6 px ;
2026-05-12 15:18:16 +08:00
color : var ( -- near - black );
margin : 0 ;
max-width : 14 ch ;
}
. s-content . lede {
font-family : var ( -- serif );
font-weight : 500 ;
font-size : 15 px ;
color : var ( -- olive );
max-width : 28 ch ;
line-height : 1.5 ;
}
. s-content . body { display : flex ; flex-direction : column ; gap : 18 px ; }
. s-content . body p {
font-family : var ( -- serif );
font-weight : 400 ;
font-size : 17 px ;
line-height : 1.55 ;
color : var ( -- dark - warm );
max-width : 64 ch ;
}
. s-content . body p strong { color : var ( -- near - black ); font-weight : 500 ; }
. s-content . body code {
font-family : var ( -- mono );
font-size : 14 px ;
color : var ( -- brand );
background : var ( -- tag -08 );
padding : 1 px 6 px ;
border-radius : 3 px ;
}
. s-content ul . dash {
list-style : none ; padding : 0 ; margin : 4 px 0 0 ;
display : flex ; flex-direction : column ; gap : 10 px ;
}
. s-content ul . dash li {
position : relative ; padding-left : 18 px ;
font-family : var ( -- serif );
font-weight : 400 ;
font-size : 16 px ;
line-height : 1.55 ;
color : var ( -- dark - warm );
}
. s-content ul . dash li :: before {
2026-06-16 16:41:04 +08:00
/* hairline tick instead of a literal dash glyph (anti-slop: no -/-- in visible text) */
content : '' ;
position : absolute ; left : 0 ; top : 0.72 em ;
width : 10 px ; height : 1 px ;
background : var ( -- brand );
2026-05-12 15:18:16 +08:00
}
. s-content . body . tag-row { margin-top : 4 px ; }
. s-content . tag {
display : inline-block ;
font-family : var ( -- sans );
font-size : 12 px ;
font-weight : 500 ;
padding : 2 px 8 px ;
2026-06-16 16:41:04 +08:00
border-radius : 2 px ;
2026-05-12 15:18:16 +08:00
color : var ( -- brand );
background : var ( -- tag -14 );
letter-spacing : 0.4 px ;
}
/* ---------- STATS slide ---------- */
. s-stats . slide-inner { grid-template-columns : 1 fr ; gap : 48 px ; }
. s-stats . head { display : flex ; flex-direction : column ; gap : 18 px ; }
. s-stats . num {
font-family : var ( -- serif );
font-weight : 500 ;
font-size : 14 px ;
letter-spacing : 0.4 px ;
color : var ( -- brand );
font-variant-numeric : tabular-nums ;
}
. s-stats h2 {
font-family : var ( -- serif );
font-weight : 500 ;
font-size : clamp ( 36 px , 4.2 vw , 60 px );
line-height : 1.1 ;
2026-06-16 16:41:04 +08:00
letter-spacing : -0.6 px ;
2026-05-12 15:18:16 +08:00
color : var ( -- near - black );
max-width : 22 ch ;
margin : 0 ;
}
. s-stats . grid {
display : grid ;
grid-template-columns : repeat ( auto - fit , minmax ( 200 px , 1 fr ));
gap : 0 ;
border-top : 1 px solid var ( -- border );
border-bottom : 1 px solid var ( -- border );
}
. s-stats . stat {
padding : 32 px 24 px 28 px ;
display : flex ;
flex-direction : column ;
gap : 8 px ;
border-right : 1 px solid var ( -- border - soft );
}
. s-stats . stat : last-child { border-right : 0 ; }
. s-stats . stat . v {
font-family : var ( -- serif );
font-weight : 500 ;
font-size : clamp ( 48 px , 6 vw , 88 px );
line-height : 1 ;
letter-spacing : -0.8 px ;
color : var ( -- brand );
font-variant-numeric : tabular-nums ;
}
. s-stats . stat . l {
font-family : var ( -- serif );
font-weight : 500 ;
font-size : 15 px ;
color : var ( -- near - black );
margin-top : 8 px ;
}
. s-stats . stat . s {
font-family : var ( -- serif );
font-weight : 400 ;
font-size : 13 px ;
color : var ( -- olive );
line-height : 1.5 ;
max-width : 28 ch ;
}
. s-stats . caption {
font-family : var ( -- mono );
font-size : 11 px ;
color : var ( -- stone );
letter-spacing : 0.4 px ;
font-variant-numeric : tabular-nums ;
}
/* ---------- QUOTE slide ---------- */
. s-quote . slide-inner {
grid-template-columns : 1 fr ;
max-width : 1080 px ;
gap : 36 px ;
align-content : center ;
}
. s-quote blockquote {
border-left : 2 px solid var ( -- brand );
padding : 6 px 0 6 px 28 px ;
font-family : var ( -- serif );
font-weight : 500 ;
font-size : clamp ( 28 px , 3.4 vw , 42 px );
2026-06-16 16:41:04 +08:00
line-height : 1.32 ;
2026-05-12 15:18:16 +08:00
color : var ( -- near - black );
margin : 0 ;
2026-06-16 16:41:04 +08:00
letter-spacing : -0.4 px ; /* display serif tracks tight, matching h1/h2; loose +tracking was residue */
2026-05-12 15:18:16 +08:00
max-width : 36 ch ;
}
. s-quote . author {
display : flex ;
align-items : center ;
gap : 16 px ;
margin-top : 12 px ;
}
. s-quote . author . glyph {
2026-06-16 16:41:04 +08:00
/* hanko-style seal: hairline square in brand ink, not a solid avatar disc */
width : 40 px ; height : 40 px ;
border-radius : 3 px ;
border : 1 px solid var ( -- brand );
background : transparent ; color : var ( -- brand );
2026-05-12 15:18:16 +08:00
font-family : var ( -- serif ); font-weight : 500 ;
2026-06-16 16:41:04 +08:00
font-size : 17 px ;
2026-05-12 15:18:16 +08:00
display : inline-flex ;
align-items : center ;
justify-content : center ;
text-transform : uppercase ;
letter-spacing : 0 ;
}
. s-quote . author p {
font-family : var ( -- serif );
font-weight : 500 ;
font-size : 14 px ;
color : var ( -- near - black );
}
. s-quote . author p span {
display : block ;
color : var ( -- olive );
font-weight : 400 ;
margin-top : 2 px ;
}
/* ---------- CTA slide ---------- */
. s-cta . slide-inner {
grid-template-columns : 1 fr ;
max-width : 980 px ;
gap : 28 px ;
align-content : center ;
text-align : left ;
}
. s-cta . eyebrow {
font-family : var ( -- sans );
font-size : 12 px ; font-weight : 500 ;
letter-spacing : 1.2 px ;
text-transform : uppercase ;
color : var ( -- brand );
}
. s-cta h2 {
font-family : var ( -- serif );
font-weight : 500 ;
font-size : clamp ( 48 px , 5.4 vw , 88 px );
line-height : 1.05 ;
letter-spacing : -0.6 px ;
color : var ( -- near - black );
margin : 0 ;
}
. s-cta . body {
font-family : var ( -- serif );
font-weight : 400 ;
font-size : 17 px ;
color : var ( -- dark - warm );
max-width : 50 ch ;
line-height : 1.55 ;
}
. s-cta . actions {
display : inline-flex ;
gap : 12 px ;
margin-top : 12 px ;
align-items : center ;
flex-wrap : wrap ;
}
. s-cta . btn {
display : inline-flex ;
align-items : center ;
gap : 8 px ;
font-family : var ( -- sans );
font-size : 13 px ;
font-weight : 500 ;
letter-spacing : 0.4 px ;
2026-06-16 16:41:04 +08:00
padding : 11 px 18 px ;
border-radius : 2 px ;
2026-05-12 15:18:16 +08:00
border : 0 ;
cursor : pointer ;
text-decoration : none ;
}
. s-cta . btn-primary {
background : var ( -- brand );
color : var ( -- ivory );
box-shadow : 0 0 0 1 px var ( -- brand );
}
. s-cta . btn-primary : hover { background : var ( -- brand - light ); box-shadow : 0 0 0 1 px var ( -- brand - light ); }
. s-cta . btn-ghost {
background : transparent ;
color : var ( -- brand );
box-shadow : 0 0 0 1 px var ( -- brand );
}
. s-cta . btn-ghost : hover { background : var ( -- tag -08 ); }
/* ---------- END slide (dark) ---------- */
. s-end . slide-inner {
grid-template-columns : 1 fr ;
align-content : end ;
padding-bottom : 24 px ;
text-align : left ;
gap : 18 px ;
max-width : none ;
}
. s-end . word {
font-family : var ( -- serif );
font-weight : 500 ;
2026-08-18 07:09:45 +00:00
/* 16vw clipped "OpenDesign." mid-glyph behind overflow-x: hidden at every
2026-06-16 16:41:04 +08:00
common width (needs ~0.93vw of run length vs ~0.85vw available after
padding); 13vw keeps the full word on screen. */
font-size : clamp ( 88 px , 13 vw , 210 px );
2026-05-12 15:18:16 +08:00
line-height : 1 ;
letter-spacing : -1.2 px ;
color : var ( -- ivory );
white-space : nowrap ;
overflow-x : hidden ;
}
2026-06-16 16:41:04 +08:00
. s-end . word . hl { color : var ( -- brand - steel ); }
2026-05-12 15:18:16 +08:00
. s-end . colophon {
border-top : 1 px solid rgba ( 250 , 249 , 245 , 0.22 );
padding-top : 22 px ;
font-family : var ( -- sans );
font-size : 11 px ;
font-weight : 500 ;
letter-spacing : 1.2 px ;
text-transform : uppercase ;
2026-06-16 16:41:04 +08:00
color : rgba ( 250 , 249 , 245 , 0.74 ); /* 11px caps colophon on navy: keep >= AA */
2026-05-12 15:18:16 +08:00
font-variant-numeric : tabular-nums ;
}
/* ---------- ESC overview ---------- */
# overview {
position : fixed ; inset : 0 ;
z-index : 100 ;
2026-06-16 16:41:04 +08:00
background : rgba ( 245 , 244 , 237 , 0.98 ); /* near-solid parchment sheet, no glass blur */
2026-05-12 15:18:16 +08:00
display : none ;
overflow-y : auto ;
padding : 60 px 56 px ;
}
# overview . ov-head {
display : flex ; justify-content : space-between ; align-items : baseline ;
margin-bottom : 32 px ;
font-family : var ( -- sans ); font-size : 11 px ;
letter-spacing : 1.2 px ; text-transform : uppercase ;
color : var ( -- stone );
font-variant-numeric : tabular-nums ;
}
# overview . ov-head b { color : var ( -- near - black ); font-weight : 500 ; }
# overview . ov-grid {
display : grid ;
grid-template-columns : repeat ( auto - fit , minmax ( 220 px , 1 fr ));
gap : 22 px ;
max-width : 1280 px ;
margin : 0 auto ;
}
# overview . ov-card {
cursor : pointer ;
2026-06-16 16:41:04 +08:00
border-radius : 3 px ;
2026-05-12 15:18:16 +08:00
overflow : hidden ;
border : 1 px solid var ( -- border );
transition : border-color 0.2 s , transform 0.2 s ;
background : var ( -- ivory );
}
# overview . ov-card : hover { border-color : var ( -- brand ); transform : translateY ( -2 px ); }
# overview . ov-card . active { border-color : var ( -- brand ); border-width : 2 px ; }
# overview . ov-thumb {
width : 100 % ;
aspect-ratio : 16 / 10 ;
overflow : hidden ;
position : relative ;
pointer-events : none ;
background : var ( -- parchment );
}
# overview . ov-thumb . clone {
width : 100 vw ; height : 100 vh ;
transform : scale ( 0.18 );
transform-origin : top left ;
position : absolute ;
top : 0 ; left : 0 ;
pointer-events : none ;
}
# overview . ov-label {
padding : 8 px 12 px ;
font-family : var ( -- mono ); font-size : 10 px ;
letter-spacing : 0.4 px ; text-transform : uppercase ;
color : var ( -- stone );
display : flex ; justify-content : space-between ; align-items : center ;
font-variant-numeric : tabular-nums ;
}
# overview . ov-label b { color : var ( -- near - black ); font-weight : 500 ; }
2026-06-16 16:41:04 +08:00
/* ---------- reduced motion ---------- */
@ media ( prefers-reduced-motion : reduce ) {
# deck { transition : none ; }
. s-cover . slide-inner > * { animation : none ; }
. deck-progress . bar { transition : none ; }
# nav . dot { transition : none ; }
# overview . ov-card { transition : none ; }
# overview . ov-card : hover { transform : none ; }
}
2026-05-12 15:18:16 +08:00
/* ---------- responsive ---------- */
@ media ( max-width : 1080px ) {
. slide { padding : 64 px 56 px ; }
. slide-chrome , . slide-foot { padding : 0 56 px ; }
. s-content . slide-inner { grid-template-columns : 1 fr ; gap : 28 px ; }
}
@ media ( max-width : 640px ) {
. slide { padding : 44 px 28 px ; }
. slide-chrome , . slide-foot { padding : 0 28 px ; font-size : 9.5 px ; letter-spacing : 0.6 px ; }
# hint { display : none ; }
}
</ style >
</ head >
< body >
< div id = 'deck' >
<!-- ===== 01 · COVER (dark) ===== -->
< section class = 'slide s-cover dark' data-slide-kind = 'cover' >
< div class = 'slide-chrome' >
2026-07-10 17:41:47 +08:00
< span class = 'left' >< span class = 'mark' > kami</ span > < b > Raman Lab</ b > · Lab Meeting · Week 14</ span >
< span class = 'right' > Gut-Sleep Cohort · Academic research</ span >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'slide-inner' >
2026-07-10 17:41:47 +08:00
< span class = 'eyebrow' > Lab meeting · Raman Lab · Week 14</ span >
< h1 > Gut microbes track < span class = 'hl' > deep sleep</ span > , not total sleep.</ h1 >
< p class = 'tagline' > A 6-week shotgun-metagenomics cohort linking the Bacteroides:Firmicutes ratio to slow-wave sleep duration — the design, the results, and what we still can't claim.</ p >
2026-05-12 15:18:16 +08:00
< div class = 'meta' >
2026-07-10 17:41:47 +08:00
< span > n = 64 adults · PSG subsample n = 22</ span >
2026-05-12 15:18:16 +08:00
< span class = 'rule' ></ span >
2026-07-10 17:41:47 +08:00
< span > Dept. of Neuroscience · Sleep & Microbiome Lab</ span >
2026-05-12 15:18:16 +08:00
</ div >
</ div >
< div class = 'slide-foot' >
2026-07-10 17:41:47 +08:00
< span > Raman Lab · MMXXVI</ span >
2026-05-12 15:18:16 +08:00
< span class = 'counter' > 01 / 09</ span >
</ div >
</ section >
<!-- ===== 02 · CHAPTER (dark) ===== -->
< section class = 'slide s-chapter dark' data-slide-kind = 'chapter' >
< div class = 'slide-chrome' >
2026-07-10 17:41:47 +08:00
< span class = 'left' >< span class = 'mark' > kami</ span > < b > Raman Lab</ b > · Lab Meeting · Week 14</ span >
< span class = 'right' > Gut-Sleep Cohort · Academic research</ span >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'slide-inner' >
< p class = 'num' > 01</ p >
2026-07-10 17:41:47 +08:00
< h2 > The field: fast-moving, still noisy.</ h2 >
< p class = 'lede' > Rodent work shows the gut-brain axis can shape sleep causally, through short-chain fatty acids and vagal afferents. Human evidence stays correlational, small-n, and inconsistent across cohorts.</ p >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'slide-foot' >
2026-07-10 17:41:47 +08:00
< span > Raman Lab · MMXXVI</ span >
2026-05-12 15:18:16 +08:00
< span class = 'counter' > 02 / 09</ span >
</ div >
</ section >
<!-- ===== 03 · CONTENT ===== -->
< section class = 'slide s-content' data-slide-kind = 'content' >
< div class = 'slide-chrome' >
2026-07-10 17:41:47 +08:00
< span class = 'left' >< span class = 'mark' > kami</ span > < b > Raman Lab</ b > · Lab Meeting · Week 14</ span >
< span class = 'right' > Gut-Sleep Cohort · Academic research</ span >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'slide-inner' >
< div class = 'head' >
< p class = 'num' > 01.1</ p >
2026-07-10 17:41:47 +08:00
< h2 > The gap no cohort has closed.</ h2 >
< p class = 'lede' > Most human studies measure sleep by wristband, not EEG.</ p >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'body' >
< p >
2026-07-10 17:41:47 +08:00
Prior cohorts (typically < strong > n < 30</ strong > ) rely on consumer-grade actigraphy, which is blind to sleep stage — it cannot tell slow-wave sleep from light sleep. None have paired < code > 16S</ code > -or-deeper microbiome profiling with polysomnography-grade staging in the same participants, and few control for the confounders that move both gut and sleep at once.
2026-05-12 15:18:16 +08:00
</ p >
< ul class = 'dash' >
2026-07-10 17:41:47 +08:00
< li > Actigraphy-only designs can report "sleep quality" but not sleep architecture.</ li >
< li > Diet, BMI, and antibiotic history are rarely logged as covariates.</ li >
< li > No prior cohort repeated sampling across a full six-week window.</ li >
2026-05-12 15:18:16 +08:00
</ ul >
< div class = 'tag-row' >
2026-07-10 17:41:47 +08:00
< span class = 'tag' > Metagenomics</ span >
< span class = 'tag' > Polysomnography</ span >
< span class = 'tag' > Gut-brain axis</ span >
2026-05-12 15:18:16 +08:00
</ div >
</ div >
</ div >
< div class = 'slide-foot' >
2026-07-10 17:41:47 +08:00
< span > Raman Lab · MMXXVI</ span >
2026-05-12 15:18:16 +08:00
< span class = 'counter' > 03 / 09</ span >
</ div >
</ section >
<!-- ===== 04 · CONTENT ===== -->
< section class = 'slide s-content' data-slide-kind = 'content' >
< div class = 'slide-chrome' >
2026-07-10 17:41:47 +08:00
< span class = 'left' >< span class = 'mark' > kami</ span > < b > Raman Lab</ b > · Lab Meeting · Week 14</ span >
< span class = 'right' > Gut-Sleep Cohort · Academic research</ span >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'slide-inner' >
< div class = 'head' >
< p class = 'num' > 01.2</ p >
2026-07-10 17:41:47 +08:00
< h2 > Design: what we actually ran.</ h2 >
< p class = 'lede' > Six weeks, 64 adults, a polysomnography subsample.</ p >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'body' >
< p >
2026-07-10 17:41:47 +08:00
Stool samples were collected at week 0 and week 6 and run through shotgun metagenomic sequencing. All 64 participants wore actigraphy nightly; a < strong > 22-person subsample also underwent overnight polysomnography</ strong > at both timepoints, giving us gold-standard sleep staging alongside microbial composition.
2026-05-12 15:18:16 +08:00
</ p >
< p >
2026-07-10 17:41:47 +08:00
Diet was logged by 3-day food record each week. Linear mixed-effects models carry participant as a random intercept and adjust for BMI, dietary fiber intake, and antibiotic use in the prior 90 days.
2026-05-12 15:18:16 +08:00
</ p >
< ul class = 'dash' >
2026-07-10 17:41:47 +08:00
< li > Week 0 & week 6 stool sampling, shotgun metagenomics (Illumina NovaSeq).</ li >
< li > Nightly actigraphy, all 64; overnight PSG on a 22-person subsample.</ li >
< li > LME models adjust for BMI, fiber intake, and 90-day antibiotic history.</ li >
2026-05-12 15:18:16 +08:00
</ ul >
</ div >
</ div >
< div class = 'slide-foot' >
2026-07-10 17:41:47 +08:00
< span > Raman Lab · MMXXVI</ span >
2026-05-12 15:18:16 +08:00
< span class = 'counter' > 04 / 09</ span >
</ div >
</ section >
<!-- ===== 05 · STATS ===== -->
< section class = 'slide s-stats' data-slide-kind = 'stats' >
< div class = 'slide-chrome' >
2026-07-10 17:41:47 +08:00
< span class = 'left' >< span class = 'mark' > kami</ span > < b > Raman Lab</ b > · Lab Meeting · Week 14</ span >
< span class = 'right' > Gut-Sleep Cohort · Academic research</ span >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'slide-inner' >
< div class = 'head' >
< p class = 'num' > 01.3</ p >
2026-07-10 17:41:47 +08:00
< h2 > What moved, and what didn't.</ h2 >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'grid' >
< div class = 'stat' >
2026-07-10 17:41:47 +08:00
< div class = 'v' > +18min</ div >
< div class = 'l' > Slow-wave sleep</ div >
< div class = 's' > per SD increase in Bacteroides:Firmicutes ratio, PSG subsample.</ div >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'stat' >
2026-07-10 17:41:47 +08:00
< div class = 'v' > r=0.41</ div >
< div class = 'l' > SCFA – SWS correlation</ div >
< div class = 's' > fecal butyrate vs. slow-wave minutes, FDR q < 0.05.</ div >
2026-06-16 16:41:04 +08:00
</ div >
< div class = 'stat' >
2026-07-10 17:41:47 +08:00
< div class = 'v' > n.s.</ div >
< div class = 'l' > Total sleep time</ div >
< div class = 's' > no association with any measured microbial ratio, p = 0.61.</ div >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'stat' >
2026-07-10 17:41:47 +08:00
< div class = 'v' > 22/64</ div >
< div class = 'l' > PSG subsample</ div >
< div class = 's' > gold-standard staging; remainder actigraphy-only.</ div >
2026-05-12 15:18:16 +08:00
</ div >
</ div >
2026-07-10 17:41:47 +08:00
< p class = 'caption' > Raman Lab · shotgun metagenomics + PSG cohort · preprint in preparation · MMXXVI</ p >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'slide-foot' >
2026-07-10 17:41:47 +08:00
< span > Raman Lab · MMXXVI</ span >
2026-05-12 15:18:16 +08:00
< span class = 'counter' > 05 / 09</ span >
</ div >
</ section >
<!-- ===== 06 · CHAPTER (dark) ===== -->
< section class = 'slide s-chapter dark' data-slide-kind = 'chapter' >
< div class = 'slide-chrome' >
2026-07-10 17:41:47 +08:00
< span class = 'left' >< span class = 'mark' > kami</ span > < b > Raman Lab</ b > · Lab Meeting · Week 14</ span >
< span class = 'right' > Gut-Sleep Cohort · Academic research</ span >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'slide-inner' >
< p class = 'num' > 02</ p >
2026-07-10 17:41:47 +08:00
< h2 > The claim we can actually make.</ h2 >
< p class = 'lede' > Gut composition tracks sleep architecture — slow-wave depth — not sleep quantity. A distinction prior actigraphy-only studies could never see.</ p >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'slide-foot' >
2026-07-10 17:41:47 +08:00
< span > Raman Lab · MMXXVI</ span >
2026-05-12 15:18:16 +08:00
< span class = 'counter' > 06 / 09</ span >
</ div >
</ section >
<!-- ===== 07 · QUOTE ===== -->
< section class = 'slide s-quote' data-slide-kind = 'quote' >
< div class = 'slide-chrome' >
2026-07-10 17:41:47 +08:00
< span class = 'left' >< span class = 'mark' > kami</ span > < b > Raman Lab</ b > · Lab Meeting · Week 14</ span >
< span class = 'right' > Gut-Sleep Cohort · Academic research</ span >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'slide-inner' >
< blockquote >
2026-07-10 17:41:47 +08:00
A correlation this size, in a subsample this small, does not tell us the microbiome causes deeper sleep. It tells us exactly where to point a causal experiment next.
2026-05-12 15:18:16 +08:00
</ blockquote >
< div class = 'author' >
2026-07-10 17:41:47 +08:00
< span class = 'glyph' > e</ span >
2026-05-12 15:18:16 +08:00
< p >
2026-07-10 17:41:47 +08:00
Dr. Elena Cho
< span > Principal Investigator · Sleep & Microbiome Lab</ span >
2026-05-12 15:18:16 +08:00
</ p >
</ div >
</ div >
< div class = 'slide-foot' >
2026-07-10 17:41:47 +08:00
< span > Raman Lab · MMXXVI</ span >
2026-05-12 15:18:16 +08:00
< span class = 'counter' > 07 / 09</ span >
</ div >
</ section >
<!-- ===== 08 · CTA ===== -->
< section class = 'slide s-cta' data-slide-kind = 'cta' >
< div class = 'slide-chrome' >
2026-07-10 17:41:47 +08:00
< span class = 'left' >< span class = 'mark' > kami</ span > < b > Raman Lab</ b > · Lab Meeting · Week 14</ span >
< span class = 'right' > Gut-Sleep Cohort · Academic research</ span >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'slide-inner' >
2026-07-10 17:41:47 +08:00
< span class = 'eyebrow' > Next in the pipeline</ span >
< h2 > Can we move the ratio — and does sleep follow?</ h2 >
2026-05-12 15:18:16 +08:00
< p class = 'body' >
2026-07-10 17:41:47 +08:00
Proposed follow-up: a 4-week fiber-supplementation crossover trial (n = 40, PSG on every participant) testing whether raising the Bacteroides:Firmicutes ratio causally increases slow-wave sleep. IRB submission targeted for Q3.
2026-05-12 15:18:16 +08:00
</ p >
< div class = 'actions' >
2026-07-10 17:41:47 +08:00
< a class = 'btn btn-primary' href = '#' > Review the IRB draft</ a >
< a class = 'btn btn-ghost' href = '#' > See the full dataset</ a >
2026-05-12 15:18:16 +08:00
</ div >
</ div >
< div class = 'slide-foot' >
2026-07-10 17:41:47 +08:00
< span > Raman Lab · MMXXVI</ span >
2026-05-12 15:18:16 +08:00
< span class = 'counter' > 08 / 09</ span >
</ div >
</ section >
<!-- ===== 09 · END (dark) ===== -->
< section class = 'slide s-end dark' data-slide-kind = 'end' >
< div class = 'slide-chrome' >
2026-07-10 17:41:47 +08:00
< span class = 'left' >< span class = 'mark' > kami</ span > < b > Raman Lab</ b > · Lab Meeting · Week 14</ span >
< span class = 'right' > Gut-Sleep Cohort · Academic research</ span >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'slide-inner' >
2026-07-10 17:41:47 +08:00
< div class = 'word' > Sleep, < span class = 'hl' > deeper.</ span ></ div >
< p class = 'colophon' > Raman Lab · Dept. of Neuroscience · MMXXVI · Preprint in preparation · Lab meeting Nº 14</ p >
2026-05-12 15:18:16 +08:00
</ div >
< div class = 'slide-foot' >
2026-07-10 17:41:47 +08:00
< span > Raman Lab · MMXXVI</ span >
2026-05-12 15:18:16 +08:00
< span class = 'counter' > 09 / 09</ span >
</ div >
</ section >
</ div >
< div id = 'nav' ></ div >
< div id = 'hint' > ← / → · esc · swipe</ div >
< div class = 'deck-progress' >< div class = 'bar' ></ div ></ div >
< script >
( function () {
var deck = document . getElementById ( 'deck' );
if ( ! deck ) return ;
var slides = Array . prototype . slice . call ( deck . querySelectorAll ( '.slide' ));
var nav = document . getElementById ( 'nav' );
var bar = document . querySelector ( '.deck-progress .bar' );
var total = slides . length ;
var idx = 0 , lock = false ;
deck . style . width = ( total * 100 ) + 'vw' ;
slides . forEach ( function ( s , i ) {
var b = document . createElement ( 'button' );
b . className = 'dot' ;
b . dataset . i = i ;
b . setAttribute ( 'aria-label' , 'Slide ' + ( i + 1 ));
b . onclick = function () { go ( i ); };
nav . appendChild ( b );
});
/* Unthrottled state update. The interaction throttle (`lock`) only
guards wheel/key/touch so a fast input burst doesn't overshoot the
transition; host- and observer-driven sync must bypass it, otherwise
a host message or restoreInitialSlide that lands inside the 700ms
window after go(0) silently no-ops and the deck stays on slide 1
while the host counter advances. */
function applySlide ( n ) {
idx = Math . max ( 0 , Math . min ( total - 1 , n ));
deck . style . transform = 'translateX(' + ( - idx * 100 ) + 'vw)' ;
2026-08-18 07:09:45 +00:00
/* load-bearing: .slide.active is read by OpenDesign's host bridge
2026-05-12 15:18:16 +08:00
(src/runtime/srcdoc.ts findActiveByClass) to drive the slide
counter. No CSS targets it — do not remove. */
slides . forEach ( function ( s , i ) { s . classList . toggle ( 'active' , i === idx ); });
nav . querySelectorAll ( '.dot' ). forEach ( function ( d , i ) {
d . classList . toggle ( 'active' , i === idx );
});
if ( bar ) bar . style . width = ((( idx + 1 ) / total ) * 100 ) + '%' ;
}
function go ( n ) {
if ( lock ) return ;
applySlide ( n );
lock = true ;
setTimeout ( function () { lock = false ; }, 700 );
}
/* ESC overview */
var overviewOn = false ;
var ov = document . createElement ( 'div' );
ov . id = 'overview' ;
document . body . appendChild ( ov );
function buildOverview () {
ov . innerHTML = '' ;
var head = document . createElement ( 'div' );
head . className = 'ov-head' ;
head . innerHTML = '<span><b>Slide overview</b> · esc to close</span><span>' +
String ( idx + 1 ). padStart ( 2 , '0' ) + ' / ' + String ( total ). padStart ( 2 , '0' ) + '</span>' ;
ov . appendChild ( head );
var grid = document . createElement ( 'div' );
grid . className = 'ov-grid' ;
slides . forEach ( function ( s , i ) {
var card = document . createElement ( 'div' );
card . className = 'ov-card' + ( i === idx ? ' active' : '' );
var thumb = document . createElement ( 'div' );
thumb . className = 'ov-thumb' ;
var clone = s . cloneNode ( true );
clone . className = clone . className + ' clone' ;
clone . style . transform = 'scale(0.18)' ;
thumb . appendChild ( clone );
var label = document . createElement ( 'div' );
label . className = 'ov-label' ;
label . innerHTML = '<b>' + String ( i + 1 ). padStart ( 2 , '0' ) + '</b><span>' +
( s . dataset . slideKind || '' ) + '</span>' ;
card . appendChild ( thumb );
card . appendChild ( label );
card . onclick = function () { toggleOverview (); go ( i ); };
grid . appendChild ( card );
});
ov . appendChild ( grid );
}
function toggleOverview () {
overviewOn = ! overviewOn ;
if ( overviewOn ) { buildOverview (); ov . style . display = 'block' ; }
else { ov . style . display = 'none' ; }
}
addEventListener ( 'keydown' , function ( e ) {
if ( e . key === 'Escape' ) { e . preventDefault (); toggleOverview (); return ; }
if ( overviewOn ) return ;
if ( e . key === 'ArrowRight' || e . key === 'PageDown' || e . key === ' ' || e . key === 'ArrowDown' ) {
e . preventDefault (); go ( idx + 1 );
} else if ( e . key === 'ArrowLeft' || e . key === 'PageUp' || e . key === 'ArrowUp' ) {
e . preventDefault (); go ( idx - 1 );
} else if ( e . key === 'Home' ) {
e . preventDefault (); go ( 0 );
} else if ( e . key === 'End' ) {
e . preventDefault (); go ( total - 1 );
}
});
var wheelTO = null , wheelAcc = 0 ;
addEventListener ( 'wheel' , function ( e ) {
if ( overviewOn ) return ;
wheelAcc += e . deltaY + e . deltaX ;
if ( Math . abs ( wheelAcc ) > 60 ) {
go ( idx + ( wheelAcc > 0 ? 1 : - 1 ));
wheelAcc = 0 ;
}
clearTimeout ( wheelTO );
wheelTO = setTimeout ( function () { wheelAcc = 0 ; }, 150 );
}, { passive : true });
var tx = 0 , ty = 0 ;
addEventListener ( 'touchstart' , function ( e ) {
tx = e . touches [ 0 ]. clientX ; ty = e . touches [ 0 ]. clientY ;
}, { passive : true });
addEventListener ( 'touchend' , function ( e ) {
if ( overviewOn ) return ;
var dx = e . changedTouches [ 0 ]. clientX - tx ;
var dy = e . changedTouches [ 0 ]. clientY - ty ;
if ( Math . abs ( dx ) > 50 && Math . abs ( dx ) > Math . abs ( dy )) {
go ( idx + ( dx < 0 ? 1 : - 1 ));
}
}, { passive : true });
2026-08-18 07:09:45 +00:00
/* Host-driven navigation: OpenDesign's host bridge classifies this deck
2026-05-12 15:18:16 +08:00
as class-driven (because go() toggles .slide.active) but the visible
slide is moved by deck.style.transform, which the bridge can't drive.
Two cooperating handlers keep the deck in sync with the host:
1. An od:slide message listener routes host nav through go() and
calls stopImmediatePropagation() so the bridge's own listener
(registered after this one) doesn't run a second time and
overshoot by re-reading the freshly-toggled .active class.
2. A MutationObserver on each slide watches .active and pulls the
deck transform onto the active index for class changes that
don't come through a message — chiefly the bridge's
restoreInitialSlide path, which calls setActive() directly. */
addEventListener ( 'message' , function ( e ) {
var data = e && e . data ;
if ( ! data || data . type !== 'od:slide' ) return ;
if ( typeof e . stopImmediatePropagation === 'function' ) e . stopImmediatePropagation ();
if ( data . action === 'go' && typeof data . index === 'number' ) applySlide ( data . index );
else if ( data . action === 'next' ) applySlide ( idx + 1 );
else if ( data . action === 'prev' ) applySlide ( idx - 1 );
else if ( data . action === 'first' ) applySlide ( 0 );
else if ( data . action === 'last' ) applySlide ( total - 1 );
});
if ( typeof MutationObserver !== 'undefined' ) {
var syncFromActiveClass = function () {
for ( var i = 0 ; i < slides . length ; i ++ ) {
if ( slides [ i ]. classList && slides [ i ]. classList . contains ( 'active' ) && i !== idx ) {
applySlide ( i );
return ;
}
}
};
var mo = new MutationObserver ( syncFromActiveClass );
slides . forEach ( function ( s ) { mo . observe ( s , { attributes : true , attributeFilter : [ 'class' ] }); });
}
applySlide ( 0 );
})();
</ script >
2026-07-10 17:41:47 +08:00
2026-05-12 15:18:16 +08:00
</ body >
</ html >