diff --git a/.github/workflows/program-classification-validator.yml b/.github/workflows/program-classification-validator.yml
index 923cbc0046..34ef75b54a 100644
--- a/.github/workflows/program-classification-validator.yml
+++ b/.github/workflows/program-classification-validator.yml
@@ -89,26 +89,30 @@ jobs:
// ------------------------------------
// Metadata - new template format
// ------------------------------------
+
+ const normalizedBody = body.replace(/\r\n/g, '\n');
+ const has = (re) => re.test(normalizedBody);
if (
- body.includes('- [x] gssoc26') ||
- body.includes('program: gssoc') ||
- body.includes('- [x] gssoc')
+ has(/\bprogram\s*:\s*gssoc\b/i) ||
+ has(/^\s*[-*]\s*\[x\]\s*(gssoc26|gssoc|i am contributing under gssoc|i am participating via gssoc)\b/im) ||
+ has(/\bprogram\n\s*gssoc\b/i)
) {
actualPrograms.add('gssoc');
}
if (
- body.includes('- [x] nsoc26') ||
- body.includes('program: nsoc') ||
- body.includes('- [x] nsoc')
+ has(/\bprogram\s*:\s*nsoc\b/i) ||
+ has(/^\s*[-*]\s*\[x\]\s*(nsoc26|nsoc|i am contributing under nsoc|i am participating via nsoc)\b/im) ||
+ has(/\bprogram\n\s*nsoc\b/i)
) {
actualPrograms.add('nsoc');
}
if (
- body.includes('- [x] general contribution') ||
- body.includes('program: general')
+ has(/\bprogram\s*:\s*general\b/i) ||
+ has(/^\s*[-*]\s*\[x\]\s*(general contribution|i am a general contributor)\b/im) ||
+ has(/\bprogram\n\s*general\b/i)
) {
hasGeneralContribution = true;
}
diff --git a/index.html b/index.html
index 68c91fcccd..158d461e21 100644
--- a/index.html
+++ b/index.html
@@ -38,35 +38,62 @@
}
-
-
-
-
-
@@ -75,7 +102,12 @@
// Theme restoration - runs early to prevent FOUC
(function(){
try {
- if (localStorage.getItem('theme') === 'dark') {
+ const savedTheme = localStorage.getItem('theme');
+ if (savedTheme === 'dark') {
+ document.documentElement.classList.add('dark');
+ } else if (savedTheme === 'light') {
+ document.documentElement.classList.remove('dark');
+ } else if (globalThis.matchMedia?.('(prefers-color-scheme: dark)').matches) {
document.documentElement.classList.add('dark');
}
} catch(e) {
diff --git a/src/js/app.js b/src/js/app.js
index d1c9415db2..e2ca2cf414 100644
--- a/src/js/app.js
+++ b/src/js/app.js
@@ -109,9 +109,26 @@ const CONTACT_TIPS = {
// ══════════════════════════════════════════════
(function initTheme() {
try {
- const saved = localStorage.getItem('theme') || 'light';
- document.documentElement.classList.toggle('dark', saved === 'dark');
+ const saved = localStorage.getItem('theme');
+ if (saved === 'dark') {
+ document.documentElement.classList.add('dark');
+ } else if (saved === 'light') {
+ document.documentElement.classList.remove('dark');
+ } else if (globalThis.matchMedia?.('(prefers-color-scheme: dark)').matches) {
+ document.documentElement.classList.add('dark');
+ } else {
+ document.documentElement.classList.remove('dark');
+ }
updateThemeIcon();
+
+ if (globalThis.matchMedia) {
+ globalThis.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
+ if (!localStorage.getItem('theme')) {
+ document.documentElement.classList.toggle('dark', e.matches);
+ updateThemeIcon();
+ }
+ });
+ }
} catch (e) {
console.warn('Theme init failed:', e);
}