/** * Accessibility Styles * WCAG 2.1 AA compliant accessibility styles */ @use '../abstracts/variables' as vars; @use '../abstracts/responsive' as resp; @use 'sass:map'; /* ==================== SCREEN READER ONLY ==================== */ .screen-reader-text, .sr-only { position: absolute !important; clip: rect(1px, 1px, 1px, 1px); width: 1px !important; height: 1px !important; padding: 0 !important; border: 0 !important; overflow: hidden; white-space: nowrap; } .screen-reader-text:focus, .sr-only:focus { position: static !important; clip: auto; width: auto !important; height: auto !important; padding: 0.5rem 1rem !important; background: #000; color: #fff; font-size: 1rem; line-height: 1.5; text-decoration: none; z-index: 999999; } /* ==================== SKIP LINKS ==================== */ .skip-links { position: absolute; top: -40px; left: 6px; z-index: 999999; a { position: absolute; top: -40px; left: 6px; padding: 8px 16px; background: #000; color: #fff; text-decoration: none; border-radius: 3px; font-weight: 600; font-size: 0.875rem; line-height: 1.2; transition: top 0.3s ease; &:focus { top: 6px; outline: 2px solid #fff; outline-offset: 2px; } &:hover { background: #333; } } } /* ==================== FOCUS MANAGEMENT ==================== */ /* Default focus styles */ *:focus { outline: 2px solid vars.$color-primary; outline-offset: 2px; } /* Keyboard navigation focus styles */ .keyboard-navigation *:focus { outline: 3px solid vars.$color-primary; outline-offset: 3px; } /* Enhanced focus for interactive elements */ button:focus, [role='button']:focus, input:focus, select:focus, textarea:focus, a:focus { outline: 2px solid vars.$color-primary; outline-offset: 2px; box-shadow: 0 0 0 4px rgba(vars.$color-primary, 0.25); } /* Focus-visible support for modern browsers */ @supports selector(:focus-visible) { *:focus:not(:focus-visible) { outline: none; box-shadow: none; } *:focus-visible { outline: 2px solid vars.$color-primary; outline-offset: 2px; } } /* High contrast focus indicators */ @media (prefers-contrast: high) { *:focus { outline: 3px solid #000; outline-offset: 2px; background: #fff; color: #000; } .keyboard-navigation *:focus { outline: 4px solid #000; outline-offset: 3px; } } /* ==================== HIGH CONTRAST MODE ==================== */ @media (prefers-contrast: high) { .high-contrast { background: #fff !important; color: #000 !important; a { color: #06c !important; text-decoration: underline !important; } a:visited { color: #639 !important; } button, input, select, textarea { background: #fff !important; color: #000 !important; border: 2px solid #000 !important; } .btn-primary { background: #000 !important; color: #fff !important; border: 2px solid #000 !important; } .btn-secondary { background: #fff !important; color: #000 !important; border: 2px solid #000 !important; } } } /* ==================== REDUCED MOTION ==================== */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } .reduce-motion { * { animation: none !important; transition: none !important; } } } /* ==================== FORM ACCESSIBILITY ==================== */ /* Required field indicators */ .required-indicator { color: #d32f2f; font-weight: bold; margin-left: 0.25rem; } /* Error messages */ .error-message { display: block; color: #d32f2f; font-size: 0.875rem; margin-top: 0.25rem; padding: 0.5rem; background: #ffebee; border: 1px solid #d32f2f; border-radius: 4px; } [aria-invalid='true'] { border-color: #d32f2f !important; box-shadow: 0 0 0 2px rgb(211 47 47 / 25%) !important; } /* Form field grouping */ fieldset { border: 1px solid #ccc; border-radius: 4px; padding: 1rem; margin-bottom: 1rem; legend { font-weight: 600; padding: 0 0.5rem; } } /* ==================== TABLE ACCESSIBILITY ==================== */ table { border-collapse: collapse; width: 100%; caption { text-align: left; font-weight: 600; margin-bottom: 0.5rem; caption-side: top; } th { background: vars.$color-neutral-100; font-weight: 600; text-align: left; padding: 0.75rem; border: 1px solid vars.$border-color; } td { padding: 0.75rem; border: 1px solid vars.$border-color; } /* Zebra striping for better readability */ tbody tr:nth-child(even) { background: vars.$color-neutral-50; } } /* ==================== MENU ACCESSIBILITY ==================== */ [role='navigation'] { ul { list-style: none; padding: 0; margin: 0; } a { display: block; padding: 0.75rem 1rem; text-decoration: none; color: vars.$color-text-primary; transition: background-color 0.2s ease; &:hover, &:focus { background: vars.$color-neutral-100; } &[aria-current='page'], &.current-menu-item { background: vars.$color-primary; color: #fff; } } /* Submenu indicators */ .menu-item-has-children > a::after { content: ' (has submenu)'; font-size: 0; speak: literal-punctuation; } [aria-expanded='true']::after { content: ' (expanded)'; font-size: 0; speak: literal-punctuation; } [aria-expanded='false']::after { content: ' (collapsed)'; font-size: 0; speak: literal-punctuation; } } /* ==================== MODAL ACCESSIBILITY ==================== */ .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgb(0 0 0 / 50%); display: flex; align-items: center; justify-content: center; z-index: 999999; &[aria-hidden='true'] { display: none; } .modal-content { background: #fff; padding: 2rem; border-radius: 8px; max-width: 90vw; max-height: 90vh; overflow-y: auto; position: relative; .modal-close { position: absolute; top: 1rem; right: 1rem; background: none; border: none; font-size: 1.5rem; cursor: pointer; padding: 0.5rem; line-height: 1; &:focus { outline: 2px solid vars.$color-primary; outline-offset: 2px; } } } } /* ==================== BUTTON ACCESSIBILITY ==================== */ button, [role='button'] { cursor: pointer; border: none; background: vars.$color-primary; color: #fff; padding: 0.75rem 1.5rem; border-radius: 4px; font-size: 1rem; line-height: 1.5; transition: all 0.2s ease; &:hover { background: darken(vars.$color-primary, 10%); } &:focus { outline: 2px solid vars.$color-primary; outline-offset: 2px; box-shadow: 0 0 0 4px rgba(vars.$color-primary, 0.25); } &:disabled { background: vars.$color-neutral-300; color: vars.$color-neutral-600; cursor: not-allowed; opacity: 60%; } /* Button loading state */ &[aria-busy='true'] { cursor: wait; opacity: 70%; &::after { content: ''; width: 1rem; height: 1rem; border: 2px solid currentcolor; border-radius: 50%; border-top-color: transparent; animation: spin 1s linear infinite; display: inline-block; margin-left: 0.5rem; vertical-align: middle; } } } @keyframes spin { to { transform: rotate(360deg); } } /* ==================== LINK ACCESSIBILITY ==================== */ a { color: vars.$color-primary; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 2px; &:hover { text-decoration-thickness: 2px; } &:focus { outline: 2px solid vars.$color-primary; outline-offset: 2px; text-decoration: none; } &:visited { color: darken(vars.$color-primary, 20%); } /* External link indicators */ &[href^='http']:not([href^='#{$base-url}']):after, &[target='_blank']:after { content: ' (external link)'; font-size: 0; speak: literal-punctuation; } /* Download link indicators */ &[download]::after { content: ' (download)'; font-size: 0; speak: literal-punctuation; } } /* ==================== IMAGE ACCESSIBILITY ==================== */ img { max-width: 100%; height: auto; /* Decorative images */ &[alt=''], &[role='presentation'] { // Already handled by alt attribute } /* Loading state for lazy images */ &[data-src] { background: vars.$color-neutral-100; min-height: 200px; display: flex; align-items: center; justify-content: center; &::before { content: 'Loading image...'; color: vars.$color-neutral-600; font-size: 0.875rem; } } } /* ==================== LIVE REGION ==================== */ #live-region { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; } /* ==================== COLOR CONTRAST ==================== */ /* Ensure minimum contrast ratios */ .text-muted { color: #6c757d; /* 4.5:1 contrast ratio on white */ } .text-light { color: #868e96; /* 4.5:1 contrast ratio on dark backgrounds */ } /* ==================== RESPONSIVE ACCESSIBILITY ==================== */ @include resp.breakpoint-down('md') { /* Larger touch targets on mobile */ button, [role='button'], a, input, select, textarea { min-height: 44px; min-width: 44px; } /* Increased spacing for easier navigation */ .menu a { padding: 1rem; } /* Larger text for better readability */ body { font-size: 1.125rem; } } /* ==================== PRINT ACCESSIBILITY ==================== */ @media print { /* Remove decorative elements */ .skip-links, .screen-reader-text { display: none !important; } /* Ensure links are distinguishable */ a { text-decoration: underline !important; color: #000 !important; } /* Show URL for external links */ a[href^='http']::after { content: ' (' attr(href) ')'; font-size: 0.8em; color: #666; } /* High contrast for printing */ * { background: #fff !important; color: #000 !important; box-shadow: none !important; text-shadow: none !important; } }