Major additions: - Web-based setup wizard (setup.php, setup_wizard.php, setup-wizard.js) - Production Docker configuration (docker-compose.prod.yml, .env.production) - Database initialization SQL files (deploy/init_settings.sql) - Template builder system with drag-and-drop UI - Advanced features (OAuth, CDN, enhanced analytics, monetization) - Comprehensive documentation (deployment guides, quick start, feature docs) - Design system with accessibility and responsive layout - Deployment automation scripts (deploy.ps1, generate-secrets.ps1) Setup wizard allows customization of: - Platform name and branding - Domain configuration - Membership tiers and pricing - Admin credentials - Feature toggles Database includes 270+ tables for complete video streaming platform with advanced features for analytics, moderation, template building, and monetization. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
516 lines
9.6 KiB
CSS
516 lines
9.6 KiB
CSS
/**
|
|
* EasyStream Accessibility Enhancements
|
|
* WCAG 2.1 AA Compliance CSS
|
|
* Version: 1.0
|
|
*/
|
|
|
|
/* ==================== FOCUS INDICATORS ==================== */
|
|
|
|
/* Enhanced focus styles for keyboard navigation */
|
|
*:focus {
|
|
outline: none; /* Remove default */
|
|
}
|
|
|
|
*:focus-visible {
|
|
outline: 3px solid var(--focus-ring-color, #06a2cb);
|
|
outline-offset: 2px;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
/* Specific focus styles for interactive elements */
|
|
a:focus-visible,
|
|
button:focus-visible,
|
|
input:focus-visible,
|
|
textarea:focus-visible,
|
|
select:focus-visible,
|
|
[role="button"]:focus-visible,
|
|
[role="link"]:focus-visible,
|
|
[tabindex]:focus-visible {
|
|
outline: 3px solid var(--focus-ring-color, #06a2cb);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
/* Video player controls focus */
|
|
.video-js button:focus-visible,
|
|
.vjs-control:focus-visible {
|
|
outline: 3px solid #fff;
|
|
outline-offset: 2px;
|
|
background: rgba(255, 255, 255, 0.2);
|
|
}
|
|
|
|
/* ==================== CONTRAST IMPROVEMENTS ==================== */
|
|
|
|
/* Ensure minimum 4.5:1 contrast ratio for normal text */
|
|
body {
|
|
color: var(--color-text-primary, #111827);
|
|
background: var(--color-bg-primary, #ffffff);
|
|
}
|
|
|
|
[data-theme*="dark"] body {
|
|
color: var(--color-text-primary, #f0f0f0);
|
|
background: var(--color-bg-primary, #121212);
|
|
}
|
|
|
|
/* Link contrast */
|
|
a {
|
|
color: var(--secondary-color, #0793e2);
|
|
text-decoration-skip-ink: auto;
|
|
}
|
|
|
|
a:hover,
|
|
a:focus {
|
|
color: var(--primary-color, #06a2cb);
|
|
text-decoration: underline;
|
|
}
|
|
|
|
/* Button contrast */
|
|
.btn,
|
|
button {
|
|
/* Ensure text contrast on buttons */
|
|
position: relative;
|
|
}
|
|
|
|
.btn-primary,
|
|
.button-blue {
|
|
background: var(--primary-color, #06a2cb);
|
|
color: #ffffff;
|
|
border: 2px solid var(--primary-color, #06a2cb);
|
|
}
|
|
|
|
.btn-primary:hover,
|
|
.button-blue:hover {
|
|
background: var(--third-color, #92cefb);
|
|
border-color: var(--third-color, #92cefb);
|
|
}
|
|
|
|
/* ==================== TEXT SIZING & READABILITY ==================== */
|
|
|
|
/* Responsive font sizes */
|
|
html {
|
|
font-size: 16px; /* Base size for 1rem */
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
html {
|
|
font-size: 14px;
|
|
}
|
|
}
|
|
|
|
/* Line height for readability (WCAG SC 1.4.8) */
|
|
p,
|
|
li,
|
|
dd,
|
|
dt {
|
|
line-height: 1.5;
|
|
max-width: 80ch; /* Optimal line length for readability */
|
|
}
|
|
|
|
h1, h2, h3, h4, h5, h6 {
|
|
line-height: 1.3;
|
|
margin-top: 1em;
|
|
margin-bottom: 0.5em;
|
|
}
|
|
|
|
/* Prevent text from being too small */
|
|
.small-thumbs h2,
|
|
.small-thumbs h3,
|
|
.text-sm,
|
|
small {
|
|
font-size: max(0.875rem, 14px);
|
|
}
|
|
|
|
/* ==================== TOUCH TARGETS ==================== */
|
|
|
|
/* Minimum 44x44px touch targets (WCAG SC 2.5.5) */
|
|
button,
|
|
a,
|
|
input[type="checkbox"],
|
|
input[type="radio"],
|
|
select,
|
|
.btn,
|
|
.touch-target,
|
|
[role="button"],
|
|
[role="link"] {
|
|
min-height: 44px;
|
|
min-width: 44px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 8px 16px;
|
|
}
|
|
|
|
/* Exception for text-only links in paragraphs */
|
|
p a,
|
|
li a {
|
|
min-height: auto;
|
|
min-width: auto;
|
|
display: inline;
|
|
padding: 2px 0;
|
|
}
|
|
|
|
/* Icon buttons */
|
|
.icon-button,
|
|
button[class*="icon-"],
|
|
a[class*="icon-"] {
|
|
min-height: 44px;
|
|
min-width: 44px;
|
|
padding: 10px;
|
|
}
|
|
|
|
/* ==================== SKIP LINKS ==================== */
|
|
|
|
.skip-links {
|
|
position: absolute;
|
|
top: -100px;
|
|
left: 0;
|
|
z-index: 10000;
|
|
background: var(--primary-color, #06a2cb);
|
|
}
|
|
|
|
.skip-links a {
|
|
position: absolute;
|
|
top: -100px;
|
|
left: 0;
|
|
padding: 12px 16px;
|
|
background: var(--primary-color, #06a2cb);
|
|
color: #ffffff;
|
|
font-weight: 600;
|
|
text-decoration: none;
|
|
border-radius: 0 0 4px 0;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
.skip-links a:focus {
|
|
top: 0;
|
|
outline: 3px solid #ffffff;
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
/* ==================== SCREEN READER ONLY ==================== */
|
|
|
|
.sr-only,
|
|
.visually-hidden {
|
|
position: absolute !important;
|
|
width: 1px !important;
|
|
height: 1px !important;
|
|
padding: 0 !important;
|
|
margin: -1px !important;
|
|
overflow: hidden !important;
|
|
clip: rect(0, 0, 0, 0) !important;
|
|
white-space: nowrap !important;
|
|
border-width: 0 !important;
|
|
}
|
|
|
|
/* Allow screen reader text to be focusable when navigated to via keyboard */
|
|
.sr-only:focus,
|
|
.visually-hidden:focus {
|
|
position: static !important;
|
|
width: auto !important;
|
|
height: auto !important;
|
|
overflow: visible !important;
|
|
clip: auto !important;
|
|
white-space: normal !important;
|
|
}
|
|
|
|
/* ==================== FORM LABELS & INPUTS ==================== */
|
|
|
|
/* Ensure labels are visible and associated */
|
|
label {
|
|
display: block;
|
|
margin-bottom: 4px;
|
|
font-weight: 500;
|
|
color: var(--color-text-primary);
|
|
}
|
|
|
|
/* Required field indicator */
|
|
.required::after,
|
|
label.required::after {
|
|
content: " *";
|
|
color: var(--color-error, #ef4444);
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* Error states */
|
|
input:invalid:not(:placeholder-shown),
|
|
.input-error,
|
|
.error {
|
|
border-color: var(--color-error, #ef4444) !important;
|
|
background: var(--color-error-bg, #fee2e2);
|
|
}
|
|
|
|
.error-message {
|
|
color: var(--color-error-text, #991b1b);
|
|
font-size: 0.875rem;
|
|
margin-top: 4px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
}
|
|
|
|
.error-message::before {
|
|
content: "⚠";
|
|
font-size: 1rem;
|
|
}
|
|
|
|
/* Success states */
|
|
.input-success {
|
|
border-color: var(--color-success, #10b981) !important;
|
|
background: var(--color-success-bg, #d1fae5);
|
|
}
|
|
|
|
/* ==================== 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;
|
|
}
|
|
|
|
/* Keep essential animations but make them instant */
|
|
.spinner,
|
|
.loading,
|
|
[class*="animate"] {
|
|
animation: none !important;
|
|
}
|
|
}
|
|
|
|
/* ==================== HIGH CONTRAST MODE ==================== */
|
|
|
|
@media (prefers-contrast: high) {
|
|
* {
|
|
border-width: 2px !important;
|
|
}
|
|
|
|
button,
|
|
a,
|
|
input,
|
|
select,
|
|
textarea {
|
|
border: 2px solid currentColor !important;
|
|
}
|
|
|
|
:focus-visible {
|
|
outline-width: 4px !important;
|
|
outline-offset: 3px !important;
|
|
}
|
|
}
|
|
|
|
/* ==================== DARK MODE PREFERENCES ==================== */
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
/* Respect system preference if no theme is set */
|
|
body:not([data-theme]) {
|
|
background: #121212;
|
|
color: #f0f0f0;
|
|
}
|
|
}
|
|
|
|
/* ==================== TABLES ACCESSIBILITY ==================== */
|
|
|
|
table {
|
|
border-collapse: collapse;
|
|
width: 100%;
|
|
margin: 1rem 0;
|
|
}
|
|
|
|
th {
|
|
text-align: left;
|
|
font-weight: 600;
|
|
background: var(--color-bg-tertiary);
|
|
padding: 12px;
|
|
border: 1px solid var(--color-border-primary);
|
|
}
|
|
|
|
td {
|
|
padding: 12px;
|
|
border: 1px solid var(--color-border-primary);
|
|
}
|
|
|
|
/* Caption for table context */
|
|
caption {
|
|
font-weight: 600;
|
|
text-align: left;
|
|
padding: 8px 0;
|
|
caption-side: top;
|
|
}
|
|
|
|
/* ==================== IMAGES & MEDIA ==================== */
|
|
|
|
/* Ensure images don't overflow and have alt text */
|
|
img {
|
|
max-width: 100%;
|
|
height: auto;
|
|
}
|
|
|
|
/* Decorative images should have empty alt */
|
|
img[alt=""],
|
|
img:not([alt]) {
|
|
outline: 2px solid orange; /* Dev warning for missing alt */
|
|
}
|
|
|
|
/* Video controls must be accessible */
|
|
video:focus {
|
|
outline: 3px solid var(--focus-ring-color, #06a2cb);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
/* ==================== HEADINGS HIERARCHY ==================== */
|
|
|
|
/* Ensure proper heading hierarchy is visually clear */
|
|
h1 {
|
|
font-size: clamp(1.5rem, 5vw, 2.25rem);
|
|
font-weight: 700;
|
|
}
|
|
|
|
h2 {
|
|
font-size: clamp(1.25rem, 4vw, 1.875rem);
|
|
font-weight: 600;
|
|
}
|
|
|
|
h3 {
|
|
font-size: clamp(1.125rem, 3vw, 1.5rem);
|
|
font-weight: 600;
|
|
}
|
|
|
|
h4 {
|
|
font-size: clamp(1rem, 2.5vw, 1.25rem);
|
|
font-weight: 600;
|
|
}
|
|
|
|
h5, h6 {
|
|
font-size: 1rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* ==================== LISTS ==================== */
|
|
|
|
/* Ensure lists have proper spacing */
|
|
ul, ol {
|
|
padding-left: 1.5em;
|
|
}
|
|
|
|
li {
|
|
margin-bottom: 0.5em;
|
|
}
|
|
|
|
/* ==================== MODALS & OVERLAYS ==================== */
|
|
|
|
/* Modal focus trap indicator */
|
|
[role="dialog"]:focus,
|
|
.modal:focus {
|
|
outline: none;
|
|
}
|
|
|
|
/* Modal backdrop */
|
|
.modal-backdrop,
|
|
[role="dialog"]::backdrop {
|
|
background: rgba(0, 0, 0, 0.75);
|
|
}
|
|
|
|
/* Prevent background scroll when modal is open */
|
|
body.modal-open {
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* ==================== LANGUAGE & TEXT DIRECTION ==================== */
|
|
|
|
/* Support for RTL languages */
|
|
[dir="rtl"] {
|
|
direction: rtl;
|
|
text-align: right;
|
|
}
|
|
|
|
[dir="rtl"] .sidebar {
|
|
left: auto;
|
|
right: 0;
|
|
}
|
|
|
|
/* ==================== STATUS MESSAGES ==================== */
|
|
|
|
/* Live regions for dynamic content */
|
|
[role="status"],
|
|
[role="alert"],
|
|
[aria-live] {
|
|
position: relative;
|
|
}
|
|
|
|
.status-message,
|
|
.alert {
|
|
padding: 12px 16px;
|
|
border-radius: 4px;
|
|
margin: 8px 0;
|
|
border-left: 4px solid;
|
|
}
|
|
|
|
.status-success {
|
|
background: var(--color-success-bg);
|
|
color: var(--color-success-text);
|
|
border-color: var(--color-success);
|
|
}
|
|
|
|
.status-error {
|
|
background: var(--color-error-bg);
|
|
color: var(--color-error-text);
|
|
border-color: var(--color-error);
|
|
}
|
|
|
|
.status-warning {
|
|
background: var(--color-warning-bg);
|
|
color: var(--color-warning-text);
|
|
border-color: var(--color-warning);
|
|
}
|
|
|
|
.status-info {
|
|
background: var(--color-info-bg);
|
|
color: var(--color-info-text);
|
|
border-color: var(--color-info);
|
|
}
|
|
|
|
/* ==================== PRINT STYLES ==================== */
|
|
|
|
@media print {
|
|
/* Remove unnecessary elements */
|
|
nav,
|
|
aside,
|
|
.no-print,
|
|
.sidebar,
|
|
header,
|
|
footer {
|
|
display: none !important;
|
|
}
|
|
|
|
/* Optimize for print */
|
|
* {
|
|
background: white !important;
|
|
color: black !important;
|
|
box-shadow: none !important;
|
|
text-shadow: none !important;
|
|
}
|
|
|
|
a {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
/* Show URLs for links */
|
|
a[href]::after {
|
|
content: " (" attr(href) ")";
|
|
}
|
|
|
|
/* Prevent page breaks inside elements */
|
|
img,
|
|
pre,
|
|
blockquote,
|
|
table,
|
|
tr {
|
|
page-break-inside: avoid;
|
|
}
|
|
|
|
h1, h2, h3, h4, h5, h6 {
|
|
page-break-after: avoid;
|
|
}
|
|
}
|