]> danix's work - danix.xyz-2.git/commitdiff
test: verify accessibility (WCAG AA) - heading hierarchy, contrast, focus, motion
authorDanilo M. <redacted>
Fri, 17 Apr 2026 09:09:42 +0000 (11:09 +0200)
committerDanilo M. <redacted>
Fri, 17 Apr 2026 09:09:42 +0000 (11:09 +0200)
.claude/settings.local.json
themes/danix-xyz-hacker/assets/css/main.min.css

index f84dae28904d638f88595df22246379d9c10d7e8..b96ee8de8a015446fff38f03827823439a206640 100644 (file)
       "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)"
     ]
   }
 }
index cf5343a66cf4eb3a5872b615a84b3dbdb2391168..26cad753351aefaf4cf69a9467fa746c22e2c4e4 100644 (file)
@@ -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);
+  }
 }