diff --git a/.llm/context.md b/.llm/context.md index b94a9d2a..f9ce4b2b 100644 --- a/.llm/context.md +++ b/.llm/context.md @@ -83,7 +83,7 @@ Invoke these skills for specific tasks. **Regenerate with**: `pwsh -NoProfile -File scripts/generate-skills-index.ps1` - + ### Core Skills (Always Consider) @@ -153,6 +153,7 @@ Invoke these skills for specific tasks. | [debug-il2cpp](./skills/debug-il2cpp.md) | IL2CPP build issues or AOT errors | | [github-actions-script-pattern](./skills/github-actions-script-pattern.md) | Extract GHA logic to testable scripts | | [github-pages](./skills/github-pages.md) | GitHub Pages, Jekyll, markdown link format | +| [github-pages-theming](./skills/github-pages-theming.md) | GitHub Pages CSS theming, Jekyll theme customization | | [github-workflow-permissions](./skills/github-workflow-permissions.md) | Workflow permissions, automated PRs, debugging | | [integrate-odin-inspector](./skills/integrate-odin-inspector.md) | Odin Inspector integration patterns | | [integrate-optional-dependency](./skills/integrate-optional-dependency.md) | Odin, VContainer, Zenject integration patterns | @@ -177,10 +178,6 @@ Invoke these skills for specific tasks. ---- - -## Documentation Is a Deliverable (MANDATORY) - **Documentation is NOT optional.** Every customer-visible change MUST include documentation updates. Incomplete documentation = incomplete work. ### What Requires Documentation Updates diff --git a/.llm/skills/github-pages-theming.md b/.llm/skills/github-pages-theming.md new file mode 100644 index 00000000..86b1518a --- /dev/null +++ b/.llm/skills/github-pages-theming.md @@ -0,0 +1,235 @@ +# Skill: GitHub Pages CSS Theming + + + +**Trigger**: When customizing CSS themes for GitHub Pages or Jekyll documentation sites. + +--- + +## When to Use + +This skill applies when: + +- Overriding remote Jekyll themes (like `pages-themes/minimal`) +- Creating dark/light theme switching +- Fixing "box" appearance issues in themed pages +- Adding CSS accessibility features +- Debugging CSS specificity issues with framework components + +--- + +## CSS Variables in `:root` + +**Always define default CSS variables in `:root`** to ensure themes work before JavaScript loads: + +```css +:root { + /* Define ALL theme variables with defaults */ + --bg-primary: #1e1e1e; + --bg-secondary: #252526; + --text-primary: #d4d4d4; + --text-secondary: #b0b0b0; + --border-color: #3c3c3c; + --link-color: #569cd6; + /* ... all other variables */ +} +``` + +--- + +## Override Remote Theme Elements Comprehensively + +When using a remote theme (like `pages-themes/minimal`), override ALL structural elements to prevent "box" appearance: + +```css +/* Make all nested elements transparent */ +.wrapper, +.wrapper > *, +.inner, +header, +header *, +section, +section *, +footer, +footer * { + background-color: transparent !important; + box-shadow: none !important; +} + +/* Re-apply backgrounds ONLY to root containers */ +body { + background-color: var(--bg-primary) !important; +} + +header { + background-color: var(--bg-primary) !important; + border-bottom: 1px solid var(--border-color) !important; +} + +section { + background-color: var(--bg-primary) !important; +} + +footer { + background-color: var(--bg-primary) !important; + border-top: 1px solid var(--border-color) !important; +} +``` + +--- + +## Theming Best Practices + +| Principle | Implementation | +| ---------------------------- | --------------------------------------------------------------------- | +| Transparent nested elements | Apply `background: transparent` to all children | +| Root-only backgrounds | Apply background colors only to `body`, `header`, `section`, `footer` | +| Consistent color family | Use same `--bg-primary` for all containers | +| No box shadows on containers | Remove `box-shadow` from theme elements | +| Use `!important` sparingly | Required to override remote theme styles | + +--- + +## Theme Switching Support + +```css +/* Dark theme (default) */ +[data-theme="dark"] { + --bg-primary: var(--dark-bg-primary); + --text-primary: var(--dark-text-primary); + /* ... */ +} + +/* Light theme */ +[data-theme="light"] { + --bg-primary: var(--light-bg-primary); + --text-primary: var(--light-text-primary); + /* ... */ +} +``` + +--- + +## CSS Accessibility Requirements + +**Always respect `prefers-reduced-motion` for animations**. This is required by WCAG 2.1 SC 2.3.3 (Animation from Interactions) for users with vestibular disorders. + +```css +/* ✅ CORRECT: Completely disable animation */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0s !important; + transition-duration: 0s !important; + scroll-behavior: auto !important; + } +} + +/* ❌ WRONG: Near-zero values still trigger animation */ +@media (prefers-reduced-motion: reduce) { + * { + animation-duration: 0.01ms !important; /* Still plays briefly! */ + } +} +``` + +**Why `0s` not `0.01ms`**: + +- `0s` truly disables the animation—no visual flicker, no animation callbacks +- `0.01ms` was a legacy workaround for old browser bugs that is now obsolete +- Semantically clearer: `0s` means "no animation" while `0.01ms` implies "very fast animation" + +--- + +## CSS Selector Scoping Consistency + +**CRITICAL**: When styling components in a framework (MkDocs, Jekyll themes, etc.), use consistent scoping for related rules. Inconsistent prefixes cause specificity bugs. + +```css +/* ❌ WRONG: Inconsistent scoping - some rules use .md-typeset, some don't */ +.md-typeset table { + width: 100%; +} +.md-typeset th { + background: var(--bg-secondary); +} +td { + /* Missing .md-typeset prefix! */ + padding: 0.5rem; +} + +/* ✅ CORRECT: All related rules use same scoping */ +.md-typeset table { + width: 100%; +} +.md-typeset th { + background: var(--bg-secondary); +} +.md-typeset td { + padding: 0.5rem; +} +``` + +**Why this matters:** + +1. **Specificity consistency** — All rules have same weight, predictable cascade +2. **Scope isolation** — Styles only affect intended context, don't leak +3. **Maintainability** — Easy to identify which rules belong together + +**Rule**: If one rule in a group uses a parent scope (`.md-typeset`, `.markdown-body`, etc.), ALL related rules must use the same scope. + +--- + +## Avoid Overly Broad Structural Selectors + +When targeting specific page elements (banners, hero sections, featured content), use pseudo-classes to prevent unintended side effects on similar elements: + +```css +/* ❌ WRONG: Affects ALL centered paragraphs including badges */ +section p[align="center"] { + margin: 1rem auto; + max-width: 800px; +} + +/* ✅ CORRECT: Only affects the first centered paragraph (banner) */ +section p[align="center"]:first-of-type { + margin: 1rem auto; + max-width: 800px; +} +``` + +**Why this matters:** + +1. **Unintended cascade** — Multiple elements may match broad selectors +2. **Structural precision** — `:first-of-type`, `:last-of-type`, `:nth-of-type()` target specific positions +3. **Future-proofing** — Prevents CSS conflicts when page content structure changes + +--- + +## Use ARIA Attributes for JavaScript-Controlled States + +```css +/* ❌ WRONG: CSS class never applied by JavaScript */ +table[data-sortable] th.sort-indicator-active::after { + display: none; +} + +/* ✅ CORRECT: Use ARIA attributes that JavaScript already manages */ +table[data-sortable] th[aria-sort]:not([aria-sort="none"])::after { + display: none; +} +``` + +**Why ARIA over custom classes:** + +1. **Single source of truth** — JavaScript sets ARIA for accessibility; CSS uses same attributes +2. **No orphaned classes** — Can't have CSS targeting a class that JavaScript never applies +3. **Accessibility alignment** — Visual presentation matches what screen readers see + +--- + +## Related Skills + +- [github-pages](./github-pages.md) — Jekyll configuration, markdown links, CI/CD validation +- [markdown-reference](./markdown-reference.md) — Link formatting, escaping, linting rules diff --git a/.llm/skills/github-pages.md b/.llm/skills/github-pages.md index eb5cb53f..2d0ab784 100644 --- a/.llm/skills/github-pages.md +++ b/.llm/skills/github-pages.md @@ -187,158 +187,9 @@ Final (correct): ../overview/getting-started (with extension) --- -## CSS Theming for Unified Appearance - -### CSS Variables in `:root` - -**Always define default CSS variables in `:root`** to ensure themes work before JavaScript loads: - -```css -:root { - /* Define ALL theme variables with defaults */ - --bg-primary: #1e1e1e; - --bg-secondary: #252526; - --text-primary: #d4d4d4; - --text-secondary: #b0b0b0; - --border-color: #3c3c3c; - --link-color: #569cd6; - /* ... all other variables */ -} -``` - -### Override Remote Theme Elements Comprehensively - -When using a remote theme (like `pages-themes/minimal`), override ALL structural elements to prevent "box" appearance: - -```css -/* Make all nested elements transparent */ -.wrapper, -.wrapper > *, -.inner, -header, -header *, -section, -section *, -footer, -footer * { - background-color: transparent !important; - box-shadow: none !important; -} - -/* Re-apply backgrounds ONLY to root containers */ -body { - background-color: var(--bg-primary) !important; -} - -header { - background-color: var(--bg-primary) !important; - border-bottom: 1px solid var(--border-color) !important; -} - -section { - background-color: var(--bg-primary) !important; -} - -footer { - background-color: var(--bg-primary) !important; - border-top: 1px solid var(--border-color) !important; -} -``` - -### Theming Best Practices - -| Principle | Implementation | -| ---------------------------- | --------------------------------------------------------------------- | -| Transparent nested elements | Apply `background: transparent` to all children | -| Root-only backgrounds | Apply background colors only to `body`, `header`, `section`, `footer` | -| Consistent color family | Use same `--bg-primary` for all containers | -| No box shadows on containers | Remove `box-shadow` from theme elements | -| Use `!important` sparingly | Required to override remote theme styles | - -### Theme Switching Support - -```css -/* Dark theme (default) */ -[data-theme="dark"] { - --bg-primary: var(--dark-bg-primary); - --text-primary: var(--dark-text-primary); - /* ... */ -} - -/* Light theme */ -[data-theme="light"] { - --bg-primary: var(--light-bg-primary); - --text-primary: var(--light-text-primary); - /* ... */ -} -``` - -### CSS Accessibility Requirements - -**Always respect `prefers-reduced-motion` for animations**. This is required by WCAG 2.1 SC 2.3.3 (Animation from Interactions) for users with vestibular disorders. - -```css -/* ✅ CORRECT: Completely disable animation */ -@media (prefers-reduced-motion: reduce) { - *, - *::before, - *::after { - animation-duration: 0s !important; - transition-duration: 0s !important; - scroll-behavior: auto !important; - } -} - -/* ❌ WRONG: Near-zero values still trigger animation */ -@media (prefers-reduced-motion: reduce) { - * { - animation-duration: 0.01ms !important; /* Still plays briefly! */ - } -} -``` - -**Why `0s` not `0.01ms`**: - -- `0s` truly disables the animation—no visual flicker, no animation callbacks -- `0.01ms` was a legacy workaround for old browser bugs that is now obsolete -- Semantically clearer: `0s` means "no animation" while `0.01ms` implies "very fast animation" - -### CSS Selector Scoping Consistency - -**CRITICAL**: When styling components in a framework (MkDocs, Jekyll themes, etc.), use consistent scoping for related rules. Inconsistent prefixes cause specificity bugs. - -```css -/* ❌ WRONG: Inconsistent scoping - some rules use .md-typeset, some don't */ -.md-typeset table { - width: 100%; -} -.md-typeset th { - background: var(--bg-secondary); -} -td { - /* Missing .md-typeset prefix! */ - padding: 0.5rem; -} - -/* ✅ CORRECT: All related rules use same scoping */ -.md-typeset table { - width: 100%; -} -.md-typeset th { - background: var(--bg-secondary); -} -.md-typeset td { - padding: 0.5rem; -} -``` - -**Why this matters:** - -1. **Specificity consistency** — All rules have same weight, predictable cascade -2. **Scope isolation** — Styles only affect intended context, don't leak -3. **Maintainability** — Easy to identify which rules belong together +## CSS Theming -**Rule**: If one rule in a group uses a parent scope (`.md-typeset`, `.markdown-body`, etc.), ALL related rules must use the same scope. +For comprehensive CSS theming guidance including theme switching, accessibility requirements, and selector best practices, see [github-pages-theming](./github-pages-theming.md). --- @@ -470,6 +321,7 @@ npx prettier --write "**/*.md" ## Related Skills +- [github-pages-theming](./github-pages-theming.md) — CSS theming, accessibility, selectors - [markdown-reference](./markdown-reference.md) — Link formatting, escaping, linting rules - [update-documentation](./update-documentation.md) — Documentation standards and CHANGELOG format - [formatting](./formatting.md) — CSharpier, Prettier, markdownlint workflow diff --git a/assets/css/style.scss b/assets/css/style.scss index 6ed717dd..5cc3dd62 100644 --- a/assets/css/style.scss +++ b/assets/css/style.scss @@ -175,8 +175,11 @@ table[data-sortable] th::after { color: var(--text-muted); } -/* Hide default indicator when sort indicator is present */ -table[data-sortable] th:has(.sort-indicator)::after { +/* + * Hide default indicator when column is actively sorted + * Uses aria-sort attribute which is set by the JavaScript sorting logic + */ +table[data-sortable] th[aria-sort]:not([aria-sort="none"])::after { display: none; } diff --git a/assets/css/theme.css b/assets/css/theme.css index f1cfe3f4..aec291ee 100644 --- a/assets/css/theme.css +++ b/assets/css/theme.css @@ -556,6 +556,82 @@ img { border-radius: 6px; } +/* SVG banner styling - ensure transparency and proper blending */ +img[src*="banner.svg"], +img[alt*="Banner"] { + background: transparent !important; + border: none !important; + box-shadow: none !important; + border-radius: 12px; +} + +/* Light mode banner - subtle shadow for depth on light backgrounds */ +[data-theme="light"] img[src*="banner.svg"], +[data-theme="light"] img[alt*="Banner"] { + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1) !important; +} + +/* Dark mode banner - no shadow needed */ +[data-theme="dark"] img[src*="banner.svg"], +[data-theme="dark"] img[alt*="Banner"] { + box-shadow: none !important; +} + +/* + * Banner container centering for Jekyll pages + * Note: HTML uses
which handles centering natively. + * These styles provide additional sizing constraints. + * Using :first-of-type to target only the banner, not other centered paragraphs (e.g., badges). + */ +section p[align="center"]:first-of-type { + margin: 1rem auto 2rem; + max-width: 800px; +} + +/* Responsive banner sizing - tablet */ +@media (max-width: 960px) { + section p[align="center"]:first-of-type { + max-width: 100%; + margin: 0.75rem auto 1.5rem; + padding: 0 1rem; + } +} + +/* Responsive banner sizing - small tablet */ +@media (max-width: 768px) { + section p[align="center"]:first-of-type { + margin: 0.5rem auto 1.25rem; + padding: 0 0.75rem; + } + + img[src*="banner.svg"], + img[alt*="Banner"] { + border-radius: 10px; + } +} + +/* Responsive banner sizing - mobile */ +@media (max-width: 600px) { + section p[align="center"]:first-of-type { + margin: 0.5rem auto 1rem; + padding: 0 0.5rem; + } + + img[src*="banner.svg"], + img[alt*="Banner"] { + border-radius: 8px; + } +} + +/* Print media query - hide banner for cleaner print output */ +@media print { + section p[align="center"]:first-of-type, + img[src*="banner.svg"], + img[alt*="Banner"] { + display: none !important; + } +} + /* Ensure mermaid diagrams respect theme */ .mermaid { background-color: transparent !important; diff --git a/docs/images/unity-helpers-banner.svg b/docs/images/unity-helpers-banner.svg index e65dbe3d..44b3de32 100644 --- a/docs/images/unity-helpers-banner.svg +++ b/docs/images/unity-helpers-banner.svg @@ -1,4 +1,4 @@ -