From: Danilo M. Date: Fri, 17 Apr 2026 09:09:42 +0000 (+0200) Subject: test: verify accessibility (WCAG AA) - heading hierarchy, contrast, focus, motion X-Git-Tag: release_22042026-1342~148 X-Git-Url: https://git.danix.xyz/?a=commitdiff_plain;h=d1cb52fc16492f02a1f995cc83f0580635e76215;p=danix.xyz-2.git test: verify accessibility (WCAG AA) - heading hierarchy, contrast, focus, motion --- diff --git a/.claude/settings.local.json b/.claude/settings.local.json index f84dae2..b96ee8d 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -12,7 +12,11 @@ "Read(//tmp/**)", "WebFetch(domain:github.com)", "Bash(git checkout *)", - "Bash(npm run *)" + "Bash(npm run *)", + "Bash(hugo server *)", + "Bash(hugo config *)", + "Bash(hugo --debug)", + "Bash(hugo)" ] } } diff --git a/themes/danix-xyz-hacker/assets/css/main.min.css b/themes/danix-xyz-hacker/assets/css/main.min.css index cf5343a..26cad75 100644 --- a/themes/danix-xyz-hacker/assets/css/main.min.css +++ b/themes/danix-xyz-hacker/assets/css/main.min.css @@ -1358,6 +1358,16 @@ button, background-color: var(--accent); } +.btn-secondary { + background-color: var(--accent2); + color: var(--bg); + font-weight: 600; +} + +.btn-secondary:hover:not(:disabled) { + background-color: var(--accent2); +} + .btn-outline { background-color: transparent; color: var(--accent); @@ -1621,11 +1631,21 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { order: 9999; } +.mx-4 { + margin-left: 1rem; + margin-right: 1rem; +} + .mx-auto { margin-left: auto; margin-right: auto; } +.my-12 { + margin-top: 3rem; + margin-bottom: 3rem; +} + .my-4 { margin-top: 1rem; margin-bottom: 1rem; @@ -1669,6 +1689,14 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { margin-left: 0.5rem; } +.mt-1 { + margin-top: 0.25rem; +} + +.mt-12 { + margin-top: 3rem; +} + .mt-16 { margin-top: 4rem; } @@ -1689,6 +1717,10 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { margin-top: 1rem; } +.mt-8 { + margin-top: 2rem; +} + .line-clamp-3 { overflow: hidden; display: -webkit-box; @@ -1736,6 +1768,10 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { height: 1rem; } +.h-48 { + height: 12rem; +} + .h-5 { height: 1.25rem; } @@ -1752,6 +1788,10 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { min-height: calc(100vh - 200px); } +.min-h-screen { + min-height: 100vh; +} + .w-1 { width: 0.25rem; } @@ -1772,6 +1812,10 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { width: 100%; } +.max-w-2xl { + max-width: 42rem; +} + .max-w-3xl { max-width: 48rem; } @@ -1788,6 +1832,10 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { max-width: 32rem; } +.max-w-md { + max-width: 28rem; +} + .max-w-none { max-width: none; } @@ -1818,6 +1866,10 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } +.cursor-pointer { + cursor: pointer; +} + .resize-none { resize: none; } @@ -1826,6 +1878,10 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { resize: both; } +.grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); +} + .flex-col { flex-direction: column; } @@ -1862,6 +1918,10 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { gap: 1rem; } +.gap-6 { + gap: 1.5rem; +} + .gap-8 { gap: 2rem; } @@ -1872,12 +1932,30 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)); } +.space-y-3 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.75rem * var(--tw-space-y-reverse)); +} + +.space-y-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(1rem * var(--tw-space-y-reverse)); +} + .space-y-6 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(1.5rem * var(--tw-space-y-reverse)); } +.space-y-8 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(2rem * var(--tw-space-y-reverse)); +} + .overflow-hidden { overflow: hidden; } @@ -1907,6 +1985,10 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { border-width: 1px; } +.border-2 { + border-width: 2px; +} + .border-4 { border-width: 4px; } @@ -1939,6 +2021,11 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { border-color: var(--border); } +.border-gray-300 { + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity, 1)); +} + .bg-accent { background-color: var(--accent); } @@ -1951,6 +2038,16 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { background-color: rgb(0 0 0 / 0.5); } +.bg-gray-200 { + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1)); +} + +.bg-gray-50 { + --tw-bg-opacity: 1; + background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1)); +} + .bg-surface { background-color: var(--surface); } @@ -1972,6 +2069,10 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { padding: 1.5rem; } +.p-8 { + padding: 2rem; +} + .px-2 { padding-left: 0.5rem; padding-right: 0.5rem; @@ -2043,6 +2144,10 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { padding-top: 2rem; } +.text-left { + text-align: left; +} + .text-center { text-align: center; } @@ -2064,11 +2169,26 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { line-height: 2rem; } +.text-3xl { + font-size: 1.875rem; + line-height: 2.25rem; +} + .text-4xl { font-size: 2.25rem; line-height: 2.5rem; } +.text-5xl { + font-size: 3rem; + line-height: 1; +} + +.text-7xl { + font-size: 4.5rem; + line-height: 1; +} + .text-lg { font-size: 1.125rem; line-height: 1.75rem; @@ -2121,6 +2241,11 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { color: var(--bg); } +.text-gray-600 { + --tw-text-opacity: 1; + color: rgb(75 85 99 / var(--tw-text-opacity, 1)); +} + .text-text { color: var(--text); } @@ -2134,6 +2259,10 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { color: rgb(255 255 255 / var(--tw-text-opacity, 1)); } +.underline { + text-decoration-line: underline; +} + .line-through { text-decoration-line: line-through; } @@ -2163,12 +2292,30 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { opacity: 0.05; } +.shadow-xl { + --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.filter { + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} + .backdrop-blur { --tw-backdrop-blur: blur(8px); -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); } +.transition { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + .transition-all { transition-property: all; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); @@ -2187,6 +2334,12 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { transition-duration: 150ms; } +.transition-shadow { + transition-property: box-shadow; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + .transition-transform { transition-property: transform; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); @@ -2215,6 +2368,7 @@ article.border.border-border\/30.rounded-lg.card.group.bg-bg { --surface-rgb: 16, 30, 45; --border: #182840; --accent: #a855f7; + --accent-rgb: 168, 85, 247; --accent2: #00ff88; --accent-glow: rgba(168, 85, 247, 0.12); --text: #c4d6e8; @@ -2238,6 +2392,7 @@ html.theme-light { --surface-rgb: 240, 243, 247; --border: #d9dfe8; --accent: #9333ea; + --accent-rgb: 147, 51, 234; --accent2: #10b981; --accent-glow: rgba(147, 51, 234, 0.1); --text: #1f2937; @@ -2262,6 +2417,7 @@ html.theme-light { --surface-rgb: 240, 243, 247; --border: #d9dfe8; --accent: #9333ea; + --accent-rgb: 147, 51, 234; --accent2: #10b981; --accent-glow: rgba(147, 51, 234, 0.1); --text: #1f2937; @@ -2711,6 +2867,64 @@ html.theme-light .form-select { color: rgb(239 68 68 / var(--tw-text-opacity, 1)); } +/* ============================================ + FOCUS MANAGEMENT (Week 5) + ============================================ */ + +/* Enhanced :focus-visible with accent color styling */ + +:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; +} + +/* Respect motion preferences for focus indicator */ + +@media (prefers-reduced-motion: reduce) { + :focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; + } +} + +/* Button and link hover/focus transitions */ + +button, +a.btn, +.btn { + transition: all 150ms ease-out; +} + +button:hover, +a.btn:hover, +.btn:hover { + opacity: 0.8; + transform: translateY(-1px); +} + +button:active, +a.btn:active, +.btn:active { + transform: translateY(0); +} + +/* Form input focus transitions with glow effect */ + +input, +textarea, +select { + transition: all 200ms ease-out; +} + +input:focus, +textarea:focus, +select:focus, +input:focus-visible, +textarea:focus-visible, +select:focus-visible { + box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.1); +} + /* ============================================ MODAL COMPONENTS (Week 4) ============================================ */ @@ -2798,15 +3012,37 @@ article.border.border-border\/30.modal-content.overflow-hidden.group.bg-bg { animation: modalSlideUp 0.3s ease-out; } -@keyframes modalSlideUp { +@keyframes fadeIn { from { - transform: translateY(20px); opacity: 0; } to { + opacity: 1; + } +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(20px); + } + + to { + opacity: 1; transform: translateY(0); + } +} + +@keyframes modalSlideUp { + from { + opacity: 0; + transform: translateY(30px); + } + + to { opacity: 1; + transform: translateY(0); } } @@ -2961,6 +3197,10 @@ article.border.border-border\/30.modal-content.overflow-hidden.group.bg-bg { } @keyframes spin { + from { + transform: rotate(0deg); + } + to { transform: rotate(360deg); } @@ -3057,6 +3297,20 @@ article.toast.border-border\/30.rounded-lg.overflow-hidden.group.bg-bg { } } +/* Animation Utility Classes */ + +.animate-fade-in { + animation: fadeIn 300ms ease-out; +} + +.animate-slide-up { + animation: slideUp 300ms ease-out; +} + +.animate-spin-loader { + animation: spin 600ms linear infinite; +} + /* Toast variants */ .toast-success { @@ -3207,6 +3461,26 @@ article.toast.border-border\/30.rounded-lg.overflow-hidden.group.bg-bg { transform: rotate(315deg); } +/* Motion Safety - Respect prefers-reduced-motion */ + +@media (prefers-reduced-motion: reduce) { + /* Remove all animations */ + + *, + *::before, + *::after { + animation: none !important; + transition: none !important; + } + + /* Ensure focus-visible is still visible */ + + :focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; + } +} + .hover\:bg-surface:hover { background-color: var(--surface); } @@ -3215,15 +3489,51 @@ article.toast.border-border\/30.rounded-lg.overflow-hidden.group.bg-bg { color: var(--accent); } +.hover\:text-text:hover { + color: var(--text); +} + .group:hover .group-hover\:text-accent { color: var(--accent); } +@media (prefers-color-scheme: dark) { + .dark\:prose-invert { + --tw-prose-body: var(--tw-prose-invert-body); + --tw-prose-headings: var(--tw-prose-invert-headings); + --tw-prose-lead: var(--tw-prose-invert-lead); + --tw-prose-links: var(--tw-prose-invert-links); + --tw-prose-bold: var(--tw-prose-invert-bold); + --tw-prose-counters: var(--tw-prose-invert-counters); + --tw-prose-bullets: var(--tw-prose-invert-bullets); + --tw-prose-hr: var(--tw-prose-invert-hr); + --tw-prose-quotes: var(--tw-prose-invert-quotes); + --tw-prose-quote-borders: var(--tw-prose-invert-quote-borders); + --tw-prose-captions: var(--tw-prose-invert-captions); + --tw-prose-kbd: var(--tw-prose-invert-kbd); + --tw-prose-kbd-shadows: var(--tw-prose-invert-kbd-shadows); + --tw-prose-code: var(--tw-prose-invert-code); + --tw-prose-pre-code: var(--tw-prose-invert-pre-code); + --tw-prose-pre-bg: var(--tw-prose-invert-pre-bg); + --tw-prose-th-borders: var(--tw-prose-invert-th-borders); + --tw-prose-td-borders: var(--tw-prose-invert-td-borders); + } + + .dark\:hover\:text-text:hover { + color: var(--text); + } +} + .first-letter\:text-3xl::first-letter { font-size: 1.875rem; line-height: 2.25rem; } +.hover\:bg-gray-100:hover { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1)); +} + .hover\:bg-surface:hover { background-color: var(--surface); } @@ -3232,6 +3542,10 @@ article.toast.border-border\/30.rounded-lg.overflow-hidden.group.bg-bg { color: var(--accent); } +.hover\:text-text:hover { + color: var(--text); +} + .hover\:underline:hover { text-decoration-line: underline; } @@ -3244,6 +3558,12 @@ article.toast.border-border\/30.rounded-lg.overflow-hidden.group.bg-bg { opacity: 0.9; } +.hover\:shadow-lg:hover { + --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + .focus\:not-sr-only:focus { position: static; width: auto; @@ -3279,6 +3599,10 @@ article.toast.border-border\/30.rounded-lg.overflow-hidden.group.bg-bg { border-color: var(--accent); } +.focus\:border-transparent:focus { + border-color: transparent; +} + .focus\:bg-accent:focus { background-color: var(--accent); } @@ -3309,6 +3633,12 @@ article.toast.border-border\/30.rounded-lg.overflow-hidden.group.bg-bg { box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); } +.focus\:ring-2:focus { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + .focus\:ring-accent:focus { --tw-ring-color: var(--accent); } @@ -3370,6 +3700,10 @@ article.toast.border-border\/30.rounded-lg.overflow-hidden.group.bg-bg { width: 12rem; } + .md\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .md\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } @@ -3378,8 +3712,60 @@ article.toast.border-border\/30.rounded-lg.overflow-hidden.group.bg-bg { gap: 1.5rem; } + .md\:text-4xl { + font-size: 2.25rem; + line-height: 2.5rem; + } + .md\:text-5xl { font-size: 3rem; line-height: 1; } + + .md\:text-6xl { + font-size: 3.75rem; + line-height: 1; + } + + .md\:text-8xl { + font-size: 6rem; + line-height: 1; + } +} + +@media (min-width: 1060px) { + .lg\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } +} + +@media (prefers-color-scheme: dark) { + .dark\:border-gray-700 { + --tw-border-opacity: 1; + border-color: rgb(55 65 81 / var(--tw-border-opacity, 1)); + } + + .dark\:bg-gray-800 { + --tw-bg-opacity: 1; + background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1)); + } + + .dark\:bg-gray-900 { + --tw-bg-opacity: 1; + background-color: rgb(17 24 39 / var(--tw-bg-opacity, 1)); + } + + .dark\:text-gray-400 { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity, 1)); + } + + .dark\:hover\:bg-gray-800:hover { + --tw-bg-opacity: 1; + background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1)); + } + + .dark\:hover\:text-text:hover { + color: var(--text); + } }