diff --git a/mkdocs.yml b/mkdocs.yml index be26604c..7d1c639b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,15 +1,27 @@ site_name: VanBUG docs_dir: src +exclude_docs: theme/ theme: name: material - logo: images/logo.light.svg + custom_dir: src/theme + logo: images/logo.svg favicon: images/logo.svg + font: false + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: octicons/sun-16 + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: octicons/moon-16 + name: Switch to light mode features: - navigation.tabs - - navigation.top - navigation.tabs.sticky - - navigation.instant - - toc.integrate + - navigation.indexes site_dir: dist markdown_extensions: - codehilite @@ -30,11 +42,9 @@ markdown_extensions: - toc: permalink: true extra_javascript: - - https://polyfill.io/v3/polyfill.min.js?features=es6 - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js - https://platform.twitter.com/widgets.js extra_css: -- styles/image-list.css - styles/timeline.css - styles/palette.css - styles/general.css @@ -192,12 +202,21 @@ plugins: 2002/francis-ouellette-a-human-aided-automated-pipeline-to-the-annotate-the-human-genome-work-in-progress/index.md: archive/2002/2002-09-12.md nav: - Home: index.md + - Schedule: schedule.md - ... + - About Us: about.md + - Contact: contact.md extra: social: - - icon: fontawesome/brands/twitter + - icon: simple/x + name: X link: https://twitter.com/VanBUG_ - - icon: fontawesome/brands/github - link: https://github.com/van-bug - - icon: fontawesome/brands/youtube + - icon: simple/instagram + name: Instagram + link: https://www.instagram.com/vanbug_ + - icon: simple/youtube + name: YouTube link: https://www.youtube.com/channel/UCO_BUmZqGLx_w9-IpAj4idQ + - icon: simple/github + name: GitHub + link: https://github.com/van-bug diff --git a/src/about.md b/src/about.md new file mode 100644 index 00000000..1c05d1d9 --- /dev/null +++ b/src/about.md @@ -0,0 +1,81 @@ +# About Us + +VanBUG (Vancouver Bioinformatics User Group) is a non-profit association of researchers, other professionals and students in the B.C. Lower Mainland who have an interest in the field of bioinformatics, computational biology, and data sciences. VanBUG meets every month from September through April. Research presentations by bioinformatics leaders, students and industry representatives are followed by networking over pizza and refreshments. + +Visit our sister groups for bioinformatics events in Montreal ([MonBUG](https://www.monbug.ca/)), Toronto ([TorBUG](https://torbug.org/)), Edmonton ([yegBUG](https://yegbug.ca/)) and Ottawa ([OttBUG](https://ottbug.ca/))! + +/// html | div[class="image-gallery"] + +- [![MonBUG](sponsors/images/monbug.logo.png)](https://www.monbug.ca/) +- [![TorBUG](sponsors/images/torbug.logo.png)](https://torbug.org/) +- [![yegBUG](sponsors/images/yegbug.logo.png)](https://yegbug.ca/) +- [![OttBUG](sponsors/images/ottbug.logo.png)](https://ottbug.ca/) + +/// + +## Acknowledgements + +### VanBUG development group includes + +- William Hsiao, Associate Professor, Faculty of Health Sciences, SFU +- Amy Lee, Assistant Professor, Department of Molecular Biology and Biochemistry, SFU +- Faraz Hach, Assistant Professor, Vancouver Prostate Centre, UBC +- Tian Rabbani, Researcher, Project Lead & Regional Coordinator, Hsiao Lab, Faculty of Health Sciences, SFU +- Johnathan Wong, PhD student, Bioinformatics, Birol Lab, UBC +- Emily Zhang, MSc student, Bioinformatics, Birol Lab, BC Cancer, UBC +- Berke Ucar, PhD student, Bioinformatics, Birol Lab, BC Cancer, UBC +- Mahdi Asmae, PhD student, Computer Science, Hach Lab, Vancouver Prostate Centre, UBC +- Ali Salehi, PhD candidate, Department of Medical Genetics, Birol Lab, BC Cancer, UBC +- David Lin, MSc student, Bioinformatics, Steif Lab, BC Cancer, UBC +- Maxwell Douglas, PhD student, Bioinformatics, Park Lab, BC Cancer, UBC +- Esme Padgett, PhD student, Genome Science and Technology, UBC + +### Special thanks go to the following friends of VanBUG + +- Pratima Shrivastava for helping manage VanBUG finances. + +### VanBug Team Alumni + +/// html | div[class="columns"] + +- Cedric Chauve +- Ryan Brinkman +- Jonathan Lim +- Carri-Lyn Mead +- Stephen Montgomery +- Ryan Morin +- Olena Morozova +- Francis Ouellette +- Paul Pavlidis +- Stefanie Butland +- Elodie Portales +- Bhavjinder Dhillon +- Shing Hei Zhan +- Thea Van Rossum +- Kieran O’Neill +- Sam Hinshaw +- Kristina Gagalova +- Rodrigo Goya +- Raunak Shrestha +- Phillip Richmond +- Jasleen Grewal +- Evan Morien +- Nicole Zhang +- Lisa Wei +- Nafiseh Kouchekian +- Rodrigo Vallejos +- Venus Lau +- Ka Ming Nip +- Baraa Orabi +- William Casazza +- Juliana Sobral de Barros +- Fatemeh Hosseini +- Rhiannon Cameron +- Parham Kazemi +- Lenneth Li +- Caralyn Reisle +- Madeline Iseminger +- Yerin Kim +- Bardia Masudy + +/// diff --git a/src/archive/2026/2026-09-17.md b/src/archive/2026/2026-09-17.md index b06a6f50..c6b7709a 100644 --- a/src/archive/2026/2026-09-17.md +++ b/src/archive/2026/2026-09-17.md @@ -30,6 +30,8 @@ /// +![type:video](https://www.youtube.com/embed/kDeGiKEc5dc) + **Bio:** Dr. Tuan Amith is an assistant professor with School of Health Information Sciences from the University of Victoria. He received his PhD in Biomedical Informatics from the McWilliams School of Biomedical Informatics at the University of Texas Health Science Center at Houston (UTHealth), under the supervision of Dr. Cui Tao. diff --git a/src/archive/2026/2026-10-22.md b/src/archive/2026/2026-10-22.md index beb4b4db..5b526088 100644 --- a/src/archive/2026/2026-10-22.md +++ b/src/archive/2026/2026-10-22.md @@ -55,6 +55,6 @@ Together, these findings support a model in which air pollution promotes lung ca **Trainee Speaker:** Asli Munzur -**Affiliation:** PhD student in Genome Sciences and Technology, Wyatt Lab, UBC & Vancouver Prostate Centre +**Affiliation:** PhD candidate in Genome Sciences and Technology, Wyatt Lab, UBC & Vancouver Prostate Centre **Talk Title**: Characterizing clonal hematopoiesis using targeted DNA sequencing in advanced genitourinary cancers diff --git a/src/archive/2026/2026-11-19.md b/src/archive/2026/2026-11-19.md index 1bb413ca..e0fc0659 100644 --- a/src/archive/2026/2026-11-19.md +++ b/src/archive/2026/2026-11-19.md @@ -4,7 +4,7 @@ **Date/Time:** - Thursday, September 17th, 2026 :material-clock: 6:00pm - 8:00pm + Thursday, November 19th, 2026 :material-clock: 6:00pm - 8:00pm **Location:** diff --git a/src/contact.md b/src/contact.md index 3e20a318..c8c464a0 100644 --- a/src/contact.md +++ b/src/contact.md @@ -15,9 +15,11 @@ Sponsorship Inquiries: vanbioinfo+sponsors [at] gmail.com ## Mailing List We use our low-volume mailing list to diseminate information about our events and job postings.
-To subscribe, fill out [this form](https://dashboard.mailerlite.com/forms/1208260/139100012863816994/share).
+To subscribe to our mailing list, fill out the [Mailing List Form](https://dashboard.mailerlite.com/forms/1208260/139100012863816994/share).
-### [**Suggest a Speaker**](https://forms.gle/kXtGzhC2t9ngxnHz5 "Suggest a Speaker") +## Suggest a Speaker + +To suggest a speaker for the upcoming event, please fill out the [Speaker Suggestion Form](https://forms.gle/kXtGzhC2t9ngxnHz5). ## Mailing Address @@ -28,59 +30,3 @@ Blusson Hall, Room 11008
Simon Fraser University
8888 University Drive, Burnaby, BC
V5A 1S6 Canada - -## Acknowledgements - -### VanBUG development group includes - -- William Hsiao, Associate Professor, Faculty of Health Sciences, SFU -- Amy Lee, Assistant Professor, Dept of Molecular Biology and Biochemistry, SFU -- Faraz Hach, Assistant Professor, Vancouver Prostate Centre, UBC -- Caralyn Reisle, PhD candidate, Jones Lab, Canada’s Michael Smith Genome Sciences Centre, UBC -- Johnathan Wong, PhD student, Birol Lab, Canada’s Michael Smith Genome Sciences Centre, UBC -- Bardia Masudy, BSc Biochemistry and Chemistry, UBC -- Madeline Iseminger, MSc student, Hsiao Lab, The Centre for Infectious Disease Genomics and One Health, SFU -- Yerin Kim, MSc graduate, Jones Lab, Canada’s Michael Smith Genome Sciences Centre, UBC - -### Special thanks go to the following friends of VanBUG - -- Pratima Shrivastava for helping manage VanBUG finances. -- VanBUG volunteers for helping with setup, cleanup and serving refreshments. - -### VanBug Team Alumni - -- Cedric Chauve -- Ryan Brinkman -- Jonathan Lim -- Carri-Lyn Mead -- Stephen Montgomery -- Ryan Morin -- Olena Morozova -- Francis Ouellette -- Paul Pavlidis -- Stefanie Butland -- Elodie Portales -- Bhavjinder Dhillon -- Shing Hei Zhan -- Thea Van Rossum -- Kieran O’Neill -- Sam Hinshaw -- Kristina Gagalova -- Rodrigo Goya -- Raunak Shrestha -- Phillip Richmond -- Jasleen Grewal -- Evan Morien -- Nicole Zhang -- Lisa Wei -- Nafiseh Kouchekian -- Rodrigo Vallejos -- Venus Lau -- Ka Ming Nip -- Baraa Orabi -- William Casazza -- Juliana Sobral de Barros -- Fatemeh Hosseini -- Rhiannon Cameron -- Parham Kazemi -- Lenneth Li diff --git a/src/images/apple-logo.svg b/src/images/apple-logo.svg new file mode 100644 index 00000000..521805c6 --- /dev/null +++ b/src/images/apple-logo.svg @@ -0,0 +1,5 @@ + diff --git a/src/images/google-logo.svg b/src/images/google-logo.svg new file mode 100644 index 00000000..87986d69 --- /dev/null +++ b/src/images/google-logo.svg @@ -0,0 +1 @@ + diff --git a/src/images/microsoft-outlook.svg b/src/images/microsoft-outlook.svg new file mode 100644 index 00000000..1b349617 --- /dev/null +++ b/src/images/microsoft-outlook.svg @@ -0,0 +1 @@ + diff --git a/src/index.md b/src/index.md index cd29be5d..e330a79d 100644 --- a/src/index.md +++ b/src/index.md @@ -1,13 +1,5 @@ # **Vancouver Bioinformatics User Group** -VanBUG (Vancouver Bioinformatics User Group) is an association of researchers, other professionals and students in the B.C. Lower Mainland who have an interest in the field of bioinformatics, computational biology, and data sciences. VanBUG meets every month from September through April. Research presentations by bioinformatics leaders, students and industry representatives are followed by networking over pizza and refreshments - -[Regular in-person monthly meetings](./schedule) will be held monthly on Thursdays from **6:00pm to 8:00pm** and are free and open to all. Please refer to the [Schedule](./schedule) page or [subscribe to our Calendar](https://calendar.google.com/calendar/u/1?cid=dmFuYmlvaW5mb0BnbWFpbC5jb20) for specific details regarding speaker location and room information. - -As a service to the community, local VanBUG and other bioinformatics events are posted to the [Calendar](https://calendar.google.com/calendar/embed?src=vanbioinfo%40gmail.com&ctz=America%2FVancouver). Click [Subscribe](https://calendar.google.com/calendar/u/1?cid=dmFuYmlvaW5mb0BnbWFpbC5jb20) to subscribe to this calendar, so that all current and future events appear on your personal calendar. - -Visit our sister groups for bioinformatics events in Montreal ([MonBUG](https://www.monbug.ca/)) and Toronto ([TorBUG](https://torbug.org/))! - ## VanBUG Monthly Event {% diff --git a/src/schedule.md b/src/schedule.md index 2c102165..79f8d6ed 100644 --- a/src/schedule.md +++ b/src/schedule.md @@ -1,5 +1,16 @@ # Schedule +As a service to the community, local VanBUG and other bioinformatics events are posted to the [Calendar](https://calendar.google.com/calendar/embed?src=vanbioinfo%40gmail.com&ctz=America%2FVancouver). Regular in-person monthly meetings will be held monthly on Thursdays from 6:00pm to 8:00pm and are free and open to all. + +
+Subscribe to Calendar + +- [![](images/google-logo.svg) Google Calendar](https://calendar.google.com/calendar/u/0?cid=dmFuYmlvaW5mb0BnbWFpbC5jb20) +- [![](images/apple-logo.svg) Apple Calendar](webcal://calendar.google.com/calendar/ical/vanbioinfo%40gmail.com/public/basic.ics) +- [![](images/microsoft-outlook.svg) Outlook](https://outlook.live.com/calendar/0/addfromweb?url=https%3A%2F%2Fcalendar.google.com%2Fcalendar%2Fical%2Fvanbioinfo%2540gmail.com%2Fpublic%2Fbasic.ics&name=VanBUG) + +
+ ## Fall 2026 /// html | div[class="timeline"] @@ -43,7 +54,3 @@ Special Event /// - - - -/// diff --git a/src/sponsors/images/CBH-Logo-EN-Red.png b/src/sponsors/images/CBH-Logo-EN-Red.png index e4f7b224..ba33b4e0 100644 Binary files a/src/sponsors/images/CBH-Logo-EN-Red.png and b/src/sponsors/images/CBH-Logo-EN-Red.png differ diff --git a/src/sponsors/images/bccancer.logo.png b/src/sponsors/images/bccancer.logo.png index 237ebd86..a5dbfcf9 100644 Binary files a/src/sponsors/images/bccancer.logo.png and b/src/sponsors/images/bccancer.logo.png differ diff --git a/src/sponsors/images/bccdc.logo.png b/src/sponsors/images/bccdc.logo.png index ade53f5d..e47515f1 100644 Binary files a/src/sponsors/images/bccdc.logo.png and b/src/sponsors/images/bccdc.logo.png differ diff --git a/src/sponsors/images/bigdatahub.logo.jpg b/src/sponsors/images/bigdatahub.logo.jpg deleted file mode 100644 index 7cabd735..00000000 Binary files a/src/sponsors/images/bigdatahub.logo.jpg and /dev/null differ diff --git a/src/sponsors/images/bigdatahub.logo.png b/src/sponsors/images/bigdatahub.logo.png new file mode 100644 index 00000000..290b73c8 Binary files /dev/null and b/src/sponsors/images/bigdatahub.logo.png differ diff --git a/src/sponsors/images/canexia.logo.png b/src/sponsors/images/canexia.logo.png index f487e12a..7e4448b8 100644 Binary files a/src/sponsors/images/canexia.logo.png and b/src/sponsors/images/canexia.logo.png differ diff --git a/src/sponsors/images/ecoscope.logo.png b/src/sponsors/images/ecoscope.logo.png index df708203..a77a4dd5 100644 Binary files a/src/sponsors/images/ecoscope.logo.png and b/src/sponsors/images/ecoscope.logo.png differ diff --git a/src/sponsors/images/genomebc.logo.jpg b/src/sponsors/images/genomebc.logo.jpg deleted file mode 100644 index 8641b213..00000000 Binary files a/src/sponsors/images/genomebc.logo.jpg and /dev/null differ diff --git a/src/sponsors/images/genomebc.logo.png b/src/sponsors/images/genomebc.logo.png new file mode 100644 index 00000000..98de0723 Binary files /dev/null and b/src/sponsors/images/genomebc.logo.png differ diff --git a/src/sponsors/images/iscb.logo.dark.png b/src/sponsors/images/iscb.logo.dark.png new file mode 100644 index 00000000..0ed6cfa1 Binary files /dev/null and b/src/sponsors/images/iscb.logo.dark.png differ diff --git a/src/sponsors/images/iscb.logo.png b/src/sponsors/images/iscb.logo.png index 7d7ae595..c5c3c877 100644 Binary files a/src/sponsors/images/iscb.logo.png and b/src/sponsors/images/iscb.logo.png differ diff --git a/src/sponsors/images/langara.logo.png b/src/sponsors/images/langara.logo.png deleted file mode 100644 index 46ceb439..00000000 Binary files a/src/sponsors/images/langara.logo.png and /dev/null differ diff --git a/src/sponsors/images/langara.logo.svg b/src/sponsors/images/langara.logo.svg new file mode 100644 index 00000000..f4a44af9 --- /dev/null +++ b/src/sponsors/images/langara.logo.svg @@ -0,0 +1,45 @@ + + + + Langara at Musqueam logo - hex + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/sponsors/images/michaelsmith.logo.png b/src/sponsors/images/michaelsmith.logo.png index 95396552..0cf5f7bc 100644 Binary files a/src/sponsors/images/michaelsmith.logo.png and b/src/sponsors/images/michaelsmith.logo.png differ diff --git a/src/sponsors/images/mitacs.logo.jpg b/src/sponsors/images/mitacs.logo.jpg deleted file mode 100644 index a48ef589..00000000 Binary files a/src/sponsors/images/mitacs.logo.jpg and /dev/null differ diff --git a/src/sponsors/images/mitacs.logo.svg b/src/sponsors/images/mitacs.logo.svg new file mode 100644 index 00000000..8da7025b --- /dev/null +++ b/src/sponsors/images/mitacs.logo.svg @@ -0,0 +1,5 @@ + + + Mitacs 2026 logo, navy + + \ No newline at end of file diff --git a/src/sponsors/images/monbug.logo.jpeg b/src/sponsors/images/monbug.logo.jpeg deleted file mode 100644 index bc5a49d7..00000000 Binary files a/src/sponsors/images/monbug.logo.jpeg and /dev/null differ diff --git a/src/sponsors/images/monbug.logo.png b/src/sponsors/images/monbug.logo.png new file mode 100644 index 00000000..40e49fa4 Binary files /dev/null and b/src/sponsors/images/monbug.logo.png differ diff --git a/src/sponsors/images/ottbug.logo.png b/src/sponsors/images/ottbug.logo.png new file mode 100644 index 00000000..4cd2c08a Binary files /dev/null and b/src/sponsors/images/ottbug.logo.png differ diff --git a/src/sponsors/images/pims.logo.jpg b/src/sponsors/images/pims.logo.jpg deleted file mode 100644 index ebe71a3a..00000000 Binary files a/src/sponsors/images/pims.logo.jpg and /dev/null differ diff --git a/src/sponsors/images/pims.logo.png b/src/sponsors/images/pims.logo.png new file mode 100644 index 00000000..0336bb2c Binary files /dev/null and b/src/sponsors/images/pims.logo.png differ diff --git a/src/sponsors/images/stpauls.logo.png b/src/sponsors/images/stpauls.logo.png index a5d87501..6b187bc5 100644 Binary files a/src/sponsors/images/stpauls.logo.png and b/src/sponsors/images/stpauls.logo.png differ diff --git a/src/sponsors/images/torbug.logo.png b/src/sponsors/images/torbug.logo.png index 3ba09378..f7059076 100644 Binary files a/src/sponsors/images/torbug.logo.png and b/src/sponsors/images/torbug.logo.png differ diff --git a/src/sponsors/images/ubc-dom.logo.dark.png b/src/sponsors/images/ubc-dom.logo.dark.png new file mode 100644 index 00000000..370590d1 Binary files /dev/null and b/src/sponsors/images/ubc-dom.logo.dark.png differ diff --git a/src/sponsors/images/ubc-dom.logo.jpg b/src/sponsors/images/ubc-dom.logo.jpg deleted file mode 100644 index cac1e024..00000000 Binary files a/src/sponsors/images/ubc-dom.logo.jpg and /dev/null differ diff --git a/src/sponsors/images/ubc-dom.logo.png b/src/sponsors/images/ubc-dom.logo.png new file mode 100644 index 00000000..d0952a05 Binary files /dev/null and b/src/sponsors/images/ubc-dom.logo.png differ diff --git a/src/sponsors/images/yegbug.logo.png b/src/sponsors/images/yegbug.logo.png new file mode 100644 index 00000000..9db3060b Binary files /dev/null and b/src/sponsors/images/yegbug.logo.png differ diff --git a/src/sponsors/index.md b/src/sponsors/index.md index a32a0bad..2d272a50 100644 --- a/src/sponsors/index.md +++ b/src/sponsors/index.md @@ -13,11 +13,11 @@ VanBUG is an Affiliate Partner of the Canadian Bioinformatics Hub and is support /// html | div[class="image-gallery"] - [![Canadian Bioinformatics Hub](./images/CBH-Logo-EN-Red.png)](http://www.bioinformatics.ca) -- [![Bioinformatics Graduate Program at UBC and SFU](./images/bcbioinformaticsgrad.logo.png)](https://bcbioinformaticsgrad.ca) +- ![Bioinformatics Graduate Program at UBC and SFU](./images/bcbioinformaticsgrad.logo.png) - [![UBC Michael Smith Laboratories](./images/michaelsmith.logo.png)](https://www.msl.ubc.ca/) -- [![SFU Big Data Hub](./images/bigdatahub.logo.jpg)](https://www.sfu.ca/big-data.html) -- [![Genome BC](./images/genomebc.logo.jpg)](http://www.genomebc.ca) -- [![Langara College](./images/langara.logo.png)](https://langara.ca) +- [![SFU Big Data Hub](./images/bigdatahub.logo.png)](https://www.sfu.ca/big-data.html) +- [![Genome BC](./images/genomebc.logo.png)](http://www.genomebc.ca) +- [![Langara College](./images/langara.logo.svg)](https://langara.ca) - [![Stemcell Technologies](./images/stemcell.logo.png)](https://www.stemcell.com) /// @@ -26,9 +26,11 @@ VanBUG is an Affiliate Partner of the Canadian Bioinformatics Hub and is support /// html | div[class="image-gallery"] -- [![ISCB](./images/iscb.logo.png)](http://www.iscb.org) -- [![MonBUG](./images/monbug.logo.jpeg)](http://www.monbug.ca) +- [![ISCB](./images/iscb.logo.png){ data-dark="./images/iscb.logo.dark.png" }](http://www.iscb.org) +- [![MonBUG](./images/monbug.logo.png)](http://www.monbug.ca) - [![TorBUG](./images/torbug.logo.png)](http://www.torbug.org) +- [![yegBUG](./images/yegbug.logo.png)](https://yegbug.ca) +- [![OttBUG](./images/ottbug.logo.png)](https://ottbug.ca) /// @@ -42,10 +44,10 @@ We have previously been provided generous support from: - [![BC Cancer Research Centre](./images/bccancer.logo.png)](http://www.bccrc.ca) - [![BCCDC](./images/bccdc.logo.png)](http://www.bccdc.ca) - [![ECOSCOPE](./images/ecoscope.logo.png)](https://ecoscope.microbiology.ubc.ca) -- [![MITACS](./images/mitacs.logo.jpg)](https://www.mitacs.ca/en) -- [![Pacific Institute for the Mathematical Sciences](./images/pims.logo.jpg)](http://www.pims.math.ca) -- [![UBC Faculty of Medicine](./images/ubc-dom.logo.jpg)](https://www.med.ubc.ca) -- [![Imagia Canexia Health](./images/canexia.logo.png)](https://imagiacanexiahealth.com) +- [![MITACS](./images/mitacs.logo.svg)](https://www.mitacs.ca/en) +- [![Pacific Institute for the Mathematical Sciences](./images/pims.logo.png)](http://www.pims.math.ca) +- [![UBC Faculty of Medicine](./images/ubc-dom.logo.png){ data-dark="./images/ubc-dom.logo.dark.png" }](https://www.med.ubc.ca) +- ![Imagia Canexia Health](./images/canexia.logo.png) - [![St. Paul's Hospital](./images/stpauls.logo.png)](https://www.providencehealthcare.org/hospitals-residences/st-paul%27s-hospital) /// diff --git a/src/styles/InstrumentSans.woff2 b/src/styles/InstrumentSans.woff2 new file mode 100644 index 00000000..665fa65c Binary files /dev/null and b/src/styles/InstrumentSans.woff2 differ diff --git a/src/styles/general.css b/src/styles/general.css index 6447d219..e406307a 100644 --- a/src/styles/general.css +++ b/src/styles/general.css @@ -1,22 +1,805 @@ -iframe.twitter-timeline.twitter-timeline-rendered { - max-width: 500px !important; - max-height: 1000px; +@font-face { + font-display: swap; + font-family: "Instrument Sans"; + font-style: normal; + font-weight: 400 700; + src: url("InstrumentSans.woff2") format("woff2"); } -/* use two column layout when there is space to do so */ -@media (min-width: 700px) { - .bio { - display: grid; - grid-template-columns: 30% 1fr; - } +html { + background: var(--md-default-bg-color); + overflow-y: scroll; + scrollbar-gutter: stable; } -.bio> :first-child { - max-height: 500px; - grid-column: 0; - margin-right: 20px; +.md-typeset { + font-size: .85rem; + line-height: 1.6; } -.bio> :first-child img { - max-height: 500px; +.md-typeset h1, +.md-typeset h2, +.md-typeset h3 { + color: var(--vb-text); + font-weight: 600; + text-wrap: balance; +} + +.md-typeset h1 { + font-size: 1.9em; + letter-spacing: -.03em; + line-height: 1.1; + margin: 0 0 1em; +} + +.md-typeset h2 { + font-size: 1.25em; + letter-spacing: -.015em; + line-height: 1.25; + margin: 2em 0 .7em; +} + +.md-typeset h3 { + font-size: 1.05em; + line-height: 1.3; + margin: 1.6em 0 .5em; +} + +:is(.md-typeset, .vb-hero) :is(h1, h2, h3, h4) strong { font-weight: inherit; } +:is(.md-typeset, .vb-hero) .headerlink { display: none; } +.md-typeset p { text-wrap: pretty; } + +.md-typeset a { + font-weight: 500; + text-decoration: underline; + text-decoration-color: color-mix(in srgb, currentcolor 35%, transparent); + text-decoration-thickness: 1px; + text-underline-offset: .2em; + transition: text-decoration-color .15s, color .15s; +} + +.md-typeset a:hover, +.md-typeset a:focus-visible { text-decoration-color: currentcolor; } + +.md-typeset p > strong:first-child { + color: var(--vb-muted); + font-weight: 500; +} + +.md-typeset :not(.admonition) > p > strong:only-child { + color: var(--vb-text); + font-size: 1.05em; + font-weight: 600; + letter-spacing: -.01em; +} + +:focus-visible { + outline: 2px solid var(--vb-link); + outline-offset: 2px; +} + +.md-grid { max-width: var(--vb-grid); } + +.md-header.vb-header { + background: var(--vb-bg); + border-bottom: 1px solid var(--vb-rule); + color: var(--vb-text); +} + +.md-header.vb-header.md-header--shadow { box-shadow: none; } + +.vb-header__inner { + align-items: center; + display: flex; + gap: .2rem; + min-height: 3.4rem; + padding: 0 .3rem 0 .8rem; +} + +.vb-brand { + align-items: center; + color: inherit; + display: inline-flex; + flex-shrink: 0; + gap: .55rem; + margin-right: auto; + text-decoration: none; +} + +.vb-brand__mark { + height: 1.8rem; + width: 1.8rem; +} + +.vb-brand__name { + font-size: 1rem; + font-weight: 600; + letter-spacing: -.02em; + line-height: 1; +} + +.vb-nav { + display: none; + flex-shrink: 0; + gap: .2rem; + list-style: none; + margin: 0 .6rem 0 0; + padding: 0; + white-space: nowrap; +} + +.vb-nav__link { + border-radius: var(--vb-radius); + color: var(--vb-muted); + display: block; + font-size: .75rem; + font-weight: 500; + padding: .45rem .55rem; + transition: color .15s, background-color .15s; +} + +.vb-nav__link:hover, +.vb-nav__link:focus-visible { + background: var(--vb-tint); + color: var(--vb-text); +} + +.vb-nav__link--active { + box-shadow: inset 0 -2px 0 var(--vb-green); + border-radius: 0; + color: var(--vb-text); +} + +.vb-header .md-header__option { + align-items: center; + height: 2.4rem; + justify-content: center; + width: 2.4rem; +} + +.vb-header .md-header__button.md-icon { + border-radius: 50%; + color: var(--vb-muted); + margin: 0; + padding: .55rem; + transition: background-color .15s, color .15s; + -webkit-user-select: none; + user-select: none; +} + +.vb-header .md-header__button.md-icon:hover { + background: var(--vb-tint); + color: var(--vb-text); + opacity: 1; +} + +.vb-header .md-header__option svg { height: 1.05rem; width: 1.05rem; } + +[data-md-toggle="search"]:checked ~ .md-header.vb-header .md-header__option { + max-width: none; + opacity: 1; +} + +html[data-md-color-scheme="default"] .md-header__option label[for="__palette_2"], +html[data-md-color-scheme="slate"] .md-header__option label[for="__palette_1"], +html:not([data-md-color-scheme]) .md-header__option label[for="__palette_2"] { display: inline-block; } + +@media (prefers-color-scheme: dark) { + html:not([data-md-color-scheme]) .md-header__option label[for="__palette_2"] { display: none; } + html:not([data-md-color-scheme]) .md-header__option label[for="__palette_1"] { display: inline-block; } +} + +@media (min-width: 60em) { + .vb-nav { display: flex; } + .vb-header .vb-header__menu { display: none; } + + .vb-header .md-search { + flex: 0 1 9rem; + min-width: 9rem; + transition: flex-basis .25s cubic-bezier(.4, 0, .2, 1); + } + + [data-md-toggle="search"]:checked ~ .md-header.vb-header .md-search { flex-basis: 24rem; } + + .vb-header .md-search__inner, + [data-md-toggle="search"]:checked ~ .md-header.vb-header .md-search__inner { + transition: none; + width: 100%; + } + + .md-search__overlay { background: none; } +} + +.vb-header .md-search__form { + background: var(--vb-tint); + border-radius: var(--vb-radius); +} + +.vb-header .md-search__form .md-search__icon, +.vb-header .md-search__input::placeholder { color: var(--vb-muted); } + +.vb-header .md-search__input:focus-visible { outline: none; } + +@media (max-width: 59.9375em) { + [data-md-toggle="search"]:checked ~ .md-header .md-search__overlay { + border-radius: 0; + height: auto; + inset: 0; + position: fixed; + transform: none; + width: auto; + } +} + +[data-md-toggle="search"]:checked ~ .md-header .md-search__form { + background: var(--vb-surface); + border: 1px solid var(--vb-rule); + border-radius: var(--vb-radius); + box-shadow: none; +} + +.vb-header .md-search__output { + border: 1px solid var(--vb-rule); + border-radius: var(--vb-radius); + box-shadow: 0 24px 48px -24px rgb(21 29 25 / 25%); + margin-top: .3rem; +} + +.md-search__inner:has(.md-search__input:placeholder-shown) .md-search__output { display: none; } + +.md-search__scrollwrap { background: var(--vb-surface); } + +.md-search-result__meta { + background: var(--vb-tint); + font-size: .7rem; +} + +@media (min-width: 60em) and (max-width: 76.1875em) { + .vb-header.vb-header--archive .vb-header__menu { display: inline-block; } +} + +.md-main__inner { margin-top: 0; } + +.md-content__inner { + margin: 0 auto; + max-width: 48rem; + padding: 2.8rem .8rem 3.2rem; +} + +.md-content__inner::before { display: none; } +.md-typeset .vb-page > :last-child { margin-bottom: 0; } + +.md-content__inner:has(> .vb-event) { + max-width: none; + padding-top: .6rem; +} + +.md-sidebar--primary:not([hidden]) ~ .md-content > .md-content__inner { max-width: 50rem; } +.md-sidebar { top: 3.4rem; } + +.md-nav { line-height: 1.4; } +.md-nav__link { transition: background-color .15s, color .15s; } +.md-nav__icon { color: var(--vb-muted); } +.md-nav__icon:hover { background: none; } +.md-nav__toggle:checked ~ .md-nav__link { color: var(--vb-text); } +.md-nav--primary .md-nav__link[for="__toc"], +.md-nav--primary .md-nav__link[for="__toc"] ~ .md-nav { display: none; } +.md-nav--primary .md-nav__link[for="__toc"] + .md-nav__link { display: flex; } + +.md-sidebar--primary .md-nav__toggle ~ .md-nav { + display: grid; + grid-template-rows: 0fr; + overflow: hidden; + transition: grid-template-rows .3s cubic-bezier(.2, .7, .2, 1), visibility 0s .3s; + visibility: hidden; +} + +.md-sidebar--primary .md-nav__toggle:checked ~ .md-nav { + grid-template-rows: 1fr; + transition: grid-template-rows .3s cubic-bezier(.2, .7, .2, 1); + visibility: visible; +} + +.md-sidebar--primary .md-nav__toggle ~ .md-nav > .md-nav__list { min-height: 0; } + +@media (min-width: 76.25em) { + .md-sidebar--primary .md-sidebar__scrollwrap { margin: 0; } + .md-sidebar--primary .md-nav--lifted .md-nav__item, + .md-sidebar--primary .md-nav--lifted .md-nav[data-md-level="1"] > .md-nav__list > .md-nav__item { padding: 0; } + + .md-sidebar--primary .md-nav--lifted > .md-nav__list > .md-nav__item--active > .md-nav__link { + color: var(--vb-text); + font-size: .8rem; + font-weight: 600; + letter-spacing: -.01em; + padding: .1rem .5rem .6rem; + } + + .md-sidebar--primary .md-nav__link { + border-radius: var(--vb-radius); + color: var(--vb-muted); + margin: .1rem 0 0; + padding: .28rem .5rem; + } + + .md-sidebar--primary .md-nav__link:hover { background: var(--vb-tint); color: var(--vb-text); } + .md-sidebar--primary .md-nav__icon { height: .8rem; width: .8rem; } + + .md-sidebar--primary .md-nav[data-md-level="2"] > .md-nav__list { + border-left: 1px solid var(--vb-rule); + margin: .1rem 0 .5rem .6rem; + padding-left: .4rem; + } + + .md-sidebar--primary .md-nav[data-md-level="2"] .md-nav__link { position: relative; } + .md-sidebar--primary .md-nav[data-md-level="2"] .md-nav__link--active { color: var(--vb-link); font-weight: 500; } + + .md-sidebar--primary .md-nav[data-md-level="2"] .md-nav__link--active::before { + background: var(--vb-link); + border-radius: 1px; + bottom: .3rem; + content: ""; + left: calc(-.4rem - 1.5px); + position: absolute; + top: .3rem; + width: 2px; + } +} + +@media (max-width: 76.1875em) { + :root { --vb-drawer: min(17rem, 86vw); } + .md-sidebar.md-sidebar--primary { left: calc(-1 * var(--vb-drawer)); width: var(--vb-drawer); } + [data-md-toggle="drawer"]:checked ~ .md-container .md-sidebar--primary { transform: translateX(var(--vb-drawer)); } + .md-overlay { background: rgb(21 29 25 / 40%); } + + .md-nav--primary .md-nav__title[for="__drawer"] { + align-items: center; + background: var(--vb-bg); + border-bottom: 1px solid var(--vb-rule); + color: var(--vb-text); + display: flex; + font-size: 1rem; + font-weight: 600; + height: 3.4rem; + letter-spacing: -.02em; + line-height: 1; + padding: 0 .8rem; + } + + .md-nav--primary .md-nav__title .md-logo { display: none; } + + .md-nav--primary .md-nav__title[for="__drawer"]::after { + background: + linear-gradient(currentcolor, currentcolor) center / 100% 1.5px no-repeat, + linear-gradient(currentcolor, currentcolor) center / 1.5px 100% no-repeat; + content: ""; + height: .9rem; + margin: 0 .2rem 0 auto; + opacity: .75; + transform: rotate(45deg); + width: .9rem; + } + + .md-nav--primary .md-nav__toggle ~ .md-nav { + height: auto; + opacity: 1; + position: static; + transform: none; + } + + .md-nav--primary .md-nav .md-nav__title { display: none; } + .md-nav--primary .md-nav__title ~ .md-nav__list { + box-shadow: none; + padding: .6rem 0 1.2rem; + scroll-snap-type: none; + scrollbar-color: var(--vb-rule) transparent; + scrollbar-width: thin; + } + + .md-nav--primary .md-nav__item { border-top: 0; } + + .md-nav--primary .md-nav__link { + color: var(--vb-text); + font-weight: 500; + padding: .55rem .8rem; + } + + .md-nav--primary .md-nav__link .md-nav__icon { height: .9rem; transition: transform .2s; width: .9rem; } + .md-nav--primary .md-nav__toggle:checked ~ .md-nav__link .md-nav__icon { transform: rotate(90deg); } + + .md-nav--primary .md-nav .md-nav__list { + border-left: 1px solid var(--vb-rule); + margin: 0 .8rem 0 1.15rem; + overflow: visible; + padding: 0; + } + + .md-nav--primary .md-nav .md-nav__list .md-nav__list { margin: 0 0 0 .8rem; } + + .md-nav--primary .md-nav__toggle:checked ~ .md-nav > .md-nav__list:has(> .md-nav__item) { margin-bottom: .4rem; } + .md-nav--primary .md-nav .md-nav__link { padding: .45rem .4rem .45rem .8rem; } + .md-nav--primary .md-nav[data-md-level="2"] .md-nav__link { color: var(--vb-muted); font-weight: 400; position: relative; } + .md-nav--primary .md-nav[data-md-level="2"] .md-nav__link--active { color: var(--vb-link); font-weight: 600; } + + .md-nav--primary .md-nav[data-md-level="2"] .md-nav__link--active::before { + background: var(--vb-link); + border-radius: 1px; + bottom: .4rem; + content: ""; + left: -1.5px; + position: absolute; + top: .4rem; + width: 2px; + } +} + +@media (max-width: 59.9375em) { + .md-sidebar.md-sidebar--primary { + left: 0; + opacity: 0; + top: 0; + transform: none; + transition: opacity .2s, visibility 0s .2s; + visibility: hidden; + width: 100%; + } + + [data-md-toggle="drawer"]:checked ~ .md-container .md-sidebar--primary { + box-shadow: none; + opacity: 1; + transform: none; + transition: opacity .2s; + visibility: visible; + } + + .md-overlay { display: none; } + + .md-nav--primary .md-nav__title[for="__drawer"] { gap: .55rem; } + + .md-nav--primary .md-nav__title .md-logo { + display: block; + margin: 0; + padding: 0; + position: static; + } + + .md-nav--primary .md-nav__title .md-logo.md-nav__button img { + height: 1.8rem; + width: 1.8rem; + } +} + +.md-typeset :is(.vb-page--about, .vb-page--contact, .vb-page--sponsors) h2 { + border-top: 1px solid var(--vb-rule); + margin-top: 2.4rem; + padding-top: 1.8rem; +} + +.md-typeset .columns > ul { + column-gap: 2rem; + columns: 10rem 3; +} + +.md-typeset .columns li { break-inside: avoid; } + +.vb-hero { + overflow: hidden; + position: relative; +} + +.vb-hero__canvas { + inset: 0; + -webkit-mask-composite: source-in; + -webkit-mask-image: + linear-gradient(90deg, rgb(0 0 0 / 30%) 0%, rgb(0 0 0 / 55%) 45%, #000 68%), + linear-gradient(180deg, transparent 0%, #000 12%, #000 62%, transparent 100%); + mask-composite: intersect; + mask-image: + linear-gradient(90deg, rgb(0 0 0 / 30%) 0%, rgb(0 0 0 / 55%) 45%, #000 68%), + linear-gradient(180deg, transparent 0%, #000 12%, #000 62%, transparent 100%); + pointer-events: none; + position: absolute; +} + +.vb-hero__inner { + align-items: center; + display: grid; + gap: 1rem; + grid-template-areas: "title mark" "lede lede"; + grid-template-columns: auto minmax(0, 1fr); + padding: 2.8rem .8rem 1rem; + position: relative; +} + +.vb-hero__figure { + align-self: stretch; + grid-area: mark; + position: relative; + -webkit-user-select: none; + user-select: none; +} + +.vb-hero__mark { + height: 100%; + object-fit: contain; + position: absolute; + width: 100%; +} + +.vb-hero h1 { + font-size: clamp(1.8rem, min(.935rem + 4.8vw, 1.4rem + 3.6vw), 3.9rem); + font-weight: 600; + grid-area: title; + letter-spacing: -.04em; + line-height: .98; + margin: 0; + max-width: 6.8em; + text-wrap: balance; +} + +.vb-hero__lede { + color: var(--vb-muted); + font-size: 1.05rem; + grid-area: lede; + line-height: 1.45; + margin: .2rem 0 0; + max-width: 28rem; + text-wrap: pretty; +} + +@media (min-width: 48em) { + .vb-hero__inner { + column-gap: 0; + grid-template-areas: "title mark" "lede mark"; + grid-template-columns: min(28rem, 58%) minmax(10rem, 1fr); + margin-right: 0; + max-width: calc(50% + var(--vb-grid) / 2); + padding: 4.4rem .8rem 1.2rem; + } + + .vb-hero h1 { max-width: min(14ch, 28rem); } +} + +.vb-event { + background: var(--vb-surface); + border: 1px solid var(--vb-rule); + border-radius: calc(var(--vb-radius) * 1.5); + padding: 2rem 2.4rem 1.8rem; +} + +.vb-event > h2:first-child { + font-size: 1.1em; + margin: 0 0 1.4rem; +} + +.md-typeset .admonition.info { + background: none; + border: 0; + border-bottom: 1px solid var(--vb-rule); + border-radius: 0; + box-shadow: none; + font-size: 1em; + margin: 0 0 1.8rem; + padding: 0 0 1.5rem; +} + +.md-typeset .admonition.info > .admonition-title { display: none; } +.md-typeset .admonition.info > p { margin: 0; } + +.md-typeset .admonition.info > p:has(> strong:only-child) { + font-size: .8em; + margin-bottom: .2em; +} + +.md-typeset .admonition.info > p + p:has(> strong:only-child) { margin-top: .9em; } + +.md-typeset .admonition.info .twemoji, +.md-typeset .timeline .twemoji { + color: var(--vb-muted); + vertical-align: -.1em; +} + +.md-typeset .bio { + align-items: start; + display: grid; + gap: 1.6rem; + grid-template-columns: 8rem 1fr; + margin: 1.8rem 0; +} + +.md-typeset .bio > p:first-child { margin: 0; } + +.md-typeset .bio img { + aspect-ratio: 4 / 5; + display: block; + object-fit: cover; + width: 100%; +} + +.md-typeset .bio > div > p { margin: 0 0 .5em; } + +.md-typeset .bio > div > p:first-child { + font-size: 1.35em; + font-weight: 600; + letter-spacing: -.025em; + line-height: 1.15; + margin-bottom: .7em; +} + +.md-typeset .bio > div > p:first-child > strong { + display: block; + font-size: .62em; + font-weight: 500; + letter-spacing: 0; + margin-bottom: .5em; +} + +.md-typeset .bio > div ul { margin: .2em 0 0; } + +@media (min-width: 60em) { + .md-typeset .bio { + gap: 2rem; + grid-template-columns: 10rem 1fr; + } +} + +.md-typeset p > img:only-child { + border-radius: var(--vb-radius); + max-width: 16rem; +} + +.md-typeset hr { + border: 0; + border-top: 1px solid var(--vb-rule); + margin: 2.2rem 0; +} + +.vb-event hr { margin: 1.6rem 0; } + +@media (max-width: 30em) { + .vb-event { padding: 1.4rem 1.1rem 1.3rem; } + + .md-typeset .bio { + gap: 1rem; + grid-template-columns: 5.6rem 1fr; + } +} + +.vb-footer .md-footer__inner { + border-bottom: 1px solid rgb(255 255 255 / 12%); + padding: .4rem; +} + +.vb-footer__inner { + align-items: center; + display: flex; + flex-wrap: wrap; + gap: 1rem 1.6rem; + justify-content: space-between; + padding: 2.4rem .8rem; +} + +.vb-brand__mark--large { + height: 2.8rem; + width: 2.8rem; +} + +.vb-brand__text { + display: grid; + gap: .2rem; +} + +.vb-brand__full { + font-size: .72rem; + opacity: .72; +} + +.vb-footer .md-social { + display: flex; + gap: .2rem; + margin: 0; + padding: 0; +} + +.vb-footer .md-social__link { + align-items: center; + border-radius: var(--vb-radius); + display: inline-flex; + height: 2rem; + justify-content: center; + opacity: .8; + transition: opacity .15s, background-color .15s; + width: 2rem; +} + +.vb-footer .md-social__link:hover, +.vb-footer .md-social__link:focus-visible { + background: rgb(255 255 255 / 10%); + opacity: 1; +} + +.vb-footer .md-social__link svg { + height: 1rem; + max-height: none; + vertical-align: middle; +} + +.vb-footer .md-social__link[title="X"] svg { height: .85rem; } + +.md-typeset .vb-fold { + display: grid; + grid-template-rows: 0fr; + overflow: hidden; + transition: grid-template-rows .4s cubic-bezier(.2, .7, .2, 1), visibility 0s .4s; + visibility: hidden; +} + +.md-typeset .vb-fold--open { + grid-template-rows: 1fr; + transition: grid-template-rows .4s cubic-bezier(.2, .7, .2, 1); + visibility: visible; +} + +.md-typeset .vb-fold__body { + min-height: 0; + opacity: 0; + transition: opacity .25s; +} + +.md-typeset .vb-fold--open .vb-fold__body { + opacity: 1; + transition: none; +} + +.md-typeset .vb-fold__body > :first-child { margin-top: 1.4rem; } + +.md-typeset .vb-fold__body > p, +.md-typeset .vb-page--archive > p { + hyphens: auto; + text-align: justify; +} + +.md-typeset .vb-fold__toggle { + margin: 1rem 0 0; + text-align: center; +} + +.md-typeset .bio:has(+ .vb-fold) { margin-bottom: .4rem; } + +.md-typeset .vb-fold__button { + background: var(--vb-surface); + border: 1px solid var(--vb-rule); + border-radius: var(--vb-radius); + color: var(--vb-text); + cursor: pointer; + font: 600 .72rem/1 var(--vb-font); + padding: .5rem .9rem; + transition: background-color .15s, border-color .15s; +} + +.md-typeset .vb-fold__button:hover, +.md-typeset .vb-fold__button:focus-visible { + background: var(--vb-tint); + border-color: var(--vb-muted); +} + +.md-typeset .video-container { + aspect-ratio: 16 / 9; + background: var(--vb-tint); + border-radius: var(--vb-radius); + margin: 1.2rem 0; + overflow: hidden; + position: relative; +} + +.md-typeset .video-container iframe { + border: 0; + height: 100% !important; + position: absolute !important; +} + +@media (prefers-reduced-motion: reduce) { + .md-sidebar--primary .md-nav__toggle ~ .md-nav, + .md-typeset .vb-fold, + .md-typeset .vb-fold__body { transition: none; } } diff --git a/src/styles/image-gallery.css b/src/styles/image-gallery.css index 3c6f0936..54232d5b 100644 --- a/src/styles/image-gallery.css +++ b/src/styles/image-gallery.css @@ -1,26 +1,35 @@ -.image-gallery ul { - list-style: none; - margin: 0; - padding: 0; - display: grid; - grid-template-columns: masonry; - grid-template-rows: repeat(1fr, 1fr); +.md-typeset .image-gallery > ul { + align-items: center; + display: flex; + flex-wrap: wrap; + gap: 1.6rem 2.8rem; + justify-content: center; + list-style: none; + margin: 1.8rem 0 0; } -.image-gallery ul li { - margin: 0; - margin-bottom: 30px; - /* border: 1px solid red; */ - display: inline-block; +.md-typeset .image-gallery { transition: opacity .3s; } +.js .md-typeset .image-gallery:not(.vb-ready) { opacity: 0; } - max-width: 300px; - max-height: 300px; - min-height: 100px; - min-width: 100px; +.md-typeset .image-gallery > ul > li { margin: 0; min-width: 0; } +.md-typeset .image-gallery li a { display: block; } + +.md-typeset .image-gallery img { + display: block; + max-height: 3.8rem; + max-width: min(15rem, 100%); +} + +@media (min-width: 60em) { + .md-typeset .image-gallery > ul:not(:has(> li:nth-child(6))) { flex-wrap: nowrap; } } +.md-typeset .image-gallery img[src$="monbug.logo.png"] { translate: 0 -10%; } +.md-typeset .image-gallery img[src$="torbug.logo.png"] { translate: 0 -9.9%; } +.md-typeset .image-gallery img[src$="ottbug.logo.png"] { translate: 0 -29.5%; } +.md-typeset .image-gallery img[src$="yegbug.logo.png"] { translate: 0 -9.9%; } -/* image */ -.image-gallery ul li img { - width: 100%; +[data-md-color-scheme="slate"] .md-typeset .image-gallery img { + filter: brightness(0) invert(1); + opacity: .88; } diff --git a/src/styles/palette.css b/src/styles/palette.css index d7a70bf0..9759af2d 100644 --- a/src/styles/palette.css +++ b/src/styles/palette.css @@ -1,8 +1,60 @@ -:root>* { - --md-primary-fg-color: #3d5c52; - --md-primary-fg-color--light: #a3c2b8; - --md-primary-fg-color--dark: #141f1b; - --md-accent-fg-color: #329acd; - --md-accent-fg-color--light: #bbddee; - --md-accent-fg-color--dark: #113344; +:root, +[data-md-color-scheme="default"] { + --vb-bg: #fbfcfb; + --vb-surface: #fff; + --vb-tint: #eff3f0; + --vb-text: #151d19; + --vb-muted: #5f6d68; + --vb-rule: #e1e7e3; + --vb-green: #3d5c52; + --vb-green-deep: #2f4a41; + --vb-lime: #69cc07; + --vb-glow: 0; + --vb-link: var(--vb-green); + --vb-link-hover: var(--vb-green-deep); + --vb-footer: #151d19; + --vb-radius: .4rem; + --vb-grid: 70rem; + --vb-font: "Instrument Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; + + --md-text-font: var(--vb-font); + --md-code-font: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + --md-primary-fg-color: var(--vb-green); + --md-primary-fg-color--light: #a3c2b8; + --md-primary-fg-color--dark: #141f1b; + --md-accent-fg-color--transparent: rgb(61 92 82 / 10%); + --md-default-fg-color--lighter: #8d9994; + --md-footer-fg-color--light: rgb(255 255 255 / 72%); + --md-footer-fg-color--lighter: rgb(255 255 255 / 45%); + color-scheme: light; +} + +[data-md-color-scheme="slate"] { + --vb-bg: #0f1512; + --vb-surface: #161d1a; + --vb-tint: #1a2420; + --vb-text: #e8ede9; + --vb-muted: #a0ada7; + --vb-rule: #26312c; + --vb-glow: 14; + --vb-link: #a3c2b8; + --vb-link-hover: #c4dbd3; + --vb-footer: #090d0b; + + --md-accent-fg-color--transparent: rgb(163 194 184 / 12%); + --md-default-fg-color--lighter: #6f7f79; + --md-code-bg-color: #090d0b; + --md-code-fg-color: var(--vb-text); + color-scheme: dark; +} + +:root, +[data-md-color-scheme] { + --md-accent-fg-color: var(--vb-link-hover); + --md-default-bg-color: var(--vb-bg); + --md-default-fg-color: var(--vb-text); + --md-default-fg-color--light: var(--vb-muted); + --md-default-fg-color--lightest: var(--vb-rule); + --md-typeset-a-color: var(--vb-link); + --md-footer-bg-color: var(--vb-footer); } diff --git a/src/styles/timeline.css b/src/styles/timeline.css index 9b28b5ff..d77c69cb 100644 --- a/src/styles/timeline.css +++ b/src/styles/timeline.css @@ -1,67 +1,198 @@ -.timeline ul li { - list-style-type: none; - position: relative; - width: 6px; - margin: 0 auto; - padding-top: 20px; - background: #C0C0C0; +.md-typeset .timeline > ul { + border-top: 1px solid var(--vb-rule); + list-style: none; + margin: 1.6rem 0 0; } -.timeline ul li::after { - content: ''; - position: absolute; - left: 50%; - bottom: 0; - transform: translateX(-50%); - width: 30px; - height: 30px; - border-radius: 50%; - background: inherit; - z-index: 1; +.md-typeset .timeline > ul > li { + border-bottom: 1px solid var(--vb-rule); + column-gap: 2rem; + display: grid; + margin: 0; + padding: 1.4rem 0; } -.timeline ul li>p, .timeline ul li>h3 { - position: relative; - bottom: 0; - width: 600px; - padding-left: 15px; - padding-right: 15px; - background: var(--md-accent-fg-color--light); +.md-typeset .timeline > ul > li.vb-past { opacity: .45; } + +.md-typeset .timeline h3 { margin: 0 0 .3em; } + +.md-typeset .timeline h3 a { color: inherit; + text-decoration: none; } +.vb-date { + display: grid; + justify-items: center; + line-height: 1.2; + width: max-content; +} +.vb-date__day { + font-size: 2.4rem; + font-weight: 600; + letter-spacing: -.05em; + line-height: .9; + margin-bottom: .35rem; +} -.timeline ul li>*:first-child { - padding-top: 15px; - border-top-left-radius: 5px; - border-top-right-radius: 5px; - font-size: large; +.vb-date__month { + font-size: .78rem; + font-weight: 600; } -.timeline ul li>p:last-child { - padding-bottom: 15px; - border-bottom-left-radius: 5px; - border-bottom-right-radius: 5px; +.vb-date__weekday { + color: var(--vb-muted); + font-size: .72rem; + font-weight: 400; } +.md-typeset .timeline li > p { margin: 0 0 .3rem; } +.md-typeset .timeline li > p:first-of-type { color: var(--vb-muted); } -.timeline ul li>p:last-child:before { - content: ''; - position: absolute; - bottom: 7px; - width: 0; - height: 0; - border-style: solid; +.md-typeset .timeline .vb-more { margin: .4rem 0 0; } + +.md-typeset .timeline .vb-more a { + font-weight: 600; + text-decoration: none; +} + +.md-typeset .timeline .vb-more a::after { content: " \2192"; } +.md-typeset .timeline .vb-more a:hover { text-decoration: underline; } + +@media (min-width: 40em) { + .md-typeset .timeline > ul > li { + align-items: start; + grid-template-columns: 7rem 1fr; + grid-template-rows: repeat(8, auto); + } + + .md-typeset .timeline li > h3 { + grid-column: 1; + grid-row: 1 / -1; + margin: 0; + } + + .md-typeset .timeline li > p { grid-column: 2; } +} + +@media (max-width: 39.9375em) { + .md-typeset .timeline h3:has(.vb-date) { margin-bottom: .8em; } + + .vb-date { + align-items: baseline; + column-gap: .5rem; + grid-auto-flow: column; + justify-content: start; + } + + .vb-date__day { + font-size: 1.6rem; + margin: 0; + } +} + +.md-typeset details.vb-calendar { + background: none; + border: 0; + box-shadow: none; + display: inline-block; + font-size: inherit; + margin: 0; + padding: 0; + position: relative; + -webkit-user-select: none; + user-select: none; } -.timeline ul li>p, .timeline ul li>h3 { - left: 45px; +.md-typeset details.vb-calendar > summary { + align-items: center; + background: var(--vb-surface); + border: 1px solid var(--vb-rule); + border-radius: var(--vb-radius); + display: inline-flex; + font: 600 .72rem/1 var(--vb-font); + gap: .35rem; margin: 0; + padding: .5rem .7rem .5rem .9rem; + transition: background-color .15s, border-color .15s; +} + +.md-typeset details.vb-calendar > summary:hover, +.md-typeset details.vb-calendar[open] > summary { + background: var(--vb-tint); + border-color: var(--vb-muted); } -.timeline ul li>p::before, .timeline ul li>h3::before { - left: -15px; - border-width: 8px 16px 8px 0; - border-color: transparent var(--md-accent-fg-color--light) transparent transparent; +.md-typeset details.vb-calendar > summary::before { content: none; } + +.md-typeset details.vb-calendar > summary::after { + height: .8rem; + position: static; + transform: rotate(90deg); + transition: transform .15s; + width: .8rem; } + +.md-typeset details.vb-calendar[open] > summary::after { transform: rotate(-90deg); } + +.md-typeset details.vb-calendar > ul { + background: var(--vb-surface); + border: 1px solid var(--vb-rule); + border-radius: var(--vb-radius); + box-shadow: 0 24px 48px -24px rgb(21 29 25 / 25%); + list-style: none; + margin: .3rem 0 0; + min-width: 12rem; + padding: .3rem; + position: absolute; + z-index: 2; +} + +.md-typeset details.vb-calendar > ul > li { margin: 0; } + +.md-typeset details.vb-calendar a { + align-items: center; + border-radius: calc(var(--vb-radius) * .75); + color: var(--vb-text); + display: flex; + font-size: .75rem; + gap: .6rem; + padding: .5rem .6rem; + text-decoration: none; +} + +.md-typeset details.vb-calendar a:hover, +.md-typeset details.vb-calendar a:focus-visible { background: var(--vb-tint); } + +.md-typeset details.vb-calendar img { + height: 1rem; + width: 1rem; +} + +@media (min-width: 48em) { + .md-typeset details.vb-calendar > summary::after { transform: none; } + .md-typeset details.vb-calendar[open] > summary::after { transform: rotate(180deg); } + + .md-typeset details.vb-calendar > ul { + bottom: 0; + box-shadow: none; + display: flex; + gap: .1rem; + left: 100%; + margin: 0 0 0 .3rem; + padding: .15rem; + top: 0; + white-space: nowrap; + width: max-content; + } + + .md-typeset details.vb-calendar > ul > li { flex: none; } + + .md-typeset details.vb-calendar a { + height: 100%; + padding: 0 .6rem; + } +} + +[data-md-color-scheme="slate"] .md-typeset details.vb-calendar img[src$="apple-logo.svg"] { filter: invert(1); } diff --git a/src/theme/.icons/simple/x.svg b/src/theme/.icons/simple/x.svg new file mode 100644 index 00000000..a7c37cff --- /dev/null +++ b/src/theme/.icons/simple/x.svg @@ -0,0 +1 @@ +X \ No newline at end of file diff --git a/src/theme/main.html b/src/theme/main.html new file mode 100644 index 00000000..2244e53e --- /dev/null +++ b/src/theme/main.html @@ -0,0 +1,141 @@ +{% extends "base.html" %} + +{% block fonts %} + +{% endblock %} + +{% block extrahead %} + +{% endblock %} + +{% block header %} +
+ +
+{% endblock %} + +{% block hero %} + {% if page and page.is_homepage and "" in page.content %} +
+
+
+ {{ page.content.split("", 1) | first }} +

Researchers, students and industry people from across the Lower Mainland, sharing work over an evening of talks and networking.

+
+
+ {% endif %} +{% endblock %} + +{% block site_nav %} + {% if nav %} +
+
+
+ {% include "partials/nav.html" %} +
+
+
+ {% endif %} +{% endblock %} + +{% block content %} + {% if page and page.is_homepage and "" in page.content %} +
{{ page.content.split("", 1) | last }}
+ {% else %} +
+ {{ super() }} +
+ {% endif %} +{% endblock %} + +{% block footer %} + {% set in_archive = page and page.url.startswith("archive/") %} + {% set prev = page.previous_page if in_archive and page.previous_page and page.previous_page.url.startswith("archive/") %} + {% set next = page.next_page if in_archive and page.next_page and page.next_page.url.startswith("archive/") %} + +{% endblock %} + +{% block scripts %} + + {{ super() }} +{% endblock %} diff --git a/src/theme/vanbug.js b/src/theme/vanbug.js new file mode 100644 index 00000000..45189dd7 --- /dev/null +++ b/src/theme/vanbug.js @@ -0,0 +1,331 @@ +(() => { + const SCHEME = ["data-md-color-scheme", "data-md-color-primary", "data-md-color-accent"]; + new MutationObserver(() => { + for (const a of SCHEME) document.documentElement.setAttribute(a, document.body.getAttribute(a)); + }).observe(document.body, { attributes: true, attributeFilter: SCHEME }); + + const today = new Date(); + today.setHours(0, 0, 0, 0); + const sections = document.querySelectorAll(".md-nav--primary > .md-nav__list > .md-nav__item"); + document.querySelectorAll(".vb-nav__link").forEach((tab, i) => { + let latest = 0; + for (const link of sections[i]?.querySelectorAll("a") ?? []) { + const date = link.pathname.match(/(\d{4})-(\d\d)-(\d\d)\/$/); + if (!date) continue; + const when = new Date(date[1], date[2] - 1, date[3]); + if (when <= today && when > latest) { latest = when; tab.href = link.href; } + } + }); + + const article = document.querySelector("article.md-typeset"); + if (!article) return; + + for (const strong of article.querySelectorAll("p > strong:first-child")) { + const text = strong.nextSibling; + if (text && text.nodeType === Node.TEXT_NODE && /^\s*:/.test(text.data)) { + text.data = text.data.replace(/^\s*:\s*/, " "); + strong.textContent = strong.textContent.trim().replace(/:?$/, ":"); + } + if (strong.parentElement.matches(".bio > div > p:first-child")) { + strong.textContent = strong.textContent.replace(/:$/, ""); + } + } + + for (const repeat of article.querySelectorAll("p > .twemoji:first-child + strong")) { + const label = repeat.parentElement.previousElementSibling; + if (label && label.textContent.trim() === repeat.textContent.trim()) repeat.remove(); + } + + for (const heading of article.querySelectorAll(".timeline li > h3")) { + const link = heading.querySelector("a:not(.headerlink)"); + const text = (link ? link.textContent : heading.firstChild?.textContent) || ""; + const parts = text.match(/^\s*([A-Za-z]{3})[a-z]*\s+(\d{1,2})\w*,?\s*(\d{4})?,?\s*([A-Za-z]*)/); + if (parts) { + const [, month, day, year, weekday] = parts; + const monthIndex = "JanFebMarAprMayJunJulAugSepOctNovDec".indexOf(month[0].toUpperCase() + month.slice(1).toLowerCase()) / 3; + const when = new Date(year ? +year : today.getFullYear(), monthIndex, +day); + if (monthIndex >= 0 && when < today) heading.closest("li").classList.add("vb-past"); + const date = document.createElement("span"); + date.className = "vb-date"; + date.innerHTML = + `${day}` + + `${month}${year ? ` ${year}` : ""}` + + (weekday ? `${weekday}` : ""); + if (link) link.replaceChildren(date); else heading.firstChild.replaceWith(date); + } + if (!link) continue; + const more = document.createElement("a"); + more.href = link.href; + more.textContent = "Learn more"; + const line = document.createElement("p"); + line.className = "vb-more"; + line.append(more); + heading.closest("li").append(line); + } + + for (const menu of article.querySelectorAll(".vb-calendar")) { + const close = () => { menu.open = false; }; + document.addEventListener("click", ({ target }) => { if (!menu.contains(target) || target.closest("a")) close(); }); + menu.addEventListener("keydown", ({ key }) => { + if (key === "Escape" && menu.open) { close(); menu.querySelector("summary").focus(); } + }); + for (const link of menu.querySelectorAll("a[href^='http']")) { link.target = "_blank"; link.rel = "noopener"; } + } + + const schemed = [...article.querySelectorAll("img[data-dark]")]; + if (schemed.length) { + for (const img of schemed) img.dataset.light = img.getAttribute("src"); + const swap = () => { + const dark = document.body.getAttribute("data-md-color-scheme") === "slate"; + for (const img of schemed) img.setAttribute("src", dark ? img.dataset.dark : img.dataset.light); + }; + swap(); + new MutationObserver(swap).observe(document.body, { attributes: true, attributeFilter: ["data-md-color-scheme"] }); + } + + const LOGO_AREA = 9000; + const probe = document.createElement("canvas").getContext("2d", { willReadFrequently: true }); + const sizeLogo = (img) => { + const ratio = img.naturalWidth / img.naturalHeight; + if (!ratio) return; + let weight = 1; + try { + probe.canvas.width = 64; + probe.canvas.height = Math.max(1, Math.round(64 / ratio)); + probe.drawImage(img, 0, 0, probe.canvas.width, probe.canvas.height); + const { data } = probe.getImageData(0, 0, probe.canvas.width, probe.canvas.height); + let inked = 0; + for (let i = 3; i < data.length; i += 4) inked += data[i] > 127; + const fill = inked / (data.length / 4); + weight = Math.min(1.15, Math.max(0.85, (0.25 / fill) ** 0.25)); + } catch {} + const tallest = parseFloat(getComputedStyle(img).maxHeight) || Infinity; + img.style.width = `${Math.round(Math.min(Math.sqrt(LOGO_AREA * ratio) * weight, tallest * ratio))}px`; + }; + for (const gallery of article.querySelectorAll(".image-gallery")) { + const settle = (img) => img.complete ? sizeLogo(img) : new Promise((done) => { + img.onload = () => done(sizeLogo(img)); + img.onerror = done; + }); + Promise.all([...gallery.querySelectorAll("img")].map(settle)).then(() => gallery.classList.add("vb-ready")); + } + + const FOLDS = ["bio", "abstract", "talk summary"]; + const isFoldLabel = (el) => + el.tagName === "P" && + el.children.length === 1 && + el.firstElementChild.tagName === "STRONG" && + el.textContent.trim() === el.firstElementChild.textContent.trim() && + FOLDS.includes(el.textContent.trim().replace(/:$/, "").toLowerCase()); + const isDivider = (el) => el.tagName === "HR" || el.classList.contains("bio"); + + const event = article.querySelector(".vb-event"); + let start = event && [...event.children].find(isFoldLabel); + for (let n = 0; start; n++) { + const fold = document.createElement("div"); + fold.className = "vb-fold"; + fold.id = `vb-fold-${n}`; + const body = document.createElement("div"); + body.className = "vb-fold__body"; + fold.append(body); + start.before(fold); + for (let el = fold.nextElementSibling; el && !isDivider(el); el = fold.nextElementSibling) body.append(el); + + const button = document.createElement("button"); + button.type = "button"; + button.className = "vb-fold__button"; + button.setAttribute("aria-controls", fold.id); + button.setAttribute("aria-expanded", "false"); + button.textContent = "Read more"; + button.addEventListener("click", () => { + const open = fold.classList.toggle("vb-fold--open"); + button.setAttribute("aria-expanded", String(open)); + button.textContent = open ? "Read less" : "Read more"; + if (open) return; + const anchor = button.getBoundingClientRect().top; + const started = performance.now(); + const hold = (now) => { + scrollBy({ top: button.getBoundingClientRect().top - anchor, behavior: "instant" }); + if (now - started < 450) requestAnimationFrame(hold); + }; + requestAnimationFrame(hold); + }); + const toggle = document.createElement("p"); + toggle.className = "vb-fold__toggle"; + toggle.append(button); + fold.after(toggle); + + const rest = [...event.children]; + start = rest.slice(rest.indexOf(toggle) + 1).find(isFoldLabel); + } + + const sidebar = document.querySelector(".md-sidebar--primary"); + if (sidebar) { + sidebar.addEventListener("change", ({ target }) => { + if (!target.matches(".md-nav__toggle") || !target.checked) return; + const item = target.closest(".md-nav__item"); + for (const other of item.parentElement.querySelectorAll(":scope > .md-nav__item > .md-nav__toggle")) { + if (other !== target) other.checked = false; + } + let scroller = item.parentElement; + while (scroller !== sidebar && getComputedStyle(scroller).overflowY !== "auto") scroller = scroller.parentElement; + const nav = item.querySelector(":scope > .md-nav"); + const list = nav.querySelector(":scope > .md-nav__list"); + const listStyle = getComputedStyle(list); + const grown = list.scrollHeight + parseFloat(listStyle.marginTop) + parseFloat(listStyle.marginBottom); + const frame = scroller.getBoundingClientRect(); + const from = item.getBoundingClientRect().top; + const row = nav.getBoundingClientRect().top - from; + const to = Math.max(frame.top + 8, Math.min(from, frame.bottom - 8 - row - grown)); + const started = performance.now(); + const follow = (now) => { + const progress = Math.min(1, nav.getBoundingClientRect().height / grown); + scroller.scrollTop += item.getBoundingClientRect().top - (from + (to - from) * progress); + if (now - started < 400) requestAnimationFrame(follow); + }; + requestAnimationFrame(follow); + }); + } + + const search = document.querySelector(".md-search__input"); + if (search) { + const idle = search.placeholder; + search.addEventListener("focus", () => { search.placeholder = "Type to start searching"; }); + search.addEventListener("blur", () => { search.placeholder = idle; }); + } + + for (const img of article.querySelectorAll("img:not([src$='.svg'])")) { + const hide = () => { img.hidden = true; }; + if (img.complete && !img.naturalWidth) hide(); else img.addEventListener("error", hide); + } + + const hero = document.querySelector(".vb-hero"); + if (!hero || matchMedia("(prefers-reduced-motion: reduce)").matches) return; + + const canvas = document.createElement("canvas"); + canvas.className = "vb-hero__canvas"; + canvas.setAttribute("aria-hidden", "true"); + hero.prepend(canvas); + const ctx = canvas.getContext("2d"); + const BASES = "ACGT"; + const CELL = 22; + const LINE = 22; + const ALPHA = 0.16; + const HEAD = 101; + const REACH = 24; + const WANDER = 12; + const MUTATIONS = 120; + const FADE = 0.14; + const COOL = 0.72; + const pick = () => BASES[(Math.random() * 4) | 0]; + const cell = () => ({ base: pick(), prev: "", fade: 1, heat: 0, lock: 0, delay: 0, flip: 0, x: 0, y: 0 }); + let rows = []; + let width = 0; + let height = 0; + + const resize = () => { + const dpr = Math.min(devicePixelRatio || 1, 2); + width = hero.clientWidth; + height = hero.clientHeight; + canvas.width = width * dpr; + canvas.height = height * dpr; + canvas.style.width = `${width}px`; + canvas.style.height = `${height}px`; + ctx.setTransform(dpr, 0, 0, dpr, 0, 0); + ctx.font = "400 16px ui-monospace, SFMono-Regular, Menlo, monospace"; + ctx.textBaseline = "middle"; + const cols = Math.ceil(width / CELL) + 2; + rows = Array.from({ length: Math.ceil(height / LINE) + 1 }, (_, i) => + rows[i] && rows[i].cells.length >= cols + ? rows[i] + : { + cells: Array.from({ length: cols }, cell), + offset: Math.random() * CELL, + speed: (3 + Math.random() * 3.6) * (i % 2 ? 1 : -1), + debt: 0, + phase: Math.random() * 2 * Math.PI, + pace: 0.4 + Math.random() * 0.8, + }); + }; + + const rgb = (hex) => [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16)); + const mix = (a, b, t) => `rgb(${a.map((v, i) => Math.round(v + (b[i] - v) * t)).join(" ")})`; + let scheme, shades, glow; + const colours = () => { + const style = getComputedStyle(hero); + const ink = rgb(style.getPropertyValue("--vb-green").trim()); + const lime = rgb(style.getPropertyValue("--vb-lime").trim()); + glow = parseFloat(style.getPropertyValue("--vb-glow")) || 0; + shades = Array.from({ length: 33 }, (_, k) => mix(ink, lime, k / 32)); + }; + let head = -160; + let last = 0; + let visible = true; + let running = true; + + const frame = (time) => { + if (!visible) { running = false; return; } + requestAnimationFrame(frame); + if (time - last < 15) return; + const dt = Math.min((time - last) / 1000, 0.05); + const now = time / 1000; + last = time; + if (scheme !== document.body.dataset.mdColorScheme) { + scheme = document.body.dataset.mdColorScheme; + colours(); + } + const cool = Math.exp(-dt / COOL); + head = head > width + 160 + WANDER ? -160 : head + HEAD * dt; + + ctx.clearRect(0, 0, width, height); + ctx.shadowColor = shades[32]; + ctx.shadowBlur = 0; + ctx.globalAlpha = ALPHA; + ctx.fillStyle = shades[0]; + const lit = []; + rows.forEach((row, r) => { + const { cells, phase, pace } = row; + row.offset += row.speed * dt; + if (row.offset > CELL) { row.offset -= CELL; cells.unshift(cells.pop()); } + if (row.offset < -CELL) { row.offset += CELL; cells.push(cells.shift()); } + for (row.debt += MUTATIONS * dt; row.debt >= 1; row.debt--) { + const c = cells[(Math.random() * cells.length) | 0]; + if (c.lock < now) { c.prev = c.base; c.base = pick(); c.fade = 0; } + } + const y = r * LINE + LINE / 2; + const wander = 0.6 * Math.sin(now * pace + phase) + 0.4 * Math.sin(now * pace * 2.3 + phase * 1.7); + const front = head + WANDER * wander; + cells.forEach((c, i) => { + const x = i * CELL - CELL + row.offset; + c.heat *= cool; + if (Math.abs(x - front) < REACH) { + c.heat = 1; + if (c.lock < now) c.delay = 0.05 + Math.random() * 0.3; + c.lock = now + c.delay; + } + if (c.lock > now && now - c.flip > 0.05) { c.base = pick(); c.flip = now; c.fade = 1; } + if (c.fade < 1) c.fade = Math.min(1, c.fade + dt / FADE); + if (c.heat < 0.02 && c.fade === 1) ctx.fillText(c.base, x, y); + else { c.x = x; c.y = y; lit.push(c); } + }); + }); + + for (const c of lit) { + const alpha = ALPHA + (1 - ALPHA) * c.heat; + const shown = 1 - (1 - c.fade) ** 2; + ctx.fillStyle = shades[Math.round(c.heat * 32)]; + ctx.shadowBlur = c.heat > 0.5 ? glow * c.heat : 0; + if (shown < 1) { ctx.globalAlpha = alpha * (1 - shown); ctx.fillText(c.prev, c.x, c.y); } + ctx.globalAlpha = alpha * shown; + ctx.fillText(c.base, c.x, c.y); + } + }; + + resize(); + frame(performance.now()); + new ResizeObserver(resize).observe(hero); + new IntersectionObserver(([entry]) => { + visible = entry.isIntersecting; + if (visible && !running) { running = true; requestAnimationFrame(frame); } + }).observe(hero); +})();