<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://hallyu.io/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Joeeasterly</id>
	<title>Hallyu.io - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://hallyu.io/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Joeeasterly"/>
	<link rel="alternate" type="text/html" href="https://hallyu.io/Special:Contributions/Joeeasterly"/>
	<updated>2026-04-09T00:17:51Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://hallyu.io/index.php?title=Main_Page&amp;diff=22</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=Main_Page&amp;diff=22"/>
		<updated>2026-02-03T15:32:42Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: /* IT Administration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Engaged Learning &amp;amp; Research ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://uofr.sharepoint.com/sites/LibraryLiaisons?spStartSource=spappbar | label=Sharepoint | desc=Library Liaisons | icon=microsoft-sharepoint }}&lt;br /&gt;
{{DashItem | url=https://tables.hallyu.io | label=Tables | desc=PhpMyAdmin | icon=database-search }}&lt;br /&gt;
{{DashItem | url=https://data.hallyu.io | label=Data | desc=Postgres &amp;amp; PGAdmin | icon=database-cog }}&lt;br /&gt;
{{DashItem | url=https://wiki.hallyu.io | label=Wikibase | desc=Knowledge Graph | icon=graph }}&lt;br /&gt;
{{DashItem | url=https://apps.hallyu.io | label=Django | desc=App Framework | icon=language-python }}&lt;br /&gt;
{{DashItem | url=https://learn.rochester.edu | label=Blackboard Learn | desc=LMS | icon=school }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== IT Administration ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://aws.amazon.com/console/ | label=AWS | desc=Management Console | icon=aws }}&lt;br /&gt;
{{DashItem | url=https://sso.hallyu.io | label=SSO | desc=Keycloak | icon=key-variant }}&lt;br /&gt;
{{DashItem | url=https://desktop.hallyu.io | label=Desktop | desc=Guacamole Remote | icon=monitor-dashboard }}&lt;br /&gt;
{{DashItem | url=https://it.hallyu.io | label=Assets | desc=Snipe-IT | icon=barcode-scan }}&lt;br /&gt;
{{DashItem | url=https://admin.hallyu.io | label=OpenObserve | desc=Observability | icon=eye-outline }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Personal Information Management ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://tasks.google.com | label=Tasks | desc=Google Tasks | icon=checkbox-marked-circle-outline }}&lt;br /&gt;
{{DashItem | url=https://gemini.google.com | label=Gemini | desc=AI Assistant | icon=creation }}&lt;br /&gt;
{{DashItem | url=https://calendar.notion.so | label=Calendar | desc=Notion Calendar | icon=calendar-month }}&lt;br /&gt;
{{DashItem | url=https://mail.notion.so | label=Mail | desc=Notion Mail | icon=email-outline }}&lt;br /&gt;
{{DashItem | url=https://finance.hallyu.io | label=Finance | desc=Actual Budget | icon=finance }}&lt;br /&gt;
{{DashItem | url=https://notion.so | label=Notion | desc=Workspace | icon=notebook-outline }}&lt;br /&gt;
{{DashItem | url=https://archive.hallyu.io | label=Archive | desc=Paperless-ngx | icon=file-document-multiple-outline }}&lt;br /&gt;
{{DashItem | url=https://voice.google.com | label=Google Voice | desc=VoIP | icon=phone-voip }}&lt;br /&gt;
{{DashItem | url=https://messenger.com | label=Messenger | desc=Facebook | icon=facebook-messenger }}&lt;br /&gt;
{{DashItem | url=https://icloud.com | label=iCloud | desc=Apple Services | icon=apple-icloud }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projects ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://kpop.hallyu.io | label=Kpop | desc=Omeka Digital Archive | icon=music-note }}&lt;br /&gt;
{{DashItem | url=https://vscode.dev | label=VSCode | desc=Visual Studio Code | icon=microsoft-visual-studio-code }}&lt;br /&gt;
{{DashItem | url=https://github.com | label=GitHub | desc=Repositories | icon=github }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Household ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://alexa.com | label=Alexa | desc=Amazon Alexa | icon=amazon-alexa }}&lt;br /&gt;
{{DashItem | url=https://home.hallyu.io | label=Home Assistant | desc=IoT Control | icon=home-automation }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Social ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://twitter.com | label=Twitter | desc=Bird Site | icon=twitter }}&lt;br /&gt;
{{DashItem | url=https://bsky.app | label=BlueSky | desc=Clouds | icon=butterfly }}&lt;br /&gt;
{{DashItem | url=https://facebook.com | label=Facebook | desc=Social | icon=facebook }}&lt;br /&gt;
{{DashItem | url=https://instagram.com | label=Instagram | desc=Photos | icon=instagram }}&lt;br /&gt;
{{DashItem | url=https://mastodon.social | label=Mastodon | desc=Fediverse | icon=mastodon }}&lt;br /&gt;
{{DashItem | url=https://youtube.com | label=YouTube | desc=Video | icon=youtube }}&lt;br /&gt;
{{DashItem | url=https://linkedin.com | label=LinkedIn | desc=Professional | icon=linkedin }}&lt;br /&gt;
{{DashItem | url=https://whatsapp.com | label=WhatsApp | desc=Messaging | icon=whatsapp }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://crunchyroll.com | label=Crunchyroll | desc=Anime | icon=shuriken }}&lt;br /&gt;
{{DashItem | url=https://netflix.com | label=Netflix | desc=Streaming | icon=netflix }}&lt;br /&gt;
{{DashItem | url=https://hulu.com | label=Hulu | desc=Streaming | icon=hulu }}&lt;br /&gt;
{{DashItem | url=https://disneyplus.com | label=Disney+ | desc=Streaming | icon=castle }}&lt;br /&gt;
{{DashItem | url=https://spotify.com | label=Spotify | desc=Music | icon=spotify }}&lt;br /&gt;
{{DashItem | url=https://music.apple.com | label=Apple Music | desc=Music | icon=apple }}&lt;br /&gt;
{{DashItem | url=https://paramountplus.com | label=Paramount+ | desc=Streaming | icon=movie-star }}&lt;br /&gt;
{{DashItem | url=https://primevideo.com | label=Prime Video | desc=Amazon | icon=amazon }}&lt;br /&gt;
{{DashItem | url=https://max.com | label=Max | desc=HBO | icon=television-classic }}&lt;br /&gt;
{{DashItem | url=https://duolingo.com | label=Duolingo | desc=Learning | icon=owl }}&lt;br /&gt;
{{DashItem | url=https://audible.com | label=Audible | desc=Audiobooks | icon=book-music }}&lt;br /&gt;
{{DashItem | url=https://rosettastone.com | label=Rosetta Stone | desc=Learning | icon=translate }}&lt;br /&gt;
{{DashItem | url=https://kindle.com | label=Kindle | desc=Reading | icon=tablet-dashboard }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Unsorted ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://trakt.tv | label=Trakt | desc=Tracking | icon=eye-check-outline }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=Main_Page&amp;diff=21</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=Main_Page&amp;diff=21"/>
		<updated>2026-02-03T14:44:21Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: /* Personal Information Management */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Engaged Learning &amp;amp; Research ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://uofr.sharepoint.com/sites/LibraryLiaisons?spStartSource=spappbar | label=Sharepoint | desc=Library Liaisons | icon=microsoft-sharepoint }}&lt;br /&gt;
{{DashItem | url=https://tables.hallyu.io | label=Tables | desc=PhpMyAdmin | icon=database-search }}&lt;br /&gt;
{{DashItem | url=https://data.hallyu.io | label=Data | desc=Postgres &amp;amp; PGAdmin | icon=database-cog }}&lt;br /&gt;
{{DashItem | url=https://wiki.hallyu.io | label=Wikibase | desc=Knowledge Graph | icon=graph }}&lt;br /&gt;
{{DashItem | url=https://apps.hallyu.io | label=Django | desc=App Framework | icon=language-python }}&lt;br /&gt;
{{DashItem | url=https://learn.rochester.edu | label=Blackboard Learn | desc=LMS | icon=school }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== IT Administration ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://aws.amazon.com/console/ | label=AWS | desc=Management Console | icon=aws }}&lt;br /&gt;
{{DashItem | url=https://sso.hallyu.io | label=SSO | desc=Keycloak | icon=key-variant }}&lt;br /&gt;
{{DashItem | url=https://flow.hallyu.io | label=Flow | desc=Node-Red | icon=pipe }}&lt;br /&gt;
{{DashItem | url=https://desktop.hallyu.io | label=Desktop | desc=Guacamole Remote | icon=monitor-dashboard }}&lt;br /&gt;
{{DashItem | url=https://s3.hallyu.io | label=RClone | desc=Cloud Storage | icon=cloud-sync }}&lt;br /&gt;
{{DashItem | url=https://it.hallyu.io | label=Assets | desc=Snipe-IT | icon=barcode-scan }}&lt;br /&gt;
{{DashItem | url=https://containers.hallyu.io | label=Portainer | desc=Docker Management | icon=docker }}&lt;br /&gt;
{{DashItem | url=https://admin.hallyu.io | label=OpenObserve | desc=Observability | icon=eye-outline }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Personal Information Management ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://tasks.google.com | label=Tasks | desc=Google Tasks | icon=checkbox-marked-circle-outline }}&lt;br /&gt;
{{DashItem | url=https://gemini.google.com | label=Gemini | desc=AI Assistant | icon=creation }}&lt;br /&gt;
{{DashItem | url=https://calendar.notion.so | label=Calendar | desc=Notion Calendar | icon=calendar-month }}&lt;br /&gt;
{{DashItem | url=https://mail.notion.so | label=Mail | desc=Notion Mail | icon=email-outline }}&lt;br /&gt;
{{DashItem | url=https://finance.hallyu.io | label=Finance | desc=Actual Budget | icon=finance }}&lt;br /&gt;
{{DashItem | url=https://notion.so | label=Notion | desc=Workspace | icon=notebook-outline }}&lt;br /&gt;
{{DashItem | url=https://archive.hallyu.io | label=Archive | desc=Paperless-ngx | icon=file-document-multiple-outline }}&lt;br /&gt;
{{DashItem | url=https://voice.google.com | label=Google Voice | desc=VoIP | icon=phone-voip }}&lt;br /&gt;
{{DashItem | url=https://messenger.com | label=Messenger | desc=Facebook | icon=facebook-messenger }}&lt;br /&gt;
{{DashItem | url=https://icloud.com | label=iCloud | desc=Apple Services | icon=apple-icloud }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projects ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://kpop.hallyu.io | label=Kpop | desc=Omeka Digital Archive | icon=music-note }}&lt;br /&gt;
{{DashItem | url=https://vscode.dev | label=VSCode | desc=Visual Studio Code | icon=microsoft-visual-studio-code }}&lt;br /&gt;
{{DashItem | url=https://github.com | label=GitHub | desc=Repositories | icon=github }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Household ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://alexa.com | label=Alexa | desc=Amazon Alexa | icon=amazon-alexa }}&lt;br /&gt;
{{DashItem | url=https://home.hallyu.io | label=Home Assistant | desc=IoT Control | icon=home-automation }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Social ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://twitter.com | label=Twitter | desc=Bird Site | icon=twitter }}&lt;br /&gt;
{{DashItem | url=https://bsky.app | label=BlueSky | desc=Clouds | icon=butterfly }}&lt;br /&gt;
{{DashItem | url=https://facebook.com | label=Facebook | desc=Social | icon=facebook }}&lt;br /&gt;
{{DashItem | url=https://instagram.com | label=Instagram | desc=Photos | icon=instagram }}&lt;br /&gt;
{{DashItem | url=https://mastodon.social | label=Mastodon | desc=Fediverse | icon=mastodon }}&lt;br /&gt;
{{DashItem | url=https://youtube.com | label=YouTube | desc=Video | icon=youtube }}&lt;br /&gt;
{{DashItem | url=https://linkedin.com | label=LinkedIn | desc=Professional | icon=linkedin }}&lt;br /&gt;
{{DashItem | url=https://whatsapp.com | label=WhatsApp | desc=Messaging | icon=whatsapp }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://crunchyroll.com | label=Crunchyroll | desc=Anime | icon=shuriken }}&lt;br /&gt;
{{DashItem | url=https://netflix.com | label=Netflix | desc=Streaming | icon=netflix }}&lt;br /&gt;
{{DashItem | url=https://hulu.com | label=Hulu | desc=Streaming | icon=hulu }}&lt;br /&gt;
{{DashItem | url=https://disneyplus.com | label=Disney+ | desc=Streaming | icon=castle }}&lt;br /&gt;
{{DashItem | url=https://spotify.com | label=Spotify | desc=Music | icon=spotify }}&lt;br /&gt;
{{DashItem | url=https://music.apple.com | label=Apple Music | desc=Music | icon=apple }}&lt;br /&gt;
{{DashItem | url=https://paramountplus.com | label=Paramount+ | desc=Streaming | icon=movie-star }}&lt;br /&gt;
{{DashItem | url=https://primevideo.com | label=Prime Video | desc=Amazon | icon=amazon }}&lt;br /&gt;
{{DashItem | url=https://max.com | label=Max | desc=HBO | icon=television-classic }}&lt;br /&gt;
{{DashItem | url=https://duolingo.com | label=Duolingo | desc=Learning | icon=owl }}&lt;br /&gt;
{{DashItem | url=https://audible.com | label=Audible | desc=Audiobooks | icon=book-music }}&lt;br /&gt;
{{DashItem | url=https://rosettastone.com | label=Rosetta Stone | desc=Learning | icon=translate }}&lt;br /&gt;
{{DashItem | url=https://kindle.com | label=Kindle | desc=Reading | icon=tablet-dashboard }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Unsorted ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://trakt.tv | label=Trakt | desc=Tracking | icon=eye-check-outline }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=Main_Page&amp;diff=20</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=Main_Page&amp;diff=20"/>
		<updated>2026-02-02T22:57:16Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: /* Engaged Learning &amp;amp; Research */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Engaged Learning &amp;amp; Research ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://uofr.sharepoint.com/sites/LibraryLiaisons?spStartSource=spappbar | label=Sharepoint | desc=Library Liaisons | icon=microsoft-sharepoint }}&lt;br /&gt;
{{DashItem | url=https://tables.hallyu.io | label=Tables | desc=PhpMyAdmin | icon=database-search }}&lt;br /&gt;
{{DashItem | url=https://data.hallyu.io | label=Data | desc=Postgres &amp;amp; PGAdmin | icon=database-cog }}&lt;br /&gt;
{{DashItem | url=https://wiki.hallyu.io | label=Wikibase | desc=Knowledge Graph | icon=graph }}&lt;br /&gt;
{{DashItem | url=https://apps.hallyu.io | label=Django | desc=App Framework | icon=language-python }}&lt;br /&gt;
{{DashItem | url=https://learn.rochester.edu | label=Blackboard Learn | desc=LMS | icon=school }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== IT Administration ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://aws.amazon.com/console/ | label=AWS | desc=Management Console | icon=aws }}&lt;br /&gt;
{{DashItem | url=https://sso.hallyu.io | label=SSO | desc=Keycloak | icon=key-variant }}&lt;br /&gt;
{{DashItem | url=https://flow.hallyu.io | label=Flow | desc=Node-Red | icon=pipe }}&lt;br /&gt;
{{DashItem | url=https://desktop.hallyu.io | label=Desktop | desc=Guacamole Remote | icon=monitor-dashboard }}&lt;br /&gt;
{{DashItem | url=https://s3.hallyu.io | label=RClone | desc=Cloud Storage | icon=cloud-sync }}&lt;br /&gt;
{{DashItem | url=https://it.hallyu.io | label=Assets | desc=Snipe-IT | icon=barcode-scan }}&lt;br /&gt;
{{DashItem | url=https://containers.hallyu.io | label=Portainer | desc=Docker Management | icon=docker }}&lt;br /&gt;
{{DashItem | url=https://admin.hallyu.io | label=OpenObserve | desc=Observability | icon=eye-outline }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Personal Information Management ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://tasks.google.com | label=Tasks | desc=Google Tasks | icon=checkbox-marked-circle-outline }}&lt;br /&gt;
{{DashItem | url=https://gemini.google.com | label=Gemini | desc=AI Assistant | icon=creation }}&lt;br /&gt;
{{DashItem | url=https://calendar.notion.so | label=Calendar | desc=Notion Calendar | icon=calendar-month }}&lt;br /&gt;
{{DashItem | url=https://mail.notion.so | label=Mail | desc=Notion Mail | icon=email-outline }}&lt;br /&gt;
{{DashItem | url=https://links.hallyu.io | label=Links | desc=Linkding Bookmarks | icon=bookmark-multiple }}&lt;br /&gt;
{{DashItem | url=https://finance.hallyu.io | label=Finance | desc=Actual Budget | icon=finance }}&lt;br /&gt;
{{DashItem | url=https://notion.so | label=Notion | desc=Workspace | icon=notebook-outline }}&lt;br /&gt;
{{DashItem | url=https://archive.hallyu.io | label=Archive | desc=Paperless-ngx | icon=file-document-multiple-outline }}&lt;br /&gt;
{{DashItem | url=https://voice.google.com | label=Google Voice | desc=VoIP | icon=phone-voip }}&lt;br /&gt;
{{DashItem | url=https://messenger.com | label=Messenger | desc=Facebook | icon=facebook-messenger }}&lt;br /&gt;
{{DashItem | url=https://icloud.com | label=iCloud | desc=Apple Services | icon=apple-icloud }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projects ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://kpop.hallyu.io | label=Kpop | desc=Omeka Digital Archive | icon=music-note }}&lt;br /&gt;
{{DashItem | url=https://vscode.dev | label=VSCode | desc=Visual Studio Code | icon=microsoft-visual-studio-code }}&lt;br /&gt;
{{DashItem | url=https://github.com | label=GitHub | desc=Repositories | icon=github }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Household ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://alexa.com | label=Alexa | desc=Amazon Alexa | icon=amazon-alexa }}&lt;br /&gt;
{{DashItem | url=https://home.hallyu.io | label=Home Assistant | desc=IoT Control | icon=home-automation }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Social ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://twitter.com | label=Twitter | desc=Bird Site | icon=twitter }}&lt;br /&gt;
{{DashItem | url=https://bsky.app | label=BlueSky | desc=Clouds | icon=butterfly }}&lt;br /&gt;
{{DashItem | url=https://facebook.com | label=Facebook | desc=Social | icon=facebook }}&lt;br /&gt;
{{DashItem | url=https://instagram.com | label=Instagram | desc=Photos | icon=instagram }}&lt;br /&gt;
{{DashItem | url=https://mastodon.social | label=Mastodon | desc=Fediverse | icon=mastodon }}&lt;br /&gt;
{{DashItem | url=https://youtube.com | label=YouTube | desc=Video | icon=youtube }}&lt;br /&gt;
{{DashItem | url=https://linkedin.com | label=LinkedIn | desc=Professional | icon=linkedin }}&lt;br /&gt;
{{DashItem | url=https://whatsapp.com | label=WhatsApp | desc=Messaging | icon=whatsapp }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://crunchyroll.com | label=Crunchyroll | desc=Anime | icon=shuriken }}&lt;br /&gt;
{{DashItem | url=https://netflix.com | label=Netflix | desc=Streaming | icon=netflix }}&lt;br /&gt;
{{DashItem | url=https://hulu.com | label=Hulu | desc=Streaming | icon=hulu }}&lt;br /&gt;
{{DashItem | url=https://disneyplus.com | label=Disney+ | desc=Streaming | icon=castle }}&lt;br /&gt;
{{DashItem | url=https://spotify.com | label=Spotify | desc=Music | icon=spotify }}&lt;br /&gt;
{{DashItem | url=https://music.apple.com | label=Apple Music | desc=Music | icon=apple }}&lt;br /&gt;
{{DashItem | url=https://paramountplus.com | label=Paramount+ | desc=Streaming | icon=movie-star }}&lt;br /&gt;
{{DashItem | url=https://primevideo.com | label=Prime Video | desc=Amazon | icon=amazon }}&lt;br /&gt;
{{DashItem | url=https://max.com | label=Max | desc=HBO | icon=television-classic }}&lt;br /&gt;
{{DashItem | url=https://duolingo.com | label=Duolingo | desc=Learning | icon=owl }}&lt;br /&gt;
{{DashItem | url=https://audible.com | label=Audible | desc=Audiobooks | icon=book-music }}&lt;br /&gt;
{{DashItem | url=https://rosettastone.com | label=Rosetta Stone | desc=Learning | icon=translate }}&lt;br /&gt;
{{DashItem | url=https://kindle.com | label=Kindle | desc=Reading | icon=tablet-dashboard }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Unsorted ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://trakt.tv | label=Trakt | desc=Tracking | icon=eye-check-outline }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=MediaWiki:Citizen.js&amp;diff=19</id>
		<title>MediaWiki:Citizen.js</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=MediaWiki:Citizen.js&amp;diff=19"/>
		<updated>2026-02-02T22:56:00Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* All JavaScript here will be loaded for users of the Citizen skin */&lt;br /&gt;
/**&lt;br /&gt;
 * Dashboard Quick-Jump (v2)&lt;br /&gt;
 * Listens for typing on the Dashboard page and jumps to matching cards.&lt;br /&gt;
 * Now with description searching and strict edit-mode discipline.&lt;br /&gt;
 */&lt;br /&gt;
(function() {&lt;br /&gt;
    // 1. GLOBAL GUARD: If we aren&#039;t in &#039;view&#039; mode, kill the script immediately.&lt;br /&gt;
    // We do not want this running on ?action=edit, ?action=history, etc.&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) !== &#039;view&#039;) return;&lt;br /&gt;
&lt;br /&gt;
    // 2. CONTEXT GUARD: If there are no dashboard cards, go back to sleep.&lt;br /&gt;
    if (!document.querySelector(&#039;.dashboard-card&#039;)) return;&lt;br /&gt;
&lt;br /&gt;
    const CONFIG = {&lt;br /&gt;
        selectorCard: &#039;.dashboard-card&#039;,&lt;br /&gt;
        selectorLabel: &#039;.dashboard-label&#039;,&lt;br /&gt;
        selectorDesc: &#039;.dashboard-desc&#039;, // New: Search descriptions too&lt;br /&gt;
        selectorLink: &#039;a&#039;,&lt;br /&gt;
        classActive: &#039;dashboard-jump-active&#039;,&lt;br /&gt;
        timeout: 1500&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    let searchBuffer = &#039;&#039;;&lt;br /&gt;
    let clearTimer = null;&lt;br /&gt;
&lt;br /&gt;
    document.addEventListener(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        // 3. EDITING GUARD:&lt;br /&gt;
        // If the user is typing in a form field, a contentEditable div (VisualEditor),&lt;br /&gt;
        // or if the html has the &#039;ve-active&#039; class (VisualEditor active state), ignore them.&lt;br /&gt;
        const targetTag = e.target.tagName.toLowerCase();&lt;br /&gt;
        const isInput = [&#039;input&#039;, &#039;textarea&#039;, &#039;select&#039;].includes(targetTag);&lt;br /&gt;
        const isEditable = e.target.isContentEditable;&lt;br /&gt;
        const isVEActive = document.documentElement.classList.contains(&#039;ve-active&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (isInput || isEditable || isVEActive) {&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 4. Modifier Key Guard: Ctrl, Alt, Meta (Command) are strictly off-limits.&lt;br /&gt;
        if (e.ctrlKey || e.altKey || e.metaKey) {&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Logic handling&lt;br /&gt;
        if (e.key === &#039;Escape&#039;) {&lt;br /&gt;
            resetSearch();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (e.key === &#039;Enter&#039;) {&lt;br /&gt;
            const active = document.querySelector(`.${CONFIG.classActive} ${CONFIG.selectorLink}`);&lt;br /&gt;
            if (active) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
                active.click();&lt;br /&gt;
            }&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (e.key === &#039;Backspace&#039;) {&lt;br /&gt;
            searchBuffer = searchBuffer.slice(0, -1);&lt;br /&gt;
            if (searchBuffer.length === 0) resetSearch();&lt;br /&gt;
            else updateSelection();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Capture typing (Single character keys only)&lt;br /&gt;
        if (e.key.length === 1) {&lt;br /&gt;
            // Optional: If you want to prevent Citizen&#039;s shortcuts (like &#039;/&#039;)&lt;br /&gt;
            // if (e.key === &#039;/&#039;) e.stopPropagation(); &lt;br /&gt;
&lt;br /&gt;
            searchBuffer += e.key;&lt;br /&gt;
            updateSelection();&lt;br /&gt;
&lt;br /&gt;
            // Reset the &amp;quot;clear buffer&amp;quot; timer&lt;br /&gt;
            clearTimeout(clearTimer);&lt;br /&gt;
            clearTimer = setTimeout(resetSearch, CONFIG.timeout);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateSelection() {&lt;br /&gt;
        // Clear previous highlighting&lt;br /&gt;
        document.querySelectorAll(`.${CONFIG.classActive}`).forEach(el =&amp;gt; el.classList.remove(CONFIG.classActive));&lt;br /&gt;
&lt;br /&gt;
        if (!searchBuffer) return;&lt;br /&gt;
&lt;br /&gt;
        const cards = document.querySelectorAll(CONFIG.selectorCard);&lt;br /&gt;
        &lt;br /&gt;
        // Escape regex characters to prevent syntax errors if you type a bracket&lt;br /&gt;
        const safeBuffer = searchBuffer.replace(/[.*+?^${}()|[\]\\]/g, &#039;\\$&amp;amp;&#039;);&lt;br /&gt;
        const regex = new RegExp(`^${safeBuffer}`, &#039;i&#039;); // Case-insensitive, starts-with&lt;br /&gt;
&lt;br /&gt;
        for (const card of cards) {&lt;br /&gt;
            // Get text content&lt;br /&gt;
            const labelEl = card.querySelector(CONFIG.selectorLabel);&lt;br /&gt;
            const descEl = card.querySelector(CONFIG.selectorDesc);&lt;br /&gt;
            &lt;br /&gt;
            const labelText = labelEl ? labelEl.innerText.trim() : &#039;&#039;;&lt;br /&gt;
            const descText = descEl ? descEl.innerText.trim() : &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
            // Priority 1: Check the Label (Title)&lt;br /&gt;
            if (labelText &amp;amp;&amp;amp; regex.test(labelText)) {&lt;br /&gt;
                activateCard(card);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // Priority 2: Check the Description&lt;br /&gt;
            if (descText &amp;amp;&amp;amp; regex.test(descText)) {&lt;br /&gt;
                activateCard(card);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function activateCard(card) {&lt;br /&gt;
        card.classList.add(CONFIG.classActive);&lt;br /&gt;
        card.scrollIntoView({ behavior: &#039;smooth&#039;, block: &#039;center&#039; });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetSearch() {&lt;br /&gt;
        searchBuffer = &#039;&#039;;&lt;br /&gt;
        document.querySelectorAll(`.${CONFIG.classActive}`).forEach(el =&amp;gt; el.classList.remove(CONFIG.classActive));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
})();&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=MediaWiki:Citizen.js&amp;diff=18</id>
		<title>MediaWiki:Citizen.js</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=MediaWiki:Citizen.js&amp;diff=18"/>
		<updated>2026-02-02T12:56:37Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: Replaced content with &amp;quot;/* All JavaScript here will be loaded for users of the Citizen skin */&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* All JavaScript here will be loaded for users of the Citizen skin */&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=MediaWiki:Citizen.js&amp;diff=17</id>
		<title>MediaWiki:Citizen.js</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=MediaWiki:Citizen.js&amp;diff=17"/>
		<updated>2026-02-02T00:34:45Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* All JavaScript here will be loaded for users of the Citizen skin */&lt;br /&gt;
/**&lt;br /&gt;
 * Dashboard Quick-Jump (v2)&lt;br /&gt;
 * Listens for typing on the Dashboard page and jumps to matching cards.&lt;br /&gt;
 * Now with description searching and strict edit-mode discipline.&lt;br /&gt;
 */&lt;br /&gt;
(function() {&lt;br /&gt;
    // 1. GLOBAL GUARD: If we aren&#039;t in &#039;view&#039; mode, kill the script immediately.&lt;br /&gt;
    // We do not want this running on ?action=edit, ?action=history, etc.&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) !== &#039;view&#039;) return;&lt;br /&gt;
&lt;br /&gt;
    // 2. CONTEXT GUARD: If there are no dashboard cards, go back to sleep.&lt;br /&gt;
    if (!document.querySelector(&#039;.dashboard-card&#039;)) return;&lt;br /&gt;
&lt;br /&gt;
    const CONFIG = {&lt;br /&gt;
        selectorCard: &#039;.dashboard-card&#039;,&lt;br /&gt;
        selectorLabel: &#039;.dashboard-label&#039;,&lt;br /&gt;
        selectorDesc: &#039;.dashboard-desc&#039;, // New: Search descriptions too&lt;br /&gt;
        selectorLink: &#039;a&#039;,&lt;br /&gt;
        classActive: &#039;dashboard-jump-active&#039;,&lt;br /&gt;
        timeout: 1500&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    let searchBuffer = &#039;&#039;;&lt;br /&gt;
    let clearTimer = null;&lt;br /&gt;
&lt;br /&gt;
    document.addEventListener(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        // 3. EDITING GUARD:&lt;br /&gt;
        // If the user is typing in a form field, a contentEditable div (VisualEditor),&lt;br /&gt;
        // or if the html has the &#039;ve-active&#039; class (VisualEditor active state), ignore them.&lt;br /&gt;
        const targetTag = e.target.tagName.toLowerCase();&lt;br /&gt;
        const isInput = [&#039;input&#039;, &#039;textarea&#039;, &#039;select&#039;].includes(targetTag);&lt;br /&gt;
        const isEditable = e.target.isContentEditable;&lt;br /&gt;
        const isVEActive = document.documentElement.classList.contains(&#039;ve-active&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (isInput || isEditable || isVEActive) {&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 4. Modifier Key Guard: Ctrl, Alt, Meta (Command) are strictly off-limits.&lt;br /&gt;
        if (e.ctrlKey || e.altKey || e.metaKey) {&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Logic handling&lt;br /&gt;
        if (e.key === &#039;Escape&#039;) {&lt;br /&gt;
            resetSearch();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (e.key === &#039;Enter&#039;) {&lt;br /&gt;
            const active = document.querySelector(`.${CONFIG.classActive} ${CONFIG.selectorLink}`);&lt;br /&gt;
            if (active) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
                active.click();&lt;br /&gt;
            }&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (e.key === &#039;Backspace&#039;) {&lt;br /&gt;
            searchBuffer = searchBuffer.slice(0, -1);&lt;br /&gt;
            if (searchBuffer.length === 0) resetSearch();&lt;br /&gt;
            else updateSelection();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Capture typing (Single character keys only)&lt;br /&gt;
        if (e.key.length === 1) {&lt;br /&gt;
            // Optional: If you want to prevent Citizen&#039;s shortcuts (like &#039;/&#039;)&lt;br /&gt;
            // if (e.key === &#039;/&#039;) e.stopPropagation(); &lt;br /&gt;
&lt;br /&gt;
            searchBuffer += e.key;&lt;br /&gt;
            updateSelection();&lt;br /&gt;
&lt;br /&gt;
            // Reset the &amp;quot;clear buffer&amp;quot; timer&lt;br /&gt;
            clearTimeout(clearTimer);&lt;br /&gt;
            clearTimer = setTimeout(resetSearch, CONFIG.timeout);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateSelection() {&lt;br /&gt;
        // Clear previous highlighting&lt;br /&gt;
        document.querySelectorAll(`.${CONFIG.classActive}`).forEach(el =&amp;gt; el.classList.remove(CONFIG.classActive));&lt;br /&gt;
&lt;br /&gt;
        if (!searchBuffer) return;&lt;br /&gt;
&lt;br /&gt;
        const cards = document.querySelectorAll(CONFIG.selectorCard);&lt;br /&gt;
        &lt;br /&gt;
        // Escape regex characters to prevent syntax errors if you type a bracket&lt;br /&gt;
        const safeBuffer = searchBuffer.replace(/[.*+?^${}()|[\]\\]/g, &#039;\\$&amp;amp;&#039;);&lt;br /&gt;
        const regex = new RegExp(`^${safeBuffer}`, &#039;i&#039;); // Case-insensitive, starts-with&lt;br /&gt;
&lt;br /&gt;
        for (const card of cards) {&lt;br /&gt;
            // Get text content&lt;br /&gt;
            const labelEl = card.querySelector(CONFIG.selectorLabel);&lt;br /&gt;
            const descEl = card.querySelector(CONFIG.selectorDesc);&lt;br /&gt;
            &lt;br /&gt;
            const labelText = labelEl ? labelEl.innerText.trim() : &#039;&#039;;&lt;br /&gt;
            const descText = descEl ? descEl.innerText.trim() : &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
            // Priority 1: Check the Label (Title)&lt;br /&gt;
            if (labelText &amp;amp;&amp;amp; regex.test(labelText)) {&lt;br /&gt;
                activateCard(card);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // Priority 2: Check the Description&lt;br /&gt;
            if (descText &amp;amp;&amp;amp; regex.test(descText)) {&lt;br /&gt;
                activateCard(card);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function activateCard(card) {&lt;br /&gt;
        card.classList.add(CONFIG.classActive);&lt;br /&gt;
        card.scrollIntoView({ behavior: &#039;smooth&#039;, block: &#039;center&#039; });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetSearch() {&lt;br /&gt;
        searchBuffer = &#039;&#039;;&lt;br /&gt;
        document.querySelectorAll(`.${CONFIG.classActive}`).forEach(el =&amp;gt; el.classList.remove(CONFIG.classActive));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
})();&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=MediaWiki:Citizen.js&amp;diff=16</id>
		<title>MediaWiki:Citizen.js</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=MediaWiki:Citizen.js&amp;diff=16"/>
		<updated>2026-02-02T00:22:47Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/**&lt;br /&gt;
 * Dashboard Quick-Jump (v5 - ES5 Compatible)&lt;br /&gt;
 * Listens for typing on the Dashboard page and jumps to matching cards.&lt;br /&gt;
 * Replaced modern syntax to appease the MediaWiki ResourceLoader gods.&lt;br /&gt;
 */&lt;br /&gt;
$(function() { &lt;br /&gt;
    try {&lt;br /&gt;
        // 1. EDIT MODE GUARD (URL Check)&lt;br /&gt;
        // Check if we are trying to edit.&lt;br /&gt;
        var search = window.location.search;&lt;br /&gt;
        if (search.indexOf(&#039;veaction&#039;) !== -1) return;&lt;br /&gt;
        if (search.indexOf(&#039;action=edit&#039;) !== -1) return;&lt;br /&gt;
        if (search.indexOf(&#039;action=submit&#039;) !== -1) return;&lt;br /&gt;
&lt;br /&gt;
        // 2. CONTEXT GUARD&lt;br /&gt;
        // If there are no dashboard cards, exit.&lt;br /&gt;
        var cards = document.querySelectorAll(&#039;.dashboard-card&#039;);&lt;br /&gt;
        if (cards.length === 0) return;&lt;br /&gt;
&lt;br /&gt;
        var CONFIG = {&lt;br /&gt;
            selectorCard: &#039;.dashboard-card&#039;,&lt;br /&gt;
            selectorLabel: &#039;.dashboard-label&#039;,&lt;br /&gt;
            selectorDesc: &#039;.dashboard-desc&#039;,&lt;br /&gt;
            selectorLink: &#039;a&#039;,&lt;br /&gt;
            classActive: &#039;dashboard-jump-active&#039;,&lt;br /&gt;
            timeout: 1500&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        var searchBuffer = &#039;&#039;;&lt;br /&gt;
        var clearTimer = null;&lt;br /&gt;
&lt;br /&gt;
        document.addEventListener(&#039;keydown&#039;, function(e) {&lt;br /&gt;
            // 3. EDIT INTERFACE GUARD (Dynamic)&lt;br /&gt;
            // Check for active editor classes or elements&lt;br /&gt;
            if (document.documentElement.classList.contains(&#039;ve-active&#039;) || &lt;br /&gt;
                document.querySelector(&#039;.ve-ui-surface&#039;) || &lt;br /&gt;
                document.querySelector(&#039;.wikiEditor-ui&#039;)) {&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // 4. INPUT GUARD&lt;br /&gt;
            // Don&#039;t intercept typing in search bars or inputs&lt;br /&gt;
            var target = e.target;&lt;br /&gt;
            var tagName = target.tagName;&lt;br /&gt;
            if (tagName === &#039;INPUT&#039; || &lt;br /&gt;
                tagName === &#039;TEXTAREA&#039; || &lt;br /&gt;
                tagName === &#039;SELECT&#039; || &lt;br /&gt;
                target.isContentEditable) {&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // 5. MODIFIER GUARD&lt;br /&gt;
            if (e.ctrlKey || e.altKey || e.metaKey) return;&lt;br /&gt;
&lt;br /&gt;
            // --- Logic ---&lt;br /&gt;
            &lt;br /&gt;
            if (e.key === &#039;Escape&#039;) {&lt;br /&gt;
                resetSearch();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            if (e.key === &#039;Enter&#039;) {&lt;br /&gt;
                var active = document.querySelector(&#039;.&#039; + CONFIG.classActive + &#039; &#039; + CONFIG.selectorLink);&lt;br /&gt;
                if (active) {&lt;br /&gt;
                    e.preventDefault();&lt;br /&gt;
                    e.stopPropagation();&lt;br /&gt;
                    active.click();&lt;br /&gt;
                }&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            if (e.key === &#039;Backspace&#039;) {&lt;br /&gt;
                searchBuffer = searchBuffer.slice(0, -1);&lt;br /&gt;
                if (searchBuffer.length === 0) resetSearch();&lt;br /&gt;
                else updateSelection();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // Capture single char keys (letters/numbers)&lt;br /&gt;
            if (e.key.length === 1) {&lt;br /&gt;
                searchBuffer += e.key;&lt;br /&gt;
                updateSelection();&lt;br /&gt;
                &lt;br /&gt;
                clearTimeout(clearTimer);&lt;br /&gt;
                clearTimer = setTimeout(resetSearch, CONFIG.timeout);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function updateSelection() {&lt;br /&gt;
            // Clear previous highlights&lt;br /&gt;
            var actives = document.querySelectorAll(&#039;.&#039; + CONFIG.classActive);&lt;br /&gt;
            for (var i = 0; i &amp;lt; actives.length; i++) {&lt;br /&gt;
                actives[i].classList.remove(CONFIG.classActive);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            if (!searchBuffer) return;&lt;br /&gt;
&lt;br /&gt;
            // Escape special regex chars&lt;br /&gt;
            var safeBuffer = searchBuffer.replace(/[.*+?^${}()|[\]\\]/g, &#039;\\$&amp;amp;&#039;);&lt;br /&gt;
            var regex = new RegExp(&#039;^&#039; + safeBuffer, &#039;i&#039;); &lt;br /&gt;
&lt;br /&gt;
            for (var j = 0; j &amp;lt; cards.length; j++) {&lt;br /&gt;
                var card = cards[j];&lt;br /&gt;
                var labelEl = card.querySelector(CONFIG.selectorLabel);&lt;br /&gt;
                var descEl = card.querySelector(CONFIG.selectorDesc);&lt;br /&gt;
                &lt;br /&gt;
                // Old school null checks (No optional chaining ?.)&lt;br /&gt;
                var label = labelEl ? labelEl.innerText.trim() : &#039;&#039;;&lt;br /&gt;
                var desc = descEl ? descEl.innerText.trim() : &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Priority 1: Label match&lt;br /&gt;
                if (label &amp;amp;&amp;amp; regex.test(label)) {&lt;br /&gt;
                    activateCard(card);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                // Priority 2: Description match&lt;br /&gt;
                if (desc &amp;amp;&amp;amp; regex.test(desc)) {&lt;br /&gt;
                    activateCard(card);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function activateCard(card) {&lt;br /&gt;
            card.classList.add(CONFIG.classActive);&lt;br /&gt;
            card.scrollIntoView({ behavior: &#039;smooth&#039;, block: &#039;center&#039; });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function resetSearch() {&lt;br /&gt;
            searchBuffer = &#039;&#039;;&lt;br /&gt;
            var actives = document.querySelectorAll(&#039;.&#039; + CONFIG.classActive);&lt;br /&gt;
            for (var i = 0; i &amp;lt; actives.length; i++) {&lt;br /&gt;
                actives[i].classList.remove(CONFIG.classActive);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
    } catch (err) {&lt;br /&gt;
        console.error(&#039;Hallyu Dashboard Script Error:&#039;, err);&lt;br /&gt;
    }&lt;br /&gt;
});&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=MediaWiki:Citizen.js&amp;diff=15</id>
		<title>MediaWiki:Citizen.js</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=MediaWiki:Citizen.js&amp;diff=15"/>
		<updated>2026-02-02T00:20:31Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/**&lt;br /&gt;
 * Dashboard Quick-Jump (v4 - Bulletproof)&lt;br /&gt;
 * Listens for typing on the Dashboard page and jumps to matching cards.&lt;br /&gt;
 * Wrapped in strict safety guards to prevent breaking the editor.&lt;br /&gt;
 */&lt;br /&gt;
$(function() { // Wait for the DOM to be fully ready&lt;br /&gt;
    try {&lt;br /&gt;
        // 1. EDIT MODE GUARD (URL Check)&lt;br /&gt;
        // If the URL contains &#039;veaction&#039; (VisualEditor) or &#039;action=edit&#039;, stop immediately.&lt;br /&gt;
        // We use simple string checking here for maximum compatibility.&lt;br /&gt;
        if (window.location.search.indexOf(&#039;veaction&#039;) !== -1) return;&lt;br /&gt;
        if (window.location.search.indexOf(&#039;action=edit&#039;) !== -1) return;&lt;br /&gt;
        if (window.location.search.indexOf(&#039;action=submit&#039;) !== -1) return;&lt;br /&gt;
&lt;br /&gt;
        // 2. CONTEXT GUARD&lt;br /&gt;
        // If there are no dashboard cards, exit.&lt;br /&gt;
        if (!document.querySelector(&#039;.dashboard-card&#039;)) return;&lt;br /&gt;
&lt;br /&gt;
        const CONFIG = {&lt;br /&gt;
            selectorCard: &#039;.dashboard-card&#039;,&lt;br /&gt;
            selectorLabel: &#039;.dashboard-label&#039;,&lt;br /&gt;
            selectorDesc: &#039;.dashboard-desc&#039;,&lt;br /&gt;
            selectorLink: &#039;a&#039;,&lt;br /&gt;
            classActive: &#039;dashboard-jump-active&#039;,&lt;br /&gt;
            timeout: 1500&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        let searchBuffer = &#039;&#039;;&lt;br /&gt;
        let clearTimer = null;&lt;br /&gt;
&lt;br /&gt;
        document.addEventListener(&#039;keydown&#039;, function(e) {&lt;br /&gt;
            // 3. EDIT INTERFACE GUARD (Dynamic)&lt;br /&gt;
            // Even if the URL looked safe, check if an editor overlay is actually open.&lt;br /&gt;
            if (document.documentElement.classList.contains(&#039;ve-active&#039;) || &lt;br /&gt;
                document.querySelector(&#039;.ve-ui-surface&#039;) || &lt;br /&gt;
                document.querySelector(&#039;.wikiEditor-ui&#039;)) {&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // 4. INPUT GUARD&lt;br /&gt;
            // Don&#039;t intercept typing in search bars or inputs&lt;br /&gt;
            const target = e.target;&lt;br /&gt;
            if (target.tagName === &#039;INPUT&#039; || &lt;br /&gt;
                target.tagName === &#039;TEXTAREA&#039; || &lt;br /&gt;
                target.tagName === &#039;SELECT&#039; || &lt;br /&gt;
                target.isContentEditable) {&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // 5. MODIFIER GUARD&lt;br /&gt;
            if (e.ctrlKey || e.altKey || e.metaKey) return;&lt;br /&gt;
&lt;br /&gt;
            // --- Logic ---&lt;br /&gt;
            &lt;br /&gt;
            if (e.key === &#039;Escape&#039;) {&lt;br /&gt;
                resetSearch();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            if (e.key === &#039;Enter&#039;) {&lt;br /&gt;
                const active = document.querySelector(`.${CONFIG.classActive} ${CONFIG.selectorLink}`);&lt;br /&gt;
                if (active) {&lt;br /&gt;
                    e.preventDefault();&lt;br /&gt;
                    e.stopPropagation();&lt;br /&gt;
                    active.click();&lt;br /&gt;
                }&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            if (e.key === &#039;Backspace&#039;) {&lt;br /&gt;
                searchBuffer = searchBuffer.slice(0, -1);&lt;br /&gt;
                if (searchBuffer.length === 0) resetSearch();&lt;br /&gt;
                else updateSelection();&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // Capture single char keys (letters/numbers)&lt;br /&gt;
            if (e.key.length === 1) {&lt;br /&gt;
                searchBuffer += e.key;&lt;br /&gt;
                updateSelection();&lt;br /&gt;
                &lt;br /&gt;
                clearTimeout(clearTimer);&lt;br /&gt;
                clearTimer = setTimeout(resetSearch, CONFIG.timeout);&lt;br /&gt;
            }&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        function updateSelection() {&lt;br /&gt;
            // Clear previous highlights&lt;br /&gt;
            document.querySelectorAll(`.${CONFIG.classActive}`).forEach(el =&amp;gt; el.classList.remove(CONFIG.classActive));&lt;br /&gt;
&lt;br /&gt;
            if (!searchBuffer) return;&lt;br /&gt;
&lt;br /&gt;
            const cards = document.querySelectorAll(CONFIG.selectorCard);&lt;br /&gt;
            // Escape special regex chars to avoid crashes&lt;br /&gt;
            const safeBuffer = searchBuffer.replace(/[.*+?^${}()|[\]\\]/g, &#039;\\$&amp;amp;&#039;);&lt;br /&gt;
            const regex = new RegExp(`^${safeBuffer}`, &#039;i&#039;); &lt;br /&gt;
&lt;br /&gt;
            for (const card of cards) {&lt;br /&gt;
                const label = card.querySelector(CONFIG.selectorLabel)?.innerText.trim() || &#039;&#039;;&lt;br /&gt;
                const desc = card.querySelector(CONFIG.selectorDesc)?.innerText.trim() || &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Priority 1: Label match&lt;br /&gt;
                if (label &amp;amp;&amp;amp; regex.test(label)) {&lt;br /&gt;
                    activateCard(card);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
                // Priority 2: Description match&lt;br /&gt;
                if (desc &amp;amp;&amp;amp; regex.test(desc)) {&lt;br /&gt;
                    activateCard(card);&lt;br /&gt;
                    return;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function activateCard(card) {&lt;br /&gt;
            card.classList.add(CONFIG.classActive);&lt;br /&gt;
            card.scrollIntoView({ behavior: &#039;smooth&#039;, block: &#039;center&#039; });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function resetSearch() {&lt;br /&gt;
            searchBuffer = &#039;&#039;;&lt;br /&gt;
            document.querySelectorAll(`.${CONFIG.classActive}`).forEach(el =&amp;gt; el.classList.remove(CONFIG.classActive));&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
    } catch (err) {&lt;br /&gt;
        console.error(&#039;Hallyu Dashboard Script Error:&#039;, err);&lt;br /&gt;
    }&lt;br /&gt;
});&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=MediaWiki:Citizen.js&amp;diff=14</id>
		<title>MediaWiki:Citizen.js</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=MediaWiki:Citizen.js&amp;diff=14"/>
		<updated>2026-02-02T00:16:08Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/**&lt;br /&gt;
 * Dashboard Quick-Jump (v3 - The &amp;quot;Shy&amp;quot; Version)&lt;br /&gt;
 * Listens for typing on the Dashboard page and jumps to matching cards.&lt;br /&gt;
 * Aggressively disables itself if ANY editing interface is detected.&lt;br /&gt;
 */&lt;br /&gt;
(function() {&lt;br /&gt;
    // 1. INITIAL LOAD GUARD&lt;br /&gt;
    // If we are already in a non-view action, or the URL indicates an edit intent, stop immediately.&lt;br /&gt;
    const uri = new URL(window.location.href);&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) !== &#039;view&#039;) return;&lt;br /&gt;
    if (uri.searchParams.has(&#039;veaction&#039;)) return;&lt;br /&gt;
    if (uri.searchParams.has(&#039;action&#039;) &amp;amp;&amp;amp; uri.searchParams.get(&#039;action&#039;) !== &#039;view&#039;) return;&lt;br /&gt;
&lt;br /&gt;
    // 2. CONTEXT GUARD&lt;br /&gt;
    // If there are no dashboard cards, don&#039;t even add the listener.&lt;br /&gt;
    if (!document.querySelector(&#039;.dashboard-card&#039;)) return;&lt;br /&gt;
&lt;br /&gt;
    const CONFIG = {&lt;br /&gt;
        selectorCard: &#039;.dashboard-card&#039;,&lt;br /&gt;
        selectorLabel: &#039;.dashboard-label&#039;,&lt;br /&gt;
        selectorDesc: &#039;.dashboard-desc&#039;, &lt;br /&gt;
        selectorLink: &#039;a&#039;,&lt;br /&gt;
        classActive: &#039;dashboard-jump-active&#039;,&lt;br /&gt;
        timeout: 1500&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    let searchBuffer = &#039;&#039;;&lt;br /&gt;
    let clearTimer = null;&lt;br /&gt;
&lt;br /&gt;
    document.addEventListener(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        // 3. DYNAMIC EDITOR DETECTION (The Fix)&lt;br /&gt;
        // Check for VisualEditor, NWE, or Source Editor surfaces.&lt;br /&gt;
        // If these exist, the user is editing. Do not interfere.&lt;br /&gt;
        const isVEActive = document.documentElement.classList.contains(&#039;ve-active&#039;);&lt;br /&gt;
        const hasVESurface = document.querySelector(&#039;.ve-ui-surface&#039;);&lt;br /&gt;
        const hasWikiEditor = document.querySelector(&#039;.wikiEditor-ui&#039;);&lt;br /&gt;
        &lt;br /&gt;
        if (isVEActive || hasVESurface || hasWikiEditor) {&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 4. INPUT GUARD&lt;br /&gt;
        // Standard check for typing in search bars, forms, etc.&lt;br /&gt;
        const targetTag = e.target.tagName.toLowerCase();&lt;br /&gt;
        const isInput = [&#039;input&#039;, &#039;textarea&#039;, &#039;select&#039;].includes(targetTag);&lt;br /&gt;
        const isEditable = e.target.isContentEditable;&lt;br /&gt;
&lt;br /&gt;
        if (isInput || isEditable) {&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 5. MODIFIER GUARD&lt;br /&gt;
        if (e.ctrlKey || e.altKey || e.metaKey) {&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // --- LOGIC STARTS HERE ---&lt;br /&gt;
&lt;br /&gt;
        if (e.key === &#039;Escape&#039;) {&lt;br /&gt;
            resetSearch();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (e.key === &#039;Enter&#039;) {&lt;br /&gt;
            const active = document.querySelector(`.${CONFIG.classActive} ${CONFIG.selectorLink}`);&lt;br /&gt;
            if (active) {&lt;br /&gt;
                // Only prevent default if we actually have a card selected&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
                e.stopPropagation();&lt;br /&gt;
                active.click();&lt;br /&gt;
            }&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (e.key === &#039;Backspace&#039;) {&lt;br /&gt;
            searchBuffer = searchBuffer.slice(0, -1);&lt;br /&gt;
            if (searchBuffer.length === 0) resetSearch();&lt;br /&gt;
            else updateSelection();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Capture typing (Single character keys only)&lt;br /&gt;
        if (e.key.length === 1) {&lt;br /&gt;
            searchBuffer += e.key;&lt;br /&gt;
            updateSelection();&lt;br /&gt;
&lt;br /&gt;
            // Reset the &amp;quot;clear buffer&amp;quot; timer&lt;br /&gt;
            clearTimeout(clearTimer);&lt;br /&gt;
            clearTimer = setTimeout(resetSearch, CONFIG.timeout);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateSelection() {&lt;br /&gt;
        // Clean up previous highlights&lt;br /&gt;
        document.querySelectorAll(`.${CONFIG.classActive}`).forEach(el =&amp;gt; el.classList.remove(CONFIG.classActive));&lt;br /&gt;
&lt;br /&gt;
        if (!searchBuffer) return;&lt;br /&gt;
&lt;br /&gt;
        const cards = document.querySelectorAll(CONFIG.selectorCard);&lt;br /&gt;
        // Escape regex to prevent crashes on special chars&lt;br /&gt;
        const safeBuffer = searchBuffer.replace(/[.*+?^${}()|[\]\\]/g, &#039;\\$&amp;amp;&#039;);&lt;br /&gt;
        const regex = new RegExp(`^${safeBuffer}`, &#039;i&#039;); &lt;br /&gt;
&lt;br /&gt;
        for (const card of cards) {&lt;br /&gt;
            const labelEl = card.querySelector(CONFIG.selectorLabel);&lt;br /&gt;
            const descEl = card.querySelector(CONFIG.selectorDesc);&lt;br /&gt;
            &lt;br /&gt;
            const labelText = labelEl ? labelEl.innerText.trim() : &#039;&#039;;&lt;br /&gt;
            const descText = descEl ? descEl.innerText.trim() : &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
            // Priority 1: Label&lt;br /&gt;
            if (labelText &amp;amp;&amp;amp; regex.test(labelText)) {&lt;br /&gt;
                activateCard(card);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
            // Priority 2: Description&lt;br /&gt;
            if (descText &amp;amp;&amp;amp; regex.test(descText)) {&lt;br /&gt;
                activateCard(card);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function activateCard(card) {&lt;br /&gt;
        card.classList.add(CONFIG.classActive);&lt;br /&gt;
        card.scrollIntoView({ behavior: &#039;smooth&#039;, block: &#039;center&#039; });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetSearch() {&lt;br /&gt;
        searchBuffer = &#039;&#039;;&lt;br /&gt;
        document.querySelectorAll(`.${CONFIG.classActive}`).forEach(el =&amp;gt; el.classList.remove(CONFIG.classActive));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
})();&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=MediaWiki:Common.css&amp;diff=13</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=MediaWiki:Common.css&amp;diff=13"/>
		<updated>2026-02-02T00:12:05Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Import Material Design Icons */&lt;br /&gt;
@import url(&#039;https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css&#039;);&lt;br /&gt;
&lt;br /&gt;
/* Target the logo icon in the header */&lt;br /&gt;
.citizen-header__logo .mw-logo-icon {&lt;br /&gt;
    /* Step 1: Hide the actual &amp;lt;img&amp;gt; content (the default black) */&lt;br /&gt;
    content: &amp;quot;&amp;quot;; &lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    &lt;br /&gt;
    /* Step 2: Use the SVG as a mask */&lt;br /&gt;
    -webkit-mask-image: url(&#039;/assets/momoiro_logo.svg&#039;);&lt;br /&gt;
    mask-image: url(&#039;/assets/momoiro_logo.svg&#039;);&lt;br /&gt;
    -webkit-mask-repeat: no-repeat;&lt;br /&gt;
    mask-repeat: no-repeat;&lt;br /&gt;
    -webkit-mask-size: contain;&lt;br /&gt;
    mask-size: contain;&lt;br /&gt;
&lt;br /&gt;
    /* Step 3: Fill the mask with the Citizen icon color variable */&lt;br /&gt;
    background-color: var(--color-base, #202122);&lt;br /&gt;
    &lt;br /&gt;
    /* Maintain dimensions from your HTML */&lt;br /&gt;
    width: 32px;&lt;br /&gt;
    height: 32px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Ensure the drawer version also scales correctly */&lt;br /&gt;
.citizen-drawer__logo .mw-logo-icon {&lt;br /&gt;
    width: 80px;&lt;br /&gt;
    height: 80px;&lt;br /&gt;
    background-color: var(--color-base, #202122);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Dashboard Grid Container */&lt;br /&gt;
.dashboard-grid {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
    gap: 12px; /* Slightly tighter gap */&lt;br /&gt;
    margin-bottom: 20px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Individual Dashboard Cards */&lt;br /&gt;
.dashboard-card {&lt;br /&gt;
    flex: 1 1 220px;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-direction: row; /* Force row direction explicitly */&lt;br /&gt;
    align-items: center; /* Vertically center everything */&lt;br /&gt;
    background-color: var(--background-color-surface);&lt;br /&gt;
    border: 1px solid var(--border-color-subtle);&lt;br /&gt;
    border-radius: var(--border-radius-base, 8px);&lt;br /&gt;
    padding: 12px; /* Reduced from 15px to look less puffy */&lt;br /&gt;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);&lt;br /&gt;
    transition: all 0.2s ease-in-out;&lt;br /&gt;
    text-decoration: none !important;&lt;br /&gt;
    min-width: 200px;&lt;br /&gt;
    color: var(--color-base);&lt;br /&gt;
    overflow: hidden; /* Safety mechanism against rogue scrollbars */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.dashboard-card:hover {&lt;br /&gt;
    transform: translateY(-2px);&lt;br /&gt;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);&lt;br /&gt;
    border-color: var(--color-primary);&lt;br /&gt;
    background-color: var(--background-color-interactive-hover);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* The Icon Box - NO SCROLLBARS ALLOWED */&lt;br /&gt;
.dashboard-icon {&lt;br /&gt;
    width: 42px; /* Fixed width */&lt;br /&gt;
    height: 42px; /* Fixed height */&lt;br /&gt;
    flex-shrink: 0; /* Do not let the text crush the icon */&lt;br /&gt;
    margin-right: 12px;&lt;br /&gt;
    background-color: var(--background-color-overlay);&lt;br /&gt;
    border-radius: 6px;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    color: var(--color-primary);&lt;br /&gt;
    overflow: hidden; /* The nuclear option for scrollbars */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* The actual icon font */&lt;br /&gt;
.dashboard-icon .mdi {&lt;br /&gt;
    font-size: 24px; /* Ensure this fits inside the 42px box */&lt;br /&gt;
    line-height: 1; /* Stop line-height from adding phantom vertical space */&lt;br /&gt;
    display: block; /* Behaves better than inline for transform/sizing */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* The Text Area */&lt;br /&gt;
.dashboard-text {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-direction: column;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    line-height: 1.3; /* Tighten text spacing */&lt;br /&gt;
    flex-grow: 1; /* Take up remaining space */&lt;br /&gt;
    min-width: 0; /* CSS Grid/Flex hack to prevent text overflow issues */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.dashboard-label {&lt;br /&gt;
    font-weight: 700;&lt;br /&gt;
    font-size: 1rem;&lt;br /&gt;
    color: var(--color-base);&lt;br /&gt;
    white-space: nowrap; /* Keep title on one line if you prefer */&lt;br /&gt;
    overflow: hidden;&lt;br /&gt;
    text-overflow: ellipsis; /* ... if it&#039;s too long */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.dashboard-desc {&lt;br /&gt;
    font-size: 0.8rem;&lt;br /&gt;
    color: var(--color-subtle);&lt;br /&gt;
    margin-top: 2px;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
    overflow: hidden;&lt;br /&gt;
    text-overflow: ellipsis;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Kill the external link icon */&lt;br /&gt;
.dashboard-card a.external {&lt;br /&gt;
    background-image: none !important;&lt;br /&gt;
    padding-right: 0 !important;&lt;br /&gt;
}&lt;br /&gt;
/* Dashboard Quick-Jump Highlighting */&lt;br /&gt;
.dashboard-jump-active {&lt;br /&gt;
    /* A nice, sharp border to indicate focus */&lt;br /&gt;
    outline: 2px solid var(--color-primary, #36c); &lt;br /&gt;
    outline-offset: 2px;&lt;br /&gt;
    &lt;br /&gt;
    /* Subtle background shift to show it&#039;s &amp;quot;hot&amp;quot; */&lt;br /&gt;
    background-color: var(--background-color-interactive-subtle, #f8f9fa);&lt;br /&gt;
    &lt;br /&gt;
    /* A tiny scale pop, because we aren&#039;t barbarians */&lt;br /&gt;
    transform: scale(1.02);&lt;br /&gt;
    transition: all 0.1s ease-out;&lt;br /&gt;
    z-index: 10; /* Ensure it pops over neighbors */&lt;br /&gt;
    border-radius: var(--border-radius-base, 4px);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Ensure the text inside doesn&#039;t disappear if the theme shifts colors on hover/active */&lt;br /&gt;
.dashboard-jump-active .dashboard-label a {&lt;br /&gt;
    text-decoration: underline;&lt;br /&gt;
    color: var(--color-primary--hover, #447ff5);&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=MediaWiki:Citizen.js&amp;diff=12</id>
		<title>MediaWiki:Citizen.js</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=MediaWiki:Citizen.js&amp;diff=12"/>
		<updated>2026-02-02T00:08:00Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: Created page with &amp;quot;/* All JavaScript here will be loaded for users of the Citizen skin */ /**  * Dashboard Quick-Jump (v2)  * Listens for typing on the Dashboard page and jumps to matching cards.  * Now with description searching and strict edit-mode discipline.  */ (function() {     // 1. GLOBAL GUARD: If we aren&amp;#039;t in &amp;#039;view&amp;#039; mode, kill the script immediately.     // We do not want this running on ?action=edit, ?action=history, etc.     if (mw.config.get(&amp;#039;wgAction&amp;#039;) !== &amp;#039;view&amp;#039;) return;...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* All JavaScript here will be loaded for users of the Citizen skin */&lt;br /&gt;
/**&lt;br /&gt;
 * Dashboard Quick-Jump (v2)&lt;br /&gt;
 * Listens for typing on the Dashboard page and jumps to matching cards.&lt;br /&gt;
 * Now with description searching and strict edit-mode discipline.&lt;br /&gt;
 */&lt;br /&gt;
(function() {&lt;br /&gt;
    // 1. GLOBAL GUARD: If we aren&#039;t in &#039;view&#039; mode, kill the script immediately.&lt;br /&gt;
    // We do not want this running on ?action=edit, ?action=history, etc.&lt;br /&gt;
    if (mw.config.get(&#039;wgAction&#039;) !== &#039;view&#039;) return;&lt;br /&gt;
&lt;br /&gt;
    // 2. CONTEXT GUARD: If there are no dashboard cards, go back to sleep.&lt;br /&gt;
    if (!document.querySelector(&#039;.dashboard-card&#039;)) return;&lt;br /&gt;
&lt;br /&gt;
    const CONFIG = {&lt;br /&gt;
        selectorCard: &#039;.dashboard-card&#039;,&lt;br /&gt;
        selectorLabel: &#039;.dashboard-label&#039;,&lt;br /&gt;
        selectorDesc: &#039;.dashboard-desc&#039;, // New: Search descriptions too&lt;br /&gt;
        selectorLink: &#039;a&#039;,&lt;br /&gt;
        classActive: &#039;dashboard-jump-active&#039;,&lt;br /&gt;
        timeout: 1500&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    let searchBuffer = &#039;&#039;;&lt;br /&gt;
    let clearTimer = null;&lt;br /&gt;
&lt;br /&gt;
    document.addEventListener(&#039;keydown&#039;, function(e) {&lt;br /&gt;
        // 3. EDITING GUARD:&lt;br /&gt;
        // If the user is typing in a form field, a contentEditable div (VisualEditor),&lt;br /&gt;
        // or if the html has the &#039;ve-active&#039; class (VisualEditor active state), ignore them.&lt;br /&gt;
        const targetTag = e.target.tagName.toLowerCase();&lt;br /&gt;
        const isInput = [&#039;input&#039;, &#039;textarea&#039;, &#039;select&#039;].includes(targetTag);&lt;br /&gt;
        const isEditable = e.target.isContentEditable;&lt;br /&gt;
        const isVEActive = document.documentElement.classList.contains(&#039;ve-active&#039;);&lt;br /&gt;
&lt;br /&gt;
        if (isInput || isEditable || isVEActive) {&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // 4. Modifier Key Guard: Ctrl, Alt, Meta (Command) are strictly off-limits.&lt;br /&gt;
        if (e.ctrlKey || e.altKey || e.metaKey) {&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Logic handling&lt;br /&gt;
        if (e.key === &#039;Escape&#039;) {&lt;br /&gt;
            resetSearch();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (e.key === &#039;Enter&#039;) {&lt;br /&gt;
            const active = document.querySelector(`.${CONFIG.classActive} ${CONFIG.selectorLink}`);&lt;br /&gt;
            if (active) {&lt;br /&gt;
                e.preventDefault();&lt;br /&gt;
                active.click();&lt;br /&gt;
            }&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (e.key === &#039;Backspace&#039;) {&lt;br /&gt;
            searchBuffer = searchBuffer.slice(0, -1);&lt;br /&gt;
            if (searchBuffer.length === 0) resetSearch();&lt;br /&gt;
            else updateSelection();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Capture typing (Single character keys only)&lt;br /&gt;
        if (e.key.length === 1) {&lt;br /&gt;
            // Optional: If you want to prevent Citizen&#039;s shortcuts (like &#039;/&#039;)&lt;br /&gt;
            // if (e.key === &#039;/&#039;) e.stopPropagation(); &lt;br /&gt;
&lt;br /&gt;
            searchBuffer += e.key;&lt;br /&gt;
            updateSelection();&lt;br /&gt;
&lt;br /&gt;
            // Reset the &amp;quot;clear buffer&amp;quot; timer&lt;br /&gt;
            clearTimeout(clearTimer);&lt;br /&gt;
            clearTimer = setTimeout(resetSearch, CONFIG.timeout);&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateSelection() {&lt;br /&gt;
        // Clear previous highlighting&lt;br /&gt;
        document.querySelectorAll(`.${CONFIG.classActive}`).forEach(el =&amp;gt; el.classList.remove(CONFIG.classActive));&lt;br /&gt;
&lt;br /&gt;
        if (!searchBuffer) return;&lt;br /&gt;
&lt;br /&gt;
        const cards = document.querySelectorAll(CONFIG.selectorCard);&lt;br /&gt;
        &lt;br /&gt;
        // Escape regex characters to prevent syntax errors if you type a bracket&lt;br /&gt;
        const safeBuffer = searchBuffer.replace(/[.*+?^${}()|[\]\\]/g, &#039;\\$&amp;amp;&#039;);&lt;br /&gt;
        const regex = new RegExp(`^${safeBuffer}`, &#039;i&#039;); // Case-insensitive, starts-with&lt;br /&gt;
&lt;br /&gt;
        for (const card of cards) {&lt;br /&gt;
            // Get text content&lt;br /&gt;
            const labelEl = card.querySelector(CONFIG.selectorLabel);&lt;br /&gt;
            const descEl = card.querySelector(CONFIG.selectorDesc);&lt;br /&gt;
            &lt;br /&gt;
            const labelText = labelEl ? labelEl.innerText.trim() : &#039;&#039;;&lt;br /&gt;
            const descText = descEl ? descEl.innerText.trim() : &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
            // Priority 1: Check the Label (Title)&lt;br /&gt;
            if (labelText &amp;amp;&amp;amp; regex.test(labelText)) {&lt;br /&gt;
                activateCard(card);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // Priority 2: Check the Description&lt;br /&gt;
            if (descText &amp;amp;&amp;amp; regex.test(descText)) {&lt;br /&gt;
                activateCard(card);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function activateCard(card) {&lt;br /&gt;
        card.classList.add(CONFIG.classActive);&lt;br /&gt;
        card.scrollIntoView({ behavior: &#039;smooth&#039;, block: &#039;center&#039; });&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetSearch() {&lt;br /&gt;
        searchBuffer = &#039;&#039;;&lt;br /&gt;
        document.querySelectorAll(`.${CONFIG.classActive}`).forEach(el =&amp;gt; el.classList.remove(CONFIG.classActive));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
})();&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=MediaWiki:Common.css&amp;diff=11</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=MediaWiki:Common.css&amp;diff=11"/>
		<updated>2026-01-31T21:59:33Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Import Material Design Icons */&lt;br /&gt;
@import url(&#039;https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css&#039;);&lt;br /&gt;
&lt;br /&gt;
/* Target the logo icon in the header */&lt;br /&gt;
.citizen-header__logo .mw-logo-icon {&lt;br /&gt;
    /* Step 1: Hide the actual &amp;lt;img&amp;gt; content (the default black) */&lt;br /&gt;
    content: &amp;quot;&amp;quot;; &lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    &lt;br /&gt;
    /* Step 2: Use the SVG as a mask */&lt;br /&gt;
    -webkit-mask-image: url(&#039;/assets/momoiro_logo.svg&#039;);&lt;br /&gt;
    mask-image: url(&#039;/assets/momoiro_logo.svg&#039;);&lt;br /&gt;
    -webkit-mask-repeat: no-repeat;&lt;br /&gt;
    mask-repeat: no-repeat;&lt;br /&gt;
    -webkit-mask-size: contain;&lt;br /&gt;
    mask-size: contain;&lt;br /&gt;
&lt;br /&gt;
    /* Step 3: Fill the mask with the Citizen icon color variable */&lt;br /&gt;
    background-color: var(--color-base, #202122);&lt;br /&gt;
    &lt;br /&gt;
    /* Maintain dimensions from your HTML */&lt;br /&gt;
    width: 32px;&lt;br /&gt;
    height: 32px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Ensure the drawer version also scales correctly */&lt;br /&gt;
.citizen-drawer__logo .mw-logo-icon {&lt;br /&gt;
    width: 80px;&lt;br /&gt;
    height: 80px;&lt;br /&gt;
    background-color: var(--color-base, #202122);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Dashboard Grid Container */&lt;br /&gt;
.dashboard-grid {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
    gap: 12px; /* Slightly tighter gap */&lt;br /&gt;
    margin-bottom: 20px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Individual Dashboard Cards */&lt;br /&gt;
.dashboard-card {&lt;br /&gt;
    flex: 1 1 220px;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-direction: row; /* Force row direction explicitly */&lt;br /&gt;
    align-items: center; /* Vertically center everything */&lt;br /&gt;
    background-color: var(--background-color-surface);&lt;br /&gt;
    border: 1px solid var(--border-color-subtle);&lt;br /&gt;
    border-radius: var(--border-radius-base, 8px);&lt;br /&gt;
    padding: 12px; /* Reduced from 15px to look less puffy */&lt;br /&gt;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);&lt;br /&gt;
    transition: all 0.2s ease-in-out;&lt;br /&gt;
    text-decoration: none !important;&lt;br /&gt;
    min-width: 200px;&lt;br /&gt;
    color: var(--color-base);&lt;br /&gt;
    overflow: hidden; /* Safety mechanism against rogue scrollbars */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.dashboard-card:hover {&lt;br /&gt;
    transform: translateY(-2px);&lt;br /&gt;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);&lt;br /&gt;
    border-color: var(--color-primary);&lt;br /&gt;
    background-color: var(--background-color-interactive-hover);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* The Icon Box - NO SCROLLBARS ALLOWED */&lt;br /&gt;
.dashboard-icon {&lt;br /&gt;
    width: 42px; /* Fixed width */&lt;br /&gt;
    height: 42px; /* Fixed height */&lt;br /&gt;
    flex-shrink: 0; /* Do not let the text crush the icon */&lt;br /&gt;
    margin-right: 12px;&lt;br /&gt;
    background-color: var(--background-color-overlay);&lt;br /&gt;
    border-radius: 6px;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    color: var(--color-primary);&lt;br /&gt;
    overflow: hidden; /* The nuclear option for scrollbars */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* The actual icon font */&lt;br /&gt;
.dashboard-icon .mdi {&lt;br /&gt;
    font-size: 24px; /* Ensure this fits inside the 42px box */&lt;br /&gt;
    line-height: 1; /* Stop line-height from adding phantom vertical space */&lt;br /&gt;
    display: block; /* Behaves better than inline for transform/sizing */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* The Text Area */&lt;br /&gt;
.dashboard-text {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-direction: column;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    line-height: 1.3; /* Tighten text spacing */&lt;br /&gt;
    flex-grow: 1; /* Take up remaining space */&lt;br /&gt;
    min-width: 0; /* CSS Grid/Flex hack to prevent text overflow issues */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.dashboard-label {&lt;br /&gt;
    font-weight: 700;&lt;br /&gt;
    font-size: 1rem;&lt;br /&gt;
    color: var(--color-base);&lt;br /&gt;
    white-space: nowrap; /* Keep title on one line if you prefer */&lt;br /&gt;
    overflow: hidden;&lt;br /&gt;
    text-overflow: ellipsis; /* ... if it&#039;s too long */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.dashboard-desc {&lt;br /&gt;
    font-size: 0.8rem;&lt;br /&gt;
    color: var(--color-subtle);&lt;br /&gt;
    margin-top: 2px;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
    overflow: hidden;&lt;br /&gt;
    text-overflow: ellipsis;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Kill the external link icon */&lt;br /&gt;
.dashboard-card a.external {&lt;br /&gt;
    background-image: none !important;&lt;br /&gt;
    padding-right: 0 !important;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=Main_Page&amp;diff=10</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=Main_Page&amp;diff=10"/>
		<updated>2026-01-27T17:54:41Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Engaged Learning &amp;amp; Research ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://uofr.sharepoint.com/sites/LibraryLiaisons?spStartSource=spappbar | label=Sharepoint | desc=Library Liaisons | icon=microsoft-sharepoint }}&lt;br /&gt;
{{DashItem | url=https://tables.hallyu.io | label=Tables | desc=PhpMyAdmin | icon=database-search }}&lt;br /&gt;
{{DashItem | url=https://data.hallyu.io | label=Data | desc=Postgres &amp;amp; PGAdmin | icon=database-cog }}&lt;br /&gt;
{{DashItem | url=https://wiki.hallyu.io | label=Wikibase | desc=Knowledge Graph | icon=graph }}&lt;br /&gt;
{{DashItem | url=https://apps.hallyu.io | label=Django | desc=App Framework | icon=language-python }}&lt;br /&gt;
{{DashItem | url=https://learn.rochester.edu | label=Blackboard | desc=LMS | icon=school }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== IT Administration ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://aws.amazon.com/console/ | label=AWS | desc=Management Console | icon=aws }}&lt;br /&gt;
{{DashItem | url=https://sso.hallyu.io | label=SSO | desc=Keycloak | icon=key-variant }}&lt;br /&gt;
{{DashItem | url=https://flow.hallyu.io | label=Flow | desc=Node-Red | icon=pipe }}&lt;br /&gt;
{{DashItem | url=https://desktop.hallyu.io | label=Desktop | desc=Guacamole Remote | icon=monitor-dashboard }}&lt;br /&gt;
{{DashItem | url=https://s3.hallyu.io | label=RClone | desc=Cloud Storage | icon=cloud-sync }}&lt;br /&gt;
{{DashItem | url=https://it.hallyu.io | label=Assets | desc=Snipe-IT | icon=barcode-scan }}&lt;br /&gt;
{{DashItem | url=https://containers.hallyu.io | label=Portainer | desc=Docker Management | icon=docker }}&lt;br /&gt;
{{DashItem | url=https://admin.hallyu.io | label=OpenObserve | desc=Observability | icon=eye-outline }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Personal Information Management ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://tasks.google.com | label=Tasks | desc=Google Tasks | icon=checkbox-marked-circle-outline }}&lt;br /&gt;
{{DashItem | url=https://gemini.google.com | label=Gemini | desc=AI Assistant | icon=creation }}&lt;br /&gt;
{{DashItem | url=https://calendar.notion.so | label=Calendar | desc=Notion Calendar | icon=calendar-month }}&lt;br /&gt;
{{DashItem | url=https://mail.notion.so | label=Mail | desc=Notion Mail | icon=email-outline }}&lt;br /&gt;
{{DashItem | url=https://links.hallyu.io | label=Links | desc=Linkding Bookmarks | icon=bookmark-multiple }}&lt;br /&gt;
{{DashItem | url=https://finance.hallyu.io | label=Finance | desc=Actual Budget | icon=finance }}&lt;br /&gt;
{{DashItem | url=https://notion.so | label=Notion | desc=Workspace | icon=notebook-outline }}&lt;br /&gt;
{{DashItem | url=https://archive.hallyu.io | label=Archive | desc=Paperless-ngx | icon=file-document-multiple-outline }}&lt;br /&gt;
{{DashItem | url=https://voice.google.com | label=Google Voice | desc=VoIP | icon=phone-voip }}&lt;br /&gt;
{{DashItem | url=https://messenger.com | label=Messenger | desc=Facebook | icon=facebook-messenger }}&lt;br /&gt;
{{DashItem | url=https://icloud.com | label=iCloud | desc=Apple Services | icon=apple-icloud }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projects ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://kpop.hallyu.io | label=Kpop | desc=Omeka Digital Archive | icon=music-note }}&lt;br /&gt;
{{DashItem | url=https://vscode.dev | label=VSCode | desc=Visual Studio Code | icon=microsoft-visual-studio-code }}&lt;br /&gt;
{{DashItem | url=https://github.com | label=GitHub | desc=Repositories | icon=github }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Household ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://alexa.com | label=Alexa | desc=Amazon Alexa | icon=amazon-alexa }}&lt;br /&gt;
{{DashItem | url=https://home.hallyu.io | label=Home Assistant | desc=IoT Control | icon=home-automation }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Social ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://twitter.com | label=Twitter | desc=Bird Site | icon=twitter }}&lt;br /&gt;
{{DashItem | url=https://bsky.app | label=BlueSky | desc=Clouds | icon=butterfly }}&lt;br /&gt;
{{DashItem | url=https://facebook.com | label=Facebook | desc=Social | icon=facebook }}&lt;br /&gt;
{{DashItem | url=https://instagram.com | label=Instagram | desc=Photos | icon=instagram }}&lt;br /&gt;
{{DashItem | url=https://mastodon.social | label=Mastodon | desc=Fediverse | icon=mastodon }}&lt;br /&gt;
{{DashItem | url=https://youtube.com | label=YouTube | desc=Video | icon=youtube }}&lt;br /&gt;
{{DashItem | url=https://linkedin.com | label=LinkedIn | desc=Professional | icon=linkedin }}&lt;br /&gt;
{{DashItem | url=https://whatsapp.com | label=WhatsApp | desc=Messaging | icon=whatsapp }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://crunchyroll.com | label=Crunchyroll | desc=Anime | icon=shuriken }}&lt;br /&gt;
{{DashItem | url=https://netflix.com | label=Netflix | desc=Streaming | icon=netflix }}&lt;br /&gt;
{{DashItem | url=https://hulu.com | label=Hulu | desc=Streaming | icon=hulu }}&lt;br /&gt;
{{DashItem | url=https://disneyplus.com | label=Disney+ | desc=Streaming | icon=castle }}&lt;br /&gt;
{{DashItem | url=https://spotify.com | label=Spotify | desc=Music | icon=spotify }}&lt;br /&gt;
{{DashItem | url=https://music.apple.com | label=Apple Music | desc=Music | icon=apple }}&lt;br /&gt;
{{DashItem | url=https://paramountplus.com | label=Paramount+ | desc=Streaming | icon=movie-star }}&lt;br /&gt;
{{DashItem | url=https://primevideo.com | label=Prime Video | desc=Amazon | icon=amazon }}&lt;br /&gt;
{{DashItem | url=https://max.com | label=Max | desc=HBO | icon=television-classic }}&lt;br /&gt;
{{DashItem | url=https://duolingo.com | label=Duolingo | desc=Learning | icon=owl }}&lt;br /&gt;
{{DashItem | url=https://audible.com | label=Audible | desc=Audiobooks | icon=book-music }}&lt;br /&gt;
{{DashItem | url=https://rosettastone.com | label=Rosetta Stone | desc=Learning | icon=translate }}&lt;br /&gt;
{{DashItem | url=https://kindle.com | label=Kindle | desc=Reading | icon=tablet-dashboard }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Unsorted ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://trakt.tv | label=Trakt | desc=Tracking | icon=eye-check-outline }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=Template:DashItem&amp;diff=9</id>
		<title>Template:DashItem</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=Template:DashItem&amp;diff=9"/>
		<updated>2026-01-27T17:47:25Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;dashboard-card&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;dashboard-icon&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;mdi mdi-{{{icon|web}}}&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div class=&amp;quot;dashboard-text&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;dashboard-label&amp;quot;&amp;gt;[{{{url}}} {{{label}}}]&amp;lt;/span&amp;gt;{{#if:{{{desc|}}}|&amp;lt;span class=&amp;quot;dashboard-desc&amp;quot;&amp;gt;{{{desc}}}&amp;lt;/span&amp;gt;}}&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=MediaWiki:Common.css&amp;diff=8</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=MediaWiki:Common.css&amp;diff=8"/>
		<updated>2026-01-27T17:45:06Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Import Material Design Icons */&lt;br /&gt;
@import url(&#039;https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css&#039;);&lt;br /&gt;
&lt;br /&gt;
/* Dashboard Grid Container */&lt;br /&gt;
.dashboard-grid {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
    gap: 12px; /* Slightly tighter gap */&lt;br /&gt;
    margin-bottom: 20px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Individual Dashboard Cards */&lt;br /&gt;
.dashboard-card {&lt;br /&gt;
    flex: 1 1 220px;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-direction: row; /* Force row direction explicitly */&lt;br /&gt;
    align-items: center; /* Vertically center everything */&lt;br /&gt;
    background-color: var(--background-color-surface);&lt;br /&gt;
    border: 1px solid var(--border-color-subtle);&lt;br /&gt;
    border-radius: var(--border-radius-base, 8px);&lt;br /&gt;
    padding: 12px; /* Reduced from 15px to look less puffy */&lt;br /&gt;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);&lt;br /&gt;
    transition: all 0.2s ease-in-out;&lt;br /&gt;
    text-decoration: none !important;&lt;br /&gt;
    min-width: 200px;&lt;br /&gt;
    color: var(--color-base);&lt;br /&gt;
    overflow: hidden; /* Safety mechanism against rogue scrollbars */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.dashboard-card:hover {&lt;br /&gt;
    transform: translateY(-2px);&lt;br /&gt;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);&lt;br /&gt;
    border-color: var(--color-primary);&lt;br /&gt;
    background-color: var(--background-color-interactive-hover);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* The Icon Box - NO SCROLLBARS ALLOWED */&lt;br /&gt;
.dashboard-icon {&lt;br /&gt;
    width: 42px; /* Fixed width */&lt;br /&gt;
    height: 42px; /* Fixed height */&lt;br /&gt;
    flex-shrink: 0; /* Do not let the text crush the icon */&lt;br /&gt;
    margin-right: 12px;&lt;br /&gt;
    background-color: var(--background-color-overlay);&lt;br /&gt;
    border-radius: 6px;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    color: var(--color-primary);&lt;br /&gt;
    overflow: hidden; /* The nuclear option for scrollbars */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* The actual icon font */&lt;br /&gt;
.dashboard-icon .mdi {&lt;br /&gt;
    font-size: 24px; /* Ensure this fits inside the 42px box */&lt;br /&gt;
    line-height: 1; /* Stop line-height from adding phantom vertical space */&lt;br /&gt;
    display: block; /* Behaves better than inline for transform/sizing */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* The Text Area */&lt;br /&gt;
.dashboard-text {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-direction: column;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    line-height: 1.3; /* Tighten text spacing */&lt;br /&gt;
    flex-grow: 1; /* Take up remaining space */&lt;br /&gt;
    min-width: 0; /* CSS Grid/Flex hack to prevent text overflow issues */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.dashboard-label {&lt;br /&gt;
    font-weight: 700;&lt;br /&gt;
    font-size: 1rem;&lt;br /&gt;
    color: var(--color-base);&lt;br /&gt;
    white-space: nowrap; /* Keep title on one line if you prefer */&lt;br /&gt;
    overflow: hidden;&lt;br /&gt;
    text-overflow: ellipsis; /* ... if it&#039;s too long */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.dashboard-desc {&lt;br /&gt;
    font-size: 0.8rem;&lt;br /&gt;
    color: var(--color-subtle);&lt;br /&gt;
    margin-top: 2px;&lt;br /&gt;
    white-space: nowrap;&lt;br /&gt;
    overflow: hidden;&lt;br /&gt;
    text-overflow: ellipsis;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Kill the external link icon */&lt;br /&gt;
.dashboard-card a.external {&lt;br /&gt;
    background-image: none !important;&lt;br /&gt;
    padding-right: 0 !important;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=MediaWiki:Common.css&amp;diff=7</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=MediaWiki:Common.css&amp;diff=7"/>
		<updated>2026-01-27T17:41:54Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Import Material Design Icons */&lt;br /&gt;
@import url(&#039;https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css&#039;);&lt;br /&gt;
&lt;br /&gt;
/* Dashboard Grid Container */&lt;br /&gt;
.dashboard-grid {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
    gap: 15px;&lt;br /&gt;
    margin-bottom: 20px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Individual Dashboard Cards */&lt;br /&gt;
.dashboard-card {&lt;br /&gt;
    flex: 1 1 250px;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    /* DYNAMIC COLOR: Matches the skin&#039;s card/surface color */&lt;br /&gt;
    background-color: var(--background-color-surface);&lt;br /&gt;
    /* DYNAMIC BORDER: Subtle in both light/dark modes */&lt;br /&gt;
    border: 1px solid var(--border-color-subtle);&lt;br /&gt;
    border-radius: var(--border-radius-base, 8px);&lt;br /&gt;
    padding: 15px;&lt;br /&gt;
    /* Shadow uses a transparent black so it works on dark backgrounds too */&lt;br /&gt;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);&lt;br /&gt;
    transition: all 0.2s ease-in-out;&lt;br /&gt;
    text-decoration: none !important;&lt;br /&gt;
    min-width: 200px;&lt;br /&gt;
    /* Ensure text color inherits from the skin */&lt;br /&gt;
    color: var(--color-base);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.dashboard-card:hover {&lt;br /&gt;
    transform: translateY(-3px);&lt;br /&gt;
    box-shadow: 0 5px 15px rgba(0,0,0,0.2);&lt;br /&gt;
    /* DYNAMIC: Highlight border using the skin&#039;s primary link color */&lt;br /&gt;
    border-color: var(--color-primary);&lt;br /&gt;
    background-color: var(--background-color-interactive-hover);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* The Icon Box */&lt;br /&gt;
.dashboard-icon {&lt;br /&gt;
    /* Fixed square size so they align perfectly */&lt;br /&gt;
    width: 48px;&lt;br /&gt;
    height: 48px;&lt;br /&gt;
    flex-shrink: 0;&lt;br /&gt;
    margin-right: 15px;&lt;br /&gt;
    &lt;br /&gt;
    /* DYNAMIC: This is your &amp;quot;distance&amp;quot; color. &lt;br /&gt;
       It is always slightly distinct from the surface. */&lt;br /&gt;
    background-color: var(--background-color-overlay);&lt;br /&gt;
    &lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
    &lt;br /&gt;
    /* Icon Color: Use primary skin color */&lt;br /&gt;
    color: var(--color-primary);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Force the icon font size inside the box */&lt;br /&gt;
.dashboard-icon .mdi {&lt;br /&gt;
    font-size: 28px;&lt;br /&gt;
    line-height: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* The Text Area */&lt;br /&gt;
.dashboard-text {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-direction: column;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.dashboard-label {&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    font-size: 1.1em;&lt;br /&gt;
    color: var(--color-base);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.dashboard-desc {&lt;br /&gt;
    font-size: 0.85em;&lt;br /&gt;
    /* DYNAMIC: Subtle text color */&lt;br /&gt;
    color: var(--color-subtle);&lt;br /&gt;
    margin-top: 2px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Kill the external link icon */&lt;br /&gt;
.dashboard-card a.external {&lt;br /&gt;
    background-image: none !important;&lt;br /&gt;
    padding-right: 0 !important;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=Main_Page&amp;diff=6</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=Main_Page&amp;diff=6"/>
		<updated>2026-01-27T16:09:06Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Engaged Learning &amp;amp; Research ==&lt;br /&gt;
* [https://uofr.sharepoint.com/sites/LibraryLiaisons?spStartSource=spappbar ELR Sharepoint]&lt;br /&gt;
* [https://tables.hallyu.io Tables] - PhpMyAdmin and Mariadb&lt;br /&gt;
* [https://data.hallyu.io Data] - Postgresql and PGAdmin&lt;br /&gt;
* [https://wiki.hallyu.io Wikibase]&lt;br /&gt;
* [https://apps.hallyu.io Django]&lt;br /&gt;
* [https://learn.rochester.edu Blackboard]&lt;br /&gt;
&lt;br /&gt;
== IT Administration ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;dashboard-grid&amp;quot;&amp;gt;&lt;br /&gt;
{{DashItem | url=https://aws.amazon.com/console/ | label=AWS | desc=Management Console | icon=aws }}&lt;br /&gt;
{{DashItem | url=https://sso.hallyu.io | label=SSO | desc=Keycloak | icon=key-variant }}&lt;br /&gt;
{{DashItem | url=https://flow.hallyu.io | label=Flow | desc=Node-Red | icon=pipe }}&lt;br /&gt;
{{DashItem | url=https://desktop.hallyu.io | label=Desktop | desc=Guacamole Remote | icon=monitor-dashboard }}&lt;br /&gt;
{{DashItem | url=https://s3.hallyu.io | label=RClone | desc=Cloud Storage | icon=cloud-sync }}&lt;br /&gt;
{{DashItem | url=https://it.hallyu.io | label=Assets | desc=Snipe-IT | icon=barcode-scan }}&lt;br /&gt;
{{DashItem | url=https://containers.hallyu.io | label=Portainer | desc=Docker Management | icon=docker }}&lt;br /&gt;
{{DashItem | url=https://admin.hallyu.io | label=OpenObserve | desc=Observability | icon=eye-outline }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Collections ==&lt;br /&gt;
* [https://books.hallyu.io Komga] - Komga Manga Reader&lt;br /&gt;
* [https://media.hallyu.io Media] - Jellyfin Media server&lt;br /&gt;
* [https://subs.hallyu.io Wallos] - Wallos Subscription Manager&lt;br /&gt;
* [https://audio.hallyu.io Audiobooks] - Audiobook Shelf&lt;br /&gt;
&lt;br /&gt;
== Personal Information Management ==&lt;br /&gt;
* [https://tasks.hallyu.io Tasks] - Task management&lt;br /&gt;
* [https://intranet.hallyu.io Intranet] - Pydio&lt;br /&gt;
* [https://calendar.notion.so Calendar] - Notion Calendar&lt;br /&gt;
* [https://mail.notion.so Mail] - Notion Mail&lt;br /&gt;
* [https://links.hallyu.io Links] - Linkding Bookmarks Manager&lt;br /&gt;
* [https://finance.hallyu.io Finance] - Actual Budget&lt;br /&gt;
* [https://notion.so Notion]&lt;br /&gt;
* [https://people.hallyu.io People] - Monica CRM Address Book&lt;br /&gt;
* [https://archive.hallyu.io Archive] - Paperless Document Management&lt;br /&gt;
* [https://voice.google.com Google Voice]&lt;br /&gt;
* [https://messenger.com Messenger] - Facebook Messenger&lt;br /&gt;
&lt;br /&gt;
== Projects ==&lt;br /&gt;
* [https://kpop.hallyu.io Kpop] - Omeka Digital Archive&lt;br /&gt;
* [https://apps.hallyu.io Apps] - Budibase Low Code Platform&lt;br /&gt;
* [https://vscode.dev VSCode] - Visual Studio Code&lt;br /&gt;
* [https://github.com GitHub]&lt;br /&gt;
&lt;br /&gt;
== Household ==&lt;br /&gt;
* [https://chat.openai.com ChatGPT]&lt;br /&gt;
* [https://alexa.com Alexa] - Amazon Alexa&lt;br /&gt;
* [https://home.hallyu.io Home Assistant]&lt;br /&gt;
* [https://cookbook.hallyu.io Mealie] - Mealie Recipe Manager&lt;br /&gt;
&lt;br /&gt;
== Social ==&lt;br /&gt;
* [https://twitter.com Twitter]&lt;br /&gt;
* [https://bsky.app BlueSky]&lt;br /&gt;
* [https://facebook.com Facebook]&lt;br /&gt;
* [https://instagram.com Instagram]&lt;br /&gt;
* [https://mastodon.social Mastodon]&lt;br /&gt;
* [https://youtube.com YouTube]&lt;br /&gt;
* [https://linkedin.com LinkedIn]&lt;br /&gt;
* [https://whatsapp.com WhatsApp]&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
* [https://crunchyroll.com Crunchyroll]&lt;br /&gt;
* [https://netflix.com Netflix]&lt;br /&gt;
* [https://hulu.com Hulu]&lt;br /&gt;
* [https://disneyplus.com Disney+]&lt;br /&gt;
* [https://spotify.com Spotify]&lt;br /&gt;
* [https://music.apple.com Apple Music]&lt;br /&gt;
* [https://paramountplus.com Paramount+]&lt;br /&gt;
* [https://primevideo.com Prime Video] - Amazon Prime Video&lt;br /&gt;
* [https://max.com Max Go] - Max&lt;br /&gt;
* [https://duolingo.com Duolingo]&lt;br /&gt;
* [https://audible.com Audible]&lt;br /&gt;
* [https://rosettastone.com Rosetta Stone]&lt;br /&gt;
* [https://kindle.com Kindle]&lt;br /&gt;
&lt;br /&gt;
== Unsorted ==&lt;br /&gt;
* [https://trakt.tv traktv] - Trakt.tv&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=Template:DashItem&amp;diff=5</id>
		<title>Template:DashItem</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=Template:DashItem&amp;diff=5"/>
		<updated>2026-01-27T16:08:28Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: Created page with &amp;quot;&amp;lt;div class=&amp;quot;dashboard-card&amp;quot;&amp;gt;   &amp;lt;div class=&amp;quot;dashboard-icon&amp;quot;&amp;gt;     &amp;lt;span class=&amp;quot;mdi mdi-{{#if:{{{icon|}}}|{{{icon}}}|web}}&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;   &amp;lt;/div&amp;gt;   &amp;lt;div class=&amp;quot;dashboard-text&amp;quot;&amp;gt;     &amp;lt;span class=&amp;quot;dashboard-label&amp;quot;&amp;gt;[{{{url}}} {{{label}}}]&amp;lt;/span&amp;gt;     {{#if:{{{desc|}}}|&amp;lt;span class=&amp;quot;dashboard-desc&amp;quot;&amp;gt;{{{desc}}}&amp;lt;/span&amp;gt;}}   &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;dashboard-card&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;div class=&amp;quot;dashboard-icon&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;span class=&amp;quot;mdi mdi-{{#if:{{{icon|}}}|{{{icon}}}|web}}&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;div class=&amp;quot;dashboard-text&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;span class=&amp;quot;dashboard-label&amp;quot;&amp;gt;[{{{url}}} {{{label}}}]&amp;lt;/span&amp;gt;&lt;br /&gt;
    {{#if:{{{desc|}}}|&amp;lt;span class=&amp;quot;dashboard-desc&amp;quot;&amp;gt;{{{desc}}}&amp;lt;/span&amp;gt;}}&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=MediaWiki:Common.css&amp;diff=4</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=MediaWiki:Common.css&amp;diff=4"/>
		<updated>2026-01-27T16:07:58Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: Created page with &amp;quot;/* Import Material Design Icons */ @import url(&amp;#039;https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css&amp;#039;);  /* Dashboard Grid Container */ .dashboard-grid {     display: flex;     flex-wrap: wrap;     gap: 15px;     margin-bottom: 20px; }  /* Individual Dashboard Cards */ .dashboard-card {     flex: 1 1 250px; /* Grow to fill, shrink, base width 250px */     display: flex;     align-items: center;     background-color: #ffffff; /* Or whatever matche...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Import Material Design Icons */&lt;br /&gt;
@import url(&#039;https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css&#039;);&lt;br /&gt;
&lt;br /&gt;
/* Dashboard Grid Container */&lt;br /&gt;
.dashboard-grid {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
    gap: 15px;&lt;br /&gt;
    margin-bottom: 20px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Individual Dashboard Cards */&lt;br /&gt;
.dashboard-card {&lt;br /&gt;
    flex: 1 1 250px; /* Grow to fill, shrink, base width 250px */&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    background-color: #ffffff; /* Or whatever matches your skin */&lt;br /&gt;
    border: 1px solid #e0e0e0;&lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    padding: 15px;&lt;br /&gt;
    box-shadow: 0 2px 5px rgba(0,0,0,0.05);&lt;br /&gt;
    transition: all 0.2s ease-in-out;&lt;br /&gt;
    text-decoration: none !important; /* Kill the underline */&lt;br /&gt;
    min-width: 200px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.dashboard-card:hover {&lt;br /&gt;
    transform: translateY(-3px);&lt;br /&gt;
    box-shadow: 0 5px 15px rgba(0,0,0,0.1);&lt;br /&gt;
    border-color: #b0b0b0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* The Icon Box */&lt;br /&gt;
.dashboard-icon {&lt;br /&gt;
    font-size: 24px;&lt;br /&gt;
    margin-right: 15px;&lt;br /&gt;
    color: #555;&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* The Text Area */&lt;br /&gt;
.dashboard-text {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-direction: column;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.dashboard-label {&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
    font-size: 1.1em;&lt;br /&gt;
    color: #333;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.dashboard-desc {&lt;br /&gt;
    font-size: 0.85em;&lt;br /&gt;
    color: #666;&lt;br /&gt;
    margin-top: 2px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Remove external link icon for these cards if you hate them */&lt;br /&gt;
.dashboard-card a.external {&lt;br /&gt;
    background-image: none !important;&lt;br /&gt;
    padding-right: 0 !important;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=Main_Page&amp;diff=3</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=Main_Page&amp;diff=3"/>
		<updated>2026-01-27T16:03:03Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Engaged Learning &amp;amp; Research ==&lt;br /&gt;
* [https://uofr.sharepoint.com/sites/LibraryLiaisons?spStartSource=spappbar ELR Sharepoint]&lt;br /&gt;
* [https://tables.hallyu.io Tables] - PhpMyAdmin and Mariadb&lt;br /&gt;
* [https://data.hallyu.io Data] - Postgresql and PGAdmin&lt;br /&gt;
* [https://wiki.hallyu.io Wikibase]&lt;br /&gt;
* [https://apps.hallyu.io Django]&lt;br /&gt;
* [https://learn.rochester.edu Blackboard]&lt;br /&gt;
&lt;br /&gt;
== IT Administration ==&lt;br /&gt;
* [https://aws.amazon.com/console/ Amazon Web Services] - AWS Management Console&lt;br /&gt;
* [https://sso.hallyu.io SSO] - Keycloak Single Sign On&lt;br /&gt;
* [https://flow.hallyu.io Flow] - Node-Red&lt;br /&gt;
* [https://desktop.hallyu.io Desktop] - Guacamole Remote Desktop&lt;br /&gt;
* [https://s3.hallyu.io RClone] - RClone for cloud storage management&lt;br /&gt;
* [https://it.hallyu.io IT Assets] - Snipe-IT asset manager&lt;br /&gt;
* [https://containers.hallyu.io Portainer] - Portainer Docker Management&lt;br /&gt;
* [https://admin.hallyu.io OpenObserve]&lt;br /&gt;
&lt;br /&gt;
== Collections ==&lt;br /&gt;
* [https://books.hallyu.io Komga] - Komga Manga Reader&lt;br /&gt;
* [https://media.hallyu.io Media] - Jellyfin Media server&lt;br /&gt;
* [https://subs.hallyu.io Wallos] - Wallos Subscription Manager&lt;br /&gt;
* [https://audio.hallyu.io Audiobooks] - Audiobook Shelf&lt;br /&gt;
&lt;br /&gt;
== Personal Information Management ==&lt;br /&gt;
* [https://tasks.hallyu.io Tasks] - Task management&lt;br /&gt;
* [https://intranet.hallyu.io Intranet] - Pydio&lt;br /&gt;
* [https://calendar.notion.so Calendar] - Notion Calendar&lt;br /&gt;
* [https://mail.notion.so Mail] - Notion Mail&lt;br /&gt;
* [https://links.hallyu.io Links] - Linkding Bookmarks Manager&lt;br /&gt;
* [https://finance.hallyu.io Finance] - Actual Budget&lt;br /&gt;
* [https://notion.so Notion]&lt;br /&gt;
* [https://people.hallyu.io People] - Monica CRM Address Book&lt;br /&gt;
* [https://archive.hallyu.io Archive] - Paperless Document Management&lt;br /&gt;
* [https://voice.google.com Google Voice]&lt;br /&gt;
* [https://messenger.com Messenger] - Facebook Messenger&lt;br /&gt;
&lt;br /&gt;
== Projects ==&lt;br /&gt;
* [https://kpop.hallyu.io Kpop] - Omeka Digital Archive&lt;br /&gt;
* [https://apps.hallyu.io Apps] - Budibase Low Code Platform&lt;br /&gt;
* [https://vscode.dev VSCode] - Visual Studio Code&lt;br /&gt;
* [https://github.com GitHub]&lt;br /&gt;
&lt;br /&gt;
== Household ==&lt;br /&gt;
* [https://chat.openai.com ChatGPT]&lt;br /&gt;
* [https://alexa.com Alexa] - Amazon Alexa&lt;br /&gt;
* [https://home.hallyu.io Home Assistant]&lt;br /&gt;
* [https://cookbook.hallyu.io Mealie] - Mealie Recipe Manager&lt;br /&gt;
&lt;br /&gt;
== Social ==&lt;br /&gt;
* [https://twitter.com Twitter]&lt;br /&gt;
* [https://bsky.app BlueSky]&lt;br /&gt;
* [https://facebook.com Facebook]&lt;br /&gt;
* [https://instagram.com Instagram]&lt;br /&gt;
* [https://mastodon.social Mastodon]&lt;br /&gt;
* [https://youtube.com YouTube]&lt;br /&gt;
* [https://linkedin.com LinkedIn]&lt;br /&gt;
* [https://whatsapp.com WhatsApp]&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
* [https://crunchyroll.com Crunchyroll]&lt;br /&gt;
* [https://netflix.com Netflix]&lt;br /&gt;
* [https://hulu.com Hulu]&lt;br /&gt;
* [https://disneyplus.com Disney+]&lt;br /&gt;
* [https://spotify.com Spotify]&lt;br /&gt;
* [https://music.apple.com Apple Music]&lt;br /&gt;
* [https://paramountplus.com Paramount+]&lt;br /&gt;
* [https://primevideo.com Prime Video] - Amazon Prime Video&lt;br /&gt;
* [https://max.com Max Go] - Max&lt;br /&gt;
* [https://duolingo.com Duolingo]&lt;br /&gt;
* [https://audible.com Audible]&lt;br /&gt;
* [https://rosettastone.com Rosetta Stone]&lt;br /&gt;
* [https://kindle.com Kindle]&lt;br /&gt;
&lt;br /&gt;
== Unsorted ==&lt;br /&gt;
* [https://trakt.tv traktv] - Trakt.tv&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
	<entry>
		<id>https://hallyu.io/index.php?title=Main_Page&amp;diff=2</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://hallyu.io/index.php?title=Main_Page&amp;diff=2"/>
		<updated>2026-01-26T21:51:05Z</updated>

		<summary type="html">&lt;p&gt;Joeeasterly: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Engaged Learning &amp;amp; Research ==&lt;br /&gt;
* [https://uofr.sharepoint.com/sites/LibraryLiaisons?spStartSource=spappbar ELR Sharepoint]&lt;br /&gt;
* [https://tables.hallyu.io Tables] - PhpMyAdmin and Mariadb&lt;br /&gt;
* [https://data.hallyu.io Data] - Postgresql and PGAdmin&lt;br /&gt;
* [https://wiki.hallyu.io Wikibase]&lt;br /&gt;
* [https://apps.hallyu.io Django]&lt;br /&gt;
&lt;br /&gt;
== IT Administration ==&lt;br /&gt;
* [https://aws.amazon.com/console/ Amazon Web Services] - AWS Management Console&lt;br /&gt;
* [https://sso.hallyu.io SSO] - Keycloak Single Sign On&lt;br /&gt;
* [https://flow.hallyu.io Flow] - Node-Red&lt;br /&gt;
* [https://desktop.hallyu.io Desktop] - Guacamole Remote Desktop&lt;br /&gt;
* [https://s3.hallyu.io RClone] - RClone for cloud storage management&lt;br /&gt;
* [https://it.hallyu.io IT Assets] - Snipe-IT asset manager&lt;br /&gt;
* [https://containers.hallyu.io Portainer] - Portainer Docker Management&lt;br /&gt;
* [https://admin.hallyu.io OpenObserve]&lt;br /&gt;
&lt;br /&gt;
== Collections ==&lt;br /&gt;
* [https://books.hallyu.io Komga] - Komga Manga Reader&lt;br /&gt;
* [https://media.hallyu.io Media] - Jellyfin Media server&lt;br /&gt;
* [https://subs.hallyu.io Wallos] - Wallos Subscription Manager&lt;br /&gt;
* [https://audio.hallyu.io Audiobooks] - Audiobook Shelf&lt;br /&gt;
&lt;br /&gt;
== Personal Information Management ==&lt;br /&gt;
* [https://tasks.hallyu.io Tasks] - Task management&lt;br /&gt;
* [https://intranet.hallyu.io Intranet] - Pydio&lt;br /&gt;
* [https://calendar.notion.so Calendar] - Notion Calendar&lt;br /&gt;
* [https://mail.notion.so Mail] - Notion Mail&lt;br /&gt;
* [https://links.hallyu.io Links] - Linkding Bookmarks Manager&lt;br /&gt;
* [https://finance.hallyu.io Finance] - Actual Budget&lt;br /&gt;
* [https://notion.so Notion]&lt;br /&gt;
* [https://people.hallyu.io People] - Monica CRM Address Book&lt;br /&gt;
* [https://archive.hallyu.io Archive] - Paperless Document Management&lt;br /&gt;
* [https://voice.google.com Google Voice]&lt;br /&gt;
* [https://messenger.com Messenger] - Facebook Messenger&lt;br /&gt;
&lt;br /&gt;
== Projects ==&lt;br /&gt;
* [https://kpop.hallyu.io Kpop] - Omeka Digital Archive&lt;br /&gt;
* [https://apps.hallyu.io Apps] - Budibase Low Code Platform&lt;br /&gt;
* [https://vscode.dev VSCode] - Visual Studio Code&lt;br /&gt;
* [https://github.com GitHub]&lt;br /&gt;
&lt;br /&gt;
== Household ==&lt;br /&gt;
* [https://chat.openai.com ChatGPT]&lt;br /&gt;
* [https://alexa.com Alexa] - Amazon Alexa&lt;br /&gt;
* [https://home.hallyu.io Home Assistant]&lt;br /&gt;
* [https://cookbook.hallyu.io Mealie] - Mealie Recipe Manager&lt;br /&gt;
&lt;br /&gt;
== Social ==&lt;br /&gt;
* [https://twitter.com Twitter]&lt;br /&gt;
* [https://bsky.app BlueSky]&lt;br /&gt;
* [https://facebook.com Facebook]&lt;br /&gt;
* [https://instagram.com Instagram]&lt;br /&gt;
* [https://mastodon.social Mastodon]&lt;br /&gt;
* [https://youtube.com YouTube]&lt;br /&gt;
* [https://linkedin.com LinkedIn]&lt;br /&gt;
* [https://whatsapp.com WhatsApp]&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
* [https://crunchyroll.com Crunchyroll]&lt;br /&gt;
* [https://netflix.com Netflix]&lt;br /&gt;
* [https://hulu.com Hulu]&lt;br /&gt;
* [https://disneyplus.com Disney+]&lt;br /&gt;
* [https://spotify.com Spotify]&lt;br /&gt;
* [https://music.apple.com Apple Music]&lt;br /&gt;
* [https://paramountplus.com Paramount+]&lt;br /&gt;
* [https://primevideo.com Prime Video] - Amazon Prime Video&lt;br /&gt;
* [https://max.com Max Go] - Max&lt;br /&gt;
* [https://duolingo.com Duolingo]&lt;br /&gt;
* [https://audible.com Audible]&lt;br /&gt;
* [https://rosettastone.com Rosetta Stone]&lt;br /&gt;
* [https://kindle.com Kindle]&lt;br /&gt;
&lt;br /&gt;
== Unsorted ==&lt;br /&gt;
* [https://trakt.tv traktv] - Trakt.tv&lt;/div&gt;</summary>
		<author><name>Joeeasterly</name></author>
	</entry>
</feed>